AsmWriter/Bitcode: MDExpression
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 13 Feb 2015 01:42:09 +0000 (01:42 +0000)
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>
Fri, 13 Feb 2015 01:42:09 +0000 (01:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229023 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Bitcode/LLVMBitCodes.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/AsmWriter.cpp
test/Assembler/invalid-mdexpression-large.ll [new file with mode: 0644]
test/Assembler/invalid-mdexpression-verify.ll [new file with mode: 0644]
test/Assembler/mdexpression.ll [new file with mode: 0644]
utils/vim/llvm.vim

index dff1c28..98b40d2 100644 (file)
@@ -163,7 +163,8 @@ namespace bitc {
     METADATA_TEMPLATE_TYPE = 25,  // [distinct, scope, name, type, ...]
     METADATA_TEMPLATE_VALUE= 26,  // [distinct, scope, name, type, value, ...]
     METADATA_GLOBAL_VAR    = 27,  // [distinct, ...]
-    METADATA_LOCAL_VAR     = 28   // [distinct, ...]
+    METADATA_LOCAL_VAR     = 28,  // [distinct, ...]
+    METADATA_EXPRESSION    = 29   // [distinct, n x element]
   };
 
   // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
index 63eb963..2fd9861 100644 (file)
@@ -748,6 +748,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   DWKEYWORD(ATE, DwarfAttEncoding);
   DWKEYWORD(VIRTUALITY, DwarfVirtuality);
   DWKEYWORD(LANG, DwarfLang);
+  DWKEYWORD(OP, DwarfOp);
 #undef DWKEYWORD
 
   // Check for [us]0x[0-9A-Fa-f]+ which are Hexadecimal constant generated by
index 48dbaee..dc8367c 100644 (file)
@@ -3599,9 +3599,44 @@ bool LLParser::ParseMDLocalVariable(MDNode *&Result, bool IsDistinct) {
   return false;
 }
 
+/// ParseMDExpression:
+///   ::= !MDExpression(0, 7, -1)
 bool LLParser::ParseMDExpression(MDNode *&Result, bool IsDistinct) {
-  return TokError("unimplemented parser");
+  assert(Lex.getKind() == lltok::MetadataVar && "Expected metadata type name");
+  Lex.Lex();
+
+  if (ParseToken(lltok::lparen, "expected '(' here"))
+    return true;
+
+  SmallVector<uint64_t, 8> Elements;
+  if (Lex.getKind() != lltok::rparen)
+    do {
+      if (Lex.getKind() == lltok::DwarfOp) {
+        if (unsigned Op = dwarf::getOperationEncoding(Lex.getStrVal())) {
+          Lex.Lex();
+          Elements.push_back(Op);
+          continue;
+        }
+        return TokError(Twine("invalid DWARF op '") + Lex.getStrVal() + "'");
+      }
+
+      if (Lex.getKind() != lltok::APSInt || Lex.getAPSIntVal().isSigned())
+        return TokError("expected unsigned integer");
+
+      auto &U = Lex.getAPSIntVal();
+      if (U.ugt(UINT64_MAX))
+        return TokError("element too large, limit is " + Twine(UINT64_MAX));
+      Elements.push_back(U.getZExtValue());
+      Lex.Lex();
+    } while (EatIfPresent(lltok::comma));
+
+  if (ParseToken(lltok::rparen, "expected ')' here"))
+    return true;
+
+  Result = GET_OR_DISTINCT(MDExpression, (Context, Elements));
+  return false;
 }
+
 bool LLParser::ParseMDObjCProperty(MDNode *&Result, bool IsDistinct) {
   return TokError("unimplemented parser");
 }
index ff894df..57218da 100644 (file)
@@ -198,10 +198,11 @@ namespace lltok {
     LocalVar,          // %foo %"foo"
     MetadataVar,       // !foo
     StringConstant,    // "foo"
-    DwarfTag,          // DW_TAG_foo (includes "DW_TAG_")
-    DwarfAttEncoding,  // DW_ATE_foo (includes "DW_ATE_")
-    DwarfVirtuality,   // DW_VIRTUALITY_foo (includes "DW_VIRTUALITY_")
-    DwarfLang,         // DW_LANG_foo (includes "DW_LANG_")
+    DwarfTag,          // DW_TAG_foo
+    DwarfAttEncoding,  // DW_ATE_foo
+    DwarfVirtuality,   // DW_VIRTUALITY_foo
+    DwarfLang,         // DW_LANG_foo
+    DwarfOp,           // DW_OP_foo
 
     // Type valued tokens (TyVal).
     Type,
index 5dee2f9..98b4803 100644 (file)
@@ -1552,6 +1552,16 @@ std::error_code BitcodeReader::ParseMetadata() {
           NextMDValueNo++);
       break;
     }
+    case bitc::METADATA_EXPRESSION: {
+      if (Record.size() < 1)
+        return Error("Invalid record");
+
+      MDValueList.AssignValue(
+          GET_OR_DISTINCT(MDExpression, Record[0],
+                          (Context, makeArrayRef(Record).slice(1))),
+          NextMDValueNo++);
+      break;
+    }
     case bitc::METADATA_STRING: {
       std::string String(Record.begin(), Record.end());
       llvm::UpgradeMDStringConstant(String);
index 9feb4ff..6683e3e 100644 (file)
@@ -1092,11 +1092,20 @@ static void WriteMDLocalVariable(const MDLocalVariable *N,
   Record.clear();
 }
 
-static void WriteMDExpression(const MDExpression *, const ValueEnumerator &,
-                              BitstreamWriter &, SmallVectorImpl<uint64_t> &,
-                              unsigned) {
-  llvm_unreachable("write not implemented");
+static void WriteMDExpression(const MDExpression *N, const ValueEnumerator &,
+                              BitstreamWriter &Stream,
+                              SmallVectorImpl<uint64_t> &Record,
+                              unsigned Abbrev) {
+  Record.reserve(N->getElements().size() + 1);
+
+  Record.push_back(N->isDistinct());
+  for (uint64_t I : N->getElements())
+    Record.push_back(I);
+
+  Stream.EmitRecord(bitc::METADATA_EXPRESSION, Record, Abbrev);
+  Record.clear();
 }
+
 static void WriteMDObjCProperty(const MDObjCProperty *, const ValueEnumerator &,
                                 BitstreamWriter &, SmallVectorImpl<uint64_t> &,
                                 unsigned) {
index ae9a50c..5bfbe78 100644 (file)
@@ -1781,10 +1781,27 @@ static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N,
   Out << ")";
 }
 
-static void writeMDExpression(raw_ostream &, const MDExpression *,
-                              TypePrinting *, SlotTracker *, const Module *) {
-  llvm_unreachable("write not implemented");
+static void writeMDExpression(raw_ostream &Out, const MDExpression *N,
+                              TypePrinting *TypePrinter, SlotTracker *Machine,
+                              const Module *Context) {
+  Out << "!MDExpression(";
+  FieldSeparator FS;
+  if (N->isValid()) {
+    for (auto I = N->expr_op_begin(), E = N->expr_op_end(); I != E; ++I) {
+      const char *OpStr = dwarf::OperationEncodingString(I->getOp());
+      assert(OpStr && "Expected valid opcode");
+
+      Out << FS << OpStr;
+      for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A)
+        Out << FS << I->getArg(A);
+    }
+  } else {
+    for (const auto &I : N->getElements())
+      Out << FS << I;
+  }
+  Out << ")";
 }
+
 static void writeMDObjCProperty(raw_ostream &, const MDObjCProperty *,
                                 TypePrinting *, SlotTracker *, const Module *) {
   llvm_unreachable("write not implemented");
diff --git a/test/Assembler/invalid-mdexpression-large.ll b/test/Assembler/invalid-mdexpression-large.ll
new file mode 100644 (file)
index 0000000..43b8ce0
--- /dev/null
@@ -0,0 +1,7 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK-NOT: error
+!0 = !MDExpression(18446744073709551615)
+
+; CHECK: <stdin>:[[@LINE+1]]:20: error: element too large, limit is 18446744073709551615
+!1 = !MDExpression(18446744073709551616)
diff --git a/test/Assembler/invalid-mdexpression-verify.ll b/test/Assembler/invalid-mdexpression-verify.ll
new file mode 100644 (file)
index 0000000..e573ef3
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: not llvm-as -disable-output < %s 2>&1 | FileCheck -check-prefix VERIFY %s
+; RUN: llvm-as -disable-verify < %s | llvm-dis | FileCheck -check-prefix NOVERIFY %s
+
+; NOVERIFY: !named = !{!0}
+!named = !{!0}
+
+; NOVERIFY: !0 = !MDExpression(0, 1, 9, 7, 2)
+; VERIFY: assembly parsed, but does not verify
+!0 = !MDExpression(0, 1, 9, 7, 2)
diff --git a/test/Assembler/mdexpression.ll b/test/Assembler/mdexpression.ll
new file mode 100644 (file)
index 0000000..42bbfe0
--- /dev/null
@@ -0,0 +1,16 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+; CHECK: !named = !{!0, !1, !2, !3, !4}
+!named = !{!0, !1, !2, !3, !4}
+
+; CHECK:      !0 = !MDExpression()
+; CHECK-NEXT: !1 = !MDExpression(DW_OP_deref)
+; CHECK-NEXT: !2 = !MDExpression(DW_OP_plus, 3)
+; CHECK-NEXT: !3 = !MDExpression(DW_OP_bit_piece, 3, 7)
+; CHECK-NEXT: !4 = !MDExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7)
+!0 = !MDExpression()
+!1 = !MDExpression(DW_OP_deref)
+!2 = !MDExpression(DW_OP_plus, 3)
+!3 = !MDExpression(DW_OP_bit_piece, 3, 7)
+!4 = !MDExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7)
index e3e462f..6b4b8bb 100644 (file)
@@ -79,6 +79,7 @@ syn match   llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/
 syn match   llvmType /!\zs\a\+\ze\s*(/
 syn match   llvmConstant /\<DW_TAG_[a-z_]\+\>/
 syn match   llvmConstant /\<DW_ATE_[a-zA-Z_]\+\>/
+syn match   llvmConstant /\<DW_OP_[a-zA-Z0-9_]\+\>/
 syn match   llvmConstant /\<DW_LANG_[a-zA-Z0-9_]\+\>/
 syn match   llvmConstant /\<DW_VIRTUALITY_[a-z_]\+\>/