1263320SdimPull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju): 2263320Sdim 3263320Sdim [Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code. 4263320Sdim Fixes PR#18521 5263320Sdim 6269012SemasteIntroduced here: http://svnweb.freebsd.org/changeset/base/262261 7263320Sdim 8263320SdimIndex: lib/Target/Sparc/SparcAsmPrinter.cpp 9263320Sdim=================================================================== 10263320Sdim--- lib/Target/Sparc/SparcAsmPrinter.cpp 11263320Sdim+++ lib/Target/Sparc/SparcAsmPrinter.cpp 12263320Sdim@@ -65,18 +65,24 @@ namespace { 13263320Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 14263320Sdim unsigned AsmVariant, const char *ExtraCode, 15263320Sdim raw_ostream &O); 16263320Sdim+ 17263320Sdim+ void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI); 18263320Sdim+ 19263320Sdim }; 20263320Sdim } // end of anonymous namespace 21263320Sdim 22263320Sdim-static MCOperand createPCXCallOP(MCSymbol *Label, 23263320Sdim- MCContext &OutContext) 24263320Sdim-{ 25263320Sdim- const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label, 26263320Sdim+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, 27263320Sdim+ MCSymbol *Sym, MCContext &OutContext) { 28263320Sdim+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym, 29263320Sdim OutContext); 30263320Sdim- const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None, 31263320Sdim- MCSym, OutContext); 32263320Sdim+ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext); 33263320Sdim return MCOperand::CreateExpr(expr); 34263320Sdim+ 35263320Sdim } 36263320Sdim+static MCOperand createPCXCallOP(MCSymbol *Label, 37263320Sdim+ MCContext &OutContext) { 38263320Sdim+ return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext); 39263320Sdim+} 40263320Sdim 41263320Sdim static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, 42263320Sdim MCSymbol *GOTLabel, MCSymbol *StartLabel, 43263320Sdim@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer, 44263320Sdim OutStreamer.EmitInstruction(SETHIInst); 45263320Sdim } 46263320Sdim 47263320Sdim-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, 48263320Sdim- MCOperand &Imm, MCOperand &RD) 49263320Sdim+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, 50263320Sdim+ MCOperand &RS1, MCOperand &Src2, MCOperand &RD) 51263320Sdim { 52263320Sdim- MCInst ORInst; 53263320Sdim- ORInst.setOpcode(SP::ORri); 54263320Sdim- ORInst.addOperand(RD); 55263320Sdim- ORInst.addOperand(RS1); 56263320Sdim- ORInst.addOperand(Imm); 57263320Sdim- OutStreamer.EmitInstruction(ORInst); 58263320Sdim+ MCInst Inst; 59263320Sdim+ Inst.setOpcode(Opcode); 60263320Sdim+ Inst.addOperand(RD); 61263320Sdim+ Inst.addOperand(RS1); 62263320Sdim+ Inst.addOperand(Src2); 63263320Sdim+ OutStreamer.EmitInstruction(Inst); 64263320Sdim } 65263320Sdim 66263320Sdim+static void EmitOR(MCStreamer &OutStreamer, 67263320Sdim+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { 68263320Sdim+ EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD); 69263320Sdim+} 70263320Sdim+ 71263320Sdim static void EmitADD(MCStreamer &OutStreamer, 72263320Sdim- MCOperand &RS1, MCOperand &RS2, MCOperand &RD) 73263320Sdim-{ 74263320Sdim- MCInst ADDInst; 75263320Sdim- ADDInst.setOpcode(SP::ADDrr); 76263320Sdim- ADDInst.addOperand(RD); 77263320Sdim- ADDInst.addOperand(RS1); 78263320Sdim- ADDInst.addOperand(RS2); 79263320Sdim- OutStreamer.EmitInstruction(ADDInst); 80263320Sdim+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) { 81263320Sdim+ EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD); 82263320Sdim } 83263320Sdim 84263320Sdim-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI, 85263320Sdim- MCStreamer &OutStreamer, 86263320Sdim- MCContext &OutContext) 87263320Sdim+static void EmitSHL(MCStreamer &OutStreamer, 88263320Sdim+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) { 89263320Sdim+ EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD); 90263320Sdim+} 91263320Sdim+ 92263320Sdim+ 93263320Sdim+static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, 94263320Sdim+ SparcMCExpr::VariantKind HiKind, 95263320Sdim+ SparcMCExpr::VariantKind LoKind, 96263320Sdim+ MCOperand &RD, 97263320Sdim+ MCContext &OutContext) { 98263320Sdim+ 99263320Sdim+ MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext); 100263320Sdim+ MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext); 101263320Sdim+ EmitSETHI(OutStreamer, hi, RD); 102263320Sdim+ EmitOR(OutStreamer, RD, lo, RD); 103263320Sdim+} 104263320Sdim+ 105263320Sdim+void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI) 106263320Sdim { 107263320Sdim- const MachineOperand &MO = MI->getOperand(0); 108263320Sdim- MCSymbol *StartLabel = OutContext.CreateTempSymbol(); 109263320Sdim- MCSymbol *EndLabel = OutContext.CreateTempSymbol(); 110263320Sdim- MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); 111263320Sdim MCSymbol *GOTLabel = 112263320Sdim OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_")); 113263320Sdim 114263320Sdim+ const MachineOperand &MO = MI->getOperand(0); 115263320Sdim assert(MO.getReg() != SP::O7 && 116263320Sdim "%o7 is assigned as destination for getpcx!"); 117263320Sdim 118263320Sdim MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg()); 119263320Sdim+ 120263320Sdim+ 121263320Sdim+ if (TM.getRelocationModel() != Reloc::PIC_) { 122263320Sdim+ // Just load the address of GOT to MCRegOP. 123263320Sdim+ switch(TM.getCodeModel()) { 124263320Sdim+ default: 125263320Sdim+ llvm_unreachable("Unsupported absolute code model"); 126263320Sdim+ case CodeModel::Small: 127263320Sdim+ EmitHiLo(OutStreamer, GOTLabel, 128263320Sdim+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, 129263320Sdim+ MCRegOP, OutContext); 130263320Sdim+ break; 131263320Sdim+ case CodeModel::Medium: { 132263320Sdim+ EmitHiLo(OutStreamer, GOTLabel, 133263320Sdim+ SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44, 134263320Sdim+ MCRegOP, OutContext); 135263320Sdim+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12, 136263320Sdim+ OutContext)); 137263320Sdim+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); 138263320Sdim+ MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44, 139263320Sdim+ GOTLabel, OutContext); 140263320Sdim+ EmitOR(OutStreamer, MCRegOP, lo, MCRegOP); 141263320Sdim+ break; 142263320Sdim+ } 143263320Sdim+ case CodeModel::Large: { 144263320Sdim+ EmitHiLo(OutStreamer, GOTLabel, 145263320Sdim+ SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM, 146263320Sdim+ MCRegOP, OutContext); 147263320Sdim+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32, 148263320Sdim+ OutContext)); 149263320Sdim+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP); 150263320Sdim+ // Use register %o7 to load the lower 32 bits. 151263320Sdim+ MCOperand RegO7 = MCOperand::CreateReg(SP::O7); 152263320Sdim+ EmitHiLo(OutStreamer, GOTLabel, 153263320Sdim+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO, 154263320Sdim+ RegO7, OutContext); 155263320Sdim+ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP); 156263320Sdim+ } 157263320Sdim+ } 158263320Sdim+ return; 159263320Sdim+ } 160263320Sdim+ 161263320Sdim+ MCSymbol *StartLabel = OutContext.CreateTempSymbol(); 162263320Sdim+ MCSymbol *EndLabel = OutContext.CreateTempSymbol(); 163263320Sdim+ MCSymbol *SethiLabel = OutContext.CreateTempSymbol(); 164263320Sdim+ 165263320Sdim MCOperand RegO7 = MCOperand::CreateReg(SP::O7); 166263320Sdim 167263320Sdim // <StartLabel>: 168263320Sdim@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin 169263320Sdim // FIXME: Debug Value. 170263320Sdim return; 171263320Sdim case SP::GETPCX: 172263320Sdim- LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext); 173263320Sdim+ LowerGETPCXAndEmitMCInsts(MI); 174263320Sdim return; 175263320Sdim } 176263320Sdim MachineBasicBlock::const_instr_iterator I = MI; 177263320SdimIndex: test/CodeGen/SPARC/tls.ll 178263320Sdim=================================================================== 179263320Sdim--- test/CodeGen/SPARC/tls.ll 180263320Sdim+++ test/CodeGen/SPARC/tls.ll 181263320Sdim@@ -38,8 +38,7 @@ entry: 182263320Sdim 183263320Sdim 184263320Sdim ; v8abs-LABEL: test_tls_extern 185263320Sdim-; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] 186263320Sdim-; v8abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] 187263320Sdim+; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]] 188263320Sdim ; v8abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] 189263320Sdim ; v8abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] 190263320Sdim ; v8abs: ld [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol) 191263320Sdim@@ -47,8 +46,7 @@ entry: 192263320Sdim ; v8abs: ld [%[[R4]]] 193263320Sdim 194263320Sdim ; v9abs-LABEL: test_tls_extern 195263320Sdim-; v9abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]] 196263320Sdim-; v9abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]] 197263320Sdim+; v9abs: or {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]] 198263320Sdim ; v9abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]] 199263320Sdim ; v9abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]] 200263320Sdim ; v9abs: ldx [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol) 201