Home | History | Annotate | Download | only in CodeGen
      1 //===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines the MachineRelocation class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CODEGEN_MACHINERELOCATION_H
     15 #define LLVM_CODEGEN_MACHINERELOCATION_H
     16 
     17 #include "llvm/Support/DataTypes.h"
     18 #include <cassert>
     19 
     20 namespace llvm {
     21 class GlobalValue;
     22 class MachineBasicBlock;
     23 
     24 /// MachineRelocation - This represents a target-specific relocation value,
     25 /// produced by the code emitter.  This relocation is resolved after the has
     26 /// been emitted, either to an object file or to memory, when the target of the
     27 /// relocation can be resolved.
     28 ///
     29 /// A relocation is made up of the following logical portions:
     30 ///   1. An offset in the machine code buffer, the location to modify.
     31 ///   2. A target specific relocation type (a number from 0 to 63).
     32 ///   3. A symbol being referenced, either as a GlobalValue* or as a string.
     33 ///   4. An optional constant value to be added to the reference.
     34 ///   5. A bit, CanRewrite, which indicates to the JIT that a function stub is
     35 ///      not needed for the relocation.
     36 ///   6. An index into the GOT, if the target uses a GOT
     37 ///
     38 class MachineRelocation {
     39   enum AddressType {
     40     isResult,         // Relocation has be transformed into its result pointer.
     41     isGV,             // The Target.GV field is valid.
     42     isIndirectSym,    // Relocation of an indirect symbol.
     43     isBB,             // Relocation of BB address.
     44     isExtSym,         // The Target.ExtSym field is valid.
     45     isConstPool,      // Relocation of constant pool address.
     46     isJumpTable,      // Relocation of jump table address.
     47     isGOTIndex        // The Target.GOTIndex field is valid.
     48   };
     49 
     50   /// Offset - This is the offset from the start of the code buffer of the
     51   /// relocation to perform.
     52   uintptr_t Offset;
     53 
     54   /// ConstantVal - A field that may be used by the target relocation type.
     55   intptr_t ConstantVal;
     56 
     57   union {
     58     void *Result;           // If this has been resolved to a resolved pointer
     59     GlobalValue *GV;        // If this is a pointer to a GV or an indirect ref.
     60     MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB
     61     const char *ExtSym;     // If this is a pointer to a named symbol
     62     unsigned Index;         // Constant pool / jump table index
     63     unsigned GOTIndex;      // Index in the GOT of this symbol/global
     64   } Target;
     65 
     66   unsigned TargetReloType : 6; // The target relocation ID
     67   AddressType AddrType    : 4; // The field of Target to use
     68   bool MayNeedFarStub     : 1; // True if this relocation may require a far-stub
     69   bool GOTRelative        : 1; // Should this relocation be relative to the GOT?
     70   bool TargetResolve      : 1; // True if target should resolve the address
     71 
     72 public:
     73  // Relocation types used in a generic implementation.  Currently, relocation
     74  // entries for all things use the generic VANILLA type until they are refined
     75  // into target relocation types.
     76   enum RelocationType {
     77     VANILLA
     78   };
     79 
     80   /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue.
     81   ///
     82   static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType,
     83                                  GlobalValue *GV, intptr_t cst = 0,
     84                                  bool MayNeedFarStub = 0,
     85                                  bool GOTrelative = 0) {
     86     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
     87     MachineRelocation Result;
     88     Result.Offset = offset;
     89     Result.ConstantVal = cst;
     90     Result.TargetReloType = RelocationType;
     91     Result.AddrType = isGV;
     92     Result.MayNeedFarStub = MayNeedFarStub;
     93     Result.GOTRelative = GOTrelative;
     94     Result.TargetResolve = false;
     95     Result.Target.GV = GV;
     96     return Result;
     97   }
     98 
     99   /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an
    100   /// indirect symbol.
    101   static MachineRelocation getIndirectSymbol(uintptr_t offset,
    102                                              unsigned RelocationType,
    103                                              GlobalValue *GV, intptr_t cst = 0,
    104                                              bool MayNeedFarStub = 0,
    105                                              bool GOTrelative = 0) {
    106     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
    107     MachineRelocation Result;
    108     Result.Offset = offset;
    109     Result.ConstantVal = cst;
    110     Result.TargetReloType = RelocationType;
    111     Result.AddrType = isIndirectSym;
    112     Result.MayNeedFarStub = MayNeedFarStub;
    113     Result.GOTRelative = GOTrelative;
    114     Result.TargetResolve = false;
    115     Result.Target.GV = GV;
    116     return Result;
    117   }
    118 
    119   /// MachineRelocation::getBB - Return a relocation entry for a BB.
    120   ///
    121   static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType,
    122                                  MachineBasicBlock *MBB, intptr_t cst = 0) {
    123     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
    124     MachineRelocation Result;
    125     Result.Offset = offset;
    126     Result.ConstantVal = cst;
    127     Result.TargetReloType = RelocationType;
    128     Result.AddrType = isBB;
    129     Result.MayNeedFarStub = false;
    130     Result.GOTRelative = false;
    131     Result.TargetResolve = false;
    132     Result.Target.MBB = MBB;
    133     return Result;
    134   }
    135 
    136   /// MachineRelocation::getExtSym - Return a relocation entry for an external
    137   /// symbol, like "free".
    138   ///
    139   static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType,
    140                                      const char *ES, intptr_t cst = 0,
    141                                      bool GOTrelative = 0,
    142                                      bool NeedStub = true) {
    143     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
    144     MachineRelocation Result;
    145     Result.Offset = offset;
    146     Result.ConstantVal = cst;
    147     Result.TargetReloType = RelocationType;
    148     Result.AddrType = isExtSym;
    149     Result.MayNeedFarStub = NeedStub;
    150     Result.GOTRelative = GOTrelative;
    151     Result.TargetResolve = false;
    152     Result.Target.ExtSym = ES;
    153     return Result;
    154   }
    155 
    156   /// MachineRelocation::getConstPool - Return a relocation entry for a constant
    157   /// pool entry.
    158   ///
    159   static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType,
    160                                         unsigned CPI, intptr_t cst = 0,
    161                                         bool letTargetResolve = false) {
    162     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
    163     MachineRelocation Result;
    164     Result.Offset = offset;
    165     Result.ConstantVal = cst;
    166     Result.TargetReloType = RelocationType;
    167     Result.AddrType = isConstPool;
    168     Result.MayNeedFarStub = false;
    169     Result.GOTRelative = false;
    170     Result.TargetResolve = letTargetResolve;
    171     Result.Target.Index = CPI;
    172     return Result;
    173   }
    174 
    175   /// MachineRelocation::getJumpTable - Return a relocation entry for a jump
    176   /// table entry.
    177   ///
    178   static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType,
    179                                         unsigned JTI, intptr_t cst = 0,
    180                                         bool letTargetResolve = false) {
    181     assert((RelocationType & ~63) == 0 && "Relocation type too large!");
    182     MachineRelocation Result;
    183     Result.Offset = offset;
    184     Result.ConstantVal = cst;
    185     Result.TargetReloType = RelocationType;
    186     Result.AddrType = isJumpTable;
    187     Result.MayNeedFarStub = false;
    188     Result.GOTRelative = false;
    189     Result.TargetResolve = letTargetResolve;
    190     Result.Target.Index = JTI;
    191     return Result;
    192   }
    193 
    194   /// getMachineCodeOffset - Return the offset into the code buffer that the
    195   /// relocation should be performed.
    196   intptr_t getMachineCodeOffset() const {
    197     return Offset;
    198   }
    199 
    200   /// getRelocationType - Return the target-specific relocation ID for this
    201   /// relocation.
    202   unsigned getRelocationType() const {
    203     return TargetReloType;
    204   }
    205 
    206   /// getConstantVal - Get the constant value associated with this relocation.
    207   /// This is often an offset from the symbol.
    208   ///
    209   intptr_t getConstantVal() const {
    210     return ConstantVal;
    211   }
    212 
    213   /// setConstantVal - Set the constant value associated with this relocation.
    214   /// This is often an offset from the symbol.
    215   ///
    216   void setConstantVal(intptr_t val) {
    217     ConstantVal = val;
    218   }
    219 
    220   /// isGlobalValue - Return true if this relocation is a GlobalValue, as
    221   /// opposed to a constant string.
    222   bool isGlobalValue() const {
    223     return AddrType == isGV;
    224   }
    225 
    226   /// isIndirectSymbol - Return true if this relocation is the address an
    227   /// indirect symbol
    228   bool isIndirectSymbol() const {
    229     return AddrType == isIndirectSym;
    230   }
    231 
    232   /// isBasicBlock - Return true if this relocation is a basic block reference.
    233   ///
    234   bool isBasicBlock() const {
    235     return AddrType == isBB;
    236   }
    237 
    238   /// isExternalSymbol - Return true if this is a constant string.
    239   ///
    240   bool isExternalSymbol() const {
    241     return AddrType == isExtSym;
    242   }
    243 
    244   /// isConstantPoolIndex - Return true if this is a constant pool reference.
    245   ///
    246   bool isConstantPoolIndex() const {
    247     return AddrType == isConstPool;
    248   }
    249 
    250   /// isJumpTableIndex - Return true if this is a jump table reference.
    251   ///
    252   bool isJumpTableIndex() const {
    253     return AddrType == isJumpTable;
    254   }
    255 
    256   /// isGOTRelative - Return true the target wants the index into the GOT of
    257   /// the symbol rather than the address of the symbol.
    258   bool isGOTRelative() const {
    259     return GOTRelative;
    260   }
    261 
    262   /// mayNeedFarStub - This function returns true if the JIT for this target may
    263   /// need either a stub function or an indirect global-variable load to handle
    264   /// the relocated GlobalValue reference.  For example, the x86-64 call
    265   /// instruction can only call functions within +/-2GB of the call site.
    266   /// Anything farther away needs a longer mov+call sequence, which can't just
    267   /// be written on top of the existing call.
    268   bool mayNeedFarStub() const {
    269     return MayNeedFarStub;
    270   }
    271 
    272   /// letTargetResolve - Return true if the target JITInfo is usually
    273   /// responsible for resolving the address of this relocation.
    274   bool letTargetResolve() const {
    275     return TargetResolve;
    276   }
    277 
    278   /// getGlobalValue - If this is a global value reference, return the
    279   /// referenced global.
    280   GlobalValue *getGlobalValue() const {
    281     assert((isGlobalValue() || isIndirectSymbol()) &&
    282            "This is not a global value reference!");
    283     return Target.GV;
    284   }
    285 
    286   MachineBasicBlock *getBasicBlock() const {
    287     assert(isBasicBlock() && "This is not a basic block reference!");
    288     return Target.MBB;
    289   }
    290 
    291   /// getString - If this is a string value, return the string reference.
    292   ///
    293   const char *getExternalSymbol() const {
    294     assert(isExternalSymbol() && "This is not an external symbol reference!");
    295     return Target.ExtSym;
    296   }
    297 
    298   /// getConstantPoolIndex - If this is a const pool reference, return
    299   /// the index into the constant pool.
    300   unsigned getConstantPoolIndex() const {
    301     assert(isConstantPoolIndex() && "This is not a constant pool reference!");
    302     return Target.Index;
    303   }
    304 
    305   /// getJumpTableIndex - If this is a jump table reference, return
    306   /// the index into the jump table.
    307   unsigned getJumpTableIndex() const {
    308     assert(isJumpTableIndex() && "This is not a jump table reference!");
    309     return Target.Index;
    310   }
    311 
    312   /// getResultPointer - Once this has been resolved to point to an actual
    313   /// address, this returns the pointer.
    314   void *getResultPointer() const {
    315     assert(AddrType == isResult && "Result pointer isn't set yet!");
    316     return Target.Result;
    317   }
    318 
    319   /// setResultPointer - Set the result to the specified pointer value.
    320   ///
    321   void setResultPointer(void *Ptr) {
    322     Target.Result = Ptr;
    323     AddrType = isResult;
    324   }
    325 
    326   /// setGOTIndex - Set the GOT index to a specific value.
    327   void setGOTIndex(unsigned idx) {
    328     AddrType = isGOTIndex;
    329     Target.GOTIndex = idx;
    330   }
    331 
    332   /// getGOTIndex - Once this has been resolved to an entry in the GOT,
    333   /// this returns that index.  The index is from the lowest address entry
    334   /// in the GOT.
    335   unsigned getGOTIndex() const {
    336     assert(AddrType == isGOTIndex);
    337     return Target.GOTIndex;
    338   }
    339 };
    340 }
    341 
    342 #endif
    343