]> granicus.if.org Git - llvm/commitdiff
[ARM, Asm] Add diagnostics for floating-point register operands
authorOliver Stannard <oliver.stannard@arm.com>
Tue, 10 Oct 2017 12:35:09 +0000 (12:35 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Tue, 10 Oct 2017 12:35:09 +0000 (12:35 +0000)
This adds diagnostic strings for the ARM floating-point register
classes, which will be used when these classes are expected by the
assembler, but the provided operand is not valid.

One of these, DPR, requires C++ code to select the correct error
message, as that class contains different registers depending on the
FPU. The rest can all have their diagnostic strings stored in the
tablegen decription of them.

Differential revision: https://reviews.llvm.org/D36693

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315304 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMRegisterInfo.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/armv8.2a-dotprod-error.s
test/MC/ARM/d16.s
test/MC/ARM/invalid-fp-armv8.s
test/MC/ARM/invalid-neon-v8.s
test/MC/ARM/vmov-vmvn-illegal-cases.s
test/MC/ARM/vorr-vbic-illegal-cases.s

index 6e06cbb227e3c9f79c6da1cd8e5a6b1d548ec4f2..14526b777c70a85ebf1a69378769984a37f02a28 100644 (file)
@@ -304,11 +304,14 @@ def SPR : RegisterClass<"ARM", [f32], 32, (sequence "S%u", 0, 31)> {
   let AltOrderSelect = [{
     return 1 + MF.getSubtarget<ARMSubtarget>().useStride4VFPs(MF);
   }];
+  let DiagnosticString = "operand must be a register in range [s0, s31]";
 }
 
 // Subset of SPR which can be used as a source of NEON scalars for 16-bit
 // operations
-def SPR_8 : RegisterClass<"ARM", [f32], 32, (sequence "S%u", 0, 15)>;
+def SPR_8 : RegisterClass<"ARM", [f32], 32, (sequence "S%u", 0, 15)> {
+  let DiagnosticString = "operand must be a register in range [s0, s15]";
+}
 
 // Scalar double precision floating point / generic 64-bit vector register
 // class.
@@ -323,17 +326,22 @@ def DPR : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32, v4f16], 6
   let AltOrderSelect = [{
     return 1 + MF.getSubtarget<ARMSubtarget>().useStride4VFPs(MF);
   }];
+  let DiagnosticType = "DPR";
 }
 
 // Subset of DPR that are accessible with VFP2 (and so that also have
 // 32-bit SPR subregs).
 def DPR_VFP2 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32, v4f16], 64,
-                             (trunc DPR, 16)>;
+                             (trunc DPR, 16)> {
+  let DiagnosticString = "operand must be a register in range [d0, d15]";
+}
 
 // Subset of DPR which can be used as a source of NEON scalars for 16-bit
 // operations
 def DPR_8 : RegisterClass<"ARM", [f64, v8i8, v4i16, v2i32, v1i64, v2f32, v4f16], 64,
-                          (trunc DPR, 8)>;
+                          (trunc DPR, 8)> {
+  let DiagnosticString = "operand must be a register in range [d0, d7]";
+}
 
 // Generic 128-bit vector register class.
 def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64, v8f16], 128,
@@ -341,15 +349,20 @@ def QPR : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64, v8f16]
   // Allocate non-VFP2 aliases Q8-Q15 first.
   let AltOrders = [(rotl QPR, 8)];
   let AltOrderSelect = [{ return 1; }];
+  let DiagnosticString = "operand must be a register in range [q0, q15]";
 }
 
 // Subset of QPR that have 32-bit SPR subregs.
 def QPR_VFP2 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],
-                             128, (trunc QPR, 8)>;
+                             128, (trunc QPR, 8)> {
+  let DiagnosticString = "operand must be a register in range [q0, q7]";
+}
 
 // Subset of QPR that have DPR_8 and SPR_8 subregs.
 def QPR_8 : RegisterClass<"ARM", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],
-                           128, (trunc QPR, 4)>;
+                           128, (trunc QPR, 4)> {
+  let DiagnosticString = "operand must be a register in range [q0, q3]";
+}
 
 // Pseudo-registers representing odd-even pairs of D registers. The even-odd
 // pairs are already represented by the Q registers.
