summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2017-10-03 10:26:11 +0000
committerOliver Stannard <oliver.stannard@arm.com>2017-10-03 10:26:11 +0000
commite093bad472ce7ad1715321abbb3b1fdbf42e2693 (patch)
tree35bbe814682e57c6f011b55b0dbb6b79fd34cdaf /llvm/lib/Target
parentd87af9a1c043713ef24f84258f8dfd11778e7be8 (diff)
downloadbcm5719-llvm-e093bad472ce7ad1715321abbb3b1fdbf42e2693.tar.gz
bcm5719-llvm-e093bad472ce7ad1715321abbb3b1fdbf42e2693.zip
[ARM] Use new assembler diags for ARM
This converts the ARM AsmParser to use the new assembly matcher error reporting mechanism, which allows errors to be reported for multiple instruction encodings when it is ambiguous which one the user intended to use. By itself this doesn't improve many error messages, because we don't have diagnostic text for most operand types, but as we add that then this will allow more of those diagnostic strings to be used when they are relevant. Differential revision: https://reviews.llvm.org/D31530 llvm-svn: 314779
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARM.td5
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp417
2 files changed, 289 insertions, 133 deletions
diff --git a/llvm/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td
index 25b9802f541..c1a3f639461 100644
--- a/llvm/lib/Target/ARM/ARM.td
+++ b/llvm/lib/Target/ARM/ARM.td
@@ -1022,6 +1022,10 @@ def ARMAsmWriter : AsmWriter {
bit isMCAsmWriter = 1;
}
+def ARMAsmParser : AsmParser {
+ bit ReportMultipleNearMisses = 1;
+}
+
def ARMAsmParserVariant : AsmParserVariant {
int Variant = 0;
string Name = "ARM";
@@ -1032,5 +1036,6 @@ def ARM : Target {
// Pull in Instruction Info.
let InstructionSet = ARMInstrInfo;
let AssemblyWriters = [ARMAsmWriter];
+ let AssemblyParsers = [ARMAsmParser];
let AssemblyParserVariants = [ARMAsmParserVariant];
}
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index b84a4e8b8e5..f2925f176a1 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
@@ -84,6 +85,11 @@ static cl::opt<ImplicitItModeTy> ImplicitItMode(
static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
cl::init(false));
+cl::opt<bool>
+DevDiags("arm-asm-parser-dev-diags", cl::init(false),
+ cl::desc("Use extended diagnostics, which include implementation "
+ "details useful for development"));
+
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
class UnwindContext {
@@ -608,8 +614,22 @@ public:
uint64_t &ErrorInfo,
bool MatchingInlineAsm) override;
unsigned MatchInstruction(OperandVector &Operands, MCInst &Inst,
- uint64_t &ErrorInfo, bool MatchingInlineAsm,
- bool &EmitInITBlock, MCStreamer &Out);
+ SmallVectorImpl<NearMissInfo> &NearMisses,
+ bool MatchingInlineAsm, bool &EmitInITBlock,
+ MCStreamer &Out);
+
+ struct NearMissMessage {
+ SMLoc Loc;
+ SmallString<128> Message;
+ };
+
+ const char *getOperandMatchFailDiag(ARMMatchResultTy Error);
+ void FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
+ SmallVectorImpl<NearMissMessage> &NearMissesOut,
+ SMLoc IDLoc, OperandVector &Operands);
+ void ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses, SMLoc IDLoc,
+ OperandVector &Operands);
+
void onLabelParsed(MCSymbol *Symbol) override;
};
@@ -8909,19 +8929,19 @@ bool ARMAsmParser::isITBlockTerminator(MCInst &Inst) const {
}
unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst,
- uint64_t &ErrorInfo,
+ SmallVectorImpl<NearMissInfo> &NearMisses,
bool MatchingInlineAsm,
bool &EmitInITBlock,
MCStreamer &Out) {
// If we can't use an implicit IT block here, just match as normal.
if (inExplicitITBlock() || !isThumbTwo() || !useImplicitITThumb())
- return MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
+ return MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm);
// Try to match the instruction in an extension of the current IT block (if
// there is one).
if (inImplicitITBlock()) {
extendImplicitITBlock(ITState.Cond);
- if (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm) ==
+ if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) ==
Match_Success) {
// The match succeded, but we still have to check that the instruction is
// valid in this implicit IT block.
@@ -8947,7 +8967,7 @@ unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst,
// Finish the current IT block, and try to match outside any IT block.
flushPendingInstructions(Out);
unsigned PlainMatchResult =
- MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
+ MatchInstructionImpl(Operands, Inst, &NearMisses, MatchingInlineAsm);
if (PlainMatchResult == Match_Success) {
const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
if (MCID.isPredicable()) {
@@ -8974,7 +8994,7 @@ unsigned ARMAsmParser::MatchInstruction(OperandVector &Operands, MCInst &Inst,
// condition, so we create an IT block with a dummy condition, and fix it up
// once we know the actual condition.
startImplicitITBlock();
- if (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm) ==
+ if (MatchInstructionImpl(Operands, Inst, nullptr, MatchingInlineAsm) ==
Match_Success) {
const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
if (MCID.isPredicable()) {
@@ -9004,7 +9024,8 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
unsigned MatchResult;
bool PendConditionalInstruction = false;
- MatchResult = MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm,
+ SmallVector<NearMissInfo, 4> NearMisses;
+ MatchResult = MatchInstruction(Operands, Inst, NearMisses, MatchingInlineAsm,
PendConditionalInstruction, Out);
SMLoc ErrorLoc;
@@ -9061,33 +9082,9 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
Out.EmitInstruction(Inst, getSTI());
}
return false;
- case Match_MissingFeature: {
- assert(ErrorInfo && "Unknown missing feature!");
- // Special case the error message for the very common case where only
- // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
- std::string Msg = "instruction requires:";
- uint64_t Mask = 1;
- for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
- if (ErrorInfo & Mask) {
- Msg += " ";
- Msg += getSubtargetFeatureName(ErrorInfo & Mask);
- }
- Mask <<= 1;
- }
- return Error(IDLoc, Msg);
- }
- case Match_InvalidOperand: {
- SMLoc ErrorLoc = IDLoc;
- if (ErrorInfo != ~0ULL) {
- if (ErrorInfo >= Operands.size())
- return Error(IDLoc, "too few operands for instruction");
-
- ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
- if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
- }
-
- return Error(ErrorLoc, "invalid operand for instruction");
- }
+ case Match_NearMisses:
+ ReportNearMisses(NearMisses, IDLoc, Operands);
+ return true;
case Match_MnemonicFail: {
uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
std::string Suggestion = ARMMnemonicSpellCheck(
@@ -9095,104 +9092,6 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "invalid instruction" + Suggestion,
((ARMOperand &)*Operands[0]).getLocRange());
}
- case Match_RequiresNotITBlock:
- return Error(IDLoc, "flag setting instruction only valid outside IT block");
- case Match_RequiresITBlock:
- return Error(IDLoc, "instruction only valid inside IT block");
- case Match_RequiresV6:
- return Error(IDLoc, "instruction variant requires ARMv6 or later");
- case Match_RequiresThumb2:
- return Error(IDLoc, "instruction variant requires Thumb2");
- case Match_RequiresV8:
- return Error(IDLoc, "instruction variant requires ARMv8 or later");
- case Match_RequiresFlagSetting:
- return Error(IDLoc, "no flag-preserving variant of this instruction available");
- case Match_ImmRange0_1:
- return Error(ErrorLoc, "immediate operand must be in the range [0,1]");
- case Match_ImmRange0_3:
- return Error(ErrorLoc, "immediate operand must be in the range [0,3]");
- case Match_ImmRange0_7:
- return Error(ErrorLoc, "immediate operand must be in the range [0,7]");
- case Match_ImmRange0_15:
- return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
- case Match_ImmRange0_31:
- return Error(ErrorLoc, "immediate operand must be in the range [0,31]");
- case Match_ImmRange0_32:
- return Error(ErrorLoc, "immediate operand must be in the range [0,32]");
- case Match_ImmRange0_63:
- return Error(ErrorLoc, "immediate operand must be in the range [0,63]");
- case Match_ImmRange0_239:
- return Error(ErrorLoc, "immediate operand must be in the range [0,239]");
- case Match_ImmRange0_255:
- return Error(ErrorLoc, "immediate operand must be in the range [0,255]");
- case Match_ImmRange0_4095:
- return Error(ErrorLoc, "immediate operand must be in the range [0,4095]");
- case Match_ImmRange0_65535:
- return Error(ErrorLoc, "immediate operand must be in the range [0,65535]");
- case Match_ImmRange1_7:
- return Error(ErrorLoc, "immediate operand must be in the range [1,7]");
- case Match_ImmRange1_8:
- return Error(ErrorLoc, "immediate operand must be in the range [1,8]");
- case Match_ImmRange1_15:
- return Error(ErrorLoc, "immediate operand must be in the range [1,15]");
- case Match_ImmRange1_16:
- return Error(ErrorLoc, "immediate operand must be in the range [1,16]");
- case Match_ImmRange1_31:
- return Error(ErrorLoc, "immediate operand must be in the range [1,31]");
- case Match_ImmRange1_32:
- return Error(ErrorLoc, "immediate operand must be in the range [1,32]");
- case Match_ImmRange1_64:
- return Error(ErrorLoc, "immediate operand must be in the range [1,64]");
- case Match_ImmRange8_8:
- return Error(ErrorLoc, "immediate operand must be 8.");
- case Match_ImmRange16_16:
- return Error(ErrorLoc, "immediate operand must be 16.");
- case Match_ImmRange32_32:
- return Error(ErrorLoc, "immediate operand must be 32.");
- case Match_ImmRange256_65535:
- return Error(ErrorLoc, "immediate operand must be in the range [255,65535]");
- case Match_ImmRange0_16777215:
- return Error(ErrorLoc, "immediate operand must be in the range [0,0xffffff]");
- case Match_AlignedMemoryRequiresNone:
- case Match_DupAlignedMemoryRequiresNone:
- case Match_AlignedMemoryRequires16:
- case Match_DupAlignedMemoryRequires16:
- case Match_AlignedMemoryRequires32:
- case Match_DupAlignedMemoryRequires32:
- case Match_AlignedMemoryRequires64:
- case Match_DupAlignedMemoryRequires64:
- case Match_AlignedMemoryRequires64or128:
- case Match_DupAlignedMemoryRequires64or128:
- case Match_AlignedMemoryRequires64or128or256:
- {
- SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getAlignmentLoc();
- if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
- switch (MatchResult) {
- default:
- llvm_unreachable("Missing Match_Aligned type");
- case Match_AlignedMemoryRequiresNone:
- case Match_DupAlignedMemoryRequiresNone:
- return Error(ErrorLoc, "alignment must be omitted");
- case Match_AlignedMemoryRequires16:
- case Match_DupAlignedMemoryRequires16:
- return Error(ErrorLoc, "alignment must be 16 or omitted");
- case Match_AlignedMemoryRequires32:
- case Match_DupAlignedMemoryRequires32:
- return Error(ErrorLoc, "alignment must be 32 or omitted");
- case Match_AlignedMemoryRequires64:
- case Match_DupAlignedMemoryRequires64:
- return Error(ErrorLoc, "alignment must be 64 or omitted");
- case Match_AlignedMemoryRequires64or128:
- case Match_DupAlignedMemoryRequires64or128:
- return Error(ErrorLoc, "alignment must be 64, 128 or omitted");
- case Match_AlignedMemoryRequires64or128or256:
- return Error(ErrorLoc, "alignment must be 64, 128, 256 or omitted");
- }
- }
- case Match_InvalidComplexRotationEven:
- return Error(IDLoc, "complex rotation must be 0, 90, 180 or 270");
- case Match_InvalidComplexRotationOdd:
- return Error(IDLoc, "complex rotation must be 90 or 270");
}
llvm_unreachable("Implement any new match types added!");
@@ -10203,6 +10102,258 @@ extern "C" void LLVMInitializeARMAsmParser() {
#define GET_MATCHER_IMPLEMENTATION
#include "ARMGenAsmMatcher.inc"
+const char *ARMAsmParser::getOperandMatchFailDiag(ARMMatchResultTy Error) {
+ switch (Error) {
+ case Match_AlignedMemoryRequiresNone:
+ case Match_DupAlignedMemoryRequiresNone:
+ return "alignment must be omitted";
+ case Match_AlignedMemoryRequires16:
+ case Match_DupAlignedMemoryRequires16:
+ return "alignment must be 16 or omitted";
+ case Match_AlignedMemoryRequires32:
+ case Match_DupAlignedMemoryRequires32:
+ return "alignment must be 32 or omitted";
+ case Match_AlignedMemoryRequires64:
+ case Match_DupAlignedMemoryRequires64:
+ return "alignment must be 64 or omitted";
+ case Match_AlignedMemoryRequires64or128:
+ case Match_DupAlignedMemoryRequires64or128:
+ return "alignment must be 64, 128 or omitted";
+ case Match_AlignedMemoryRequires64or128or256:
+ return "alignment must be 64, 128, 256 or omitted";
+ case Match_ImmRange0_1:
+ return "immediate operand must be in the range [0,1]";
+ case Match_ImmRange0_3:
+ return "immediate operand must be in the range [0,3]";
+ case Match_ImmRange0_7:
+ return "immediate operand must be in the range [0,7]";
+ case Match_ImmRange0_15:
+ return "immediate operand must be in the range [0,15]";
+ case Match_ImmRange0_31:
+ return "immediate operand must be in the range [0,31]";
+ case Match_ImmRange0_32:
+ return "immediate operand must be in the range [0,32]";
+ case Match_ImmRange0_63:
+ return "immediate operand must be in the range [0,63]";
+ case Match_ImmRange0_239:
+ return "immediate operand must be in the range [0,239]";
+ case Match_ImmRange0_255:
+ return "immediate operand must be in the range [0,255]";
+ case Match_ImmRange0_4095:
+ return "immediate operand must be in the range [0,4095]";
+ case Match_ImmRange0_65535:
+ return "immediate operand must be in the range [0,65535]";
+ case Match_ImmRange1_7:
+ return "immediate operand must be in the range [1,7]";
+ case Match_ImmRange1_8:
+ return "immediate operand must be in the range [1,8]";
+ case Match_ImmRange1_15:
+ return "immediate operand must be in the range [1,15]";
+ case Match_ImmRange1_16:
+ return "immediate operand must be in the range [1,16]";
+ case Match_ImmRange1_31:
+ return "immediate operand must be in the range [1,31]";
+ case Match_ImmRange1_32:
+ return "immediate operand must be in the range [1,32]";
+ case Match_ImmRange1_64:
+ return "immediate operand must be in the range [1,64]";
+ case Match_ImmRange8_8:
+ return "immediate operand must be 8.";
+ case Match_ImmRange16_16:
+ return "immediate operand must be 16.";
+ case Match_ImmRange32_32:
+ return "immediate operand must be 32.";
+ case Match_ImmRange256_65535:
+ return "immediate operand must be in the range [255,65535]";
+ case Match_ImmRange0_16777215:
+ return "immediate operand must be in the range [0,0xffffff]";
+ case Match_InvalidComplexRotationEven:
+ return "complex rotation must be 0, 90, 180 or 270";
+ case Match_InvalidComplexRotationOdd:
+ return "complex rotation must be 90 or 270";
+ default:
+ return nullptr;
+ }
+}
+
+// Process the list of near-misses, throwing away ones we don't want to report
+// to the user, and converting the rest to a source location and string that
+// should be reported.
+void
+ARMAsmParser::FilterNearMisses(SmallVectorImpl<NearMissInfo> &NearMissesIn,
+ SmallVectorImpl<NearMissMessage> &NearMissesOut,
+ SMLoc IDLoc, OperandVector &Operands) {
+ // TODO: If operand didn't match, sub in a dummy one and run target
+ // predicate, so that we can avoid reporting near-misses that are invalid?
+ // TODO: Many operand types dont have SuperClasses set, so we report
+ // redundant ones.
+ // TODO: Some operands are superclasses of registers (e.g.
+ // MCK_RegShiftedImm), we don't have any way to represent that currently.
+ // TODO: This is not all ARM-specific, can some of it be factored out?
+
+ // Record some information about near-misses that we have already seen, so
+ // that we can avoid reporting redundant ones. For example, if there are
+ // variants of an instruction that take 8- and 16-bit immediates, we want
+ // to only report the widest one.
+ std::multimap<unsigned, unsigned> OperandMissesSeen;
+ SmallSet<uint64_t, 4> FeatureMissesSeen;
+
+ // Process the near-misses in reverse order, so that we see more general ones
+ // first, and so can avoid emitting more specific ones.
+ for (NearMissInfo &I : reverse(NearMissesIn)) {
+ switch (I.getKind()) {
+ case NearMissInfo::NearMissOperand: {
+ SMLoc OperandLoc =
+ ((ARMOperand &)*Operands[I.getOperandIndex()]).getStartLoc();
+ const char *OperandDiag =
+ getOperandMatchFailDiag((ARMMatchResultTy)I.getOperandError());
+
+ // If we have already emitted a message for a superclass, don't also report
+ // the sub-class. We consider all operand classes that we don't have a
+ // specialised diagnostic for to be equal for the propose of this check,
+ // so that we don't report the generic error multiple times on the same
+ // operand.
+ unsigned DupCheckMatchClass = OperandDiag ? I.getOperandClass() : ~0U;
+ auto PrevReports = OperandMissesSeen.equal_range(I.getOperandIndex());
+ if (std::any_of(PrevReports.first, PrevReports.second,
+ [DupCheckMatchClass](
+ const std::pair<unsigned, unsigned> Pair) {
+ if (DupCheckMatchClass == ~0U)
+ return Pair.second == ~0U;
+ else
+ return isSubclass((MatchClassKind)DupCheckMatchClass,
+ (MatchClassKind)Pair.second);
+ }))
+ break;
+ OperandMissesSeen.insert(
+ std::make_pair(I.getOperandIndex(), DupCheckMatchClass));
+
+ NearMissMessage Message;
+ Message.Loc = OperandLoc;
+ raw_svector_ostream OS(Message.Message);
+ if (OperandDiag) {
+ OS << OperandDiag;
+ } else if (I.getOperandClass() == InvalidMatchClass) {
+ OS << "too many operands for instruction";
+ } else {
+ OS << "invalid operand for instruction";
+ if (DevDiags) {
+ OS << " class" << I.getOperandClass() << ", error "
+ << I.getOperandError() << ", opcode "
+ << MII.getName(I.getOpcode());
+ }
+ }
+ NearMissesOut.emplace_back(Message);
+ break;
+ }
+ case NearMissInfo::NearMissFeature: {
+ uint64_t MissingFeatures = I.getFeatures();
+ // Don't report the same set of features twice.
+ if (FeatureMissesSeen.count(MissingFeatures))
+ break;
+ FeatureMissesSeen.insert(MissingFeatures);
+
+ // Special case: don't report a feature set which includes arm-mode for
+ // targets that don't have ARM mode.
+ if ((MissingFeatures & Feature_IsARM) && !hasARM())
+ break;
+ // Don't report any near-misses that both require switching instruction
+ // set, and adding other subtarget features.
+ if (isThumb() && (MissingFeatures & Feature_IsARM) &&
+ (MissingFeatures & ~Feature_IsARM))
+ break;
+ if (!isThumb() && (MissingFeatures & Feature_IsThumb) &&
+ (MissingFeatures & ~Feature_IsThumb))
+ break;
+ if (!isThumb() && (MissingFeatures & Feature_IsThumb2) &&
+ (MissingFeatures & ~(Feature_IsThumb2 | Feature_IsThumb)))
+ break;
+
+ NearMissMessage Message;
+ Message.Loc = IDLoc;
+ raw_svector_ostream OS(Message.Message);
+
+ OS << "instruction requires:";
+ uint64_t Mask = 1;
+ for (unsigned MaskPos = 0; MaskPos < (sizeof(MissingFeatures) * 8 - 1);
+ ++MaskPos) {
+ if (MissingFeatures & Mask) {
+ OS << " " << getSubtargetFeatureName(MissingFeatures & Mask);
+ }
+ Mask <<= 1;
+ }
+ NearMissesOut.emplace_back(Message);
+
+ break;
+ }
+ case NearMissInfo::NearMissPredicate: {
+ NearMissMessage Message;
+ Message.Loc = IDLoc;
+ switch (I.getPredicateError()) {
+ case Match_RequiresNotITBlock:
+ Message.Message = "flag setting instruction only valid outside IT block";
+ break;
+ case Match_RequiresITBlock:
+ Message.Message = "instruction only valid inside IT block";
+ break;
+ case Match_RequiresV6:
+ Message.Message = "instruction variant requires ARMv6 or later";
+ break;
+ case Match_RequiresThumb2:
+ Message.Message = "instruction variant requires Thumb2";
+ break;
+ case Match_RequiresV8:
+ Message.Message = "instruction variant requires ARMv8 or later";
+ break;
+ case Match_RequiresFlagSetting:
+ Message.Message = "no flag-preserving variant of this instruction available";
+ break;
+ case Match_InvalidOperand:
+ Message.Message = "invalid operand for instruction";
+ break;
+ default:
+ llvm_unreachable("Unhandled target predicate error");
+ break;
+ }
+ NearMissesOut.emplace_back(Message);
+ break;
+ }
+ case NearMissInfo::NearMissTooFewOperands: {
+ SMLoc EndLoc = ((ARMOperand &)*Operands.back()).getEndLoc();
+ NearMissesOut.emplace_back(
+ NearMissMessage{ EndLoc, StringRef("too few operands for instruction") });
+ break;
+ }
+ case NearMissInfo::NoNearMiss:
+ // This should never leave the matcher.
+ llvm_unreachable("not a near-miss");
+ break;
+ }
+ }
+}
+
+void ARMAsmParser::ReportNearMisses(SmallVectorImpl<NearMissInfo> &NearMisses,
+ SMLoc IDLoc, OperandVector &Operands) {
+ SmallVector<NearMissMessage, 4> Messages;
+ FilterNearMisses(NearMisses, Messages, IDLoc, Operands);
+
+ if (Messages.size() == 0) {
+ // No near-misses were found, so the best we can do is "invalid
+ // instruction".
+ Error(IDLoc, "invalid instruction");
+ } else if (Messages.size() == 1) {
+ // One near miss was found, report it as the sole error.
+ Error(Messages[0].Loc, Messages[0].Message);
+ } else {
+ // More than one near miss, so report a generic "invalid instruction"
+ // error, followed by notes for each of the near-misses.
+ Error(IDLoc, "invalid instruction, any one of the following would fix this:");
+ for (auto &M : Messages) {
+ Note(M.Loc, M.Message);
+ }
+ }
+}
+
// FIXME: This structure should be moved inside ARMTargetParser
// when we start to table-generate them, and we can use the ARM
// flags below, that were generated by table-gen.
OpenPOWER on IntegriCloud