summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2018-09-18 15:08:35 +0000
committerAlex Bradbury <asb@lowrisc.org>2018-09-18 15:08:35 +0000
commit74340f1805443cdc356c8fd7c8e4a25eb396b2b4 (patch)
treea359057ef6d3663730de6122d7f6d15d46c66942 /llvm
parentd4ed32c52673337cabc2a0e9b62513d91d24f379 (diff)
downloadbcm5719-llvm-74340f1805443cdc356c8fd7c8e4a25eb396b2b4.tar.gz
bcm5719-llvm-74340f1805443cdc356c8fd7c8e4a25eb396b2b4.zip
[RISCV][MC] Tighten up checking of sybol operands to lui and auipc
Reject bare symbols and accept only %pcrel_hi(sym) for auipc and %hi(sym) for lui. Also test valid operand modifiers in rv32i-valid.s. Note this is slightly stricter than gas, which will accept either %pcrel_hi or %hi for both lui and auipc. Differential Revision: https://reviews.llvm.org/D51731 llvm-svn: 342486
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp41
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td14
-rw-r--r--llvm/test/MC/RISCV/rv32i-invalid.s23
-rw-r--r--llvm/test/MC/RISCV/rv32i-valid.s10
4 files changed, 70 insertions, 18 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 7b010f54b0b..f54d4a58627 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -443,20 +443,36 @@ public:
VK == RISCVMCExpr::VK_RISCV_None;
}
- bool isUImm20() const {
+ bool isUImm20LUI() const {
RISCVMCExpr::VariantKind VK;
int64_t Imm;
bool IsValid;
if (!isImm())
return false;
bool IsConstantImm = evaluateConstantImm(Imm, VK);
- if (!IsConstantImm)
+ if (!IsConstantImm) {
IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
- else
- IsValid = isUInt<20>(Imm);
- return IsValid && (VK == RISCVMCExpr::VK_RISCV_None ||
- VK == RISCVMCExpr::VK_RISCV_HI ||
- VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
+ return IsValid && VK == RISCVMCExpr::VK_RISCV_HI;
+ } else {
+ return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
+ VK == RISCVMCExpr::VK_RISCV_HI);
+ }
+ }
+
+ bool isUImm20AUIPC() const {
+ RISCVMCExpr::VariantKind VK;
+ int64_t Imm;
+ bool IsValid;
+ if (!isImm())
+ return false;
+ bool IsConstantImm = evaluateConstantImm(Imm, VK);
+ if (!IsConstantImm) {
+ IsValid = RISCVAsmParser::classifySymbolRef(getImm(), VK, Imm);
+ return IsValid && VK == RISCVMCExpr::VK_RISCV_PCREL_HI;
+ } else {
+ return isUInt<20>(Imm) && (VK == RISCVMCExpr::VK_RISCV_None ||
+ VK == RISCVMCExpr::VK_RISCV_PCREL_HI);
+ }
}
bool isSImm21Lsb0() const { return isBareSimmNLsb0<21>(); }
@@ -781,8 +797,15 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 12), (1 << 12) - 2,
"immediate must be a multiple of 2 bytes in the range");
- case Match_InvalidUImm20:
- return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1);
+ case Match_InvalidUImm20LUI:
+ return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 20) - 1,
+ "operand must be a symbol with %hi() "
+ "modifier or an integer in the range");
+ case Match_InvalidUImm20AUIPC:
+ return generateImmOutOfRangeError(
+ Operands, ErrorInfo, 0, (1 << 20) - 1,
+ "operand must be a symbol with %pcrel_hi() modifier or an integer in "
+ "the range");
case Match_InvalidSImm21Lsb0:
return generateImmOutOfRangeError(
Operands, ErrorInfo, -(1 << 20), (1 << 20) - 2,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 1dc60737a16..dca5759bf53 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -143,8 +143,7 @@ def simm13_lsb0 : Operand<OtherVT> {
}];
}
-def uimm20 : Operand<XLenVT> {
- let ParserMatchClass = UImmAsmOperand<20>;
+class UImm20Operand : Operand<XLenVT> {
let EncoderMethod = "getImmOpValue";
let DecoderMethod = "decodeUImmOperand<20>";
let MCOperandPredicate = [{
@@ -155,6 +154,13 @@ def uimm20 : Operand<XLenVT> {
}];
}
+def uimm20_lui : UImm20Operand {
+ let ParserMatchClass = UImmAsmOperand<20, "LUI">;
+}
+def uimm20_auipc : UImm20Operand {
+ let ParserMatchClass = UImmAsmOperand<20, "AUIPC">;
+}
+
// A 21-bit signed immediate where the least significant bit is zero.
def simm21_lsb0 : Operand<OtherVT> {
let ParserMatchClass = SImmAsmOperand<21, "Lsb0">;
@@ -285,10 +291,10 @@ class Priv<string opcodestr, bits<7> funct7>
//===----------------------------------------------------------------------===//
let hasSideEffects = 0, isReMaterializable = 1, mayLoad = 0, mayStore = 0 in {
-def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20:$imm20),
+def LUI : RVInstU<OPC_LUI, (outs GPR:$rd), (ins uimm20_lui:$imm20),
"lui", "$rd, $imm20">;
-def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20:$imm20),
+def AUIPC : RVInstU<OPC_AUIPC, (outs GPR:$rd), (ins uimm20_auipc:$imm20),
"auipc", "$rd, $imm20">;
let isCall = 1 in
diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s
index f78680602be..2128efeb56d 100644
--- a/llvm/test/MC/RISCV/rv32i-invalid.s
+++ b/llvm/test/MC/RISCV/rv32i-invalid.s
@@ -37,9 +37,9 @@ bltu t0, t1, 13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2
bgeu t0, t1, -13 # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
## uimm20
-lui a0, -1 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575]
-lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575]
-auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 1048575]
+lui a0, -1 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+lui s0, 1048576 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+auipc zero, -0xf # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
## simm21_lsb0
jal gp, -1048578 # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
@@ -92,8 +92,8 @@ bltu t0, t1, %pcrel_lo(4) # CHECK: :[[@LINE]]:14: error: immediate must be a mul
bgeu t0, t1, %pcrel_lo(d) # CHECK: :[[@LINE]]:14: error: immediate must be a multiple of 2 bytes in the range [-4096, 4094]
## uimm20
-lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 1048575]
-auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: immediate must be an integer in the range [0, 1048575]
+lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+auipc a1, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
## simm21_lsb0
jal gp, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
@@ -105,6 +105,19 @@ jal gp, %pcrel_hi(c) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple
jal gp, %pcrel_lo(4) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
jal gp, %pcrel_lo(d) # CHECK: :[[@LINE]]:9: error: immediate must be a multiple of 2 bytes in the range [-1048576, 1048574]
+# Bare symbol names when an operand modifier is required and unsupported
+# operand modifiers.
+
+lui a0, foo # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+lui a0, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+lui a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+lui a0, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi() modifier or an integer in the range [0, 1048575]
+
+auipc a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc a0, %lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc a0, %hi(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+auipc a0, %pcrel_lo(foo) # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %pcrel_hi() modifier or an integer in the range [0, 1048575]
+
# Unrecognized operand modifier
addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier
diff --git a/llvm/test/MC/RISCV/rv32i-valid.s b/llvm/test/MC/RISCV/rv32i-valid.s
index c446c881b45..03add916aaf 100644
--- a/llvm/test/MC/RISCV/rv32i-valid.s
+++ b/llvm/test/MC/RISCV/rv32i-valid.s
@@ -30,6 +30,11 @@ lui t0, 1048575
# CHECK-ASM-AND-OBJ: lui gp, 0
# CHECK-ASM: encoding: [0xb7,0x01,0x00,0x00]
lui gp, 0
+# CHECK-ASM: lui a0, %hi(foo)
+# CHECK-ASM: encoding: [0x37,0bAAAA0101,A,A]
+# CHECK-OBJ: lui a0, 0
+# CHECK-OBJ: R_RISCV_HI20 foo
+lui a0, %hi(foo)
# CHECK-ASM-AND-OBJ: auipc a0, 2
# CHECK-ASM: encoding: [0x17,0x25,0x00,0x00]
@@ -43,6 +48,11 @@ auipc t0, 1048575
# CHECK-ASM-AND-OBJ: auipc gp, 0
# CHECK-ASM: encoding: [0x97,0x01,0x00,0x00]
auipc gp, 0
+# CHECK-ASM: auipc a0, %pcrel_hi(foo)
+# CHECK-ASM: encoding: [0x17,0bAAAA0101,A,A]
+# CHECK-OBJ: auipc a0, 0
+# CHECK-OBJ: R_RISCV_PCREL_HI20 foo
+auipc a0, %pcrel_hi(foo)
# CHECK-ASM-AND-OBJ: jal a2, 1048574
# CHECK-ASM: encoding: [0x6f,0xf6,0xff,0x7f]
OpenPOWER on IntegriCloud