diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index 7232cb5af53..c221ad2dc90 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -151,7 +151,9 @@ namespace bitc { METADATA_SUBRANGE = 13, // [distinct, count, lo] METADATA_ENUMERATOR = 14, // [distinct, value, name?] METADATA_BASIC_TYPE = 15, // [distinct, tag, name, size, align, enc] - METADATA_FILE = 16 // [distinct, filename, directory] + METADATA_FILE = 16, // [distinct, filename, directory] + METADATA_DERIVED_TYPE = 17, // [distinct, ...] + METADATA_COMPOSITE_TYPE= 18 // [distinct, ...] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index c041a96cfeb..42ce206e3af 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -3233,12 +3233,61 @@ bool LLParser::ParseMDBasicType(MDNode *&Result, bool IsDistinct) { return false; } +/// ParseMDDerivedType: +/// ::= !MDDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, +/// line: 7, scope: !1, baseType: !2, size: 32, +/// align: 32, offset: 0, flags: 0, extraData: !3) bool LLParser::ParseMDDerivedType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + REQUIRED(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(extraData, MDField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT(MDDerivedType, + (Context, tag.Val, name.Val, file.Val, line.Val, + scope.Val, baseType.Val, size.Val, align.Val, + offset.Val, flags.Val, extraData.Val)); + return false; } + bool LLParser::ParseMDCompositeType(MDNode *&Result, bool IsDistinct) { - return TokError("unimplemented parser"); +#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ + REQUIRED(tag, DwarfTagField, ); \ + OPTIONAL(name, MDStringField, ); \ + OPTIONAL(file, MDField, ); \ + OPTIONAL(line, LineField, ); \ + OPTIONAL(scope, MDField, ); \ + OPTIONAL(baseType, MDField, ); \ + OPTIONAL(size, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(offset, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(flags, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(elements, MDField, ); \ + OPTIONAL(runtimeLang, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(vtableHolder, MDField, ); \ + OPTIONAL(templateParams, MDField, ); \ + OPTIONAL(identifier, MDStringField, ); + PARSE_MD_FIELDS(); +#undef VISIT_MD_FIELDS + + Result = GET_OR_DISTINCT( + MDCompositeType, + (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, + size.Val, align.Val, offset.Val, flags.Val, elements.Val, + runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val)); + return false; } + bool LLParser::ParseMDSubroutineType(MDNode *&Result, bool IsDistinct) { return TokError("unimplemented parser"); } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 2220c1dad87..6c38e0d85b4 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1183,12 +1183,17 @@ std::error_code BitcodeReader::ParseMetadata() { SmallVector Record; + auto getMD = + [&](unsigned ID) -> Metadata *{ return MDValueList.getValueFwdRef(ID); }; + auto getMDOrNull = [&](unsigned ID) -> Metadata *{ + if (ID) + return getMD(ID - 1); + return nullptr; + }; auto getMDString = [&](unsigned ID) -> MDString *{ // This requires that the ID is not really a forward reference. In // particular, the MDString must already have been resolved. - if (ID) - return cast(MDValueList.getValueFwdRef(ID - 1)); - return nullptr; + return cast_or_null(getMDOrNull(ID)); }; #define GET_OR_DISTINCT(CLASS, DISTINCT, ARGS) \ @@ -1382,6 +1387,36 @@ std::error_code BitcodeReader::ParseMetadata() { NextMDValueNo++); break; } + case bitc::METADATA_DERIVED_TYPE: { + if (Record.size() != 12) + return Error("Invalid record"); + + MDValueList.AssignValue( + GET_OR_DISTINCT(MDDerivedType, Record[0], + (Context, Record[1], getMDString(Record[2]), + getMDOrNull(Record[3]), Record[4], + getMDOrNull(Record[5]), getMD(Record[6]), Record[7], + Record[8], Record[9], Record[10], + getMDOrNull(Record[11]))), + NextMDValueNo++); + break; + } + case bitc::METADATA_COMPOSITE_TYPE: { + if (Record.size() != 16) + return Error("Invalid record"); + + MDValueList.AssignValue( + GET_OR_DISTINCT(MDCompositeType, Record[0], + (Context, Record[1], getMDString(Record[2]), + getMDOrNull(Record[3]), Record[4], + getMDOrNull(Record[5]), getMDOrNull(Record[6]), + Record[7], Record[8], Record[9], Record[10], + getMDOrNull(Record[11]), Record[12], + getMDOrNull(Record[13]), getMDOrNull(Record[14]), + getMDString(Record[15]))), + NextMDValueNo++); + break; + } case bitc::METADATA_FILE: { if (Record.size() != 3) return Error("Invalid record"); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 9460ff0a78b..0c1b1e127b9 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -853,16 +853,54 @@ static void WriteMDBasicType(const MDBasicType *N, const ValueEnumerator &VE, Record.clear(); } -static void WriteMDDerivedType(const MDDerivedType *, const ValueEnumerator &, - BitstreamWriter &, SmallVectorImpl &, - unsigned) { - llvm_unreachable("write not implemented"); +static void WriteMDDerivedType(const MDDerivedType *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back(N->isDistinct()); + Record.push_back(N->getTag()); + Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(N->getLine()); + Record.push_back(VE.getMetadataOrNullID(N->getScope())); + Record.push_back(VE.getMetadataID(N->getBaseType())); + Record.push_back(N->getSizeInBits()); + Record.push_back(N->getAlignInBits()); + Record.push_back(N->getOffsetInBits()); + Record.push_back(N->getFlags()); + Record.push_back(VE.getMetadataOrNullID(N->getExtraData())); + + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); + Record.clear(); } -static void WriteMDCompositeType(const MDCompositeType *, - const ValueEnumerator &, BitstreamWriter &, - SmallVectorImpl &, unsigned) { - llvm_unreachable("write not implemented"); + +static void WriteMDCompositeType(const MDCompositeType *N, + const ValueEnumerator &VE, + BitstreamWriter &Stream, + SmallVectorImpl &Record, + unsigned Abbrev) { + Record.push_back(N->isDistinct()); + Record.push_back(N->getTag()); + Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + Record.push_back(VE.getMetadataOrNullID(N->getFile())); + Record.push_back(N->getLine()); + Record.push_back(VE.getMetadataOrNullID(N->getScope())); + Record.push_back(VE.getMetadataOrNullID(N->getBaseType())); + Record.push_back(N->getSizeInBits()); + Record.push_back(N->getAlignInBits()); + Record.push_back(N->getOffsetInBits()); + Record.push_back(N->getFlags()); + Record.push_back(VE.getMetadataOrNullID(N->getElements())); + Record.push_back(N->getRuntimeLang()); + Record.push_back(VE.getMetadataOrNullID(N->getVTableHolder())); + Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams())); + Record.push_back(VE.getMetadataOrNullID(N->getRawIdentifier())); + + Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev); + Record.clear(); } + static void WriteMDSubroutineType(const MDSubroutineType *, const ValueEnumerator &, BitstreamWriter &, SmallVectorImpl &, unsigned) { diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 826794a2c04..77e2b2d64b9 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -1387,15 +1387,97 @@ static void writeMDBasicType(raw_ostream &Out, const MDBasicType *N, Out << ")"; } -static void writeMDDerivedType(raw_ostream &, const MDDerivedType *, - TypePrinting *, SlotTracker *, const Module *) { - llvm_unreachable("write not implemented"); +static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDDerivedType("; + FieldSeparator FS; + writeTag(Out, FS, N); + if (!N->getName().empty()) + Out << FS << "name: \"" << N->getName() << "\""; + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getScope()) { + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + } + Out << FS << "baseType: "; + writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine, Context); + if (N->getSizeInBits()) + Out << FS << "size: " << N->getSizeInBits(); + if (N->getAlignInBits()) + Out << FS << "align: " << N->getAlignInBits(); + if (N->getOffsetInBits()) + Out << FS << "offset: " << N->getOffsetInBits(); + if (N->getFlags()) + Out << FS << "flags: " << N->getFlags(); + if (N->getExtraData()) { + Out << FS << "extraData: "; + writeMetadataAsOperand(Out, N->getExtraData(), TypePrinter, Machine, + Context); + } + Out << ")"; } -static void writeMDCompositeType(raw_ostream &, const MDCompositeType *, - TypePrinting *, SlotTracker *, - const Module *) { - llvm_unreachable("write not implemented"); + +static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context) { + Out << "!MDCompositeType("; + FieldSeparator FS; + writeTag(Out, FS, N); + if (!N->getName().empty()) + Out << FS << "name: \"" << N->getName() << "\""; + if (N->getFile()) { + Out << FS << "file: "; + writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, + Context); + } + if (N->getLine()) + Out << FS << "line: " << N->getLine(); + if (N->getScope()) { + Out << FS << "scope: "; + writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context); + } + if (N->getBaseType()) { + Out << FS << "baseType: "; + writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine, + Context); + } + if (N->getSizeInBits()) + Out << FS << "size: " << N->getSizeInBits(); + if (N->getAlignInBits()) + Out << FS << "align: " << N->getAlignInBits(); + if (N->getOffsetInBits()) + Out << FS << "offset: " << N->getOffsetInBits(); + if (N->getFlags()) + Out << FS << "flags: " << N->getFlags(); + if (N->getElements()) { + Out << FS << "elements: "; + writeMetadataAsOperand(Out, N->getElements(), TypePrinter, Machine, + Context); + } + if (N->getRuntimeLang()) + Out << FS << "runtimeLang: " << N->getRuntimeLang(); + if (N->getVTableHolder()) { + Out << FS << "vtableHolder: "; + writeMetadataAsOperand(Out, N->getVTableHolder(), TypePrinter, Machine, + Context); + } + if (N->getTemplateParams()) { + Out << FS << "templateParams: "; + writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine, + Context); + } + if (!N->getIdentifier().empty()) + Out << FS << "identifier: \"" << N->getIdentifier() << "\""; + Out << ")"; } + static void writeMDSubroutineType(raw_ostream &, const MDSubroutineType *, TypePrinting *, SlotTracker *, const Module *) { diff --git a/test/Assembler/debug-info.ll b/test/Assembler/debug-info.ll index 3a3a3ef53d3..b4b29fe77a2 100644 --- a/test/Assembler/debug-info.ll +++ b/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, !9, !10, !11, !12} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14} +; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25} ; CHECK: !0 = !MDSubrange(count: 3) ; CHECK-NEXT: !1 = !MDSubrange(count: 3, lowerBound: 4) @@ -36,3 +36,27 @@ !12 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") !13 = !{null, null} !14 = !MDFile(filename: "", directory: "") + +; CHECK-NEXT: !13 = !MDDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 32, align: 32) +!15 = !MDDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 32, align: 32) + +; CHECK-NEXT: !14 = !MDCompositeType(tag: DW_TAG_structure_type, name: "MyType", file: !9, line: 2, size: 32, align: 32, identifier: "MangledMyType") +; CHECK-NEXT: !15 = distinct !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !9, line: 3, scope: !14, size: 128, align: 32, offset: 64, flags: 3, elements: !16, runtimeLang: 6, vtableHolder: !15, templateParams: !18, identifier: "MangledBase") +; CHECK-NEXT: !16 = !{!17} +; CHECK-NEXT: !17 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !9, line: 4, scope: !15, baseType: !6, size: 32, align: 32, offset: 32, flags: 3) +; CHECK-NEXT: !18 = !{!6} +; CHECK-NEXT: !19 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !9, line: 3, scope: !14, baseType: !15, size: 128, align: 32, offset: 64, flags: 3, elements: !20, runtimeLang: 6, vtableHolder: !15, templateParams: !18, identifier: "MangledBase") +; CHECK-NEXT: !20 = !{!21} +; CHECK-NEXT: !21 = !MDDerivedType(tag: DW_TAG_inheritance, scope: !19, baseType: !15) +; CHECK-NEXT: !22 = !MDDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !6, size: 32, align: 32, extraData: !15) +; CHECK-NEXT: !23 = !MDCompositeType(tag: DW_TAG_structure_type) +!16 = !MDCompositeType(tag: DW_TAG_structure_type, name: "MyType", file: !11, line: 2, size: 32, align: 32, identifier: "MangledMyType") +!17 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Base", file: !11, line: 3, scope: !16, size: 128, align: 32, offset: 64, flags: 3, elements: !18, runtimeLang: 6, vtableHolder: !17, templateParams: !20, identifier: "MangledBase") +!18 = !{!19} +!19 = !MDDerivedType(tag: DW_TAG_member, name: "field", file: !11, line: 4, scope: !17, baseType: !7, size: 32, align: 32, offset: 32, flags: 3) +!20 = !{!7} +!21 = !MDCompositeType(tag: DW_TAG_structure_type, name: "Derived", file: !11, line: 3, scope: !16, baseType: !17, size: 128, align: 32, offset: 64, flags: 3, elements: !22, runtimeLang: 6, vtableHolder: !17, templateParams: !20, identifier: "MangledBase") +!22 = !{!23} +!23 = !MDDerivedType(tag: DW_TAG_inheritance, scope: !21, baseType: !17) +!24 = !MDDerivedType(tag: DW_TAG_ptr_to_member_type, baseType: !7, size: 32, align: 32, extraData: !17) +!25 = !MDCompositeType(tag: DW_TAG_structure_type) diff --git a/test/Assembler/invalid-mdcompositetype-missing-tag.ll b/test/Assembler/invalid-mdcompositetype-missing-tag.ll new file mode 100644 index 00000000000..a3b1418d9bc --- /dev/null +++ b/test/Assembler/invalid-mdcompositetype-missing-tag.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: [[@LINE+1]]:36: error: missing required field 'tag' +!25 = !MDCompositeType(name: "Type") diff --git a/test/Assembler/invalid-mdderivedtype-missing-basetype.ll b/test/Assembler/invalid-mdderivedtype-missing-basetype.ll new file mode 100644 index 00000000000..24fa5850d9f --- /dev/null +++ b/test/Assembler/invalid-mdderivedtype-missing-basetype.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: [[@LINE+1]]:45: error: missing required field 'baseType' +!0 = !MDDerivedType(tag: DW_TAG_pointer_type) diff --git a/test/Assembler/invalid-mdderivedtype-missing-tag.ll b/test/Assembler/invalid-mdderivedtype-missing-tag.ll new file mode 100644 index 00000000000..36206281aeb --- /dev/null +++ b/test/Assembler/invalid-mdderivedtype-missing-tag.ll @@ -0,0 +1,4 @@ +; RUN: not llvm-as < %s -disable-output 2>&1 | FileCheck %s + +; CHECK: [[@LINE+1]]:34: error: missing required field 'tag' +!0 = !MDDerivedType(baseType: !{})