[llvm] r354111 - [RISCV] Add assembler support for LA pseudo-instruction
Alex Bradbury via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 15 01:53:32 PST 2019
Author: asb
Date: Fri Feb 15 01:53:32 2019
New Revision: 354111
URL: http://llvm.org/viewvc/llvm-project?rev=354111&view=rev
Log:
[RISCV] Add assembler support for LA pseudo-instruction
This patch also introduces the emitAuipcInstPair helper, which is then used
for both emitLoadAddress and emitLoadLocalAddress.
Differential Revision: https://reviews.llvm.org/D55325
Patch by James Clarke.
Added:
llvm/trunk/test/MC/RISCV/rvi-pseudos-invalid.s
Modified:
llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
llvm/trunk/test/MC/RISCV/rvi-pseudos.s
Modified: llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp?rev=354111&r1=354110&r2=354111&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp Fri Feb 15 01:53:32 2019
@@ -20,6 +20,7 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
+#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
@@ -78,9 +79,18 @@ class RISCVAsmParser : public MCTargetAs
// synthesize the desired immedate value into the destination register.
void emitLoadImm(unsigned DestReg, int64_t Value, MCStreamer &Out);
+ // Helper to emit a combination of AUIPC and SecondOpcode. Used to implement
+ // helpers such as emitLoadLocalAddress and emitLoadAddress.
+ void emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
+ const MCExpr *Symbol, RISCVMCExpr::VariantKind VKHi,
+ unsigned SecondOpcode, SMLoc IDLoc, MCStreamer &Out);
+
// Helper to emit pseudo instruction "lla" used in PC-rel addressing.
void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
+ void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+
/// Helper for processing MC instructions that have been successfully matched
/// by MatchAndEmitInstruction. Modifications to the emitted instructions,
/// like the expansion of pseudo instructions (e.g., "li"), can be performed
@@ -1409,42 +1419,82 @@ void RISCVAsmParser::emitLoadImm(unsigne
}
}
-void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
- MCStreamer &Out) {
- // The local load address pseudo-instruction "lla" is used in PC-relative
- // addressing of symbols:
- // lla rdest, symbol
- // expands to
- // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
- // ADDI rdest, %pcrel_lo(TmpLabel)
+void RISCVAsmParser::emitAuipcInstPair(MCOperand DestReg, MCOperand TmpReg,
+ const MCExpr *Symbol,
+ RISCVMCExpr::VariantKind VKHi,
+ unsigned SecondOpcode, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // A pair of instructions for PC-relative addressing; expands to
+ // TmpLabel: AUIPC TmpReg, VKHi(symbol)
+ // OP DestReg, TmpReg, %pcrel_lo(TmpLabel)
MCContext &Ctx = getContext();
MCSymbol *TmpLabel = Ctx.createTempSymbol(
"pcrel_hi", /* AlwaysAddSuffix */ true, /* CanBeUnnamed */ false);
Out.EmitLabel(TmpLabel);
- MCOperand DestReg = Inst.getOperand(0);
- const RISCVMCExpr *Symbol = RISCVMCExpr::create(
- Inst.getOperand(1).getExpr(), RISCVMCExpr::VK_RISCV_PCREL_HI, Ctx);
-
+ const RISCVMCExpr *SymbolHi = RISCVMCExpr::create(Symbol, VKHi, Ctx);
emitToStreamer(
- Out, MCInstBuilder(RISCV::AUIPC).addOperand(DestReg).addExpr(Symbol));
+ Out, MCInstBuilder(RISCV::AUIPC).addOperand(TmpReg).addExpr(SymbolHi));
const MCExpr *RefToLinkTmpLabel =
RISCVMCExpr::create(MCSymbolRefExpr::create(TmpLabel, Ctx),
RISCVMCExpr::VK_RISCV_PCREL_LO, Ctx);
- emitToStreamer(Out, MCInstBuilder(RISCV::ADDI)
- .addOperand(DestReg)
+ emitToStreamer(Out, MCInstBuilder(SecondOpcode)
.addOperand(DestReg)
+ .addOperand(TmpReg)
.addExpr(RefToLinkTmpLabel));
}
+void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // The load local address pseudo-instruction "lla" is used in PC-relative
+ // addressing of local symbols:
+ // lla rdest, symbol
+ // expands to
+ // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
+ // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
+ MCOperand DestReg = Inst.getOperand(0);
+ const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+ emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
+ RISCV::ADDI, IDLoc, Out);
+}
+
+void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out) {
+ // The load address pseudo-instruction "la" is used in PC-relative and
+ // GOT-indirect addressing of global symbols:
+ // la rdest, symbol
+ // expands to either (for non-PIC)
+ // TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
+ // ADDI rdest, rdest, %pcrel_lo(TmpLabel)
+ // or (for PIC)
+ // TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
+ // Lx rdest, %pcrel_lo(TmpLabel)(rdest)
+ MCOperand DestReg = Inst.getOperand(0);
+ const MCExpr *Symbol = Inst.getOperand(1).getExpr();
+ unsigned SecondOpcode;
+ RISCVMCExpr::VariantKind VKHi;
+ // FIXME: Should check .option (no)pic when implemented
+ if (getContext().getObjectFileInfo()->isPositionIndependent()) {
+ SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
+ VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
+ } else {
+ SecondOpcode = RISCV::ADDI;
+ VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
+ }
+ emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
+}
+
bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
Inst.setLoc(IDLoc);
- if (Inst.getOpcode() == RISCV::PseudoLI) {
+ switch (Inst.getOpcode()) {
+ default:
+ break;
+ case RISCV::PseudoLI: {
unsigned Reg = Inst.getOperand(0).getReg();
const MCOperand &Op1 = Inst.getOperand(1);
if (Op1.isExpr()) {
@@ -1464,9 +1514,13 @@ bool RISCVAsmParser::processInstruction(
Imm = SignExtend64<32>(Imm);
emitLoadImm(Reg, Imm, Out);
return false;
- } else if (Inst.getOpcode() == RISCV::PseudoLLA) {
+ }
+ case RISCV::PseudoLLA:
emitLoadLocalAddress(Inst, IDLoc, Out);
return false;
+ case RISCV::PseudoLA:
+ emitLoadAddress(Inst, IDLoc, Out);
+ return false;
}
emitToStreamer(Out, Inst);
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=354111&r1=354110&r2=354111&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Fri Feb 15 01:53:32 2019
@@ -497,7 +497,6 @@ def SFENCE_VMA : RVInstR<0b0001001, 0b00
// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
//===----------------------------------------------------------------------===//
-// TODO la
// TODO lb lh lw
// TODO RV64I: ld
// TODO sb sh sw
@@ -845,6 +844,11 @@ let hasSideEffects = 0, mayLoad = 0, may
def PseudoLLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
"lla", "$dst, $src">;
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
+ isAsmParserOnly = 1 in
+def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
+ "la", "$dst, $src">;
+
/// Loads
multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
Added: llvm/trunk/test/MC/RISCV/rvi-pseudos-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rvi-pseudos-invalid.s?rev=354111&view=auto
==============================================================================
--- llvm/trunk/test/MC/RISCV/rvi-pseudos-invalid.s (added)
+++ llvm/trunk/test/MC/RISCV/rvi-pseudos-invalid.s Fri Feb 15 01:53:32 2019
@@ -0,0 +1,22 @@
+# RUN: not llvm-mc %s -triple=riscv64 2>&1 | FileCheck %s
+# RUN: not llvm-mc %s -triple=riscv64 2>&1 | FileCheck %s
+
+lla x1, 1234 # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+lla x1, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
+
+la x1, 1234 # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %pcrel_hi(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %pcrel_lo(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %hi(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %hi(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
+la x1, %lo(foo) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
Modified: llvm/trunk/test/MC/RISCV/rvi-pseudos.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rvi-pseudos.s?rev=354111&r1=354110&r2=354111&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/rvi-pseudos.s (original)
+++ llvm/trunk/test/MC/RISCV/rvi-pseudos.s Fri Feb 15 01:53:32 2019
@@ -1,5 +1,9 @@
-# RUN: llvm-mc %s -triple=riscv32 | FileCheck %s
-# RUN: llvm-mc %s -triple=riscv64 | FileCheck %s
+# RUN: llvm-mc %s -triple=riscv32 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC
+# RUN: llvm-mc %s -triple=riscv64 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC
+# RUN: llvm-mc %s -triple=riscv32 -position-independent \
+# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV32
+# RUN: llvm-mc %s -triple=riscv64 -position-independent \
+# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV64
# CHECK: .Lpcrel_hi0:
# CHECK: auipc a0, %pcrel_hi(a_symbol)
@@ -26,3 +30,44 @@ lla a3, ra
# CHECK: auipc a4, %pcrel_hi(f1)
# CHECK: addi a4, a4, %pcrel_lo(.Lpcrel_hi4)
lla a4, f1
+
+# CHECK: .Lpcrel_hi5:
+# CHECK-NOPIC: auipc a0, %pcrel_hi(a_symbol)
+# CHECK-NOPIC: addi a0, a0, %pcrel_lo(.Lpcrel_hi5)
+# CHECK-PIC: auipc a0, %got_pcrel_hi(a_symbol)
+# CHECK-PIC-RV32: lw a0, %pcrel_lo(.Lpcrel_hi5)(a0)
+# CHECK-PIC-RV64: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0)
+la a0, a_symbol
+
+# CHECK: .Lpcrel_hi6:
+# CHECK-NOPIC: auipc a1, %pcrel_hi(another_symbol)
+# CHECK-NOPIC: addi a1, a1, %pcrel_lo(.Lpcrel_hi6)
+# CHECK-PIC: auipc a1, %got_pcrel_hi(another_symbol)
+# CHECK-PIC-RV32: lw a1, %pcrel_lo(.Lpcrel_hi6)(a1)
+# CHECK-PIC-RV64: ld a1, %pcrel_lo(.Lpcrel_hi6)(a1)
+la a1, another_symbol
+
+# Check that we can load the address of symbols that are spelled like a register
+# CHECK: .Lpcrel_hi7:
+# CHECK-NOPIC: auipc a2, %pcrel_hi(zero)
+# CHECK-NOPIC: addi a2, a2, %pcrel_lo(.Lpcrel_hi7)
+# CHECK-PIC: auipc a2, %got_pcrel_hi(zero)
+# CHECK-PIC-RV32: lw a2, %pcrel_lo(.Lpcrel_hi7)(a2)
+# CHECK-PIC-RV64: ld a2, %pcrel_lo(.Lpcrel_hi7)(a2)
+la a2, zero
+
+# CHECK: .Lpcrel_hi8:
+# CHECK-NOPIC: auipc a3, %pcrel_hi(ra)
+# CHECK-NOPIC: addi a3, a3, %pcrel_lo(.Lpcrel_hi8)
+# CHECK-PIC: auipc a3, %got_pcrel_hi(ra)
+# CHECK-PIC-RV32: lw a3, %pcrel_lo(.Lpcrel_hi8)(a3)
+# CHECK-PIC-RV64: ld a3, %pcrel_lo(.Lpcrel_hi8)(a3)
+la a3, ra
+
+# CHECK: .Lpcrel_hi9:
+# CHECK-NOPIC: auipc a4, %pcrel_hi(f1)
+# CHECK-NOPIC: addi a4, a4, %pcrel_lo(.Lpcrel_hi9)
+# CHECK-PIC: auipc a4, %got_pcrel_hi(f1)
+# CHECK-PIC-RV32: lw a4, %pcrel_lo(.Lpcrel_hi9)(a4)
+# CHECK-PIC-RV64: ld a4, %pcrel_lo(.Lpcrel_hi9)(a4)
+la a4, f1
More information about the llvm-commits
mailing list