OperandMatchResultTy parseBranchModifiers(OperandVector &Operands);
+ // Helper function for dealing with %lo / %hi in PIC mode.
+ const SparcMCExpr *adjustPICRelocation(SparcMCExpr::VariantKind VK,
+ const MCExpr *subExpr);
+
// returns true if Tok is matched to a register and returns register in RegNo.
bool matchRegisterName(const AsmToken &Tok, unsigned &RegNo,
unsigned &RegKind);
// In either case, start with the 'sethi'.
if (!IsEffectivelyImm13) {
MCInst TmpInst;
- const MCExpr *Expr =
- SparcMCExpr::create(SparcMCExpr::VK_Sparc_HI, ValExpr, getContext());
+ const MCExpr *Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_HI, ValExpr);
TmpInst.setLoc(IDLoc);
TmpInst.setOpcode(SP::SETHIi);
TmpInst.addOperand(MCRegOp);
if (IsEffectivelyImm13)
Expr = ValExpr;
else
- Expr =
- SparcMCExpr::create(SparcMCExpr::VK_Sparc_LO, ValExpr, getContext());
+ Expr = adjustPICRelocation(SparcMCExpr::VK_Sparc_LO, ValExpr);
TmpInst.setLoc(IDLoc);
TmpInst.setOpcode(SP::ORri);
TmpInst.addOperand(MCRegOp);
return false;
}
+const SparcMCExpr *
+SparcAsmParser::adjustPICRelocation(SparcMCExpr::VariantKind VK,
+ const MCExpr *subExpr)
+{
+ // When in PIC mode, "%lo(...)" and "%hi(...)" behave differently.
+ // If the expression refers contains _GLOBAL_OFFSETE_TABLE, it is
+ // actually a %pc10 or %pc22 relocation. Otherwise, they are interpreted
+ // as %got10 or %got22 relocation.
+
+ if (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) {
+ switch(VK) {
+ default: break;
+ case SparcMCExpr::VK_Sparc_LO:
+ VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC10
+ : SparcMCExpr::VK_Sparc_GOT10);
+ break;
+ case SparcMCExpr::VK_Sparc_HI:
+ VK = (hasGOTReference(subExpr) ? SparcMCExpr::VK_Sparc_PC22
+ : SparcMCExpr::VK_Sparc_GOT22);
+ break;
+ }
+ }
+
+ return SparcMCExpr::create(VK, subExpr, getContext());
+}
+
bool SparcAsmParser::matchSparcAsmModifiers(const MCExpr *&EVal,
SMLoc &EndLoc)
{
if (Parser.parseParenExpression(subExpr, EndLoc))
return false;
- bool isPIC = getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
-
- // Ugly: if a sparc assembly expression says "%hi(...)" but the
- // expression within contains _GLOBAL_OFFSET_TABLE_, it REALLY means
- // %pc22. Same with %lo -> %pc10. Worse, if it doesn't contain that,
- // the meaning depends on whether the assembler was invoked with
- // -KPIC or not: if so, it really means %got22/%got10; if not, it
- // actually means what it said! Sigh, historical mistakes...
-
- 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());
+ EVal = adjustPICRelocation(VK, subExpr);
return true;
}
-! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck %s
+! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=pic -filetype=obj | llvm-readobj -r | FileCheck --check-prefix=PIC %s
+! RUN: llvm-mc %s -arch=sparcv9 --relocation-model=static -filetype=obj | llvm-readobj -r | FileCheck --check-prefix=NOPIC %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_GOT22 .LC0 0x0
-! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 .LC0 0x0
-! CHECK-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 bar 0x0
-! CHECK: ]
+! PIC: Relocations [
+! PIC-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
+! PIC: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x4
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x8
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC22 _GLOBAL_OFFSET_TABLE_ 0x0
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_PC10 _GLOBAL_OFFSET_TABLE_ 0x0
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT22 AGlobalVar 0x0
+! PIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_GOT10 AGlobalVar 0x0
+! 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: ]
+
+! NOPIC: Relocations [
+! NOPIC-NOT: 0x{{[0-9,A-F]+}} R_SPARC_WPLT30 .text 0xC
+! NOPIC: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x4
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x8
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 _GLOBAL_OFFSET_TABLE_ 0x0
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 _GLOBAL_OFFSET_TABLE_ 0x0
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 AGlobalVar 0x0
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 AGlobalVar 0x0
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_HI22 AGlobalVar 0x0
+! NOPIC-NEXT: 0x{{[0-9,A-F]+}} R_SPARC_LO10 AGlobalVar 0x0
+! 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: ]
.section ".rodata"
.align 8
sethi %hi(_GLOBAL_OFFSET_TABLE_+(.Ltmp6-.Ltmp4)), %i1
.Ltmp5:
or %i1, %lo(_GLOBAL_OFFSET_TABLE_+(.Ltmp5-.Ltmp4)), %i1
+ set _GLOBAL_OFFSET_TABLE_, %i1
add %i1, %o7, %i1
sethi %hi(AGlobalVar), %i2
add %i2, %lo(AGlobalVar), %i2
+ set AGlobalVar, %i2
ldx [%i1+%i2], %i3
ldx [%i3], %i3
sethi %hi(.LC0), %i2