Skip to content

Commit

Permalink
[Asm, ARM] Add fallback diag for multiple invalid operands
Browse files Browse the repository at this point in the history
This adds a "invalid operands for instruction" diagnostic for
instructions where there is an instruction encoding with the correct
mnemonic and which is available for this target, but where multiple
operands do not match those which were provided. This makes it clear
that there is some combination of operands that is valid for the current
target, which the default diagnostic of "invalid instruction" does not.

Since this is a very general error, we only emit it if we don't have a
more specific error.

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



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319649 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
ostannard committed Dec 4, 2017
1 parent 62f11d9 commit a53a7f0
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 67 deletions.
27 changes: 21 additions & 6 deletions include/llvm/MC/MCParser/MCTargetAsmParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class NearMissInfo {
enum NearMissKind {
NoNearMiss,
NearMissOperand,
NearMissMultipleOperands,
NearMissFeature,
NearMissPredicate,
NearMissTooFewOperands,
Expand Down Expand Up @@ -189,6 +190,13 @@ class NearMissInfo {
return Result;
}

static NearMissInfo getMissedMultipleOperands(unsigned Opcode) {
NearMissInfo Result;
Result.Kind = NearMissMultipleOperands;
Result.MissedOperand.Opcode = Opcode;
return Result;
}

// The instruction encoding is not valid because it expects more operands
// than were parsed. OperandClass is the class of the expected operand that
// was not provided. Opcode is the instruction encoding.
Expand All @@ -208,34 +216,41 @@ class NearMissInfo {
// Feature flags required by the instruction, that the current target does
// not have.
uint64_t getFeatures() const {
assert(Kind == NearMissFeature);
assert(Kind == NearMissFeature &&
"near-miss does not have an associated target feature");
return Features;
}
// Error code returned by the target predicate when validating this
// instruction encoding.
unsigned getPredicateError() const {
assert(Kind == NearMissPredicate);
assert(Kind == NearMissPredicate &&
"near-miss does not have an associated predicate error");
return PredicateError;
}
// MatchClassKind of the operand that we expected to see.
unsigned getOperandClass() const {
assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands);
assert((Kind == NearMissOperand || Kind == NearMissTooFewOperands) &&
"near-miss does not have an associated operand class");
return MissedOperand.Class;
}
// Opcode of the encoding we were trying to match.
unsigned getOpcode() const {
assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands);
assert((Kind == NearMissOperand || Kind == NearMissTooFewOperands ||
Kind == NearMissMultipleOperands) &&
"near-miss does not have an associated opcode");
return MissedOperand.Opcode;
}
// Error code returned when validating the operand.
unsigned getOperandError() const {
assert(Kind == NearMissOperand);
assert(Kind == NearMissOperand &&
"near-miss does not have an associated operand error");
return MissedOperand.Error;
}
// Index of the actual operand we were trying to match in the list of parsed
// operands.
unsigned getOperandIndex() const {
assert(Kind == NearMissOperand);
assert(Kind == NearMissOperand &&
"near-miss does not have an associated operand index");
return MissedOperand.Index;
}

Expand Down
17 changes: 17 additions & 0 deletions lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10134,6 +10134,7 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
std::multimap<unsigned, unsigned> OperandMissesSeen;
SmallSet<uint64_t, 4> FeatureMissesSeen;
bool ReportedTooFewOperands = false;
bool HaveMultipleBadOperands = false;

// Process the near-misses in reverse order, so that we see more general ones
// first, and so can avoid emitting more specific ones.
Expand Down Expand Up @@ -10253,6 +10254,12 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
NearMissesOut.emplace_back(Message);
break;
}
case NearMissInfo::NearMissMultipleOperands: {
// Just record the fact that we have seen this, we will use it as a
// fall-back if we don't find a better operand error to report.
HaveMultipleBadOperands = true;
break;
}
case NearMissInfo::NearMissTooFewOperands: {
if (!ReportedTooFewOperands) {
SMLoc EndLoc = ((ARMOperand &)*Operands.back()).getEndLoc();
Expand All @@ -10268,6 +10275,16 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
break;
}
}

// If there is an encoding that missed on multiple operands (but matched the
// target features and early predicate), but we haven't been able to emit a
// more specific error for any operands, emit a generic error. This lets the
// user know that the mnemonic exists, and that some combination of operands
// would work for the current target.
if (HaveMultipleBadOperands && NearMissesOut.empty()) {
NearMissesOut.emplace_back(NearMissMessage{
IDLoc, StringRef("invalid operands for instruction")});
}
}

void ARMAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses,
Expand Down
6 changes: 3 additions & 3 deletions test/MC/ARM/diagnostics.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@ RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2> %t
RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V7 < %t %s
@ RUN: not llvm-mc -triple=armv8 < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V8 < %t %s
Expand Down Expand Up @@ -164,7 +164,7 @@
@ CHECK-ERRORS: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V8: invalid instruction
@ CHECK-ERRORS-V8: error: invalid operands for instruction
@ CHECK-ERRORS-V8: too many operands for instruction
@ CHECK-ERRORS: operand must be an immediate in the range [0,15]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,15]
Expand Down Expand Up @@ -208,7 +208,7 @@
@ CHECK-ERRORS: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V8: invalid instruction
@ CHECK-ERRORS-V8: error: invalid operands for instruction
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V8: too many operands for instruction
@ CHECK-ERRORS: operand must be an immediate in the range [0,15]
Expand Down
24 changes: 12 additions & 12 deletions test/MC/ARM/invalid-fp-armv8.s
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,38 @@
@ V8: error: invalid instruction

vseleq.f32 s0, d2, d1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vselgt.f64 s3, s2, s1
@ V8: error: invalid operand for instruction
vselgt.f32 s0, q3, q1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vselgt.f64 q0, s3, q1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction

vmaxnm.f32 s0, d2, d1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vminnm.f64 s3, s2, s1
@ V8: error: invalid operand for instruction
vmaxnm.f32 s0, q3, q1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vmaxnm.f64 q0, s3, q1
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vmaxnmgt.f64 q0, s3, q1
@ CHECK: error: instruction 'vmaxnm' is not predicable, but condition code specified

vcvta.s32.f64 d3, s2
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vcvtp.s32.f32 d3, s2
@ V8: error: operand must be a register in range [s0, s31]
vcvtn.u32.f64 d3, s2
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vcvtm.u32.f32 d3, s2
@ 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
@ V8: error: invalid operands for 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]
Expand All @@ -79,12 +79,12 @@ vcvtthi.f16.f64 q0, d3
@ V8: error: operand must be a register in range [s0, s31]

vrintrlo.f32.f32 d3, q0
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vrintxcs.f32.f32 d3, d0
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction

vrinta.f64.f64 s3, q0
@ V8: error: invalid instruction
@ V8: error: invalid operands for instruction
vrintn.f32.f32 d3, d0
@ V8: error: instruction requires: NEON
vrintp.f32 q3, q0
Expand Down
14 changes: 7 additions & 7 deletions test/MC/ARM/invalid-neon-v8.s
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@ RUN: not llvm-mc -triple armv8 -mattr=-fp-armv8 -show-encoding < %s 2>&1 | FileCheck %s

vmaxnm.f32 s4, d5, q1
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
vmaxnm.f64.f64 s4, d5, q1
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
vmaxnmge.f64.f64 s4, d5, q1
@ CHECK: error: instruction 'vmaxnm' is not predicable, but condition code specified

Expand All @@ -12,12 +12,12 @@ vcvta.s32.f32 s1, s2
vcvtp.u32.f32 s1, d2
@ CHECK: error: operand must be a register in range [d0, d31]
vcvtp.f32.u32 d1, q2
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
vcvtplo.f32.u32 s1, s2
@ CHECK: error: instruction 'vcvtp' is not predicable, but condition code specified

vrinta.f64.f64 s3, d12
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
vrintn.f32 d3, q12
@ CHECK: error: invalid instruction, any one of the following would fix this:
@ CHECK: note: operand must be a register in range [d0, d31]
Expand Down Expand Up @@ -50,7 +50,7 @@ sha1heq.32 q0, q1
@ CHECK: error: instruction 'sha1h' is not predicable, but condition code specified

sha1c.32 s0, d1, q2
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
sha1m.32 q0, s1, q2
@ CHECK: error: operand must be a register in range [q0, q15]
sha1p.32 s0, q1, q2
Expand All @@ -62,12 +62,12 @@ sha256h.32 q0, s1, q2
sha256h2.32 q0, q1, s2
@ CHECK: error: operand must be a register in range [q0, q15]
sha256su1.32 s0, d1, q2
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
sha256su1lt.32 q0, d1, q2
@ CHECK: error: instruction 'sha256su1' is not predicable, but condition code specified

vmull.p64 q0, s1, s3
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
vmull.p64 s1, d2, d3
@ CHECK: error: operand must be a register in range [q0, q15]
vmullge.p64 q0, d16, d17
Expand Down
8 changes: 4 additions & 4 deletions test/MC/ARM/ldrd-strd-gnu-arm-bad-regs.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

