MIR Parser: Use correct source locations for machine instruction diagnostics.
authorAlex Lorenz <arphaman@gmail.com>
Tue, 23 Jun 2015 22:39:23 +0000 (22:39 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Tue, 23 Jun 2015 22:39:23 +0000 (22:39 +0000)
This commit translates the source locations for MIParser diagnostics from
the locations in the machine instruction string to the locations in the
MIR file.

Reviewers: Duncan P. N. Exon Smith

Differential Revision: http://reviews.llvm.org/D10574

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

include/llvm/CodeGen/MIRYamlMapping.h
lib/CodeGen/MIRParser/MIRParser.cpp
test/CodeGen/MIR/X86/expected-machine-operand.mir
test/CodeGen/MIR/X86/missing-comma.mir
test/CodeGen/MIR/X86/missing-instruction.mir
test/CodeGen/MIR/X86/unknown-instruction.mir
test/CodeGen/MIR/X86/unknown-register.mir
test/CodeGen/MIR/X86/unrecognized-character.mir

index 8b205113d643d16d482f0ea80d1168c37f125a24..4325fb98078c1c624c3fdf9e880ea247ffdb0627 100644 (file)
 #include "llvm/Support/YAMLTraits.h"
 #include <vector>
 
-LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
+namespace llvm {
+namespace yaml {
+
+/// A wrapper around std::string which contains a source range that's being
+/// set during parsing.
+struct StringValue {
+  std::string Value;
+  SMRange SourceRange;
+
+  StringValue() {}
+  StringValue(std::string Value) : Value(std::move(Value)) {}
+
+  bool operator==(const StringValue &Other) const {
+    return Value == Other.Value;
+  }
+};
+
+template <> struct ScalarTraits<StringValue> {
+  static void output(const StringValue &S, void *, llvm::raw_ostream &OS) {
+    OS << S.Value;
+  }
+
+  static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) {
+    S.Value = Scalar.str();
+    if (const auto *Node =
+            reinterpret_cast<yaml::Input *>(Ctx)->getCurrentNode())
+      S.SourceRange = Node->getSourceRange();
+    return "";
+  }
+
+  static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue)
 
 namespace llvm {
 namespace yaml {
@@ -34,7 +70,7 @@ struct MachineBasicBlock {
   bool AddressTaken = false;
   // TODO: Serialize the successors and liveins.
 
-  std::vector<std::string> Instructions;
+  std::vector<StringValue> Instructions;
 };
 
 template <> struct MappingTraits<MachineBasicBlock> {
index 1ba7f1f1df22390abe0e598d4e7c0b26cc878d63..57ecacf7dce16c2d0b1be3356205d03a22e3644c 100644 (file)
@@ -84,6 +84,10 @@ public:
                                    const yaml::MachineBasicBlock &YamlMBB);
 
 private:
+  /// Return a MIR diagnostic converted from an MI string diagnostic.
+  SMDiagnostic diagFromMIStringDiag(const SMDiagnostic &Error,
+                                    SMRange SourceRange);
+
   /// Return a MIR diagnostic converted from an LLVM assembly diagnostic.
   SMDiagnostic diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
                                         SMRange SourceRange);
@@ -129,6 +133,7 @@ static void handleYAMLDiag(const SMDiagnostic &Diag, void *Context) {
 std::unique_ptr<Module> MIRParserImpl::parse() {
   yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer(),
                  /*Ctxt=*/nullptr, handleYAMLDiag, this);
+  In.setContext(&In);
 
   if (!In.setCurrentDocument()) {
     if (In.error())
@@ -235,16 +240,32 @@ bool MIRParserImpl::initializeMachineBasicBlock(
   // Parse the instructions.
   for (const auto &MISource : YamlMBB.Instructions) {
     SMDiagnostic Error;
-    if (auto *MI = parseMachineInstr(SM, MF, MISource, Error)) {
+    if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, Error)) {
       MBB.insert(MBB.end(), MI);
       continue;
     }
-    reportDiagnostic(Error);
+    reportDiagnostic(diagFromMIStringDiag(Error, MISource.SourceRange));
     return true;
   }
   return false;
 }
 
+SMDiagnostic MIRParserImpl::diagFromMIStringDiag(const SMDiagnostic &Error,
+                                                 SMRange SourceRange) {
+  assert(SourceRange.isValid() && "Invalid source range");
+  SMLoc Loc = SourceRange.Start;
+  bool HasQuote = Loc.getPointer() < SourceRange.End.getPointer() &&
+                  *Loc.getPointer() == '\'';
+  // Translate the location of the error from the location in the MI string to
+  // the corresponding location in the MIR file.
+  Loc = Loc.getFromPointer(Loc.getPointer() + Error.getColumnNo() +
+                           (HasQuote ? 1 : 0));
+
+  // TODO: Translate any source ranges as well.
+  return SM.GetMessage(Loc, Error.getKind(), Error.getMessage(), None,
+                       Error.getFixIts());
+}
+
 SMDiagnostic MIRParserImpl::diagFromLLVMAssemblyDiag(const SMDiagnostic &Error,
                                                      SMRange SourceRange) {
   assert(SourceRange.isValid());
index 262cd8bc39aa44d0f10766e10b4e89398bfafd0e..685f3bfe31aa077520e48fbd208fa4343bdccdad 100644 (file)
@@ -13,7 +13,7 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:16: expected a machine operand
+     # CHECK: [[@LINE+1]]:24: expected a machine operand
      - '%eax = XOR32rr ='
      - 'RETQ %eax'
 ...
index 76fea10e8b076a6a0d2ac5479cdc069f7734d9f7..dc06a87dc4bc28c164eba48f64583cc61be797fa 100644 (file)
@@ -13,7 +13,7 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:21: expected ',' before the next machine operand
+     # CHECK: [[@LINE+1]]:29: expected ',' before the next machine operand
      - '%eax = XOR32rr %eax %eflags'
      - 'RETQ %eax'
 ...
index 0cf4371d349498d727f6dfff5cdfdddaaec7f097..e18b667bae40e48712c4f307bb538c4f8cfcc6af 100644 (file)
@@ -13,6 +13,6 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:1: expected a machine instruction
+     # CHECK: [[@LINE+1]]:9: expected a machine instruction
      - ''
 ...
index 05decaac929a00316f6942e531229c6a356456ab..0d1db9f9a3f68f50d6afcaa1aae6e73c261cf13e 100644 (file)
@@ -15,6 +15,6 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:1: unknown machine instruction name 'retJust0'
+     # CHECK: [[@LINE+1]]:8: unknown machine instruction name 'retJust0'
      - retJust0
 ...
index c5d349345dca2daf43fdc9f3b0355590369db5cf..59284f99a6de456d4f05fda10dff199c2db0e577 100644 (file)
@@ -15,7 +15,7 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:1: unknown register name 'xax'
+     # CHECK: [[@LINE+1]]:9: unknown register name 'xax'
      - '%xax = MOV32r0'
      - 'RETQ %xax'
 ...
index b645018c42881b53a9bfc3b7d111836873d09962..0fd504fb5bb55b08506f15e8442502a618db1204 100644 (file)
@@ -13,6 +13,6 @@ name:            foo
 body:
  - name:         entry
    instructions:
-     # CHECK: 1:1: unexpected character '`'
+     # CHECK: [[@LINE+1]]:9: unexpected character '`'
      - '` RETQ'
 ...