enum NearMissKind {
NoNearMiss,
NearMissOperand,
- NearMissMultipleOperands,
NearMissFeature,
NearMissPredicate,
NearMissTooFewOperands,
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.
// Feature flags required by the instruction, that the current target does
// not have.
uint64_t getFeatures() const {
- assert(Kind == NearMissFeature &&
- "near-miss does not have an associated target feature");
+ assert(Kind == NearMissFeature);
return Features;
}
// Error code returned by the target predicate when validating this
// instruction encoding.
unsigned getPredicateError() const {
- assert(Kind == NearMissPredicate &&
- "near-miss does not have an associated predicate error");
+ assert(Kind == NearMissPredicate);
return PredicateError;
}
// MatchClassKind of the operand that we expected to see.
unsigned getOperandClass() const {
- assert((Kind == NearMissOperand || Kind == NearMissTooFewOperands) &&
- "near-miss does not have an associated operand class");
+ assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands);
return MissedOperand.Class;
}
// Opcode of the encoding we were trying to match.
unsigned getOpcode() const {
- assert((Kind == NearMissOperand || Kind == NearMissTooFewOperands ||
- Kind == NearMissMultipleOperands) &&
- "near-miss does not have an associated opcode");
+ assert(Kind == NearMissOperand || Kind == NearMissTooFewOperands);
return MissedOperand.Opcode;
}
// Error code returned when validating the operand.
unsigned getOperandError() const {
- assert(Kind == NearMissOperand &&
- "near-miss does not have an associated operand error");
+ assert(Kind == NearMissOperand);
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 &&
- "near-miss does not have an associated operand index");
+ assert(Kind == NearMissOperand);
return MissedOperand.Index;
}
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.
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();
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,
- 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
@ 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: error: invalid operands for instruction
+@ CHECK-ERRORS-V8: invalid 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]
@ 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: error: invalid operands for instruction
+@ CHECK-ERRORS-V8: invalid 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]
@ V8: error: invalid instruction
vseleq.f32 s0, d2, d1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vselgt.f64 s3, s2, s1
@ V8: error: invalid operand for instruction
vselgt.f32 s0, q3, q1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vselgt.f64 q0, s3, q1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vmaxnm.f32 s0, d2, d1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vminnm.f64 s3, s2, s1
@ V8: error: invalid operand for instruction
vmaxnm.f32 s0, q3, q1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vmaxnm.f64 q0, s3, q1
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid 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 operands for instruction
+@ V8: error: invalid 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 operands for instruction
+@ V8: error: invalid 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 operands for instruction
+@ 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: error: operand must be a register in range [s0, s31]
vrintrlo.f32.f32 d3, q0
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vrintxcs.f32.f32 d3, d0
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vrinta.f64.f64 s3, q0
-@ V8: error: invalid operands for instruction
+@ V8: error: invalid instruction
vrintn.f32.f32 d3, d0
@ V8: error: instruction requires: NEON
vrintp.f32 q3, q0
@ RUN: not llvm-mc -triple armv8 -mattr=-fp-armv8 -show-encoding < %s 2>&1 | FileCheck %s
vmaxnm.f32 s4, d5, q1
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
vmaxnm.f64.f64 s4, d5, q1
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
vmaxnmge.f64.f64 s4, d5, q1
@ CHECK: error: instruction 'vmaxnm' is not predicable, but condition code specified
vcvtp.u32.f32 s1, d2
@ CHECK: error: operand must be a register in range [d0, d31]
vcvtp.f32.u32 d1, q2
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid 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 operands for instruction
+@ CHECK: error: invalid 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]
@ CHECK: error: instruction 'sha1h' is not predicable, but condition code specified
sha1c.32 s0, d1, q2
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
sha1m.32 q0, s1, q2
@ CHECK: error: operand must be a register in range [q0, q15]
sha1p.32 s0, q1, 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 operands for instruction
+@ CHECK: error: invalid 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 operands for instruction
+@ CHECK: error: invalid instruction
vmull.p64 s1, d2, d3
@ CHECK: error: operand must be a register in range [q0, q15]
vmullge.p64 q0, d16, d17
.text
.arm
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: ldrd r12, [r0, #512]
ldrd r12, [r0, #512]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: strd r12, [r0, #512]
strd r12, [r0, #512]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: ldrd r1, [r0, #512]
ldrd r1, [r0, #512]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: strd r1, [r0, #512]
strd r1, [r0, #512]
strd r0
@ CHECK: error: too few operands for instruction
ldrd r0
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
strd s0, [r0]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
ldrd s0, [r0]
.arm
@ CHECK: error: too few operands for instruction
strd r0
@ CHECK: error: too few operands for instruction
ldrd r0
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
strd s0, [r0]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
ldrd s0, [r0]
.arm
-// V7: error: invalid operands for instruction
+// V7: error: invalid instruction
// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xc2,0xc0,0xe1]
ldrd r12, [r0, #32]
-// V7: error: invalid operands for instruction
+// V7: error: invalid instruction
// V8: strd r12, sp, [r0, #32] @ encoding: [0xf0,0xc2,0xc0,0xe1]
strd r12, [r0, #32]
.thumb
-// V7: error: invalid operands for instruction
+// V7: error: invalid instruction
// V8: ldrd r12, sp, [r0, #32] @ encoding: [0xd0,0xe9,0x08,0xcd]
ldrd r12, [r0, #32]
-// V7: error: invalid operands for instruction
+// V7: error: invalid instruction
// V8: strd r12, sp, [r0, #32] @ encoding: [0xc0,0xe9,0x08,0xcd]
strd r12, [r0, #32]
.text
.thumb
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: ldrd r12, [r0, #512]
ldrd r12, [r0, #512]
-@ CHECK: error: invalid operands for instruction
+@ CHECK: error: invalid instruction
@ CHECK: strd r12, [r0, #512]
strd r12, [r0, #512]
// CHECK-NEXT: movs r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: movs r0, pc
-// CHECK: error: invalid operands for instruction
+// CHECK: error: invalid instruction
// CHECK-NEXT: movs pc, pc
// mov.w selects t2MOVr
// CHECK-NEXT: mov.w r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: mov.w r0, pc
-// CHECK: error: invalid operands for instruction
+// CHECK: error: invalid instruction
// CHECK-NEXT: mov.w pc, pc
// movs.w selects t2MOVr
// CHECK-NEXT: movs.w r0, pc
// CHECK: note: invalid operand for instruction
// CHECK-NEXT: movs.w r0, pc
-// CHECK: error: invalid operands for instruction
+// CHECK: error: invalid instruction
// CHECK-NEXT: movs.w pc, pc
@ 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: error: invalid operands for instruction
+@ CHECK-ERRORS-V8: invalid 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]
and sp, r1, #80008000
and pc, r1, #80008000
-@ 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
+@ CHECK-ERRORS: error: invalid instruction
+@ CHECK-ERRORS: error: invalid instruction
ssat r0, #1, r0, asr #32
usat r0, #1, r0, asr #32
@ 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 operands for instruction
+@ CHECK-ERRORS: error: invalid 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
@ ARM: vfma.f64 d16, d18, d17 @ encoding: [0xa1,0x0b,0xe2,0xee]
@ THUMB: vfma.f64 d16, d18, d17 @ encoding: [0xe2,0xee,0xa1,0x0b]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfma.f64 d16, d18, d17
vfma.f64 d16, d18, d17
@ ARM: vfma.f32 d16, d18, d17 @ encoding: [0xb1,0x0c,0x42,0xf2]
@ THUMB: vfma.f32 d16, d18, d17 @ encoding: [0x42,0xef,0xb1,0x0c]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfma.f32 d16, d18, d17
vfma.f32 d16, d18, d17
@ ARM: vfnma.f64 d16, d18, d17 @ encoding: [0xe1,0x0b,0xd2,0xee]
@ THUMB: vfnma.f64 d16, d18, d17 @ encoding: [0xd2,0xee,0xe1,0x0b]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfnma.f64 d16, d18, d17
vfnma.f64 d16, d18, d17
@ ARM: vfms.f64 d16, d18, d17 @ encoding: [0xe1,0x0b,0xe2,0xee]
@ THUMB: vfms.f64 d16, d18, d17 @ encoding: [0xe2,0xee,0xe1,0x0b]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfms.f64 d16, d18, d17
vfms.f64 d16, d18, d17
@ ARM: vfms.f32 d16, d18, d17 @ encoding: [0xb1,0x0c,0x62,0xf2]
@ THUMB: vfms.f32 d16, d18, d17 @ encoding: [0x62,0xef,0xb1,0x0c]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfms.f32 d16, d18, d17
vfms.f32 d16, d18, d17
@ ARM: vfnms.f64 d16, d18, d17 @ encoding: [0xa1,0x0b,0xd2,0xee]
@ THUMB: vfnms.f64 d16, d18, d17 @ encoding: [0xd2,0xee,0xa1,0x0b]
-@ THUMB_V7EM-ERRORS: error: invalid operands for instruction
+@ THUMB_V7EM-ERRORS: error: invalid instruction
@ THUMB_V7EM-ERRORS-NEXT: vfnms.f64 d16, d18, d17
vfnms.f64 d16, d18, d17
OS << " NearMissInfo FeaturesNearMiss = NearMissInfo::getSuccess();\n";
OS << " NearMissInfo EarlyPredicateNearMiss = NearMissInfo::getSuccess();\n";
OS << " NearMissInfo LatePredicateNearMiss = NearMissInfo::getSuccess();\n";
+ OS << " bool MultipleInvalidOperands = false;\n";
}
if (HasMnemonicFirst) {
OS << " OperandNearMiss =\n";
OS << " NearMissInfo::getTooFewOperands(Formal, it->Opcode);\n";
OS << " } else if (OperandNearMiss.getKind() != NearMissInfo::NearMissTooFewOperands) {\n";
- OS << " // An invalid operand plus a missing one at the end are reported the\n";
- OS << " // same way as multiple invalid operands.\n";
+ OS << " // If more than one operand is invalid, give up on this match entry.\n";
OS << " DEBUG_WITH_TYPE(\n";
OS << " \"asm-matcher\",\n";
OS << " dbgs() << \"second invalid operand, giving up on this opcode\\n\");\n";
- OS << " OperandNearMiss = NearMissInfo::getMissedMultipleOperands(it->Opcode);\n";
+ OS << " MultipleInvalidOperands = true;\n";
OS << " break;\n";
OS << " }\n";
OS << " } else {\n";
OS << " DEBUG_WITH_TYPE(\n";
OS << " \"asm-matcher\",\n";
OS << " dbgs() << \"second operand mismatch, skipping this opcode\\n\");\n";
- OS << " OperandNearMiss = NearMissInfo::getMissedMultipleOperands(it->Opcode);\n";
+ OS << " MultipleInvalidOperands = true;\n";
OS << " break;\n";
OS << " }\n";
OS << " }\n\n";
OS << " }\n\n";
}
- if (!ReportMultipleNearMisses) {
+ if (ReportMultipleNearMisses)
+ OS << " if (MultipleInvalidOperands) {\n";
+ else
OS << " if (!OperandsValid) {\n";
- OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: multiple \"\n";
- OS << " \"operand mismatches, ignoring \"\n";
- OS << " \"this opcode\\n\");\n";
- OS << " continue;\n";
- OS << " }\n";
- }
+ OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"Opcode result: multiple \"\n";
+ OS << " \"operand mismatches, ignoring \"\n";
+ OS << " \"this opcode\\n\");\n";
+ OS << " continue;\n";
+ OS << " }\n";
// Emit check that the required features are available.
OS << " if ((AvailableFeatures & it->RequiredFeatures) "