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