diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h index 5856fdfbcb74..7232cb5af539 100644 --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -150,7 +150,8 @@ namespace bitc { METADATA_GENERIC_DEBUG = 12, // [distinct, tag, vers, header, n x md num] METADATA_SUBRANGE = 13, // [distinct, count, lo] METADATA_ENUMERATOR = 14, // [distinct, value, name?] - METADATA_BASIC_TYPE = 15 // [distinct, tag, name, size, align, enc] + METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] + METADATA_FILE = 16 // [distinct, filename, directory] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index b2a2ef38a47b..9a0546ae17b1 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -733,16 +733,23 @@ public: MDTuple *getFileNode() const { return cast(getOperand(0)); } StringRef getFilename() const { - if (auto *S = cast_or_null(getFileNode()->getOperand(0))) + if (auto *S = getRawFilename()) return S->getString(); return StringRef(); } StringRef getDirectory() const { - if (auto *S = cast_or_null(getFileNode()->getOperand(1))) + if (auto *S = getRawDirectory()) return S->getString(); return StringRef(); } + MDString *getRawFilename() const { + return cast_or_null(getFileNode()->getOperand(0)); + } + MDString *getRawDirectory() const { + return cast_or_null(getFileNode()->getOperand(1)); + } + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDFileKind; } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 992ad1092be8..c041a96cfeb3 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3242,9 +3242,20 @@ bool LLParser::ParseMDCompositeType(MDNode *&Result, bool IsDistinct) { bool LLParser::ParseMDSubroutineType(MDNode *&Result, bool IsDistinct) { return TokError("unimplemented parser"); } + +/// ParseMDFileType: +/// ::= !MDFileType(filename: "path/to/file", directory: "/path/to/dir") bool LLParser::ParseMDFile(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(filename, MDStringField, ); \ + REQUIRED(directory, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDFile, (Context, filename.Val, directory.Val)); + return false; } + bool LLParser::ParseMDCompileUnit(MDNode *&Result, bool IsDistinct) { return TokError("unimplemented parser"); } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 2d0364945f71..2220c1dad877 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1382,6 +1382,16 @@ std::error_code BitcodeReader::ParseMetadata() { NextMDValueNo++); break; } + case bitc::METADATA_FILE: { + if (Record.size() != 3) + return Error("Invalid record"); + + MDValueList.AssignValue( + GET_OR_DISTINCT(MDFile, Record[0], (Context, getMDString(Record[1]), + getMDString(Record[2]))), + NextMDValueNo++); + break; + } case bitc::METADATA_STRING: { std::string String(Record.begin(), Record.end()); llvm::UpgradeMDStringConstant(String); diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 47c414eea8a6..9460ff0a78b0 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -868,11 +868,18 @@ static void WriteMDSubroutineType(const MDSubroutineType *, SmallVectorImpl &, unsigned) { llvm_unreachable("write not implemented"); } -static void WriteMDFile(const MDFile *, const ValueEnumerator &, - BitstreamWriter &, SmallVectorImpl &, - unsigned) { - llvm_unreachable("write not implemented"); + +static void WriteMDFile(const MDFile *N, const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &Record, unsigned Abbrev) { + Record.push_back(N->isDistinct()); + Record.push_back(VE.getMetadataOrNullID(N->getRawFilename())); + Record.push_back(VE.getMetadataOrNullID(N->getRawDirectory())); + + Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev); + Record.clear(); } + static void WriteMDCompileUnit(const MDCompileUnit *, const ValueEnumerator &, BitstreamWriter &, SmallVectorImpl &, unsigned) { diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index c2d25140d7ab..826794a2c042 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1401,10 +1401,16 @@ static void writeMDSubroutineType(raw_ostream &, const MDSubroutineType *, const Module *) { llvm_unreachable("write not implemented"); } -static void writeMDFile(raw_ostream &, const MDFile *, TypePrinting *, + +static void writeMDFile(raw_ostream &Out, const MDFile *N, TypePrinting *, SlotTracker *, const Module *) { - llvm_unreachable("write not implemented"); + Out << "!MDFile("; + FieldSeparator FS; + Out << FS << "filename: \"" << N->getFilename() << "\""; + Out << FS << "directory: \"" << N->getDirectory() << "\""; + Out << ")"; } + static void writeMDCompileUnit(raw_ostream &, const MDCompileUnit *, TypePrinting *, SlotTracker *, const Module *) { llvm_unreachable("write not implemented"); diff --git a/llvm/test/Assembler/debug-info.ll b/llvm/test/Assembler/debug-info.ll index d376fea3a2fb..3a3a3ef53d32 100644 --- a/llvm/test/Assembler/debug-info.ll +++ b/llvm/test/Assembler/debug-info.ll @@ -1,8 +1,8 @@ ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s ; RUN: verify-uselistorder %s -; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10} +; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14} ; CHECK: !0 = !MDSubrange(count: 3) ; CHECK-NEXT: !1 = !MDSubrange(count: 3, lowerBound: 4) @@ -27,3 +27,12 @@ !8 = !MDBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") !9 = !MDBasicType(tag: DW_TAG_base_type) !10 = !MDBasicType(tag: DW_TAG_base_type, name: "", size: 0, align: 0, encoding: 0) + +; CHECK-NEXT: !9 = !{!"path/to/file", !"/path/to/dir"} +; CHECK-NEXT: !10 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") +; CHECK-NEXT: !11 = !{null, null} +; CHECK-NEXT: !12 = !MDFile(filename: "", directory: "") +!11 = !{!"path/to/file", !"/path/to/dir"} +!12 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") +!13 = !{null, null} +!14 = !MDFile(filename: "", directory: "") diff --git a/llvm/test/Assembler/invalid-mdfile-missing-directory.ll b/llvm/test/Assembler/invalid-mdfile-missing-directory.ll new file mode 100644 index 000000000000..825db0896566 --- /dev/null +++ b/llvm/test/Assembler/invalid-mdfile-missing-directory.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: [[@LINE+1]]:30: error: missing required field 'directory' +!0 = !MDFile(filename: "file") diff --git a/llvm/test/Assembler/invalid-mdfile-missing-filename.ll b/llvm/test/Assembler/invalid-mdfile-missing-filename.ll new file mode 100644 index 000000000000..0dd71179105d --- /dev/null +++ b/llvm/test/Assembler/invalid-mdfile-missing-filename.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: [[@LINE+1]]:30: error: missing required field 'filename' +!0 = !MDFile(directory: "dir")