diff options
-rw-r--r-- | llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h | 2 | ||||
-rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.cpp | 19 | ||||
-rw-r--r-- | llvm/test/CodeGen/SPARC/pic.ll | 14 | ||||
-rw-r--r-- | llvm/test/MC/Sparc/sparc-pic.s | 23 | ||||
-rw-r--r-- | llvm/test/MC/Sparc/sparc-relocations.s | 5 |
10 files changed, 91 insertions, 7 deletions
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp index 35d92a96abe..c7a5a1e8e6e 100644 --- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -885,9 +885,17 @@ SparcAsmParser::parseSparcAsmOperand(std::unique_ptr<SparcOperand> &Op, const MCExpr *Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); - if (isCall && getContext().getObjectFileInfo()->isPositionIndependent()) - Res = SparcMCExpr::create(SparcMCExpr::VK_Sparc_WPLT30, Res, - getContext()); + SparcMCExpr::VariantKind Kind = SparcMCExpr::VK_Sparc_13; + + if (getContext().getObjectFileInfo()->isPositionIndependent()) { + if (isCall) + Kind = SparcMCExpr::VK_Sparc_WPLT30; + else + Kind = SparcMCExpr::VK_Sparc_GOT13; + } + + Res = SparcMCExpr::create(Kind, Res, getContext()); + Op = SparcOperand::CreateImm(Res, S, E); } break; diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index 4b6c1de7d85..5f5e2ef7d45 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -54,6 +54,10 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case Sparc::fixup_sparc_hi22: return (Value >> 10) & 0x3fffff; + case Sparc::fixup_sparc_got13: + case Sparc::fixup_sparc_13: + return Value & 0x1fff; + case Sparc::fixup_sparc_pc10: case Sparc::fixup_sparc_got10: case Sparc::fixup_sparc_tls_gd_lo10: @@ -120,6 +124,7 @@ namespace { { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_13", 19, 13, 0 }, { "fixup_sparc_hi22", 10, 22, 0 }, { "fixup_sparc_lo10", 22, 10, 0 }, { "fixup_sparc_h44", 10, 22, 0 }, @@ -131,6 +136,7 @@ namespace { { "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_got22", 10, 22, 0 }, { "fixup_sparc_got10", 22, 10, 0 }, + { "fixup_sparc_got13", 19, 13, 0 }, { "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_tls_gd_hi22", 10, 22, 0 }, { "fixup_sparc_tls_gd_lo10", 22, 10, 0 }, @@ -159,6 +165,7 @@ namespace { { "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br16_2", 20, 2, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br16_14", 0, 14, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_13", 0, 13, 0 }, { "fixup_sparc_hi22", 0, 22, 0 }, { "fixup_sparc_lo10", 0, 10, 0 }, { "fixup_sparc_h44", 0, 22, 0 }, @@ -170,6 +177,7 @@ namespace { { "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_got22", 0, 22, 0 }, { "fixup_sparc_got10", 0, 10, 0 }, + { "fixup_sparc_got13", 0, 13, 0 }, { "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_tls_gd_hi22", 0, 22, 0 }, { "fixup_sparc_tls_gd_lo10", 0, 10, 0 }, diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp index 173ef8674c1..5a730947796 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp @@ -79,6 +79,7 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx, case FK_Data_8: return ((Fixup.getOffset() % 8) ? ELF::R_SPARC_UA64 : ELF::R_SPARC_64); + case Sparc::fixup_sparc_13: return ELF::R_SPARC_13; case Sparc::fixup_sparc_hi22: return ELF::R_SPARC_HI22; case Sparc::fixup_sparc_lo10: return ELF::R_SPARC_LO10; case Sparc::fixup_sparc_h44: return ELF::R_SPARC_H44; @@ -88,6 +89,7 @@ unsigned SparcELFObjectWriter::getRelocType(MCContext &Ctx, case Sparc::fixup_sparc_hm: return ELF::R_SPARC_HM10; case Sparc::fixup_sparc_got22: return ELF::R_SPARC_GOT22; case Sparc::fixup_sparc_got10: return ELF::R_SPARC_GOT10; + case Sparc::fixup_sparc_got13: return ELF::R_SPARC_GOT13; case Sparc::fixup_sparc_tls_gd_hi22: return ELF::R_SPARC_TLS_GD_HI22; case Sparc::fixup_sparc_tls_gd_lo10: return ELF::R_SPARC_TLS_GD_LO10; case Sparc::fixup_sparc_tls_gd_add: return ELF::R_SPARC_TLS_GD_ADD; diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h index 8d79396d936..99aa63fe229 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -30,6 +30,9 @@ namespace llvm { fixup_sparc_br16_2, fixup_sparc_br16_14, + /// fixup_sparc_13 - 13-bit fixup + fixup_sparc_13, + /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo) /// for sethi fixup_sparc_hi22, @@ -64,6 +67,9 @@ namespace llvm { /// fixup_sparc_got10 - 10-bit fixup corresponding to %got10(foo) fixup_sparc_got10, + /// fixup_sparc_got13 - 13-bit fixup corresponding to %got13(foo) + fixup_sparc_got13, + /// fixup_sparc_wplt30 fixup_sparc_wplt30, diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp index 2b80293df12..f736a37a266 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp @@ -58,6 +58,8 @@ bool SparcMCExpr::printVariantKind(raw_ostream &OS, VariantKind Kind) // FIXME: use %got22/%got10, if system assembler supports them. case VK_Sparc_GOT22: OS << "%hi("; break; case VK_Sparc_GOT10: OS << "%lo("; break; + case VK_Sparc_GOT13: closeParen = false; break; + case VK_Sparc_13: closeParen = false; break; case VK_Sparc_WPLT30: closeParen = false; break; case VK_Sparc_R_DISP32: OS << "%r_disp32("; break; case VK_Sparc_TLS_GD_HI22: OS << "%tgd_hi22("; break; @@ -96,6 +98,7 @@ SparcMCExpr::VariantKind SparcMCExpr::parseVariantKind(StringRef name) .Case("pc10", VK_Sparc_PC10) .Case("got22", VK_Sparc_GOT22) .Case("got10", VK_Sparc_GOT10) + .Case("got13", VK_Sparc_GOT13) .Case("r_disp32", VK_Sparc_R_DISP32) .Case("tgd_hi22", VK_Sparc_TLS_GD_HI22) .Case("tgd_lo10", VK_Sparc_TLS_GD_LO10) @@ -132,6 +135,8 @@ Sparc::Fixups SparcMCExpr::getFixupKind(SparcMCExpr::VariantKind Kind) { case VK_Sparc_PC10: return Sparc::fixup_sparc_pc10; case VK_Sparc_GOT22: return Sparc::fixup_sparc_got22; case VK_Sparc_GOT10: return Sparc::fixup_sparc_got10; + case VK_Sparc_GOT13: return Sparc::fixup_sparc_got13; + case VK_Sparc_13: return Sparc::fixup_sparc_13; case VK_Sparc_WPLT30: return Sparc::fixup_sparc_wplt30; case VK_Sparc_TLS_GD_HI22: return Sparc::fixup_sparc_tls_gd_hi22; case VK_Sparc_TLS_GD_LO10: return Sparc::fixup_sparc_tls_gd_lo10; diff --git a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h index 13f08195c76..cf2db067749 100644 --- a/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h +++ b/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h @@ -36,6 +36,8 @@ public: VK_Sparc_PC10, VK_Sparc_GOT22, VK_Sparc_GOT10, + VK_Sparc_GOT13, + VK_Sparc_13, VK_Sparc_WPLT30, VK_Sparc_R_DISP32, VK_Sparc_TLS_GD_HI22, diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index 34e0297fe9f..14a99c085f8 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1980,11 +1980,22 @@ SDValue SparcTargetLowering::makeAddress(SDValue Op, SelectionDAG &DAG) const { // Handle PIC mode first. SPARC needs a got load for every variable! if (isPositionIndependent()) { - // This is the pic32 code model, the GOT is known to be smaller than 4GB. - SDValue HiLo = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, - SparcMCExpr::VK_Sparc_GOT10, DAG); + const Module *M = DAG.getMachineFunction().getFunction().getParent(); + PICLevel::Level picLevel = M->getPICLevel(); + SDValue Idx; + + if (picLevel == PICLevel::SmallPIC) { + // This is the pic13 code model, the GOT is known to be smaller than 8KiB. + Idx = DAG.getNode(SPISD::Lo, DL, Op.getValueType(), + withTargetFlags(Op, SparcMCExpr::VK_Sparc_GOT13, DAG)); + } else { + // This is the pic32 code model, the GOT is known to be smaller than 4GB. + Idx = makeHiLoPair(Op, SparcMCExpr::VK_Sparc_GOT22, + SparcMCExpr::VK_Sparc_GOT10, DAG); + } + SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, DL, VT); - SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, HiLo); + SDValue AbsAddr = DAG.getNode(ISD::ADD, DL, VT, GlobalBase, Idx); // GLOBAL_BASE_REG codegen'ed with call. Inform MFI that this // function has calls. MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); diff --git a/llvm/test/CodeGen/SPARC/pic.ll b/llvm/test/CodeGen/SPARC/pic.ll new file mode 100644 index 00000000000..4edbffcc12b --- /dev/null +++ b/llvm/test/CodeGen/SPARC/pic.ll @@ -0,0 +1,14 @@ +; RUN: llc < %s -relocation-model=pic -mtriple=sparc | FileCheck %s + +@value = external global i32 + +define i32 @test() nounwind { +; CHECK: ld [%i0+value], %i0 +entry: + %0 = load i32, i32* @value + ret i32 %0 +} + +!llvm.module.flags = !{!0} + +!0 = !{i32 7, !"PIC Level", i32 1} diff --git a/llvm/test/MC/Sparc/sparc-pic.s b/llvm/test/MC/Sparc/sparc-pic.s index f51e1e93b50..a16ed807afc 100644 --- a/llvm/test/MC/Sparc/sparc-pic.s +++ b/llvm/test/MC/Sparc/sparc-pic.s @@ -15,6 +15,7 @@ ! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 .LC0 0x0 ! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 .LC0 0x0 ! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0 +! PIC: 0x{{[0-9,A-F]+}} R_SPARC_GOT13 value 0x0 ! PIC: ] ! NOPIC: Relocations [ @@ -30,6 +31,7 @@ ! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 .rodata 0x0 ! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 .rodata 0x0 ! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WDISP30 bar 0x0 +! NOPIC: 0x{{[0-9,A-F]+}} R_SPARC_13 value 0x0 ! NOPIC: ] .section ".rodata" @@ -78,3 +80,24 @@ foo: AGlobalVar: .xword 0 ! 0x0 .size AGlobalVar, 8 + + .section ".text" + .text + .globl pic13 + .align 4 + .type pic13,@function +pic13: + save %sp, -128, %sp +.Ltmp0: + call .Ltmp1 +.Ltmp2: + sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp2-.Ltmp0)), %i0 +.Ltmp1: + or %i0, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp1-.Ltmp0)), %i0 + add %i0, %o7, %i0 + ldx [%i0+value], %i0 + ld [%i0], %i0 + ret + restore +.Lfunc_end0: + .size pic13, .Lfunc_end0-pic13 diff --git a/llvm/test/MC/Sparc/sparc-relocations.s b/llvm/test/MC/Sparc/sparc-relocations.s index 58ad37e1da5..18fc123fac0 100644 --- a/llvm/test/MC/Sparc/sparc-relocations.s +++ b/llvm/test/MC/Sparc/sparc-relocations.s @@ -11,6 +11,7 @@ ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_L44 sym ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HH22 sym ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_HM10 sym + ! CHECK-OBJ: 0x{{[0-9,A-F]+}} R_SPARC_13 sym ! CHECK-ELF: ] ! CHECK: call foo ! encoding: [0b01AAAAAA,A,A,A] @@ -44,3 +45,7 @@ ! CHECK: or %g1, %hm(sym), %g3 ! encoding: [0x86,0x10,0b011000AA,A] ! CHECK-NEXT: ! fixup A - offset: 0, value: %hm(sym), kind: fixup_sparc_hm or %g1, %hm(sym), %g3 + + ! CHECK: or %g1, sym, %g3 ! encoding: [0x86,0x10,0b011AAAAA,A] + ! CHECK-NEXT: ! fixup A - offset: 0, value: sym, kind: fixup_sparc_13 + or %g1, sym, %g3 |