index facdf98aa4f5bdb9dc9d89c11a895159565b5634..f4089482e4a0258a6c939abd1271f315ebf16ef8 100644 (file)
@@ -10106,6 +10106,10 @@ ARMAsmParser::getCustomOperandDiag(ARMMatchResultTy MatchError) {
   case Match_rGPR:
     return hasV8Ops() ? "operand must be a register in range [r0, r14]"
                       : "operand must be a register in range [r0, r12] or r14";
+  // DPR contains 16 registers for some FPUs, and 32 for others.
+  case Match_DPR:
+    return hasD16() ? "operand must be a register in range [d0, d15]"
+                    : "operand must be a register in range [d0, d31]";
 
   // For all other diags, use the static string from tablegen.
   default:
index c8497c30a00afe7f3a1d16781c58a6a7a12288a5..1ef38df984fc7dd04a366e06e283adb0b05107bb 100644 (file)
@@ -28,9 +28,9 @@ vsdot.s8 q0, q1, d4[2]
 vudot.u8 q0, q1, d16[0]
 vsdot.s8 q0, q1, d16[0]
 
-// CHECK-ERROR: error: invalid operand for instruction
+// CHECK-ERROR: error: operand must be a register in range [d0, d15]
 // CHECK-ERROR: vudot.u8 q0, q1, d16[0]
 // CHECK-ERROR:                     ^
-// CHECK-ERROR: error: invalid operand for instruction
+// CHECK-ERROR: error: operand must be a register in range [d0, d15]
 // CHECK-ERROR: vsdot.s8 q0, q1, d16[0]
 // CHECK-ERROR:                     ^
index aa549a3d7ca1f4d682519b38658550c3498f4db3..648992e9a7b9021f2e917f15548d070244df786c 100644 (file)
@@ -3,22 +3,24 @@
 
 @ D32-NOT: error:
 
-@ D16: invalid operand for instruction
+@ D16: error: invalid instruction, any one of the following would fix this:
 @ D16-NEXT: vadd.f64 d1, d2, d16
+@ D16: note: operand must be a register in range [d0, d15]
+@ D16: note: too many operands for instruction
 vadd.f64 d1, d2, d16
 
-@ D16: invalid operand for instruction
+@ D16: error: operand must be a register in range [d0, d15]
 @ D16-NEXT: vadd.f64 d1, d17, d6
 vadd.f64 d1, d17, d6
 
-@ D16: invalid operand for instruction
+@ D16: error: operand must be a register in range [d0, d15]
 @ D16-NEXT: vadd.f64 d19, d7, d6
 vadd.f64 d19, d7, d6
 
-@ D16: invalid operand for instruction
+@ D16: error: operand must be a register in range [d0, d15]
 @ D16-NEXT: vcvt.f64.f32 d22, s4
 vcvt.f64.f32 d22, s4
 
-@ D16: invalid operand for instruction
+@ D16: error: operand must be a register in range [d0, d15]
 @ D16-NEXT: vcvt.f32.f64 s26, d30
 vcvt.f32.f64 s26, d30
index d295ffeb7f3d0d061a511b6a74129bef9230b71c..da952cf7ed67519c7ae3fd80c832ebb41ff02883 100644 (file)
@@ -57,22 +57,26 @@ vmaxnmgt.f64 q0, s3, q1
 vcvta.s32.f64 d3, s2
 @ V8: error: invalid instruction
 vcvtp.s32.f32 d3, s2
-@ V8: error: invalid operand for instruction
+@ V8: error: operand must be a register in range [s0, s31]
 vcvtn.u32.f64 d3, s2
 @ V8: error: invalid instruction
 vcvtm.u32.f32 d3, s2
-@ V8: error: invalid operand for instruction
+@ V8: error: operand must be a register in range [s0, s31]
 vcvtnge.u32.f64 d3, s2
 @ V8: error: instruction 'vcvtn' is not predicable, but condition code specified
 
 vcvtbgt.f64.f16 q0, d3
 @ V8: error: invalid instruction
 vcvttlt.f64.f16 s0, s3
+@ V8: error: invalid instruction, any one of the following would fix this:
+@ V8: note: operand must be a register in range [d0, d31]
 @ V8: note: invalid operand for instruction
 vcvttvs.f16.f64 s0, s3
+@ V8: error: invalid instruction, any one of the following would fix this:
+@ V8: note: operand must be a register in range [d0, d31]
 @ V8: note: invalid operand for instruction
 vcvtthi.f16.f64 q0, d3
-@ V8: error: invalid operand for instruction
+@ V8: error: operand must be a register in range [s0, s31]
 
 vrintrlo.f32.f32 d3, q0
 @ V8: error: invalid instruction
index fdff360abb210b12a4d9856ab81f87e09eb1fb5b..6403904c1d3e29e6903f262fccf76d1b19dd5860 100644 (file)
@@ -10,7 +10,7 @@ vmaxnmge.f64.f64 s4, d5, q1
 vcvta.s32.f32 s1, s2
 @ CHECK: error: instruction requires: FPARMv8
 vcvtp.u32.f32 s1, d2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [d0, d31]
 vcvtp.f32.u32 d1, q2
 @ CHECK: error: invalid instruction
 vcvtplo.f32.u32 s1, s2
@@ -20,47 +20,47 @@ vrinta.f64.f64 s3, d12
 @ CHECK: error: invalid instruction
 vrintn.f32 d3, q12
 @ CHECK: error: invalid instruction, any one of the following would fix this:
-@ CHECK: note: invalid operand for instruction
-@ CHECK: note: invalid operand for instruction
+@ CHECK: note: operand must be a register in range [d0, d31]
+@ CHECK: note: operand must be a register in range [q0, q15]
 vrintz.f32 d3, q12
 @ CHECK: error: invalid instruction, any one of the following would fix this:
-@ CHECK: note: invalid operand for instruction
-@ CHECK: note: invalid operand for instruction
+@ CHECK: note: operand must be a register in range [d0, d31]
+@ CHECK: note: operand must be a register in range [q0, q15]
 vrintmge.f32.f32 d3, d4
 @ CHECK: error: instruction 'vrintm' is not predicable, but condition code specified
 
 aesd.8  q0, s1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 aese.8  s0, q1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 aesimc.8  s0, q1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 aesmc.8  q0, d1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 aesdge.8 q0, q1
 @ CHECK: error: instruction 'aesd' is not predicable, but condition code specified
 
 sha1h.32  d0, q1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha1su1.32  q0, s1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha256su0.32  s0, q1
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha1heq.32  q0, q1
 @ CHECK: error: instruction 'sha1h' is not predicable, but condition code specified
 
 sha1c.32  s0, d1, q2
 @ CHECK: error: invalid instruction
 sha1m.32  q0, s1, q2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha1p.32  s0, q1, q2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha1su0.32  d0, q1, q2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha256h.32  q0, s1, q2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha256h2.32  q0, q1, s2
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 sha256su1.32  s0, d1, q2
 @ CHECK: error: invalid instruction
 sha256su1lt.32  q0, d1, q2
@@ -69,6 +69,6 @@ sha256su1lt.32  q0, d1, q2
 vmull.p64 q0, s1, s3
 @ CHECK: error: invalid instruction
 vmull.p64 s1, d2, d3
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: operand must be a register in range [q0, q15]
 vmullge.p64 q0, d16, d17
 @ CHECK: error: instruction 'vmull' is not predicable, but condition code specified
index 4609b7793551ad3435c3dc6910737c7ef5c3592b..d1938db76a0ab1cdb1ad201c9456896d88a13336 100644 (file)
@@ -1,23 +1,39 @@
 @ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s
 .text
 
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmov.i32        d2, #0xffffffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmov.i32        q2, #0xffffffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmov.i16        q2, #0xffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmov.i16        q2, #0xffab
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmov.i32        d2, #0xffffffab
+@ CHECK: note: operand must be a register in range [d0, d31]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmov.i32        q2, #0xffffffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmov.i16        q2, #0xffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmov.i16        q2, #0xffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmvn.i32        d2, #0xffffffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmvn.i32        q2, #0xffffffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmvn.i16        q2, #0xffab
-@ CHECK: error: invalid operand for instruction
-@ CHECK: vmvn.i16        q2, #0xffab
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmvn.i32        d2, #0xffffffab
+@ CHECK: note: operand must be a register in range [d0, d31]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmvn.i32        q2, #0xffffffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmvn.i16        q2, #0xffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK-NEXT: vmvn.i16        q2, #0xffab
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 
         vmov.i32        d2, #0xffffffab
         vmov.i32        q2, #0xffffffab
index 673098ad5a07a905be33bea928736658ea03eb54..ba5ee085d164479765e83f93547471e379caca77 100644 (file)
@@ -8,17 +8,29 @@
         vorr.i16        q2, #0xabab
         vorr.i16        q2, #0xabab
 
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: operand must be a register in range [d0, d31]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i32        d2, #0xffffffff
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i32        q2, #0xffffffff
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: operand must be a register in range [d0, d31]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i32        d2, #0xabababab
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i32        q2, #0xabababab
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i16        q2, #0xabab
-@ CHECK: error: invalid operand for instruction
+@ CHECK: error: invalid instruction, any one of the following would fix this:
+@ CHECK: note: operand must be a register in range [q0, q15]
+@ CHECK: note: invalid operand for instruction
 @ CHECK: vorr.i16        q2, #0xabab
 
         vbic.i32        d2, #0xffffffff