From e0c7e3d1397e1b4ffe82c4167958a6570a37ae8d Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sat, 1 Mar 2014 05:07:21 +0000 Subject: [PATCH] [Sparc] Teach SparcAsmParser to emit correct relocations for PIC code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202571 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 54 +++++++++++++++++-- .../Sparc/MCTargetDesc/SparcAsmBackend.cpp | 4 ++ test/MC/Sparc/sparc-pic.s | 49 +++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 test/MC/Sparc/sparc-pic.s diff --git a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 924e3c32c64..62d9ca0d2ad 100644 --- a/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -12,9 +12,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/TargetRegistry.h" @@ -66,7 +68,7 @@ class SparcAsmParser : public MCTargetAsmParser { StringRef Name); OperandMatchResultTy - parseSparcAsmOperand(SparcOperand *&Operand); + parseSparcAsmOperand(SparcOperand *&Operand, bool isCall = false); // returns true if Tok is matched to a register and returns register in RegNo. bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo, @@ -623,7 +625,7 @@ parseOperand(SmallVectorImpl &Operands, } SparcOperand *Op = 0; - ResTy = parseSparcAsmOperand(Op); + ResTy = parseSparcAsmOperand(Op, (Mnemonic == "call")); if (ResTy != MatchOperand_Success || !Op) return MatchOperand_ParseFail; @@ -634,7 +636,7 @@ parseOperand(SmallVectorImpl &Operands, } SparcAsmParser::OperandMatchResultTy -SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) +SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op, bool isCall) { SMLoc S = Parser.getTok().getLoc(); @@ -695,6 +697,10 @@ SparcAsmParser::parseSparcAsmOperand(SparcOperand *&Op) const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + if (isCall && + getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) + Res = SparcMCExpr::Create(SparcMCExpr::VK_Sparc_WPLT30, Res, + getContext()); Op = SparcOperand::CreateImm(Res, S, E); } break; @@ -813,6 +819,31 @@ bool SparcAsmParser::matchRegisterName(const AsmToken &Tok, return false; } +static bool hasGOTReference(const MCExpr *Expr) { + switch (Expr->getKind()) { + case MCExpr::Target: + if (const SparcMCExpr *SE = dyn_cast(Expr)) + return hasGOTReference(SE->getSubExpr()); + break; + + case MCExpr::Constant: + break; + + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Expr); + return hasGOTReference(BE->getLHS()) || hasGOTReference(BE->getRHS()); + } + + case MCExpr::SymbolRef: { + const MCSymbolRefExpr &SymRef = *cast(Expr); + return (SymRef.getSymbol().getName() == "_GLOBAL_OFFSET_TABLE_"); + } + + case MCExpr::Unary: + return hasGOTReference(cast(Expr)->getSubExpr()); + } + return false; +} bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, SMLoc &EndLoc) @@ -836,6 +867,23 @@ bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal, const MCExpr *subExpr; if (Parser.parseParenExpression(subExpr, EndLoc)) return false; + + bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; + + switch(VK) { + default: break; + case SparcMCExpr::VK_Sparc_LO: + VK = (hasGOTReference(subExpr) + ? SparcMCExpr::VK_Sparc_PC10 + : (isPIC ? SparcMCExpr::VK_Sparc_GOT10 : VK)); + break; + case SparcMCExpr::VK_Sparc_HI: + VK = (hasGOTReference(subExpr) + ? SparcMCExpr::VK_Sparc_PC22 + : (isPIC ? SparcMCExpr::VK_Sparc_GOT22 : VK)); + break; + } + EVal = SparcMCExpr::Create(VK, subExpr, getContext()); return true; } diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index db1c361c8f9..812f4b73bd1 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -11,8 +11,10 @@ #include "MCTargetDesc/SparcFixupKinds.h" #include "MCTargetDesc/SparcMCTargetDesc.h" #include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -154,6 +156,8 @@ namespace { switch ((Sparc::Fixups)Fixup.getKind()) { default: break; case Sparc::fixup_sparc_wplt30: + if (Target.getSymA()->getSymbol().isTemporary()) + return; case Sparc::fixup_sparc_tls_gd_hi22: case Sparc::fixup_sparc_tls_gd_lo10: case Sparc::fixup_sparc_tls_gd_add: diff --git a/test/MC/Sparc/sparc-pic.s b/test/MC/Sparc/sparc-pic.s new file mode 100644 index 00000000000..83c2966e597 --- /dev/null +++ b/test/MC/Sparc/sparc-pic.s @@ -0,0 +1,49 @@ +! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s + + +! CHECK: Relocations [ +! CHECK-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC +! CHECK: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4 +! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8 +! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0 +! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0 +! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0 +! CHECK: ] + + .text + .globl foo + .align 4 + .type foo,@function +foo: + .cfi_startproc + save %sp, -176, %sp + .cfi_def_cfa_register %fp + .cfi_window_save + .cfi_register 15, 31 +.Ltmp4: + call .Ltmp5 +.Ltmp6: + sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp6-.Ltmp4)), %i1 +.Ltmp5: + or %i1, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp4)), %i1 + add %i1, %o7, %i1 + sethi %hi(AGlobalVar), %i2 + add %i2, %lo(AGlobalVar), %i2 + ldx [%i1+%i2], %i1 + ldx [%i1], %i1 + call bar + add %i0, %i1, %o0 + ret + restore %g0, %o0, %o0 +.Ltmp7: + .size foo, .Ltmp7-foo + .cfi_endproc + + .type AGlobalVar,@object ! @AGlobalVar + .section .bss + .globl AGlobalVar + .align 8 +AGlobalVar: + .xword 0 ! 0x0 + .size AGlobalVar, 8 +