[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