1//===- MCLinkerOptimizationHint.h - LOH interface ---------------*- C++ -*-===// 2// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is distributed under the University of Illinois Open Source 7// License. See LICENSE.TXT for details. 8// 9//===----------------------------------------------------------------------===// 10// 11// This file declares some helpers classes to handle Linker Optimization Hint 12// (LOH). 13// 14// FIXME: LOH interface supports only MachO format at the moment. 15//===----------------------------------------------------------------------===// 16 17#ifndef LLVM_MC_MCLINKEROPTIMIZATIONHINT_H 18#define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H 19 20#include "llvm/ADT/SmallVector.h" 21#include "llvm/ADT/StringRef.h" 22#include "llvm/ADT/StringSwitch.h" 23#include "llvm/Support/raw_ostream.h" 24#include <cassert> 25#include <cstdint> 26 27namespace llvm { 28 29class MachObjectWriter; 30class MCAsmLayout; 31class MCSymbol; 32 33/// Linker Optimization Hint Type. 34enum MCLOHType { 35 MCLOH_AdrpAdrp = 0x1u, ///< Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE. 36 MCLOH_AdrpLdr = 0x2u, ///< Adrp _v@PAGE -> Ldr _v@PAGEOFF. 37 MCLOH_AdrpAddLdr = 0x3u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr. 38 MCLOH_AdrpLdrGotLdr = 0x4u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr. 39 MCLOH_AdrpAddStr = 0x5u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF -> Str. 40 MCLOH_AdrpLdrGotStr = 0x6u, ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str. 41 MCLOH_AdrpAdd = 0x7u, ///< Adrp _v@PAGE -> Add _v@PAGEOFF. 42 MCLOH_AdrpLdrGot = 0x8u ///< Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF. 43}; 44 45static inline StringRef MCLOHDirectiveName() { 46 return StringRef(".loh"); 47} 48 49static inline bool isValidMCLOHType(unsigned Kind) { 50 return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; 51} 52 53static inline int MCLOHNameToId(StringRef Name) { 54#define MCLOHCaseNameToId(Name) .Case(#Name, MCLOH_ ## Name) 55 return StringSwitch<int>(Name) 56 MCLOHCaseNameToId(AdrpAdrp) 57 MCLOHCaseNameToId(AdrpLdr) 58 MCLOHCaseNameToId(AdrpAddLdr) 59 MCLOHCaseNameToId(AdrpLdrGotLdr) 60 MCLOHCaseNameToId(AdrpAddStr) 61 MCLOHCaseNameToId(AdrpLdrGotStr) 62 MCLOHCaseNameToId(AdrpAdd) 63 MCLOHCaseNameToId(AdrpLdrGot) 64 .Default(-1); 65} 66 67static inline StringRef MCLOHIdToName(MCLOHType Kind) { 68#define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name); 69 switch (Kind) { 70 MCLOHCaseIdToName(AdrpAdrp); 71 MCLOHCaseIdToName(AdrpLdr); 72 MCLOHCaseIdToName(AdrpAddLdr); 73 MCLOHCaseIdToName(AdrpLdrGotLdr); 74 MCLOHCaseIdToName(AdrpAddStr); 75 MCLOHCaseIdToName(AdrpLdrGotStr); 76 MCLOHCaseIdToName(AdrpAdd); 77 MCLOHCaseIdToName(AdrpLdrGot); 78 } 79 return StringRef(); 80} 81 82static inline int MCLOHIdToNbArgs(MCLOHType Kind) { 83 switch (Kind) { 84 // LOH with two arguments 85 case MCLOH_AdrpAdrp: 86 case MCLOH_AdrpLdr: 87 case MCLOH_AdrpAdd: 88 case MCLOH_AdrpLdrGot: 89 return 2; 90 // LOH with three arguments 91 case MCLOH_AdrpAddLdr: 92 case MCLOH_AdrpLdrGotLdr: 93 case MCLOH_AdrpAddStr: 94 case MCLOH_AdrpLdrGotStr: 95 return 3; 96 } 97 return -1; 98} 99 100/// Store Linker Optimization Hint information (LOH). 101class MCLOHDirective { 102 MCLOHType Kind; 103 104 /// Arguments of this directive. Order matters. 105 SmallVector<MCSymbol *, 3> Args; 106 107 /// Emit this directive in \p OutStream using the information available 108 /// in the given \p ObjWriter and \p Layout to get the address of the 109 /// arguments within the object file. 110 void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, 111 const MCAsmLayout &Layout) const; 112 113public: 114 using LOHArgs = SmallVectorImpl<MCSymbol *>; 115 116 MCLOHDirective(MCLOHType Kind, const LOHArgs &Args) 117 : Kind(Kind), Args(Args.begin(), Args.end()) { 118 assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 119 } 120 121 MCLOHType getKind() const { return Kind; } 122 123 const LOHArgs &getArgs() const { return Args; } 124 125 /// Emit this directive as: 126 /// <kind, numArgs, addr1, ..., addrN> 127 void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const; 128 129 /// Get the size in bytes of this directive if emitted in \p ObjWriter with 130 /// the given \p Layout. 131 uint64_t getEmitSize(const MachObjectWriter &ObjWriter, 132 const MCAsmLayout &Layout) const; 133}; 134 135class MCLOHContainer { 136 /// Keep track of the emit size of all the LOHs. 137 mutable uint64_t EmitSize = 0; 138 139 /// Keep track of all LOH directives. 140 SmallVector<MCLOHDirective, 32> Directives; 141 142public: 143 using LOHDirectives = SmallVectorImpl<MCLOHDirective>; 144 145 MCLOHContainer() = default; 146 147 /// Const accessor to the directives. 148 const LOHDirectives &getDirectives() const { 149 return Directives; 150 } 151 152 /// Add the directive of the given kind \p Kind with the given arguments 153 /// \p Args to the container. 154 void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { 155 Directives.push_back(MCLOHDirective(Kind, Args)); 156 } 157 158 /// Get the size of the directives if emitted. 159 uint64_t getEmitSize(const MachObjectWriter &ObjWriter, 160 const MCAsmLayout &Layout) const { 161 if (!EmitSize) { 162 for (const MCLOHDirective &D : Directives) 163 EmitSize += D.getEmitSize(ObjWriter, Layout); 164 } 165 return EmitSize; 166 } 167 168 /// Emit all Linker Optimization Hint in one big table. 169 /// Each line of the table is emitted by LOHDirective::emit. 170 void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { 171 for (const MCLOHDirective &D : Directives) 172 D.emit(ObjWriter, Layout); 173 } 174 175 void reset() { 176 Directives.clear(); 177 EmitSize = 0; 178 } 179}; 180 181// Add types for specialized template using MCSymbol. 182using MCLOHArgs = MCLOHDirective::LOHArgs; 183using MCLOHDirectives = MCLOHContainer::LOHDirectives; 184 185} // end namespace llvm 186 187#endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H 188