LLVM API Documentation
00001 //===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===// 00002 // 00003 // 00004 // The LLVM Compiler Infrastructure 00005 // 00006 // This file is distributed under the University of Illinois Open Source 00007 // License. See LICENSE.TXT for details. 00008 // 00009 //===----------------------------------------------------------------------===// 00010 // 00011 // This file declares some helpers classes to handle Linker Optimization Hint 00012 // (LOH). 00013 // 00014 // FIXME: LOH interface supports only MachO format at the moment. 00015 //===----------------------------------------------------------------------===// 00016 00017 #ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H 00018 #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H 00019 00020 #include "llvm/ADT/SmallVector.h" 00021 #include "llvm/ADT/StringSwitch.h" 00022 #include "llvm/ADT/StringRef.h" 00023 #include "llvm/MC/MCMachObjectWriter.h" 00024 #include "llvm/Support/raw_ostream.h" 00025 00026 namespace llvm { 00027 00028 // Forward declarations. 00029 class MCAsmLayout; 00030 class MCSymbol; 00031 00032 /// Linker Optimization Hint Type. 00033 enum MCLOHType { 00034 MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE. 00035 MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF. 00036 MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr. 00037 MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr. 00038 MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str. 00039 MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str. 00040 MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF. 00041 MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF. 00042 }; 00043 00044 static inline StringRef MCLOHDirectiveName() { 00045 return StringRef(".loh"); 00046 } 00047 00048 static inline bool isValidMCLOHType(unsigned Kind) { 00049 return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; 00050 } 00051 00052 static inline int MCLOHNameToId(StringRef Name) { 00053 #define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name) 00054 return StringSwitch<int>(Name) 00055 MCLOHCaseNameToId(AdrpAdrp) 00056 MCLOHCaseNameToId(AdrpLdr) 00057 MCLOHCaseNameToId(AdrpAddLdr) 00058 MCLOHCaseNameToId(AdrpLdrGotLdr) 00059 MCLOHCaseNameToId(AdrpAddStr) 00060 MCLOHCaseNameToId(AdrpLdrGotStr) 00061 MCLOHCaseNameToId(AdrpAdd) 00062 MCLOHCaseNameToId(AdrpLdrGot) 00063 .Default(-1); 00064 } 00065 00066 static inline StringRef MCLOHIdToName(MCLOHType Kind) { 00067 #define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name); 00068 switch (Kind) { 00069 MCLOHCaseIdToName(AdrpAdrp); 00070 MCLOHCaseIdToName(AdrpLdr); 00071 MCLOHCaseIdToName(AdrpAddLdr); 00072 MCLOHCaseIdToName(AdrpLdrGotLdr); 00073 MCLOHCaseIdToName(AdrpAddStr); 00074 MCLOHCaseIdToName(AdrpLdrGotStr); 00075 MCLOHCaseIdToName(AdrpAdd); 00076 MCLOHCaseIdToName(AdrpLdrGot); 00077 } 00078 return StringRef(); 00079 } 00080 00081 static inline int MCLOHIdToNbArgs(MCLOHType Kind) { 00082 switch (Kind) { 00083 // LOH with two arguments 00084 case MCLOH_AdrpAdrp: 00085 case MCLOH_AdrpLdr: 00086 case MCLOH_AdrpAdd: 00087 case MCLOH_AdrpLdrGot: 00088 return 2; 00089 // LOH with three arguments 00090 case MCLOH_AdrpAddLdr: 00091 case MCLOH_AdrpLdrGotLdr: 00092 case MCLOH_AdrpAddStr: 00093 case MCLOH_AdrpLdrGotStr: 00094 return 3; 00095 } 00096 return -1; 00097 } 00098 00099 /// Store Linker Optimization Hint information (LOH). 00100 class MCLOHDirective { 00101 MCLOHType Kind; 00102 00103 /// Arguments of this directive. Order matters. 00104 SmallVector<MCSymbol *, 3> Args; 00105 00106 /// Emit this directive in @p OutStream using the information available 00107 /// in the given @p ObjWriter and @p Layout to get the address of the 00108 /// arguments within the object file. 00109 void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, 00110 const MCAsmLayout &Layout) const; 00111 00112 public: 00113 typedef SmallVectorImpl<MCSymbol *> LOHArgs; 00114 00115 MCLOHDirective(MCLOHType Kind, const LOHArgs &Args) 00116 : Kind(Kind), Args(Args.begin(), Args.end()) { 00117 assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 00118 } 00119 00120 MCLOHType getKind() const { return Kind; } 00121 00122 const LOHArgs &getArgs() const { return Args; } 00123 00124 /// Emit this directive as: 00125 /// <kind, numArgs, addr1, ..., addrN> 00126 void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { 00127 raw_ostream &OutStream = ObjWriter.getStream(); 00128 Emit_impl(OutStream, ObjWriter, Layout); 00129 } 00130 00131 /// Get the size in bytes of this directive if emitted in @p ObjWriter with 00132 /// the given @p Layout. 00133 uint64_t getEmitSize(const MachObjectWriter &ObjWriter, 00134 const MCAsmLayout &Layout) const { 00135 class raw_counting_ostream : public raw_ostream { 00136 uint64_t Count; 00137 00138 void write_impl(const char *, size_t size) override { Count += size; } 00139 00140 uint64_t current_pos() const override { return Count; } 00141 00142 public: 00143 raw_counting_ostream() : Count(0) {} 00144 ~raw_counting_ostream() { flush(); } 00145 }; 00146 00147 raw_counting_ostream OutStream; 00148 Emit_impl(OutStream, ObjWriter, Layout); 00149 return OutStream.tell(); 00150 } 00151 }; 00152 00153 class MCLOHContainer { 00154 /// Keep track of the emit size of all the LOHs. 00155 mutable uint64_t EmitSize; 00156 00157 /// Keep track of all LOH directives. 00158 SmallVector<MCLOHDirective, 32> Directives; 00159 00160 public: 00161 typedef SmallVectorImpl<MCLOHDirective> LOHDirectives; 00162 00163 MCLOHContainer() : EmitSize(0) {}; 00164 00165 /// Const accessor to the directives. 00166 const LOHDirectives &getDirectives() const { 00167 return Directives; 00168 } 00169 00170 /// Add the directive of the given kind @p Kind with the given arguments 00171 /// @p Args to the container. 00172 void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { 00173 Directives.push_back(MCLOHDirective(Kind, Args)); 00174 } 00175 00176 /// Get the size of the directives if emitted. 00177 uint64_t getEmitSize(const MachObjectWriter &ObjWriter, 00178 const MCAsmLayout &Layout) const { 00179 if (!EmitSize) { 00180 for (const MCLOHDirective &D : Directives) 00181 EmitSize += D.getEmitSize(ObjWriter, Layout); 00182 } 00183 return EmitSize; 00184 } 00185 00186 /// Emit all Linker Optimization Hint in one big table. 00187 /// Each line of the table is emitted by LOHDirective::Emit. 00188 void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { 00189 for (const MCLOHDirective &D : Directives) 00190 D.Emit(ObjWriter, Layout); 00191 } 00192 00193 void reset() { 00194 Directives.clear(); 00195 EmitSize = 0; 00196 } 00197 }; 00198 00199 // Add types for specialized template using MCSymbol. 00200 typedef MCLOHDirective::LOHArgs MCLOHArgs; 00201 typedef MCLOHContainer::LOHDirectives MCLOHDirectives; 00202 00203 } // end namespace llvm 00204 00205 #endif