|
| 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/StringSwitch.h" |
| 22 | +#include "llvm/ADT/StringRef.h" |
| 23 | +#include "llvm/MC/MCMachObjectWriter.h" |
| 24 | +#include "llvm/Support/raw_ostream.h" |
| 25 | + |
| 26 | +namespace llvm { |
| 27 | + |
| 28 | +// Forward declarations. |
| 29 | +class MCAsmLayout; |
| 30 | +class MCSymbol; |
| 31 | + |
| 32 | +/// Linker Optimization Hint Type. |
| 33 | +enum 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 | + |
| 44 | +static inline StringRef MCLOHDirectiveName() { |
| 45 | + return StringRef(".loh"); |
| 46 | +} |
| 47 | + |
| 48 | +static inline bool isValidMCLOHType(MCLOHType Kind) { |
| 49 | + return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; |
| 50 | +} |
| 51 | + |
| 52 | +static 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 | +} |
| 65 | + |
| 66 | +static inline StringRef MCLOHIdToName(MCLOHType Kind) { |
| 67 | +#define MCLOHCaseIdToName(Name) case MCLOH_ ## Name: return StringRef(#Name); |
| 68 | + switch (Kind) { |
| 69 | + MCLOHCaseIdToName(AdrpAdrp); |
| 70 | + MCLOHCaseIdToName(AdrpLdr); |
| 71 | + MCLOHCaseIdToName(AdrpAddLdr); |
| 72 | + MCLOHCaseIdToName(AdrpLdrGotLdr); |
| 73 | + MCLOHCaseIdToName(AdrpAddStr); |
| 74 | + MCLOHCaseIdToName(AdrpLdrGotStr); |
| 75 | + MCLOHCaseIdToName(AdrpAdd); |
| 76 | + MCLOHCaseIdToName(AdrpLdrGot); |
| 77 | + } |
| 78 | + return StringRef(); |
| 79 | +} |
| 80 | + |
| 81 | +static inline int MCLOHIdToNbArgs(MCLOHType Kind) { |
| 82 | + switch (Kind) { |
| 83 | + // LOH with two arguments |
| 84 | + case MCLOH_AdrpAdrp: |
| 85 | + case MCLOH_AdrpLdr: |
| 86 | + case MCLOH_AdrpAdd: |
| 87 | + case MCLOH_AdrpLdrGot: |
| 88 | + return 2; |
| 89 | + // LOH with three arguments |
| 90 | + case MCLOH_AdrpAddLdr: |
| 91 | + case MCLOH_AdrpLdrGotLdr: |
| 92 | + case MCLOH_AdrpAddStr: |
| 93 | + case MCLOH_AdrpLdrGotStr: |
| 94 | + return 3; |
| 95 | + } |
| 96 | + return -1; |
| 97 | +} |
| 98 | + |
| 99 | +/// Store Linker Optimization Hint information (LOH). |
| 100 | +template<typename T> |
| 101 | +class LOHDirective { |
| 102 | +private: |
| 103 | + MCLOHType Kind; |
| 104 | + |
| 105 | + /// Arguments of this directive. Order matters. |
| 106 | + SmallVector<T *, 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 | + /// This function is currently specialized for T = MCSymbol. |
| 112 | + void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, |
| 113 | + const MCAsmLayout &Layout) const { } |
| 114 | + |
| 115 | +public: |
| 116 | + typedef SmallVectorImpl<T *> LOHArgs; |
| 117 | + |
| 118 | + LOHDirective(MCLOHType Kind, const LOHArgs &Args) |
| 119 | + : Kind(Kind), Args(Args.begin(), Args.end()) {}; |
| 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 | + raw_ostream &OutStream = ObjWriter.getStream(); |
| 129 | + Emit_impl(OutStream, ObjWriter, Layout); |
| 130 | + } |
| 131 | + |
| 132 | + /// Get the size in bytes of this directive if emitted in @p ObjWriter with |
| 133 | + /// the given @p Layout. |
| 134 | + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, |
| 135 | + const MCAsmLayout &Layout) const { |
| 136 | + std::string Buffer; |
| 137 | + raw_string_ostream OutStream(Buffer); |
| 138 | + Emit_impl(OutStream, ObjWriter, Layout); |
| 139 | + return OutStream.tell(); |
| 140 | + } |
| 141 | +}; |
| 142 | + |
| 143 | +template<typename T> |
| 144 | +class LOHContainer { |
| 145 | +public: |
| 146 | + typedef SmallVectorImpl<LOHDirective<T> > LOHDirectives; |
| 147 | + |
| 148 | +private: |
| 149 | + /// Keep track of the emit size of all the LOHs. |
| 150 | + mutable uint64_t EmitSize; |
| 151 | + |
| 152 | + /// Keep track of all LOH directives. |
| 153 | + SmallVector<LOHDirective<T>, 32> Directives; |
| 154 | + |
| 155 | + /// Accessor to the directives. |
| 156 | + LOHDirectives &getDirectives() { return Directives; } |
| 157 | + |
| 158 | +public: |
| 159 | + LOHContainer() : EmitSize(0) {}; |
| 160 | + |
| 161 | + /// Const accessor to the directives. |
| 162 | + const LOHDirectives &getDirectives() const { |
| 163 | + return const_cast<LOHContainer *>(this)->getDirectives(); |
| 164 | + } |
| 165 | + |
| 166 | + /// Add the directive of the given kind @p Kind with the given arguments |
| 167 | + /// @p Args to the container. |
| 168 | + void addDirective(MCLOHType Kind, |
| 169 | + const typename LOHDirective<T>::LOHArgs &Args) { |
| 170 | + assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); |
| 171 | + getDirectives().push_back(LOHDirective<T>(Kind, Args)); |
| 172 | + } |
| 173 | + |
| 174 | + /// Get the size of the directives if emitted. |
| 175 | + uint64_t getEmitSize(const MachObjectWriter &ObjWriter, |
| 176 | + const MCAsmLayout &Layout) const { |
| 177 | + if (!EmitSize) { |
| 178 | + for (typename LOHDirectives::const_iterator It = getDirectives().begin(), |
| 179 | + EndIt = getDirectives().end(); It != EndIt; ++It) |
| 180 | + EmitSize += It->getEmitSize(ObjWriter, Layout); |
| 181 | + } |
| 182 | + return EmitSize; |
| 183 | + } |
| 184 | + |
| 185 | + /// Emit all Linker Optimization Hint in one big table. |
| 186 | + /// Each line of the table is emitted by LOHDirective::Emit. |
| 187 | + void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { |
| 188 | + for (typename LOHDirectives::const_iterator It = getDirectives().begin(), |
| 189 | + EndIt = getDirectives().end(); It != EndIt; ++It) |
| 190 | + It->Emit(ObjWriter, Layout); |
| 191 | + } |
| 192 | + |
| 193 | + void reset() { |
| 194 | + getDirectives().clear(); |
| 195 | + EmitSize = 0; |
| 196 | + } |
| 197 | +}; |
| 198 | + |
| 199 | +// Add types for specialized template using MCSymbol. |
| 200 | +typedef LOHDirective<MCSymbol> MCLOHDirective; |
| 201 | +typedef LOHDirective<MCSymbol>::LOHArgs MCLOHArgs; |
| 202 | + |
| 203 | +typedef LOHContainer<MCLOHDirective>::LOHDirectives MCLOHDirectives; |
| 204 | + |
| 205 | +typedef LOHContainer<MCSymbol> MCLOHContainer; |
| 206 | + |
| 207 | +// Declare the specialization for MCSymbol. |
| 208 | +template<> |
| 209 | +void MCLOHDirective::Emit_impl(raw_ostream &OutStream, |
| 210 | + const MachObjectWriter &ObjWriter, |
| 211 | + const MCAsmLayout &Layout) const; |
| 212 | +} // end namespace llvm |
| 213 | + |
| 214 | +#endif |
0 commit comments