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

include/llvm/Bitcode/LLVMBitCodes.h
include/llvm/IR/DebugInfoMetadata.h
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/AsmWriter.cpp
test/Assembler/invalid-mdsubprogram-missing-name.ll [new file with mode: 0644]
test/Assembler/mdsubprogram.ll [new file with mode: 0644]

index be35428fa05e79f2b854576266d6c24f013d3222..1936e3434d67bb0e69ee82c6631727e11f78192f 100644 (file)
@@ -155,7 +155,8 @@ namespace bitc {
     METADATA_DERIVED_TYPE  = 17,  // [distinct, ...]
     METADATA_COMPOSITE_TYPE= 18,  // [distinct, ...]
     METADATA_SUBROUTINE_TYPE=19,  // [distinct, flags, types]
     METADATA_DERIVED_TYPE  = 17,  // [distinct, ...]
     METADATA_COMPOSITE_TYPE= 18,  // [distinct, ...]
     METADATA_SUBROUTINE_TYPE=19,  // [distinct, flags, types]
-    METADATA_COMPILE_UNIT  = 20   // [distinct, ...]
+    METADATA_COMPILE_UNIT  = 20,  // [distinct, ...]
+    METADATA_SUBPROGRAM    = 21   // [distinct, ...]
   };
 
   // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
   };
 
   // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
index 6c47f755827b290d07d38455c2790ef17cc0066b..64af1a873efe5d766e78ee2553f8598b58dfb137 100644 (file)
@@ -957,6 +957,9 @@ public:
   StringRef getDisplayName() const { return getStringOperand(3); }
   StringRef getLinkageName() const { return getStringOperand(4); }
 
   StringRef getDisplayName() const { return getStringOperand(3); }
   StringRef getLinkageName() const { return getStringOperand(4); }
 
+  MDString *getRawName() const { return getOperandAs<MDString>(2); }
+  MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); }
+
   Metadata *getType() const { return getOperand(5); }
   Metadata *getContainingType() const { return getOperand(6); }
 
   Metadata *getType() const { return getOperand(5); }
   Metadata *getContainingType() const { return getOperand(6); }
 
index d7bf205ce0000139ed216c4e9b4a80e0a916fa2e..9c3bb4a58364d5560ef6d29f3ccd956134d5859b 100644 (file)
@@ -2969,6 +2969,9 @@ struct MDBoolField : public MDFieldImpl<bool> {
 struct MDField : public MDFieldImpl<Metadata *> {
   MDField() : ImplTy(nullptr) {}
 };
 struct MDField : public MDFieldImpl<Metadata *> {
   MDField() : ImplTy(nullptr) {}
 };
+struct MDConstant : public MDFieldImpl<ConstantAsMetadata *> {
+  MDConstant() : ImplTy(nullptr) {}
+};
 struct MDStringField : public MDFieldImpl<std::string> {
   MDStringField() : ImplTy(std::string()) {}
 };
 struct MDStringField : public MDFieldImpl<std::string> {
   MDStringField() : ImplTy(std::string()) {}
 };
@@ -3098,6 +3101,12 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDBoolField &Result) {
 
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
 
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
+  if (Lex.getKind() == lltok::kw_null) {
+    Lex.Lex();
+    Result.assign(nullptr);
+    return false;
+  }
+
   Metadata *MD;
   if (ParseMetadata(MD, nullptr))
     return true;
   Metadata *MD;
   if (ParseMetadata(MD, nullptr))
     return true;
@@ -3106,6 +3115,16 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) {
   return false;
 }
 
   return false;
 }
 
+template <>
+bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDConstant &Result) {
+  Metadata *MD;
+  if (ParseValueAsMetadata(MD, "expected constant", nullptr))
+    return true;
+
+  Result.assign(cast<ConstantAsMetadata>(MD));
+  return false;
+}
+
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
   std::string S;
 template <>
 bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
   std::string S;
@@ -3385,9 +3404,45 @@ bool LLParser::ParseMDCompileUnit(MDNode *&Result, bool IsDistinct) {
   return false;
 }
 
   return false;
 }
 
