diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index be35428fa05..1936e3434d6 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -155,7 +155,8 @@ namespace bitc { 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 diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 6c47f755827..64af1a873ef 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -957,6 +957,9 @@ public: StringRef getDisplayName() const { return getStringOperand(3); } StringRef getLinkageName() const { return getStringOperand(4); } + MDString *getRawName() const { return getOperandAs(2); } + MDString *getRawLinkageName() const { return getOperandAs(4); } + Metadata *getType() const { return getOperand(5); } Metadata *getContainingType() const { return getOperand(6); } diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index d7bf205ce00..9c3bb4a5836 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2969,6 +2969,9 @@ struct MDBoolField : public MDFieldImpl { struct MDField : public MDFieldImpl { MDField() : ImplTy(nullptr) {} }; +struct MDConstant : public MDFieldImpl { + MDConstant() : ImplTy(nullptr) {} +}; struct MDStringField : public MDFieldImpl { 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) { + if (Lex.getKind() == lltok::kw_null) { + Lex.Lex(); + Result.assign(nullptr); + return false; + } + Metadata *MD; if (ParseMetadata(MD, nullptr)) return true; @@ -3106,6 +3115,16 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDField &Result) { 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(MD)); + return false; +} + 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; } +/// 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) { - 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"); } @@ -3444,10 +3499,11 @@ bool LLParser::ParseMetadataAsValue(Value *&V, PerFunctionState &PFS) { /// ::= 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; - 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"); @@ -3480,7 +3536,7 @@ bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) { // ValueAsMetadata: // if (Lex.getKind() != lltok::exclaim) - return ParseValueAsMetadata(MD, PFS); + return ParseValueAsMetadata(MD, "expected metadata operand", PFS); // '!'. assert(Lex.getKind() == lltok::exclaim && "Expected '!' here"); diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 368c3054b19..5e92e570e72 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -385,7 +385,8 @@ namespace llvm { bool ParseGlobalValueVector(SmallVectorImpl &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); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index d1c122f70ab..12996d19e0d 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1452,6 +1452,22 @@ std::error_code BitcodeReader::ParseMetadata() { 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); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 5e27f30a48d..f0453fff122 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -949,11 +949,35 @@ static void WriteMDCompileUnit(const MDCompileUnit *N, Record.clear(); } -static void WriteMDSubprogram(const MDSubprogram *, const ValueEnumerator &, - BitstreamWriter &, SmallVectorImpl &, - unsigned) { - llvm_unreachable("write not implemented"); +static void WriteMDSubprogram(const MDSubprogram *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &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 &, unsigned) { diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index cf002e4d7f9..fbc12ae7ec4 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1557,10 +1557,67 @@ static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N, 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"); diff --git a/test/Assembler/invalid-mdsubprogram-missing-name.ll b/test/Assembler/invalid-mdsubprogram-missing-name.ll new file mode 100644 index 00000000000..54ded222231 --- /dev/null +++ b/test/Assembler/invalid-mdsubprogram-missing-name.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: :[[@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 index 00000000000..cbf907b6107 --- /dev/null +++ b/test/Assembler/mdsubprogram.ll @@ -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") +