.text
.arm
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: ldrd r12, [r0, #512]
ldrd r12, [r0, #512]

@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: strd r12, [r0, #512]
strd r12, [r0, #512]

@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: ldrd r1, [r0, #512]
ldrd r1, [r0, #512]

@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: strd r1, [r0, #512]
strd r1, [r0, #512]
8 changes: 4 additions & 4 deletions test/MC/ARM/ldrd-strd-gnu-bad-inst.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
strd r0
@ CHECK: error: too few operands for instruction
ldrd r0
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
strd s0, [r0]
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
ldrd s0, [r0]
.arm
@ CHECK: error: too few operands for instruction
Expand All @@ -23,7 +23,7 @@
strd r0
@ CHECK: error: too few operands for instruction
ldrd r0
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
strd s0, [r0]
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
ldrd s0, [r0]
8 changes: 4 additions & 4 deletions test/MC/ARM/ldrd-strd-gnu-sp.s
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@

.arm

// V7: error: invalid instruction
// V7: error: invalid operands for instruction
// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xc2,0xc0,0xe1]
ldrd r12, [r0, #32]

// V7: error: invalid instruction
// V7: error: invalid operands for instruction
// V8: strd r12, sp, [r0, #32] @ encoding: [0xf0,0xc2,0xc0,0xe1]
strd r12, [r0, #32]

.thumb

// V7: error: invalid instruction
// V7: error: invalid operands for instruction
// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xe9,0x08,0xcd]
ldrd r12, [r0, #32]

// V7: error: invalid instruction
// V7: error: invalid operands for instruction
// V8: strd r12, sp, [r0, #32] @ encoding: [0xc0,0xe9,0x08,0xcd]
strd r12, [r0, #32]
4 changes: 2 additions & 2 deletions test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

.text
.thumb
@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: ldrd r12, [r0, #512]
ldrd r12, [r0, #512]

@ CHECK: error: invalid instruction
@ CHECK: error: invalid operands for instruction
@ CHECK: strd r12, [r0, #512]
strd r12, [r0, #512]
6 changes: 3 additions & 3 deletions test/MC/ARM/thumb-mov.s
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// CHECK-NEXT: movs r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: movs r0, pc
// CHECK: error: invalid instruction
// CHECK: error: invalid operands for instruction
// CHECK-NEXT: movs pc, pc

// mov.w selects t2MOVr
Expand All @@ -32,7 +32,7 @@
// CHECK-NEXT: mov.w r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: mov.w r0, pc
// CHECK: error: invalid instruction
// CHECK: error: invalid operands for instruction
// CHECK-NEXT: mov.w pc, pc

// movs.w selects t2MOVr
Expand All @@ -45,7 +45,7 @@
// CHECK-NEXT: movs.w r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: movs.w r0, pc
// CHECK: error: invalid instruction
// CHECK: error: invalid operands for instruction
// CHECK-NEXT: movs.w pc, pc


Expand Down
11 changes: 7 additions & 4 deletions test/MC/ARM/thumb2-diagnostics.s
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
@ CHECK-ERRORS: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,7]
@ CHECK-ERRORS-V8: invalid instruction
@ CHECK-ERRORS-V8: error: invalid operands for instruction
@ CHECK-ERRORS-V8: too many operands for instruction
@ CHECK-ERRORS: operand must be an immediate in the range [0,15]
@ CHECK-ERRORS-V7: operand must be an immediate in the range [0,15]
Expand Down Expand Up @@ -91,8 +91,11 @@ foo2:

and sp, r1, #80008000
and pc, r1, #80008000
@ CHECK-ERRORS: error: invalid instruction
@ CHECK-ERRORS: error: invalid instruction
@ CHECK-ERRORS-V7: error: invalid operands for instruction
@ CHECK-ERRORS-V8: invalid instruction, any one of the following would fix this:
@ CHECK-ERRORS-V8: note: invalid operand for instruction
@ CHECK-ERRORS-V8: note: operand must be a register in range [r0, r14]
@ CHECK-ERRORS: error: invalid operands for instruction

ssat r0, #1, r0, asr #32
usat r0, #1, r0, asr #32
Expand Down Expand Up @@ -129,7 +132,7 @@ foo2:
@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this:
@ CHECK-ERRORS: note: instruction requires: arm-mode
@ CHECK-ERRORS: note: invalid operand for instruction
@ CHECK-ERRORS: error: invalid instruction
@ CHECK-ERRORS: error: invalid operands for instruction
@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this:
@ CHECK-ERRORS: note: invalid operand for instruction
@ CHECK-ERRORS: note: instruction requires: arm-mode
Expand Down
Loading

0 comments on commit a53a7f0

Please sign in to comment.