Joel Jones | bd2e6e0 | 2017-04-21 14:49:27 +0000 | [diff] [blame] | 1 | MIPS Relocation Principles |
| 2 | |
| 3 | In LLVM, there are several elements of the llvm::ISD::NodeType enum |
| 4 | that deal with addresses and/or relocations. These are defined in |
| 5 | include/llvm/Target/TargetSelectionDAG.td, namely: |
| 6 | GlobalAddress, GlobalTLSAddress, JumpTable, ConstantPool, |
| 7 | ExternalSymbol, BlockAddress |
| 8 | The MIPS backend uses several principles to handle these. |
| 9 | |
| 10 | 1. Code for lowering addresses references to machine dependent code is |
| 11 | factored into common code for generating different address forms and |
| 12 | is called by the relocation model specific lowering function, using |
| 13 | templated functions. For example: |
| 14 | |
| 15 | // lib/Target/Mips/MipsISelLowering.cpp |
| 16 | SDValue MipsTargetLowering:: |
| 17 | lowerJumpTable(SDValue Op, SelectionDAG &DAG) const |
| 18 | |
| 19 | calls |
| 20 | |
| 21 | template <class NodeTy> // lib/Target/Mips/MipsISelLowering.h |
| 22 | SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, |
| 23 | SelectionDAG &DAG, bool IsN32OrN64) const |
| 24 | |
| 25 | which calls the overloaded function: |
| 26 | |
| 27 | // lib/Target/Mips/MipsISelLowering.h |
| 28 | SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, |
| 29 | unsigned Flag) const; |
| 30 | |
| 31 | 2. Generic address nodes are lowered to some combination of target |
| 32 | independent and machine specific SDNodes (for example: |
| 33 | MipsISD::{Highest, Higher, Hi, Lo}) depending upon relocation model, |
| 34 | ABI, and compilation options. |
| 35 | |
| 36 | The choice of specific instructions that are to be used is delegated |
| 37 | to ISel which in turn relies on TableGen patterns to choose subtarget |
| 38 | specific instructions. For example, in getAddrLocal, the pseudo-code |
| 39 | generated is: |
| 40 | |
| 41 | (add (load (wrapper $gp, %got(sym)), %lo(sym)) |
| 42 | |
| 43 | where "%lo" represents an instance of an SDNode with opcode |
| 44 | "MipsISD::Lo", "wrapper" indicates one with opcode "MipsISD::Wrapper", |
| 45 | and "%got" the global table pointer "getGlobalReg(...)". The "add" is |
| 46 | "ISD::ADD", not a target dependent one. |
| 47 | |
| 48 | 3. A TableGen multiclass pattern "MipsHiLoRelocs" is used to define a |
| 49 | template pattern parameterized over the load upper immediate |
| 50 | instruction, add operation, the zero register, and register class. |
| 51 | Here the instantiation of MipsHiLoRelocs in MipsInstrInfo.td is used |
| 52 | to MIPS32 to compute addresses for the static relocation model. |
| 53 | |
| 54 | // lib/Target/Mips/MipsInstrInfo.td |
| 55 | multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, |
| 56 | Register ZeroReg, RegisterOperand GPROpnd> { |
| 57 | def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; |
| 58 | ... |
| 59 | def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; |
| 60 | ... |
| 61 | def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), |
| 62 | (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; |
| 63 | ... |
| 64 | } |
| 65 | defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>; |
| 66 | |
| 67 | // lib/Target/Mips/Mips64InstrInfo.td |
| 68 | defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32; |
| 69 | |
| 70 | The instantiation in Mips64InstrInfo.td is used for MIPS64 in ILP32 |
| 71 | mode, as guarded by the predicate "SYM_32" and also for a submode of |
Aleksandar Beserminji | 9d32402 | 2017-12-11 11:21:40 +0000 | [diff] [blame] | 72 | LP64 where symbols are assumed to be 32 bits wide. |
Joel Jones | bd2e6e0 | 2017-04-21 14:49:27 +0000 | [diff] [blame] | 73 | |
| 74 | More details on how multiclasses in TableGen work can be found in the |
| 75 | section "Multiclass definitions and instances" in the document |
| 76 | "TableGen Language Introduction" |
| 77 | |
| 78 | 4. Instruction definitions are multiply defined to cover the different |
| 79 | register classes. In some cases, such as LW/LW64, this also accounts |
| 80 | for the difference in the results of instruction execution. On MIPS32, |
| 81 | "lw" loads a 32 bit value from memory. On MIPS64, "lw" loads a 32 bit |
| 82 | value from memory and sign extends the value to 64 bits. |
| 83 | |
| 84 | // lib/Target/Mips/MipsInstrInfo.td |
| 85 | def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM; |
| 86 | // lib/Target/Mips/Mips64InstrInfo.td |
| 87 | def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM; |
| 88 | |
| 89 | defines two names "LUi" and "LUi64" with two different register |
| 90 | classes, but with the same encoding---"LUI_FM". These instructions load a |
| 91 | 16-bit immediate into bits 31-16 and clear the lower 15 bits. On MIPS64, |
| 92 | the result is sign-extended to 64 bits. |