[Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.

Fixes PR#18521


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@199775 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Venkatraman Govindaraju 2014-01-22 00:13:18 +00:00
parent c04f2c99ab
commit 6220c8f960
2 changed files with 96 additions and 34 deletions

View File

@ -66,17 +66,23 @@ 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,
@ -116,43 +122,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>:
@ -188,7 +252,7 @@ void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
// FIXME: Debug Value.
return;
case SP::GETPCX:
LowerGETPCXAndEmitMCInsts(MI, OutStreamer, OutContext);
LowerGETPCXAndEmitMCInsts(MI);
return;
}
MachineBasicBlock::const_instr_iterator I = MI;

View File

@ -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)