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 
     25 namespace llvm {
     26 
     27 // Forward declarations.
     28 class MCAsmLayout;
     29 class MCSymbol;
     30 class MachObjectWriter;
     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(unsigned 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 class MCLOHDirective {
    101   MCLOHType Kind;
    102 
    103   /// Arguments of this directive. Order matters.
    104   SmallVector<MCSymbol *, 3> Args;
    105 
    106   /// Emit this directive in \p OutStream using the information available
    107   /// in the given \p ObjWriter and \p Layout to get the address of the
    108   /// arguments within the object file.
    109   void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter,
    110                  const MCAsmLayout &Layout) const;
    111 
    112 public:
    113   typedef SmallVectorImpl<MCSymbol *> LOHArgs;
    114 
    115   MCLOHDirective(MCLOHType Kind, const LOHArgs &Args)
    116       : Kind(Kind), Args(Args.begin(), Args.end()) {
    117     assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
    118   }
    119 
    120   MCLOHType getKind() const { return Kind; }
    121 
    122   const LOHArgs &getArgs() const { return Args; }
    123 
    124   /// Emit this directive as:
    125   /// <kind, numArgs, addr1, ..., addrN>
    126   void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const;
    127 
    128   /// Get the size in bytes of this directive if emitted in \p ObjWriter with
    129   /// the given \p Layout.
    130   uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
    131                        const MCAsmLayout &Layout) const;
    132 };
    133 
    134 class MCLOHContainer {
    135   /// Keep track of the emit size of all the LOHs.
    136   mutable uint64_t EmitSize;
    137 
    138   /// Keep track of all LOH directives.
    139   SmallVector<MCLOHDirective, 32> Directives;
    140 
    141 public:
    142   typedef SmallVectorImpl<MCLOHDirective> LOHDirectives;
    143 
    144   MCLOHContainer() : EmitSize(0) {}
    145 
    146   /// Const accessor to the directives.
    147   const LOHDirectives &getDirectives() const {
    148     return Directives;
    149   }
    150 
    151   /// Add the directive of the given kind \p Kind with the given arguments
    152   /// \p Args to the container.
    153   void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) {
    154     Directives.push_back(MCLOHDirective(Kind, Args));
    155   }
    156 
    157   /// Get the size of the directives if emitted.
    158   uint64_t getEmitSize(const MachObjectWriter &ObjWriter,
    159                        const MCAsmLayout &Layout) const {
    160     if (!EmitSize) {
    161       for (const MCLOHDirective &D : Directives)
    162         EmitSize += D.getEmitSize(ObjWriter, Layout);
    163     }
    164     return EmitSize;
    165   }
    166 
    167   /// Emit all Linker Optimization Hint in one big table.
    168   /// Each line of the table is emitted by LOHDirective::emit.
    169   void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const {
    170     for (const MCLOHDirective &D : Directives)
    171       D.emit(ObjWriter, Layout);
    172   }
    173 
    174   void reset() {
    175     Directives.clear();
    176     EmitSize = 0;
    177   }
    178 };
    179 
    180 // Add types for specialized template using MCSymbol.
    181 typedef MCLOHDirective::LOHArgs MCLOHArgs;
    182 typedef MCLOHContainer::LOHDirectives MCLOHDirectives;
    183 
    184 } // end namespace llvm
    185 
    186 #endif
    187