+/// ParseMDSubprogram:
+///   ::= !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoo",
+///                     file: !1, line: 7, type: !2, isLocal: false,
+///                     isDefinition: true, scopeLine: 8, containingType: !3,
+///                     virtuality: 2, virtualIndex: 10, flags: 11,
+///                     isOptimized: false, function: void ()* @_Z3foov,
+///                     templateParams: !4, declaration: !5, variables: !6)
 bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) {
 bool LLParser::ParseMDSubprogram(MDNode *&Result, bool IsDistinct) {
-  return TokError("unimplemented parser");
+#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
+  OPTIONAL(scope, MDField, );                                                  \
+  REQUIRED(name, MDStringField, );                                             \
+  OPTIONAL(linkageName, MDStringField, );                                      \
+  OPTIONAL(file, MDField, );                                                   \
+  OPTIONAL(line, LineField, );                                                 \
+  OPTIONAL(type, MDField, );                                                   \
+  OPTIONAL(isLocal, MDBoolField, );                                            \
+  OPTIONAL(isDefinition, MDBoolField, (true));                                 \
+  OPTIONAL(scopeLine, LineField, );                                            \
+  OPTIONAL(containingType, MDField, );                                         \
+  OPTIONAL(virtuality, MDUnsignedField, (0, dwarf::DW_VIRTUALITY_max));        \
+  OPTIONAL(virtualIndex, MDUnsignedField, (0, UINT32_MAX));                    \
+  OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(isOptimized, MDBoolField, );                                        \
+  OPTIONAL(function, MDConstant, );                                            \
+  OPTIONAL(templateParams, MDField, );                                         \
+  OPTIONAL(declaration, MDField, );                                            \
+  OPTIONAL(variables, MDField, );
+  PARSE_MD_FIELDS();
+#undef VISIT_MD_FIELDS
+
+  Result = GET_OR_DISTINCT(
+      MDSubprogram, (Context, scope.Val, name.Val, linkageName.Val, file.Val,
+                     line.Val, type.Val, isLocal.Val, isDefinition.Val,
+                     scopeLine.Val, containingType.Val, virtuality.Val,
+                     virtualIndex.Val, flags.Val, isOptimized.Val, function.Val,
+                     templateParams.Val, declaration.Val, variables.Val));
+  return false;
 }
 }
+
 bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) {
   return TokError("unimplemented parser");
 }
 bool LLParser::ParseMDLexicalBlock(MDNode *&Result, bool IsDistinct) {
   return TokError("unimplemented parser");
 }
@@ -3444,10 +3499,11 @@ bool LLParser::ParseMetadataAsValue(Value *&V, PerFunctionState &PFS) {
 ///  ::= i32 %local
 ///  ::= i32 @global
 ///  ::= i32 7
 ///  ::= i32 %local
 ///  ::= i32 @global
 ///  ::= i32 7
-bool LLParser::ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS) {
+bool LLParser::ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
+                                    PerFunctionState *PFS) {
   Type *Ty;
   LocTy Loc;
   Type *Ty;
   LocTy Loc;
-  if (ParseType(Ty, "expected metadata operand", Loc))
+  if (ParseType(Ty, TypeMsg, Loc))
     return true;
   if (Ty->isMetadataTy())
     return Error(Loc, "invalid metadata-value-metadata roundtrip");
     return true;
   if (Ty->isMetadataTy())
     return Error(Loc, "invalid metadata-value-metadata roundtrip");
@@ -3480,7 +3536,7 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
   // ValueAsMetadata:
   // <type> <value>
   if (Lex.getKind() != lltok::exclaim)
   // ValueAsMetadata:
   // <type> <value>
   if (Lex.getKind() != lltok::exclaim)
-    return ParseValueAsMetadata(MD, PFS);
+    return ParseValueAsMetadata(MD, "expected metadata operand", PFS);
 
   // '!'.
   assert(Lex.getKind() == lltok::exclaim && "Expected '!' here");
 
   // '!'.
   assert(Lex.getKind() == lltok::exclaim && "Expected '!' here");
index 368c3054b193fd4b8d1e5d5a37dbfcc010b54092..5e92e570e7267c5025d72d50bc7af98f2192c9db 100644 (file)
@@ -385,7 +385,8 @@ namespace llvm {
     bool ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts);
     bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
     bool ParseMetadataAsValue(Value *&V, PerFunctionState &PFS);
     bool ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts);
     bool parseOptionalComdat(StringRef GlobalName, Comdat *&C);
     bool ParseMetadataAsValue(Value *&V, PerFunctionState &PFS);
-    bool ParseValueAsMetadata(Metadata *&MD, PerFunctionState *PFS);
+    bool ParseValueAsMetadata(Metadata *&MD, const Twine &TypeMsg,
+                              PerFunctionState *PFS);
     bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS);
     bool ParseMDTuple(MDNode *&MD, bool IsDistinct = false);
     bool ParseMDNode(MDNode *&MD);
     bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS);
     bool ParseMDTuple(MDNode *&MD, bool IsDistinct = false);
     bool ParseMDNode(MDNode *&MD);
