forked from OSchip/llvm-project
[Sparc] Do not add PC to _GLOBAL_OFFSET_TABLE_ address to access GOT in absolute code.
Fixes PR#18521 llvm-svn: 199775
This commit is contained in:
parent
f8e8b5f5c2
commit
f52927fb1b
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue