[llvm] r342629 - [RISCV][MC] Improve parsing of jal/j operands

Alex Bradbury via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 20 01:10:35 PDT 2018


Author: asb
Date: Thu Sep 20 01:10:35 2018
New Revision: 342629

URL: http://llvm.org/viewvc/llvm-project?rev=342629&view=rev
Log:
[RISCV][MC] Improve parsing of jal/j operands

Examples such as `jal a3`, `j a3` and `jal a3, a3` are accepted by gas 
but rejected by LLVM MC. This patch rectifies this. I introduce 
RISCVAsmParser::parseJALOffset to ensure that symbol names that coincide with 
register names can safely be parsed. This is made a somewhat fiddly due to the 
single-operand alias form (see the comment in parseJALOffset for more info).

Differential Revision: https://reviews.llvm.org/D52029

Modified:
    llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
    llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
    llvm/trunk/test/MC/RISCV/rv32i-invalid.s
    llvm/trunk/test/MC/RISCV/rv32i-valid.s
    llvm/trunk/test/MC/RISCV/rvi-aliases-valid.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=342629&r1=342628&r2=342629&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp Thu Sep 20 01:10:35 2018
@@ -92,6 +92,7 @@ class RISCVAsmParser : public MCTargetAs
   OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands);
   OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands);
   OperandMatchResultTy parseBareSymbol(OperandVector &Operands);
+  OperandMatchResultTy parseJALOffset(OperandVector &Operands);
 
   bool parseOperand(OperandVector &Operands, StringRef Mnemonic);
 
@@ -476,7 +477,7 @@ public:
     }
   }
 
-  bool isSImm21Lsb0() const { return isBareSimmNLsb0<21>(); }
+  bool isSImm21Lsb0JAL() const { return isBareSimmNLsb0<21>(); }
 
   /// getStartLoc - Gets location of the first token of this operand
   SMLoc getStartLoc() const override { return StartLoc; }
@@ -809,7 +810,7 @@ bool RISCVAsmParser::MatchAndEmitInstruc
         Operands, ErrorInfo, 0, (1 << 20) - 1,
         "operand must be a symbol with %pcrel_hi() modifier or an integer in "
         "the range");
-  case Match_InvalidSImm21Lsb0:
+  case Match_InvalidSImm21Lsb0JAL:
     return generateImmOutOfRangeError(
         Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
         "immediate must be a multiple of 2 bytes in the range");
@@ -985,6 +986,23 @@ OperandMatchResultTy RISCVAsmParser::par
   return MatchOperand_Success;
 }
 
+OperandMatchResultTy RISCVAsmParser::parseJALOffset(OperandVector &Operands) {
+  // Parsing jal operands is fiddly due to the `jal foo` and `jal ra, foo`
+  // both being acceptable forms. When parsing `jal ra, foo` this function
+  // will be called for the `ra` register operand in an attempt to match the
+  // single-operand alias. parseJALOffset must fail for this case. It would
+  // seem logical to try parse the operand using parseImmediate and return
+  // NoMatch if the next token is a comma (meaning we must be parsing a jal in
+  // the second form rather than the first). We can't do this as there's no
+  // way of rewinding the lexer state. Instead, return NoMatch if this operand
+  // is an identifier and is followed by a comma.
+  if (getLexer().is(AsmToken::Identifier) &&
+      getLexer().peekTok().is(AsmToken::Comma))
+    return MatchOperand_NoMatch;
+
+  return parseImmediate(Operands);
+}
+
 OperandMatchResultTy
 RISCVAsmParser::parseMemOpBaseReg(OperandVector &Operands) {
   if (getLexer().isNot(AsmToken::LParen)) {

Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td?rev=342629&r1=342628&r2=342629&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.td Thu Sep 20 01:10:35 2018
@@ -161,9 +161,13 @@ def uimm20_auipc : UImm20Operand {
   let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
 }
 
+def Simm21Lsb0JALAsmOperand : SImmAsmOperand<21, "Lsb0JAL"> {
+  let ParserMethod = "parseJALOffset";
+}
+
 // A 21-bit signed immediate where the least significant bit is zero.
-def simm21_lsb0 : Operand<OtherVT> {
-  let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
+def simm21_lsb0_jal : Operand<OtherVT> {
+  let ParserMatchClass = Simm21Lsb0JALAsmOperand;
   let EncoderMethod = "getImmOpValueAsr1";
   let DecoderMethod = "decodeSImmOperandAndLsl1<21>";
   let MCOperandPredicate = [{
@@ -296,7 +300,7 @@ def AUIPC : RVInstU<OPC_AUIPC, (outs GPR
                     "auipc", "$rd, $imm20">;
 
 let isCall = 1 in
-def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0:$imm20),
+def JAL : RVInstJ<OPC_JAL, (outs GPR:$rd), (ins simm21_lsb0_jal:$imm20),
                   "jal", "$rd, $imm20">;
 
 let isCall = 1 in
@@ -520,8 +524,8 @@ def : InstAlias<"bleu $rs, $rt, $offset"
                 (BGEU GPR:$rt, GPR:$rs, simm13_lsb0:$offset), 0>;
 
 // "ret" has more weight since "ret" and "jr" alias the same "jalr" instruction.
-def : InstAlias<"j $offset",   (JAL  X0, simm21_lsb0:$offset)>;
-def : InstAlias<"jal $offset", (JAL  X1, simm21_lsb0:$offset)>;
+def : InstAlias<"j $offset",   (JAL  X0, simm21_lsb0_jal:$offset)>;
+def : InstAlias<"jal $offset", (JAL  X1, simm21_lsb0_jal:$offset)>;
 def : InstAlias<"jr $rs",      (JALR X0, GPR:$rs, 0)>;
 def : InstAlias<"jalr $rs",    (JALR X1, GPR:$rs, 0)>;
 def : InstAlias<"ret",         (JALR X0,      X1, 0), 2>;
@@ -707,8 +711,8 @@ def : BccSwapPat<setule, BGEU>;
 def : Pat<(brcond GPR:$cond, bb:$imm12), (BNE GPR:$cond, X0, bb:$imm12)>;
 
 let isBarrier = 1, isBranch = 1, isTerminator = 1 in
-def PseudoBR : Pseudo<(outs), (ins simm21_lsb0:$imm20), [(br bb:$imm20)]>,
-               PseudoInstExpansion<(JAL X0, simm21_lsb0:$imm20)>;
+def PseudoBR : Pseudo<(outs), (ins simm21_lsb0_jal:$imm20), [(br bb:$imm20)]>,
+               PseudoInstExpansion<(JAL X0, simm21_lsb0_jal:$imm20)>;
 
 let isCall = 1, Defs=[X1] in
 let isBarrier = 1, isBranch = 1, isIndirectBranch = 1, isTerminator = 1 in

Modified: llvm/trunk/test/MC/RISCV/rv32i-invalid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rv32i-invalid.s?rev=342629&r1=342628&r2=342629&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/rv32i-invalid.s (original)
+++ llvm/trunk/test/MC/RISCV/rv32i-invalid.s Thu Sep 20 01:10:35 2018
@@ -152,8 +152,6 @@ lw a4, a5, 111 # CHECK: :[[@LINE]]:8: er
 # Too few operands
 ori a0, a1 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
 xor s2, s2 # CHECK: :[[@LINE]]:1: error: too few operands for instruction
-# FIXME: Fix jal behavior to interpret a3 as a symbol rather than a register.
-jal a3     # CHECK: :[[@LINE]]:1: error: too few operands for instruction
 
 # Instruction not in the base ISA
 mul a4, ra, s0 # CHECK: :[[@LINE]]:1: error: instruction use requires an option to be enabled

Modified: llvm/trunk/test/MC/RISCV/rv32i-valid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rv32i-valid.s?rev=342629&r1=342628&r2=342629&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/rv32i-valid.s (original)
+++ llvm/trunk/test/MC/RISCV/rv32i-valid.s Thu Sep 20 01:10:35 2018
@@ -60,6 +60,16 @@ jal a2, 1048574
 # CHECK-ASM-AND-OBJ: jal a3, 256
 # CHECK-ASM: encoding: [0xef,0x06,0x00,0x10]
 jal a3, 256
+# CHECK-ASM: jal a0, foo
+# CHECK-ASM: encoding: [0x6f,0bAAAA0101,A,A]
+# CHECK-OBJ: jal a0, 0
+# CHECK-OBJ: R_RISCV_JAL foo
+jal a0, foo
+# CHECK-ASM: jal a0, a0
+# CHECK-ASM: encoding: [0x6f,0bAAAA0101,A,A]
+# CHECK-OBJ: jal a0, 0
+# CHECK-OBJ: R_RISCV_JAL a0
+jal a0, a0
 
 # CHECK-ASM-AND-OBJ: jalr a0, a1, -2048
 # CHECK-ASM: encoding: [0x67,0x85,0x05,0x80]

Modified: llvm/trunk/test/MC/RISCV/rvi-aliases-valid.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/RISCV/rvi-aliases-valid.s?rev=342629&r1=342628&r2=342629&view=diff
==============================================================================
--- llvm/trunk/test/MC/RISCV/rvi-aliases-valid.s (original)
+++ llvm/trunk/test/MC/RISCV/rvi-aliases-valid.s Thu Sep 20 01:10:35 2018
@@ -7,16 +7,16 @@
 # RUN: llvm-mc %s -triple=riscv64 \
 # RUN:     | FileCheck -check-prefixes=CHECK-S,CHECK-S-OBJ %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
-# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | llvm-objdump -d -r -riscv-no-aliases - \
 # RUN:     | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-S-OBJ-NOALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv32 < %s \
-# RUN:     | llvm-objdump -d - \
+# RUN:     | llvm-objdump -d -r - \
 # RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-S-OBJ %s
 # RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
-# RUN:     | llvm-objdump -d -riscv-no-aliases - \
+# RUN:     | llvm-objdump -d -r -riscv-no-aliases - \
 # RUN:     | FileCheck -check-prefixes=CHECK-OBJ-NOALIAS,CHECK-S-OBJ-NOALIAS %s
 # RUN: llvm-mc -filetype=obj -triple riscv64 < %s \
-# RUN:     | llvm-objdump -d - \
+# RUN:     | llvm-objdump -d -r - \
 # RUN:     | FileCheck -check-prefixes=CHECK-OBJ,CHECK-S-OBJ %s
 
 # The following check prefixes are used in this test:
@@ -105,9 +105,33 @@ bleu x18, x19, 32
 # CHECK-S-OBJ-NOALIAS: jal zero, 2044
 # CHECK-S-OBJ: j 2044
 j 2044
+# CHECK-S-NOALIAS: jal zero, foo
+# CHECK-S: j foo
+# CHECK-OBJ-NOALIAS: jal zero, 0
+# CHECK-OBJ: j 0
+# CHECK-OBJ: R_RISCV_JAL foo
+j foo
+# CHECK-S-NOALIAS: jal zero, a0
+# CHECK-S: j a0
+# CHECK-OBJ-NOALIAS: jal zero, 0
+# CHECK-OBJ: j 0
+# CHECK-OBJ: R_RISCV_JAL a0
+j a0
 # CHECK-S-OBJ-NOALIAS: jal ra, 2040
 # CHECK-S-OBJ: jal 2040
 jal 2040
+# CHECK-S-NOALIAS: jal ra, foo
+# CHECK-S: jal foo
+# CHECK-OBJ-NOALIAS: jal ra, 0
+# CHECK-OBJ: jal 0
+# CHECK-OBJ: R_RISCV_JAL foo
+jal foo
+# CHECK-S-NOALIAS: jal ra, a0
+# CHECK-S: jal a0
+# CHECK-OBJ-NOALIAS: jal ra, 0
+# CHECK-OBJ: jal 0
+# CHECK-OBJ: R_RISCV_JAL a0
+jal a0
 # CHECK-S-OBJ-NOALIAS: jalr zero, s4, 0
 # CHECK-S-OBJ: jr s4
 jr x20




More information about the llvm-commits mailing list