Index: Relocation.txt =================================================================== --- Relocation.txt +++ Relocation.txt @@ -0,0 +1,102 @@ +Mips Relocation Principles + +In LLVM, there are several elements of the llvm::ISD::NodeType enum that deal +with adresses and/or relocations. These are defined in +include/llvm/Target/TargetSelectionDAG.td, namely: + GlobalAddress, GlobalTLSAddress, JumpTable, ConstantPool, ExternalSymbol, + BlockAddress +The Mips backend uses several principles to handle these. + +1. Code for lowering addresses references to machine dependent code is +factored into common code for generating different address forms and is +called by the relocation specific lowering function, using templated +functions. For example: + + SDValue MipsTargetLowering:: // lib/Target/Mips/MipsISelLowering.cpp + lowerJumpTable(SDValue Op, SelectionDAG &DAG) const + +calls + + template // lib/Target/Mips/MipsISelLowering.h + SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, + SelectionDAG &DAG, bool IsN32OrN64) const + +which calls the overloaded function: + + // lib/Target/Mips/MipsISelLowering.h + SDValue getTargetNode(JumpTableSDNode *N, EVT Ty, SelectionDAG &DAG, + unsigned Flag) const; + +2. Instruction selection is deferred by using +MipsISD::{Highest, Higher, Hi, Lo}. For example, in getAddrLocal, the +pseudo-code generated is: + + (add (load (wrapper $gp, %got(sym)), %lo(sym)) + +where "%lo" represents an instance of an SDNode with opcode "MipsISD::Lo", +"wrapper" indicates one with opcode "MipsISD::Wrapper", and "%got" the global +table pointer "getGlobalReg(...)". The "add" is "ISD::ADD", not a target +dependent one. + +3. Table-gen "multiclass" is used to define patterns varying over load, add, +zero, and type: + + // lib/Target/Mips/MipsInstrInfo.td + multiclass MipsHiLoRelocs { + def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; + ... + def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; + ... + def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), + (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; + ... + } + defm : MipsHiLoRelocs; + + // lib/Target/Mips/Mips64InstrInfo.td + defm : MipsHiLoRelocs, SYM_32; + +Here the instantiation of MipsHiLoRelocs in MipsInstrInfo.td is used by +Mips32. The instantiation in Mips64InstrInfo.td is used by Mips64 in ILP32 +mode, as guarded by the predicate "SYM_32". A similar "multiclass" for Mips64 +in LP64 mode is also defined: + + // lib/Target/Mips/Mips64InstrInfo.td + multiclass MipsHighestHigherHiLoRelocs { + ... + def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)), + (Lui tglobaladdr:$in)>; + ... + def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)), + (Daddiu ZERO_64, tglobaladdr:$in)>; + ... + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + ... + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + ... + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + } + +although it is only instantiated once: + + // lib/Target/Mips/Mips64InstrInfo.td + defm : MipsHighestHigherHiLoRelocs, SYM_64; + +4. Instruction encoding is separated from types. For example: + + // lib/Target/Mips/MipsInstrInfo.td + let AdditionalPredicates = [NotInMicroMips] in { + ... + def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, + LW_FM<0x23>; + } + + // lib/Target/Mips/Mips64InstrInfo.td + def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>; + +defines two names "LW" and "LW64" with two different types, but with the +same encoding—"LW_RM<0x23>".