Home | History | Annotate | Download | only in MC
      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 
     27 namespace llvm {
     28 
     29 class MachObjectWriter;
     30 class MCAsmLayout;
     31 class MCSymbol;
     32 
     33 /// Linker Optimization Hint Type.
     34 enum 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 
     45 static inline StringRef MCLOHDirectiveName() {
     46   return StringRef(".loh");
     47 }
     48 
     49 static inline bool isValidMCLOHType(unsigned Kind) {
     50   return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot;
     51 }
     52 
     53 static 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 
     67 static 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 
     82 static 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).
    101 class 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 
    113 public:
    114   typedef SmallVectorImpl<MCSymbol *> LOHArgs;
    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 
    135 class 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 
    142 public:
    143   typedef SmallVectorImpl<MCLOHDirective> LOHDirectives;
    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.
    182 typedef MCLOHDirective::LOHArgs MCLOHArgs;
    183 typedef MCLOHContainer::LOHDirectives MCLOHDirectives;
    184 
    185 } // end namespace llvm
    186 
    187 #endif // LLVM_MC_MCLINKEROPTIMIZATIONHINT_H
    188