index d1c122f70ab77e2dc054d1c78bc89aa60065b11e..12996d19e0dd1681d16f86411712261283aa6cda 100644 (file)
@@ -1452,6 +1452,22 @@ std::error_code BitcodeReader::ParseMetadata() {
           NextMDValueNo++);
       break;
     }
           NextMDValueNo++);
       break;
     }
+    case bitc::METADATA_SUBPROGRAM: {
+      if (Record.size() != 19)
+        return Error("Invalid record");
+
+      MDValueList.AssignValue(
+          GET_OR_DISTINCT(
+              MDSubprogram, Record[0],
+              (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
+               getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
+               getMDOrNull(Record[6]), Record[7], Record[8], Record[9],
+               getMDOrNull(Record[10]), Record[11], Record[12], Record[13],
+               Record[14], getMDOrNull(Record[15]), getMDOrNull(Record[16]),
+               getMDOrNull(Record[17]), getMDOrNull(Record[18]))),
+          NextMDValueNo++);
+      break;
+    }
     case bitc::METADATA_STRING: {
       std::string String(Record.begin(), Record.end());
       llvm::UpgradeMDStringConstant(String);
     case bitc::METADATA_STRING: {
       std::string String(Record.begin(), Record.end());
       llvm::UpgradeMDStringConstant(String);
index 5e27f30a48d8fd6a7f6cc7fb64e4c0e2c3ecb0bd..f0453fff122f8af691cde63b40cb4563475f00bb 100644 (file)
@@ -949,11 +949,35 @@ static void WriteMDCompileUnit(const MDCompileUnit *N,
   Record.clear();
 }
 
   Record.clear();
 }
 
-static void WriteMDSubprogram(const MDSubprogram *, const ValueEnumerator &,
-                              BitstreamWriter &, SmallVectorImpl<uint64_t> &,
-                              unsigned) {
-  llvm_unreachable("write not implemented");
+static void WriteMDSubprogram(const MDSubprogram *N,
+                               const ValueEnumerator &VE,
+                               BitstreamWriter &Stream,
+                               SmallVectorImpl<uint64_t> &Record,
+                               unsigned Abbrev) {
+  Record.push_back(N->isDistinct());
+  Record.push_back(VE.getMetadataOrNullID(N->getScope()));
+  Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
+  Record.push_back(VE.getMetadataOrNullID(N->getRawLinkageName()));
+  Record.push_back(VE.getMetadataOrNullID(N->getFile()));
+  Record.push_back(N->getLine());
+  Record.push_back(VE.getMetadataOrNullID(N->getType()));
+  Record.push_back(N->isLocalToUnit());
+  Record.push_back(N->isDefinition());
+  Record.push_back(N->getScopeLine());
+  Record.push_back(VE.getMetadataOrNullID(N->getContainingType()));
+  Record.push_back(N->getVirtuality());
+  Record.push_back(N->getVirtualIndex());
+  Record.push_back(N->getFlags());
+  Record.push_back(N->isOptimized());
+  Record.push_back(VE.getMetadataOrNullID(N->getFunction()));
+  Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams()));
+  Record.push_back(VE.getMetadataOrNullID(N->getDeclaration()));
+  Record.push_back(VE.getMetadataOrNullID(N->getVariables()));
+
+  Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, Record, Abbrev);
+  Record.clear();
 }
 }
+
 static void WriteMDLexicalBlock(const MDLexicalBlock *, const ValueEnumerator &,
                                 BitstreamWriter &, SmallVectorImpl<uint64_t> &,
                                 unsigned) {
 static void WriteMDLexicalBlock(const MDLexicalBlock *, const ValueEnumerator &,
                                 BitstreamWriter &, SmallVectorImpl<uint64_t> &,
                                 unsigned) {
index cf002e4d7f9cdbe7e886403189b63eafbee16433..fbc12ae7ec4e1c59c96e2d0d51cc49390b218104 100644 (file)
@@ -1557,10 +1557,67 @@ static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N,
   Out << ")";
 }
 
   Out << ")";
 }
 
