summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-22 00:13:18 +0000
committerVenkatraman Govindaraju <venkatra@cs.wisc.edu>2014-01-22 00:13:18 +0000
commit6220c8f960fe287efcfc27f46ab6ad48e5b3c5d2 (patch)
treec3ac9b14285c726fee710c84dc46a96dcb2d4a0d /lib
parentc04f2c99aba75a5e05177c35360d16bee7da09b2 (diff)
downloadllvm-6220c8f960fe287efcfc27f46ab6ad48e5b3c5d2.tar.gz
llvm-6220c8f960fe287efcfc27f46ab6ad48e5b3c5d2.tar.bz2
llvm-6220c8f960fe287efcfc27f46ab6ad48e5b3c5d2.tar.xz
[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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/Sparc/SparcAsmPrinter.cpp124
1 files changed, 94 insertions, 30 deletions
diff --git a/lib/Target/Sparc/SparcAsmPrinter.cpp b/lib/Target/Sparc/SparcAsmPrinter.cpp
index 336571e375..639713ca9a 100644
--- a/lib/Target/Sparc/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/SparcAsmPrinter.cpp
@@ -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 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);
}
-static void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
- MCStreamer &OutStreamer,
- MCContext &OutContext)
+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;