[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