201 lines
7.9 KiB
Diff
201 lines
7.9 KiB
Diff
Pull in r199775 from upstream llvm trunk (by Venkatraman Govindaraju):
|
|
|
|
[Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.
|
|
Fixes PR#18521
|
|
|
|
Introduced here: http://svnweb.freebsd.org/changeset/base/262261
|
|
|
|
Index: lib/Target/Sparc/SparcAsmPrinter.cpp
|
|
===================================================================
|
|
--- lib/Target/Sparc/SparcAsmPrinter.cpp
|
|
+++ lib/Target/Sparc/SparcAsmPrinter.cpp
|
|
@@ -65,18 +65,24 @@ namespace {
|
|
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
|
unsigned AsmVariant, const char *ExtraCode,
|
|
raw_ostream &O);
|
|
+
|
|
+ void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI);
|
|
+
|
|
};
|
|
} // end of anonymous namespace
|
|
|
|
-static MCOperand createPCXCallOP(MCSymbol *Label,
|
|
- MCContext &OutContext)
|
|
-{
|
|
- const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Label,
|
|
+static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind,
|
|
+ MCSymbol *Sym, MCContext &OutContext) {
|
|
+ const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Sym,
|
|
OutContext);
|
|
- const SparcMCExpr *expr = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_None,
|
|
- MCSym, OutContext);
|
|
+ const SparcMCExpr *expr = SparcMCExpr::Create(Kind, MCSym, OutContext);
|
|
return MCOperand::CreateExpr(expr);
|
|
+
|
|
}
|
|
+static MCOperand createPCXCallOP(MCSymbol *Label,
|
|
+ MCContext &OutContext) {
|
|
+ return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
|
|
+}
|
|
|
|
static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind,
|
|
MCSymbol *GOTLabel, MCSymbol *StartLabel,
|
|
@@ -115,43 +121,101 @@ static void EmitSETHI(MCStreamer &OutStreamer,
|
|
OutStreamer.EmitInstruction(SETHIInst);
|
|
}
|
|
|
|
-static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1,
|
|
- MCOperand &Imm, MCOperand &RD)
|
|
+static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
|
|
+ MCOperand &RS1, MCOperand &Src2, MCOperand &RD)
|
|
{
|
|
- MCInst ORInst;
|
|
- ORInst.setOpcode(SP::ORri);
|
|
- ORInst.addOperand(RD);
|
|
- ORInst.addOperand(RS1);
|
|
- ORInst.addOperand(Imm);
|
|
- OutStreamer.EmitInstruction(ORInst);
|
|
+ MCInst Inst;
|
|
+ Inst.setOpcode(Opcode);
|
|
+ Inst.addOperand(RD);
|
|
+ Inst.addOperand(RS1);
|
|
+ Inst.addOperand(Src2);
|
|
+ OutStreamer.EmitInstruction(Inst);
|
|
}
|
|
|
|
+static void EmitOR(MCStreamer &OutStreamer,
|
|
+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
|
|
+ EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD);
|
|
+}
|
|
+
|
|
static void EmitADD(MCStreamer &OutStreamer,
|
|
- MCOperand &RS1, MCOperand &RS2, MCOperand &RD)
|
|
-{
|
|
- MCInst ADDInst;
|
|
- ADDInst.setOpcode(SP::ADDrr);
|
|
- ADDInst.addOperand(RD);
|
|
- ADDInst.addOperand(RS1);
|
|
- ADDInst.addOperand(RS2);
|
|
- OutStreamer.EmitInstruction(ADDInst);
|
|
+ MCOperand &RS1, MCOperand &RS2, MCOperand &RD) {
|
|
+ EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD);
|
|
}
|
|
|
|
-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
|
|
- MCStreamer &OutStreamer,
|
|
- MCContext &OutContext)
|
|
+static void EmitSHL(MCStreamer &OutStreamer,
|
|
+ MCOperand &RS1, MCOperand &Imm, MCOperand &RD) {
|
|
+ EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD);
|
|
+}
|
|
+
|
|
+
|
|
+static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
|
|
+ SparcMCExpr::VariantKind HiKind,
|
|
+ SparcMCExpr::VariantKind LoKind,
|
|
+ MCOperand &RD,
|
|
+ MCContext &OutContext) {
|
|
+
|
|
+ MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
|
|
+ MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
|
|
+ EmitSETHI(OutStreamer, hi, RD);
|
|
+ EmitOR(OutStreamer, RD, lo, RD);
|
|
+}
|
|
+
|
|
+void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI)
|
|
{
|
|
- const MachineOperand &MO = MI->getOperand(0);
|
|
- MCSymbol *StartLabel = OutContext.CreateTempSymbol();
|
|
- MCSymbol *EndLabel = OutContext.CreateTempSymbol();
|
|
- MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
|
|
MCSymbol *GOTLabel =
|
|
OutContext.GetOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
|
|
|
|
+ const MachineOperand &MO = MI->getOperand(0);
|
|
assert(MO.getReg() != SP::O7 &&
|
|
"%o7 is assigned as destination for getpcx!");
|
|
|
|
MCOperand MCRegOP = MCOperand::CreateReg(MO.getReg());
|
|
+
|
|
+
|
|
+ if (TM.getRelocationModel() != Reloc::PIC_) {
|
|
+ // Just load the address of GOT to MCRegOP.
|
|
+ switch(TM.getCodeModel()) {
|
|
+ default:
|
|
+ llvm_unreachable("Unsupported absolute code model");
|
|
+ case CodeModel::Small:
|
|
+ EmitHiLo(OutStreamer, GOTLabel,
|
|
+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
|
|
+ MCRegOP, OutContext);
|
|
+ break;
|
|
+ case CodeModel::Medium: {
|
|
+ EmitHiLo(OutStreamer, GOTLabel,
|
|
+ SparcMCExpr::VK_Sparc_H44, SparcMCExpr::VK_Sparc_M44,
|
|
+ MCRegOP, OutContext);
|
|
+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(12,
|
|
+ OutContext));
|
|
+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
|
|
+ MCOperand lo = createSparcMCOperand(SparcMCExpr::VK_Sparc_L44,
|
|
+ GOTLabel, OutContext);
|
|
+ EmitOR(OutStreamer, MCRegOP, lo, MCRegOP);
|
|
+ break;
|
|
+ }
|
|
+ case CodeModel::Large: {
|
|
+ EmitHiLo(OutStreamer, GOTLabel,
|
|
+ SparcMCExpr::VK_Sparc_HH, SparcMCExpr::VK_Sparc_HM,
|
|
+ MCRegOP, OutContext);
|
|
+ MCOperand imm = MCOperand::CreateExpr(MCConstantExpr::Create(32,
|
|
+ OutContext));
|
|
+ EmitSHL(OutStreamer, MCRegOP, imm, MCRegOP);
|
|
+ // Use register %o7 to load the lower 32 bits.
|
|
+ MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
|
|
+ EmitHiLo(OutStreamer, GOTLabel,
|
|
+ SparcMCExpr::VK_Sparc_HI, SparcMCExpr::VK_Sparc_LO,
|
|
+ RegO7, OutContext);
|
|
+ EmitADD(OutStreamer, MCRegOP, RegO7, MCRegOP);
|
|
+ }
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ MCSymbol *StartLabel = OutContext.CreateTempSymbol();
|
|
+ MCSymbol *EndLabel = OutContext.CreateTempSymbol();
|
|
+ MCSymbol *SethiLabel = OutContext.CreateTempSymbol();
|
|
+
|
|
MCOperand RegO7 = MCOperand::CreateReg(SP::O7);
|
|
|
|
// <StartLabel>:
|
|
@@ -187,7 +251,7 @@ void SparcAsmPrinter::EmitInstruction(const Machin
|
|
// FIXME: Debug Value.
|
|
return;
|
|
case SP::GETPCX:
|
|
- LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
|
|
+ LowerGETPCXAndEmitMCInsts(MI);
|
|
return;
|
|
}
|
|
MachineBasicBlock::const_instr_iterator I = MI;
|
|
Index: test/CodeGen/SPARC/tls.ll
|
|
===================================================================
|
|
--- test/CodeGen/SPARC/tls.ll
|
|
+++ test/CodeGen/SPARC/tls.ll
|
|
@@ -38,8 +38,7 @@ entry:
|
|
|
|
|
|
; v8abs-LABEL: test_tls_extern
|
|
-; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
|
|
-; v8abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
|
|
+; v8abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
|
|
; v8abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
|
|
; v8abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
|
|
; v8abs: ld [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ld(extern_symbol)
|
|
@@ -47,8 +46,7 @@ entry:
|
|
; v8abs: ld [%[[R4]]]
|
|
|
|
; v9abs-LABEL: test_tls_extern
|
|
-; v9abs: or {{%[goli][0-7]}}, %lo(_GLOBAL_OFFSET_TABLE_+{{.+}}), [[PC:%[goli][0-7]]]
|
|
-; v9abs: add [[PC]], %o7, %[[GOTBASE:[goli][0-7]]]
|
|
+; v9abs: or {{%[goli][0-7]}}, %l44(_GLOBAL_OFFSET_TABLE_), %[[GOTBASE:[goli][0-7]]]
|
|
; v9abs: sethi %tie_hi22(extern_symbol), [[R1:%[goli][0-7]]]
|
|
; v9abs: add [[R1]], %tie_lo10(extern_symbol), %[[R2:[goli][0-7]]]
|
|
; v9abs: ldx [%[[GOTBASE]]+%[[R2]]], [[R3:%[goli][0-7]]], %tie_ldx(extern_symbol)
|