[llvm] r245305 - [mips] Expand JAL instructions when PIC is enabled.
Daniel Sanders via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 18 09:18:09 PDT 2015
Author: dsanders
Date: Tue Aug 18 11:18:09 2015
New Revision: 245305
URL: http://llvm.org/viewvc/llvm-project?rev=245305&view=rev
Log:
[mips] Expand JAL instructions when PIC is enabled.
Summary: This is the correct way to handle JAL instructions when PIC is enabled.
Patch by Toma Tabacu
Reviewers: seanbruno, tomatabacu
Subscribers: brooks, seanbruno, emaste, llvm-commits
Differential Revision: http://reviews.llvm.org/D6231
Added:
llvm/trunk/test/MC/Mips/expansion-jal-sym-pic.s
Modified:
llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s
llvm/trunk/test/MC/Mips/set-nomacro.s
Modified: llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp?rev=245305&r1=245304&r2=245305&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/Mips/AsmParser/MipsAsmParser.cpp Tue Aug 18 11:18:09 2015
@@ -1318,6 +1318,44 @@ static bool hasShortDelaySlot(unsigned O
}
}
+static const MCSymbol *getSingleMCSymbol(const MCExpr *Expr) {
+ if (const MCSymbolRefExpr *SRExpr = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ return &SRExpr->getSymbol();
+ }
+
+ if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr)) {
+ const MCSymbol *LHSSym = getSingleMCSymbol(BExpr->getLHS());
+ const MCSymbol *RHSSym = getSingleMCSymbol(BExpr->getRHS());
+
+ if (LHSSym)
+ return LHSSym;
+
+ if (RHSSym)
+ return RHSSym;
+
+ return nullptr;
+ }
+
+ if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
+ return getSingleMCSymbol(UExpr->getSubExpr());
+
+ return nullptr;
+}
+
+static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
+ if (isa<MCSymbolRefExpr>(Expr))
+ return 1;
+
+ if (const MCBinaryExpr *BExpr = dyn_cast<MCBinaryExpr>(Expr))
+ return countMCSymbolRefExpr(BExpr->getLHS()) +
+ countMCSymbolRefExpr(BExpr->getRHS());
+
+ if (const MCUnaryExpr *UExpr = dyn_cast<MCUnaryExpr>(Expr))
+ return countMCSymbolRefExpr(UExpr->getSubExpr());
+
+ return 0;
+}
+
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
@@ -1468,6 +1506,94 @@ bool MipsAsmParser::processInstruction(M
}
}
+ // This expansion is not in a function called by expandInstruction() because
+ // the pseudo-instruction doesn't have a distinct opcode.
+ if ((Inst.getOpcode() == Mips::JAL || Inst.getOpcode() == Mips::JAL_MM) &&
+ inPicMode()) {
+ warnIfNoMacro(IDLoc);
+
+ const MCExpr *JalExpr = Inst.getOperand(0).getExpr();
+
+ // We can do this expansion if there's only 1 symbol in the argument
+ // expression.
+ if (countMCSymbolRefExpr(JalExpr) > 1)
+ return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
+
+ // FIXME: This is checking the expression can be handled by the later stages
+ // of the assembler. We ought to leave it to those later stages but
+ // we can't do that until we stop evaluateRelocExpr() rewriting the
+ // expressions into non-equivalent forms.
+ const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
+
+ // FIXME: Add support for label+offset operands (currently causes an error).
+ // FIXME: Add support for forward-declared local symbols.
+ // FIXME: Add expansion for when the LargeGOT option is enabled.
+ if (JalSym->isInSection() || JalSym->isTemporary()) {
+ if (isABI_O32()) {
+ // If it's a local symbol and the O32 ABI is being used, we expand to:
+ // lw  $25, 0($gp)
+ // R_(MICRO)MIPS_GOT16 label
+ // addiu $25, $25, 0
+ // R_(MICRO)MIPS_LO16 label
+ // jalr $25
+ const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
+ const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
+
+ MCInst LwInst;
+ LwInst.setOpcode(Mips::LW);
+ LwInst.addOperand(MCOperand::createReg(Mips::T9));
+ LwInst.addOperand(MCOperand::createReg(Mips::GP));
+ LwInst.addOperand(MCOperand::createExpr(Got16RelocExpr));
+ Instructions.push_back(LwInst);
+
+ MCInst AddiuInst;
+ AddiuInst.setOpcode(Mips::ADDiu);
+ AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
+ AddiuInst.addOperand(MCOperand::createReg(Mips::T9));
+ AddiuInst.addOperand(MCOperand::createExpr(Lo16RelocExpr));
+ Instructions.push_back(AddiuInst);
+ } else if (isABI_N32() || isABI_N64()) {
+ // If it's a local symbol and the N32/N64 ABIs are being used,
+ // we expand to:
+ // lw/ld  $25, 0($gp)
+ // R_(MICRO)MIPS_GOT_DISP label
+ // jalr $25
+ const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
+
+ MCInst LoadInst;
+ LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
+ LoadInst.addOperand(MCOperand::createReg(Mips::T9));
+ LoadInst.addOperand(MCOperand::createReg(Mips::GP));
+ LoadInst.addOperand(MCOperand::createExpr(GotDispRelocExpr));
+ Instructions.push_back(LoadInst);
+ }
+ } else {
+ // If it's an external/weak symbol, we expand to:
+ // lw/ld $25, 0($gp)
+ // R_(MICRO)MIPS_CALL16 label
+ // jalr $25
+ const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
+
+ MCInst LoadInst;
+ LoadInst.setOpcode(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW);
+ LoadInst.addOperand(MCOperand::createReg(Mips::T9));
+ LoadInst.addOperand(MCOperand::createReg(Mips::GP));
+ LoadInst.addOperand(MCOperand::createExpr(Call16RelocExpr));
+ Instructions.push_back(LoadInst);
+ }
+
+ MCInst JalrInst;
+ JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR);
+ JalrInst.addOperand(MCOperand::createReg(Mips::RA));
+ JalrInst.addOperand(MCOperand::createReg(Mips::T9));
+
+ // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
+ // This relocation is supposed to be an optimization hint for the linker
+ // and is not necessary for correctness.
+
+ Inst = JalrInst;
+ }
+
if (MCID.mayLoad() || MCID.mayStore()) {
// Check the offset of memory operand, if it is a symbol
// reference or immediate we may have to expand instructions.
Modified: llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s?rev=245305&r1=245304&r2=245305&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s (original)
+++ llvm/trunk/test/ExecutionEngine/RuntimeDyld/Mips/ELF_Mips64r2N64_PIC_relocations.s Tue Aug 18 11:18:09 2015
@@ -41,7 +41,9 @@ bar:
# Test R_MIPS_26 relocation.
# rtdyld-check: decode_operand(insn1, 0)[25:0] = foo
insn1:
+ .option pic0
jal foo
+ .option pic2
nop
# Test R_MIPS_PC16 relocation.
Added: llvm/trunk/test/MC/Mips/expansion-jal-sym-pic.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/expansion-jal-sym-pic.s?rev=245305&view=auto
==============================================================================
--- llvm/trunk/test/MC/Mips/expansion-jal-sym-pic.s (added)
+++ llvm/trunk/test/MC/Mips/expansion-jal-sym-pic.s Tue Aug 18 11:18:09 2015
@@ -0,0 +1,183 @@
+# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=NORMAL -check-prefix=O32
+
+# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=NORMAL -check-prefix=N32
+
+# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=NORMAL -check-prefix=N64
+
+# RUN: llvm-mc %s -arch=mips -mcpu=mips32 -mattr=micromips -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=MICROMIPS -check-prefix=O32-MICROMIPS
+
+# RUN: llvm-mc %s -arch=mips -mcpu=mips64 -target-abi n32 -mattr=micromips -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=MICROMIPS -check-prefix=N32-MICROMIPS
+
+# RUN: llvm-mc %s -arch=mips64 -mcpu=mips64 -target-abi n64 -mattr=micromips -show-encoding |\
+# RUN: FileCheck %s -check-prefix=ALL -check-prefix=MICROMIPS -check-prefix=N64-MICROMIPS
+
+ .weak weak_label
+
+ .text
+ .option pic2
+
+ .ent local_label
+local_label:
+ .frame $sp, 0, $ra
+ .set noreorder
+
+ jal local_label
+ nop
+
+ jal weak_label
+ nop
+
+ jal global_label
+ nop
+
+ jal .text
+ nop
+
+ # local labels ($tmp symbols)
+ jal 1f
+ nop
+
+ .end local_label
+
+1:
+ nop
+ add $8, $8, $8
+ nop
+
+# Expanding "jal local_label":
+# O32: lw $25, %got(local_label)($gp) # encoding: [0x8f,0x99,A,A]
+# O32: # fixup A - offset: 0, value: local_label at GOT, kind: fixup_Mips_GOT_Local
+# O32: addiu $25, $25, %lo(local_label) # encoding: [0x27,0x39,A,A]
+# O32: # fixup A - offset: 0, value: local_label at ABS_LO, kind: fixup_Mips_LO16
+
+# N32: lw $25, %got_disp(local_label)($gp) # encoding: [0x8f,0x99,A,A]
+# N32: # fixup A - offset: 0, value: local_label at GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# N64: ld $25, %got_disp(local_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64: # fixup A - offset: 0, value: local_label at GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# O32-MICROMIPS: lw $25, %got(local_label)($gp) # encoding: [0xff,0x3c,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: local_label at GOT, kind: fixup_MICROMIPS_GOT16
+# O32-MICROMIPS: addiu $25, $25, %lo(local_label) # encoding: [0x33,0x39,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: local_label at ABS_LO, kind: fixup_MICROMIPS_LO16
+
+# N32-MICROMIPS: lw $25, %got_disp(local_label)($gp) # encoding: [0xff,0x3c,A,A]
+# N32-MICROMIPS: # fixup A - offset: 0, value: local_label at GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# N64-MICROMIPS: ld $25, %got_disp(local_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-MICROMIPS: # fixup A - offset: 0, value: local_label at GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# NORMAL: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
+# MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
+# ALL: nop # encoding: [0x00,0x00,0x00,0x00]
+
+
+# Expanding "jal weak_label":
+# O32: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A]
+# O32: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# N32: lw $25, %call16(weak_label)($gp) # encoding: [0x8f,0x99,A,A]
+# N32: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# N64: ld $25, %call16(weak_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# O32-MICROMIPS: lw $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# N32-MICROMIPS: lw $25, %call16(weak_label)($gp) # encoding: [0xff,0x3c,A,A]
+# N32-MICROMIPS: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# N64-MICROMIPS: ld $25, %call16(weak_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-MICROMIPS: # fixup A - offset: 0, value: weak_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# NORMAL: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
+# MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
+# ALL: nop # encoding: [0x00,0x00,0x00,0x00]
+
+
+# Expanding "jal global_label":
+# O32: lw $25, %call16(global_label)($gp) # encoding: [0x8f,0x99,A,A]
+# O32: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# N32: lw $25, %call16(global_label)($gp) # encoding: [0x8f,0x99,A,A]
+# N32: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# N64: ld $25, %call16(global_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_Mips_CALL16
+
+# O32-MICROMIPS: lw $25, %call16(global_label)($gp) # encoding: [0xff,0x3c,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# N32-MICROMIPS: lw $25, %call16(global_label)($gp) # encoding: [0xff,0x3c,A,A]
+# N32-MICROMIPS: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# N64-MICROMIPS: ld $25, %call16(global_label)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-MICROMIPS: # fixup A - offset: 0, value: global_label at GOT_CALL, kind: fixup_MICROMIPS_CALL16
+
+# NORMAL: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
+# MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
+# ALL: nop # encoding: [0x00,0x00,0x00,0x00]
+
+
+# FIXME: The .text section MCSymbol isn't created when printing assembly. However,
+# it is created when generating an ELF object file.
+# Expanding "jal .text":
+# O32-FIXME: lw $25, %got(.text)($gp) # encoding: [0x8f,0x99,A,A]
+# O32-FIXME: # fixup A - offset: 0, value: .text at GOT, kind: fixup_Mips_GOT_Local
+# O32-FIXME: addiu $25, $25, %lo(.text) # encoding: [0x27,0x39,A,A]
+# O32-FIXME: # fixup A - offset: 0, value: .text at ABS_LO, kind: fixup_Mips_LO16
+
+# N32-FIXME: lw $25, %got_disp(.text)($gp) # encoding: [0x8f,0x99,A,A]
+# N32-FIXME: # fixup A - offset: 0, value: .text at GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# N64-FIXME: ld $25, %got_disp(.text)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-FIXME: # fixup A - offset: 0, value: .text at GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# O32-MICROMIPS-FIXME: lw $25, %got(.text)($gp) # encoding: [0xff,0x3c,A,A]
+# O32-MICROMIPS-FIXME: # fixup A - offset: 0, value: .text at GOT, kind: fixup_MICROMIPS_GOT16
+# O32-MICROMIPS-FIXME: addiu $25, $25, %lo(.text) # encoding: [0x33,0x39,A,A]
+# O32-MICROMIPS-FIXME: # fixup A - offset: 0, value: .text at ABS_LO, kind: fixup_MICROMIPS_LO16
+
+# N32-MICROMIPS-FIXME: lw $25, %got_disp(.text)($gp) # encoding: [0xff,0x3c,A,A]
+# N32-MICROMIPS-FIXME: # fixup A - offset: 0, value: .text at GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# N64-MICROMIPS-FIXME: ld $25, %got_disp(.text)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-MICROMIPS-FIXME: # fixup A - offset: 0, value: .text at GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# NORMAL: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
+# MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
+# ALL: nop # encoding: [0x00,0x00,0x00,0x00]
+
+
+# Expanding "jal 1f":
+# O32: lw $25, %got($tmp0)($gp) # encoding: [0x8f,0x99,A,A]
+# O32: # fixup A - offset: 0, value: ($tmp0)@GOT, kind: fixup_Mips_GOT_Local
+# O32: addiu $25, $25, %lo($tmp0) # encoding: [0x27,0x39,A,A]
+# O32: # fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind: fixup_Mips_LO16
+
+# N32: lw $25, %got_disp($tmp0)($gp) # encoding: [0x8f,0x99,A,A]
+# N32: # fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# N64: ld $25, %got_disp($tmp0)($gp) # encoding: [0xdf,0x99,A,A]
+# N64: # fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_Mips_GOT_DISP
+
+# O32-MICROMIPS: lw $25, %got($tmp0)($gp) # encoding: [0xff,0x3c,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: ($tmp0)@GOT, kind: fixup_MICROMIPS_GOT16
+# O32-MICROMIPS: addiu $25, $25, %lo($tmp0) # encoding: [0x33,0x39,A,A]
+# O32-MICROMIPS: # fixup A - offset: 0, value: ($tmp0)@ABS_LO, kind: fixup_MICROMIPS_LO16
+
+# N32-MICROMIPS: lw $25, %got_disp($tmp0)($gp) # encoding: [0xff,0x3c,A,A]
+# N32-MICROMIPS: # fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# N64-MICROMIPS: ld $25, %got_disp($tmp0)($gp) # encoding: [0xdf,0x99,A,A]
+# N64-MICROMIPS: # fixup A - offset: 0, value: ($tmp0)@GOT_DISP, kind: fixup_MICROMIPS_GOT_DISP
+
+# NORMAL: jalr $25 # encoding: [0x03,0x20,0xf8,0x09]
+# MICROMIPS: jalr $ra, $25 # encoding: [0x03,0xf9,0x0f,0x3c]
+# ALL: nop # encoding: [0x00,0x00,0x00,0x00]
Modified: llvm/trunk/test/MC/Mips/set-nomacro.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Mips/set-nomacro.s?rev=245305&r1=245304&r2=245305&view=diff
==============================================================================
--- llvm/trunk/test/MC/Mips/set-nomacro.s (original)
+++ llvm/trunk/test/MC/Mips/set-nomacro.s Tue Aug 18 11:18:09 2015
@@ -67,6 +67,11 @@
ulw $8, 2($9)
ulw $8, 0x8000($9)
+ jal foo
+ .option pic2
+ jal foo
+ .option pic0
+
add $4, $5, $6
.set noreorder
@@ -187,5 +192,12 @@
ulw $8, 0x8000($9)
# CHECK: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+ jal foo
+# CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+ .option pic2
+ jal foo
+# CHECK: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
+ .option pic0
+
add $4, $5, $6
# CHECK-NOT: [[@LINE-1]]:3: warning: macro instruction expanded into multiple instructions
More information about the llvm-commits
mailing list