-static void writeMDSubprogram(raw_ostream &, const MDSubprogram *,
-                              TypePrinting *, SlotTracker *, const Module *) {
-  llvm_unreachable("write not implemented");
+static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N,
+                              TypePrinting *TypePrinter, SlotTracker *Machine,
+                              const Module *Context) {
+  Out << "!MDSubprogram(";
+  FieldSeparator FS;
+  Out << FS << "scope: ";
+  writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+  Out << FS << "name: \"" << N->getName() << "\"";
+  if (!N->getLinkageName().empty())
+    Out << FS << "linkageName: \"" << N->getLinkageName() << "\"";
+  if (N->getFile()) {
+    Out << FS << "file: ";
+    writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+                           Context);
+  }
+  if (N->getLine())
+    Out << FS << "line: " << N->getLine();
+  if (N->getType()) {
+    Out << FS << "type: ";
+    writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine,
+                           Context);
+  }
+  Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false");
+  Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false");
+  if (N->getScopeLine())
+    Out << FS << "scopeLine: " << N->getScopeLine();
+  if (N->getContainingType()) {
+    Out << FS << "containingType: ";
+    writeMetadataAsOperand(Out, N->getContainingType(), TypePrinter, Machine,
+                           Context);
+  }
+  if (N->getVirtuality())
+    Out << FS << "virtuality: " << N->getVirtuality();
+  if (N->getVirtualIndex())
+    Out << FS << "virtualIndex: " << N->getVirtualIndex();
+  if (N->getFlags())
+    Out << FS << "flags: " << N->getFlags();
+  Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false");
+  if (N->getFunction()) {
+    Out << FS << "function: ";
+    writeMetadataAsOperand(Out, N->getFunction(), TypePrinter, Machine,
+                           Context);
+  }
+  if (N->getTemplateParams()) {
+    Out << FS << "templateParams: ";
+    writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine,
+                           Context);
+  }
+  if (N->getDeclaration()) {
+    Out << FS << "declaration: ";
+    writeMetadataAsOperand(Out, N->getDeclaration(), TypePrinter, Machine,
+                           Context);
+  }
+  if (N->getVariables()) {
+    Out << FS << "variables: ";
+    writeMetadataAsOperand(Out, N->getVariables(), TypePrinter, Machine,
+                           Context);
+  }
+  Out << ")";
 }
 }
+
 static void writeMDLexicalBlock(raw_ostream &, const MDLexicalBlock *,
                                 TypePrinting *, SlotTracker *, const Module *) {
   llvm_unreachable("write not implemented");
 static void writeMDLexicalBlock(raw_ostream &, const MDLexicalBlock *,
                                 TypePrinting *, SlotTracker *, const Module *) {
   llvm_unreachable("write not implemented");
diff --git a/test/Assembler/invalid-mdsubprogram-missing-name.ll b/test/Assembler/invalid-mdsubprogram-missing-name.ll
new file mode 100644 (file)
index 0000000..54ded22
--- /dev/null
@@ -0,0 +1,4 @@
+; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s
+
+; CHECK: <stdin>:[[@LINE+1]]:38: error: missing required field 'name'
+!0 = !MDSubprogram(linkageName: "foo")
diff --git a/test/Assembler/mdsubprogram.ll b/test/Assembler/mdsubprogram.ll
new file mode 100644 (file)
index 0000000..cbf907b
--- /dev/null
@@ -0,0 +1,28 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder %s
+
+declare void @_Z3foov()
+
+; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
+
+!0 = distinct !{}
+!1 = !{!"path/to/file", !"/path/to/dir"}
+!2 = !MDFile(filename: "path/to/file", directory: "/path/to/dir")
+!3 = distinct !{}
+!4 = distinct !{}
+!5 = distinct !{}
+!6 = distinct !{}
+!7 = distinct !{}
+
+; CHECK: !8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov", file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, scopeLine: 8, containingType: !4, virtuality: 2, virtualIndex: 10, flags: 11, isOptimized: true, function: void ()* @_Z3foov, templateParams: !5, declaration: !6, variables: !7)
+!8 = !MDSubprogram(scope: !0, name: "foo", linkageName: "_Zfoov",
+                   file: !2, line: 7, type: !3, isLocal: true,
+                   isDefinition: false, scopeLine: 8, containingType: !4,
+                   virtuality: 2, virtualIndex: 10, flags: 11,
+                   isOptimized: true, function: void ()* @_Z3foov,
+                   templateParams: !5, declaration: !6, variables: !7)
+
+; CHECK: !9 = !MDSubprogram(scope: null, name: "bar", isLocal: false, isDefinition: true, isOptimized: false)
+!9 = !MDSubprogram(name: "bar")
+