diff options
author | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-01-22 00:13:18 +0000 |
---|---|---|
committer | Venkatraman Govindaraju <venkatra@cs.wisc.edu> | 2014-01-22 00:13:18 +0000 |
commit | 6220c8f960fe287efcfc27f46ab6ad48e5b3c5d2 (patch) | |
tree | c3ac9b14285c726fee710c84dc46a96dcb2d4a0d /lib | |
parent | c04f2c99aba75a5e05177c35360d16bee7da09b2 (diff) | |
download | llvm-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.cpp | 124 |
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; |