diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -279,12 +279,13 @@ /// \param OffsetInBits Member offset. /// \param Flags Flags to encode member attribute, e.g. private /// \param Ty Parent type. + /// \param Annotations Member annotations. DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, - uint64_t SizeInBits, - uint32_t AlignInBits, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, - DINode::DIFlags Flags, DIType *Ty); + DINode::DIFlags Flags, DIType *Ty, + DINodeArray Annotations = nullptr); /// Create debugging information entry for a variant. A variant /// normally should be a member of a variant part. @@ -317,10 +318,14 @@ /// \param StorageOffsetInBits Member storage offset. /// \param Flags Flags to encode member attribute. /// \param Ty Parent type. - DIDerivedType *createBitFieldMemberType( - DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo, - uint64_t SizeInBits, uint64_t OffsetInBits, - uint64_t StorageOffsetInBits, DINode::DIFlags Flags, DIType *Ty); + /// \param Annotations Member annotations. + DIDerivedType *createBitFieldMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + uint64_t SizeInBits, + uint64_t OffsetInBits, + uint64_t StorageOffsetInBits, + DINode::DIFlags Flags, DIType *Ty, + DINodeArray Annotations = nullptr); /// Create debugging information entry for a /// C++ static data member. diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -936,25 +936,26 @@ unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { + Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); - } - static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint32_t AlignInBits, - uint64_t OffsetInBits, - Optional DWARFAddressSpace, - DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate = true); + DWARFAddressSpace, Flags, ExtraData, Annotations.get(), + Storage, ShouldCreate); + } + static DIDerivedType * + getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, + unsigned Line, Metadata *Scope, Metadata *BaseType, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + Optional DWARFAddressSpace, DIFlags Flags, + Metadata *ExtraData, Metadata *Annotations, StorageType Storage, + bool ShouldCreate = true); TempDIDerivedType cloneImpl() const { - return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), - getScope(), getBaseType(), getSizeInBits(), - getAlignInBits(), getOffsetInBits(), - getDWARFAddressSpace(), getFlags(), getExtraData()); + return getTemporary( + getContext(), getTag(), getName(), getFile(), getLine(), getScope(), + getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), + getDWARFAddressSpace(), getFlags(), getExtraData(), getAnnotations()); } public: @@ -964,19 +965,21 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr), + Metadata *ExtraData = nullptr, + Metadata *Annotations = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)) + ExtraData, Annotations)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr), + Metadata *ExtraData = nullptr, + DINodeArray Annotations = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)) + ExtraData, Annotations)) TempDIDerivedType clone() const { return cloneImpl(); } @@ -999,6 +1002,12 @@ Metadata *getExtraData() const { return getRawExtraData(); } Metadata *getRawExtraData() const { return getOperand(4); } + /// Get annotations associated with this derived type. + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } + Metadata *getRawAnnotations() const { return getOperand(5); } + /// Get casted version of extra data. /// @{ DIType *getClassType() const { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4554,7 +4554,8 @@ OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(extraData, MDField, ); \ - OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); + OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4566,7 +4567,7 @@ (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, offset.Val, DWARFAddressSpace, flags.Val, - extraData.Val)); + extraData.Val, annotations.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1437,7 +1437,7 @@ break; } case bitc::METADATA_DERIVED_TYPE: { - if (Record.size() < 12 || Record.size() > 13) + if (Record.size() < 12 || Record.size() > 14) return error("Invalid record"); // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means @@ -1446,6 +1446,10 @@ if (Record.size() > 12 && Record[12]) DWARFAddressSpace = Record[12] - 1; + Metadata *Annotations = nullptr; + if (Record.size() > 13 && Record[13]) + Annotations = getMDOrNull(Record[13]); + IsDistinct = Record[0]; DINode::DIFlags Flags = static_cast(Record[10]); MetadataList.assignValue( @@ -1455,7 +1459,7 @@ getDITypeRefOrNull(Record[5]), getDITypeRefOrNull(Record[6]), Record[7], Record[8], Record[9], DWARFAddressSpace, Flags, - getDITypeRefOrNull(Record[11]))), + getDITypeRefOrNull(Record[11]), Annotations)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1687,6 +1687,8 @@ else Record.push_back(0); + Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2039,6 +2039,7 @@ if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace, /* ShouldSkipZero */ false); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -345,15 +345,14 @@ Flags, ExtraData); } -DIDerivedType *DIBuilder::createMemberType(DIScope *Scope, StringRef Name, - DIFile *File, unsigned LineNumber, - uint64_t SizeInBits, - uint32_t AlignInBits, - uint64_t OffsetInBits, - DINode::DIFlags Flags, DIType *Ty) { +DIDerivedType *DIBuilder::createMemberType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, + DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { return DIDerivedType::get(VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, - SizeInBits, AlignInBits, OffsetInBits, None, Flags); + SizeInBits, AlignInBits, OffsetInBits, None, Flags, + nullptr, Annotations); } static ConstantAsMetadata *getConstantOrNull(Constant *C) { @@ -375,14 +374,15 @@ DIDerivedType *DIBuilder::createBitFieldMemberType( DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t OffsetInBits, uint64_t StorageOffsetInBits, - DINode::DIFlags Flags, DIType *Ty) { + DINode::DIFlags Flags, DIType *Ty, DINodeArray Annotations) { Flags |= DINode::FlagBitField; return DIDerivedType::get( VMContext, dwarf::DW_TAG_member, Name, File, LineNumber, getNonCompileUnitScope(Scope), Ty, SizeInBits, /* AlignInBits */ 0, OffsetInBits, None, Flags, ConstantAsMetadata::get(ConstantInt::get(IntegerType::get(VMContext, 64), - StorageOffsetInBits))); + StorageOffsetInBits)), + Annotations); } DIDerivedType * diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -582,13 +582,13 @@ unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate) { + Metadata *Annotations, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)); - Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; + ExtraData, Annotations)); + Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData, Annotations}; DEFINE_GETIMPL_STORE( DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags), Ops); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -471,23 +471,24 @@ Optional DWARFAddressSpace; unsigned Flags; Metadata *ExtraData; + Metadata *Annotations; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, unsigned Flags, - Metadata *ExtraData) + Metadata *ExtraData, Metadata *Annotations) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace), - Flags(Flags), ExtraData(ExtraData) {} + Flags(Flags), ExtraData(ExtraData), Annotations(Annotations) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()), DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()), - ExtraData(N->getRawExtraData()) {} + ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIDerivedType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -497,8 +498,8 @@ AlignInBits == RHS->getAlignInBits() && OffsetInBits == RHS->getOffsetInBits() && DWARFAddressSpace == RHS->getDWARFAddressSpace() && - Flags == RHS->getFlags() && - ExtraData == RHS->getRawExtraData(); + Flags == RHS->getFlags() && ExtraData == RHS->getRawExtraData() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { diff --git a/llvm/test/Bitcode/attr-btf_tag-field.ll b/llvm/test/Bitcode/attr-btf_tag-field.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-field.ll @@ -0,0 +1,91 @@ +; REQUIRES: x86-registered-target +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +%struct.t1 = type { i32 } +%struct.t2 = type { i8, [3 x i8] } + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @foo(%struct.t1* %arg) #0 !dbg !9 { +entry: + %arg.addr = alloca %struct.t1*, align 8 + store %struct.t1* %arg, %struct.t1** %arg.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.t1** %arg.addr, metadata !20, metadata !DIExpression()), !dbg !21 + %0 = load %struct.t1*, %struct.t1** %arg.addr, align 8, !dbg !22 + %a = getelementptr inbounds %struct.t1, %struct.t1* %0, i32 0, i32 0, !dbg !23 + %1 = load i32, i32* %a, align 4, !dbg !23 + ret i32 %1, !dbg !24 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @foo2(%struct.t2* %arg) #0 !dbg !25 { +entry: + %arg.addr = alloca %struct.t2*, align 8 + store %struct.t2* %arg, %struct.t2** %arg.addr, align 8 + call void @llvm.dbg.declare(metadata %struct.t2** %arg.addr, metadata !32, metadata !DIExpression()), !dbg !33 + %0 = load %struct.t2*, %struct.t2** %arg.addr, align 8, !dbg !34 + %1 = bitcast %struct.t2* %0 to i8*, !dbg !35 + %bf.load = load i8, i8* %1, align 4, !dbg !35 + %bf.shl = shl i8 %bf.load, 7, !dbg !35 + %bf.ashr = ashr i8 %bf.shl, 7, !dbg !35 + %bf.cast = sext i8 %bf.ashr to i32, !dbg !35 + ret i32 %bf.cast, !dbg !36 +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6, !7} +!llvm.ident = !{!8} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 4cbaee98885ead226304e8836090069db6596965)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "attr-btf_tag-field.c", directory: "/home/yhs/work/tests/llvm/btf_tag") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{i32 7, !"frame-pointer", i32 2} +!8 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 4cbaee98885ead226304e8836090069db6596965)"} +!9 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 11, type: !10, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!10 = !DISubroutineType(types: !11) +!11 = !{!12, !13} +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64) +!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !1, line: 7, size: 32, elements: !15) +!15 = !{!16} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 8, baseType: !12, size: 32, annotations: !17) +!17 = !{!18, !19} +!18 = !{!"btf_tag", !"tag1"} +!19 = !{!"btf_tag", !"tag2"} + +; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "a" +; CHECK-SAME: annotations: ![[ANNOT:[0-9]+]] +; CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +; CHECK: ![[TAG1]] = !{!"btf_tag", !"tag1"} +; CHECK: ![[TAG2]] = !{!"btf_tag", !"tag2"} + +!20 = !DILocalVariable(name: "arg", arg: 1, scope: !9, file: !1, line: 11, type: !13) +!21 = !DILocation(line: 11, column: 20, scope: !9) +!22 = !DILocation(line: 12, column: 10, scope: !9) +!23 = !DILocation(line: 12, column: 15, scope: !9) +!24 = !DILocation(line: 12, column: 3, scope: !9) +!25 = distinct !DISubprogram(name: "foo2", scope: !1, file: !1, line: 19, type: !26, scopeLine: 19, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!26 = !DISubroutineType(types: !27) +!27 = !{!12, !28} +!28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 64) +!29 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", file: !1, line: 15, size: 32, elements: !30) +!30 = !{!31} +!31 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !29, file: !1, line: 16, baseType: !12, size: 1, flags: DIFlagBitField, extraData: i64 0, annotations: !17) + +; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "b" +; CHECK-SAME: annotations: ![[ANNOT]] + +!32 = !DILocalVariable(name: "arg", arg: 1, scope: !25, file: !1, line: 19, type: !28) +!33 = !DILocation(line: 19, column: 21, scope: !25) +!34 = !DILocation(line: 20, column: 10, scope: !25) +!35 = !DILocation(line: 20, column: 15, scope: !25) +!36 = !DILocation(line: 20, column: 3, scope: !25)