From 5ad452a913cd102d38deec130a09a9e5cc2d2b30 Mon Sep 17 00:00:00 2001 From: Eduard Zingerman Date: Tue, 14 Feb 2023 01:19:50 +0200 Subject: [PATCH] [DebugInfo][BPF] Add 'btf:type_tag' annotation in DWARF This commit is a follow-up for BPF mailing list discussion at [1]. It changes the way `__attribute__((btf_type_tag("...")))`s are represented in DWARF. Prior to this commit type tags could only be attached to pointers. Such attachments associated the tags with a pointee type. E.g. for the following C code: int __attribute__((btf_type_tag("tag1"))) *g; Generated DWARF looked as follows: 0x0000001e: DW_TAG_variable DW_AT_name ("g") DW_AT_type (0x00000029 "int *") 0x00000029: DW_TAG_pointer_type DW_AT_type (0x00000032 "int") 0x0000002e: DW_TAG_LLVM_annotation DW_AT_name ("btf_type_tag") DW_AT_const_value ("tag1") 0x00000032: DW_TAG_base_type DW_AT_name ("int") The goal of this commit is to allow attachment of type tags to the tagged types instead. E.g. for the same example DWARF should look as follows: 0x0000001e: DW_TAG_variable DW_AT_name ("g") DW_AT_type (0x00000029 "int *") 0x00000029: DW_TAG_pointer_type DW_AT_type (0x00000032 "int") 0x00000032: DW_TAG_base_type DW_AT_name ("int") 0x00000036: DW_TAG_LLVM_annotation DW_AT_name ("btf:type_tag") DW_AT_const_value ("tag1") A new tag name, `btf:type_tag`, is used so that DWARF consumers could distinguish between old and new attachment semantics. In order to preserve backwards compatibility both `btf_type_tag` and `btf:type_tag` are generated. `btf_type_tag` might be deprecated in the future. The commit includes the following changes: - Changes in debug info generation: - New method `DIBuilder::createAnnotationsPlaceholder()` is added, it creates a temporary `DIDerivedType` that plays as annotations placeholder while debug info metadata is being constructed; - New overload for `CGDebugInfo::CreateType` method is added: llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty, llvm::DIFile *Unit); This overload collects BTF type tags in `Ty`, creates annotations placeholder pointing to the base type of `Ty`, registers the placeholder in the `CGDebugInfo::AnnotationsPlaceholder` vector. - `CGDebugInfo::finalize()` is updated to do the following for each annotation placeholder: - clone underlying base type; - attach annotations the clone using `replaceAnnotations()` call; - replace all placeholder usages by a clone. Such scheme allows to deal with type cycles. - Changes in AST construction: - `ASTContext::getBTFTagAttributedType()` is updated to ensure that `BTFTagAttributedType` always wraps `QualType` w/o local constant/volatile/restricted qualifiers. This simplifies debug info generation. [1] https://lore.kernel.org/bpf/87r0w9jjoq.fsf@oracle.com/ Depends on D143966 Differential Revision: https://reviews.llvm.org/D143967 --- clang/lib/CodeGen/CGDebugInfo.cpp | 192 +++++++++++++++--- clang/lib/CodeGen/CGDebugInfo.h | 1 + .../test/CodeGen/attr-btf_type_tag-circular.c | 18 ++ clang/test/CodeGen/attr-btf_type_tag-const.c | 43 ++++ .../test/CodeGen/attr-btf_type_tag-func-ptr.c | 12 +- clang/test/CodeGen/attr-btf_type_tag-func.c | 25 ++- .../test/CodeGen/attr-btf_type_tag-restrict.c | 21 ++ .../CodeGen/attr-btf_type_tag-similar-type.c | 32 +-- .../CodeGen/attr-btf_type_tag-typedef-field.c | 43 ++-- clang/test/CodeGen/attr-btf_type_tag-var.c | 47 +++-- clang/test/CodeGen/attr-btf_type_tag-void.c | 12 ++ .../test/CodeGen/attr-btf_type_tag-volatile.c | 18 ++ llvm/include/llvm/IR/DIBuilder.h | 2 + llvm/lib/IR/DIBuilder.cpp | 11 + 14 files changed, 385 insertions(+), 92 deletions(-) create mode 100644 clang/test/CodeGen/attr-btf_type_tag-circular.c create mode 100644 clang/test/CodeGen/attr-btf_type_tag-const.c create mode 100644 clang/test/CodeGen/attr-btf_type_tag-restrict.c create mode 100644 clang/test/CodeGen/attr-btf_type_tag-void.c create mode 100644 clang/test/CodeGen/attr-btf_type_tag-volatile.c diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index f049a682cfed6f..cee63f75177d7e 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1179,6 +1179,158 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty, return RetTy; } +static QualType collectBTFTypeTagAnnotations( + llvm::LLVMContext &Context, llvm::DIBuilder &DBuilder, + llvm::SmallVectorImpl &Annots, + const BTFTagAttributedType *BTFAttrTy, const char *TagName) { + QualType WrappedTy; + + do { + StringRef TagValue = BTFAttrTy->getAttr()->getBTFTypeTag(); + if (!TagValue.empty()) { + llvm::Metadata *Ops[] = { + llvm::MDString::get(Context, TagName), + llvm::MDString::get(Context, TagValue), + }; + Annots.insert(Annots.begin(), llvm::MDNode::get(Context, Ops)); + } + WrappedTy = BTFAttrTy->getWrappedType(); + BTFAttrTy = dyn_cast(WrappedTy); + } while (BTFAttrTy); + + return WrappedTy; +} + +static bool retreiveCVR(llvm::DIDerivedType *DTy, QualifierCollector &Qc) { + switch (DTy->getTag()) { + case llvm::dwarf::DW_TAG_const_type: + Qc.addConst(); + return true; + case llvm::dwarf::DW_TAG_volatile_type: + Qc.addVolatile(); + return true; + case llvm::dwarf::DW_TAG_restrict_type: + Qc.addRestrict(); + return true; + default: + return false; + } +} + +// Tags returned by QualifierCollector::getNextQualifier() should be +// applied in the reverse order, thus use recursive function. +static llvm::DIType *applyQualifiers(llvm::DIBuilder &DBuilder, + llvm::DIType *Ty, QualifierCollector &Qc) { + llvm::dwarf::Tag Tag = getNextQualifier(Qc); + if (!Tag) + return Ty; + Ty = applyQualifiers(DBuilder, Ty, Qc); + return DBuilder.createQualifiedType(Tag, Ty); +} + +static llvm::DIType *cloneAndAddAnnotations(llvm::DIBuilder &DBuilder, + SmallVector Annotations, + llvm::DIType *WrappedDI) { + auto AddAnnotations = [&](auto *Type) { + if (llvm::DINodeArray OldAnnotations = Type->getAnnotations()) + for (const llvm::Metadata *O : OldAnnotations->operands()) + Annotations.push_back(const_cast(O)); + auto Clone = Type->clone(); + Clone->replaceAnnotations(DBuilder.getOrCreateArray(Annotations)); + return llvm::MDNode::replaceWithPermanent(std::move(Clone)); + }; + + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty); + + return WrappedDI; +} + +static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C); + +llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty, + llvm::DIFile *Unit) { + SmallVector Annotations; + QualType WrappedTy = collectBTFTypeTagAnnotations( + CGM.getLLVMContext(), DBuilder, Annotations, Ty, "btf:type_tag"); + if (Annotations.size() == 0) + return getOrCreateType(WrappedTy, Unit); + + // After discussion with GCC BPF team in [1] it was decided to avoid + // attaching BTF type tags to const/volatile/restrict DWARF DIEs. + // So, strip qualifiers from WrappedTy and apply those to a final + // annotations placeholder instance at the end of this function. + // + // [1] https://reviews.llvm.org/D143967 + QualifierCollector Qc; + Qc.addCVRQualifiers(WrappedTy.getLocalCVRQualifiers()); + WrappedTy.removeLocalFastQualifiers(Qualifiers::CVRMask); + + // We are going to invoke CreateTypeNode(WrappedTy, ...), to avoid + // infinite cycle in the case like below add ourselves to the + // TypeCache. The Placeholder node is temporary and would be + // replaced at the end of this function. Example: + // + // #define __tag1 __attribute__((btf_type_tag("tag1"))) + // struct st { + // struct st __tag1 *self; + // } g; + // + auto *Placeholder = DBuilder.createAnnotationsPlaceholder(); + TypeCache[Ty].reset(Placeholder); + // Invoke CreateTypeNode(WrappedTy, ...) in order to clone the + // result and attach annotations to it at the end of this function. + // Can't call getOrCreateType() because that might return existing + // temporary node created by getOrCreateLimitedType(). Clone of that + // temporary node will not be finalized with correct members. + WrappedTy = UnwrapTypeForDebugInfo(WrappedTy, CGM.getContext()); + llvm::DIType *WrappedDI = CreateTypeNode(WrappedTy, Unit); + if (WrappedDI == nullptr) + WrappedDI = DBuilder.createUnspecifiedType("void"); + + // Stripping local CVR qualifiers might not be enough in cases like this: + // + // #define __tag __attribute__((btf_type_tag("tag"))) + // const int *foo; + // const int *bar(void) { + // return (typeof(*foo) __tag *)(0); + // } + // + // Here the AST looks like: + // + // BTFTagAttributedType + // | 'typeof (*foo) __attribute__((btf_type_tag("tag")))' sugar + // `-TypeOfExprType 'typeof (*foo)' sugar + // |-ParenExpr 'const int' lvalue + // | `- ... + // `-QualType 'const int' const + // `-BuiltinType 'int' + // + // The BTFTagAttributedType is applied to TypeOfExpr. + // For TypeOfExpr the getOrCreateType(), would return instance of + // DIDerivedType with tag DW_TAG_const_type. + // + // To avoid repeating UnwrapTypeForDebugInfo() logic here just + // rebuild CVR metadata nodes if necessary. + // The above local CVR qualifiers processing is redundant, + // but avoids rebuilding metadata nodes in the most common case. + while (auto *DTy = dyn_cast(WrappedDI)) { + if (!retreiveCVR(DTy, Qc)) + break; + WrappedDI = DTy->getBaseType(); + } + + WrappedDI = cloneAndAddAnnotations(DBuilder, Annotations, WrappedDI); + DBuilder.replaceTemporary(llvm::TempDIType(Placeholder), WrappedDI); + return applyQualifiers(DBuilder, WrappedDI, Qc); +} + llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty, QualType PointeeTy, @@ -1191,32 +1343,23 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, CGM.getTarget().getDWARFAddressSpace( CGM.getTypes().getTargetAddressSpace(PointeeTy)); - SmallVector Annots; - auto *BTFAttrTy = dyn_cast(PointeeTy); - while (BTFAttrTy) { - StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag(); - if (!Tag.empty()) { - llvm::Metadata *Ops[2] = { - llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")), - llvm::MDString::get(CGM.getLLVMContext(), Tag)}; - Annots.insert(Annots.begin(), - llvm::MDNode::get(CGM.getLLVMContext(), Ops)); - } - BTFAttrTy = dyn_cast(BTFAttrTy->getWrappedType()); - } - llvm::DINodeArray Annotations = nullptr; - if (Annots.size() > 0) - Annotations = DBuilder.getOrCreateArray(Annots); + if (auto *BTFAttrTy = + dyn_cast(PointeeTy.getTypePtr())) { + SmallVector AnnotationsVec; + collectBTFTypeTagAnnotations(CGM.getLLVMContext(), DBuilder, AnnotationsVec, + BTFAttrTy, "btf_type_tag"); + Annotations = DBuilder.getOrCreateArray(AnnotationsVec); + } if (Tag == llvm::dwarf::DW_TAG_reference_type || Tag == llvm::dwarf::DW_TAG_rvalue_reference_type) return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit), Size, Align, DWARFAddressSpace); - else - return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size, - Align, DWARFAddressSpace, StringRef(), - Annotations); + + return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size, + Align, DWARFAddressSpace, StringRef(), + Annotations); } llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name, @@ -2659,7 +2802,7 @@ void CGDebugInfo::completeRequiredType(const RecordDecl *RD) { llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) { RecordDecl *RD = Ty->getDecl(); llvm::DIType *T = cast_or_null(getTypeOrNull(QualType(Ty, 0))); - if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, + if (/*T || */shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD, CGM.getLangOpts())) { if (!T) T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD)); @@ -3432,9 +3575,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) { case Type::Attributed: T = cast(T)->getEquivalentType(); break; - case Type::BTFTagAttributed: - T = cast(T)->getWrappedType(); - break; case Type::Elaborated: T = cast(T)->getNamedType(); break; @@ -3626,9 +3766,11 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::TemplateSpecialization: return CreateType(cast(Ty), Unit); + case Type::BTFTagAttributed: + return CreateType(cast(Ty), Unit); + case Type::Auto: case Type::Attributed: - case Type::BTFTagAttributed: case Type::Adjusted: case Type::Decayed: case Type::DeducedTemplateSpecialization: diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 1fd08626358b93..1689da20abae75 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -217,6 +217,7 @@ class CGDebugInfo { llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F); llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F); + llvm::DIType *CreateType(const BTFTagAttributedType *Ty, llvm::DIFile *F); /// Get enumeration type. llvm::DIType *CreateEnumType(const EnumType *Ty); llvm::DIType *CreateTypeDefinition(const EnumType *Ty); diff --git a/clang/test/CodeGen/attr-btf_type_tag-circular.c b/clang/test/CodeGen/attr-btf_type_tag-circular.c new file mode 100644 index 00000000000000..5c3f0e1c9abf83 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-circular.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s + +#define __tag1 __attribute__((btf_type_tag("tag1"))) + +struct st { + struct st __tag1 *self; +} g; + +// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true) +// CHECK: ![[L1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2:[0-9]+]]) +// CHECK: ![[L2]] = !{![[L3:[0-9]+]]} +// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_member, name: "self", scope: ![[L1]], file: ![[#]], line: [[#]], baseType: ![[L4:[0-9]+]], size: [[#]]) +// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], size: [[#]], annotations: ![[L6:[0-9]+]]) +// CHECK: ![[L5]] = !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2]], annotations: ![[L7:[0-9]+]]) +// CHECK: ![[L7]] = !{![[L8:[0-9]+]]} +// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L6]] = !{![[L9:[0-9]+]]} +// CHECK: ![[L9]] = !{!"btf_type_tag", !"tag1"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-const.c b/clang/test/CodeGen/attr-btf_type_tag-const.c new file mode 100644 index 00000000000000..527ba3adcc4bf8 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-const.c @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 \ +// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \ +// RUN: -S -emit-llvm -o - %s | FileCheck %s + +// Check that BTF type tags are not attached to DW_TAG_const_type DIEs +// in presence of "sugar" expressions that are transparent for +// CGDebugInfo.cpp:UnwrapTypeForDebugInfo(), but are not transparent +// for local qualifiers. +// +// For details see: +// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile) + +#define __tag1 __attribute__((btf_type_tag("tag1"))) +#define __tag2 __attribute__((btf_type_tag("tag2"))) +#define __tag3 __attribute__((btf_type_tag("tag3"))) + +const int *foo; +typeof(*foo) __tag1 bar; + +// CHECK: distinct !DIGlobalVariable(name: "bar", {{.*}}, type: ![[L01:[0-9]+]], {{.*}}) +// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L02:[0-9]+]]) +// CHECK: ![[L02]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L03:[0-9]+]]) +// CHECK: ![[L03]] = !{![[L04:[0-9]+]]} +// CHECK: ![[L04]] = !{!"btf:type_tag", !"tag1"} + +const int __tag2 *buz; + +// CHECK: distinct !DIGlobalVariable(name: "buz", {{.*}}, type: ![[L05:[0-9]+]], {{.*}}) +// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], {{.*}}, annotations: ![[L07:[0-9]+]]) +// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]]) +// CHECK: ![[L08]] = !DIBasicType(name: "int", size: [[#]], {{.*}}, annotations: ![[L09:[0-9]+]]) +// CHECK: ![[L09]] = !{![[L10:[0-9]+]]} +// CHECK: ![[L10]] = !{!"btf:type_tag", !"tag2"} +// CHECK: ![[L07]] = !{![[L11:[0-9]+]]} +// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag2"} + +typeof(*buz) __tag3 quux; + +// CHECK: distinct !DIGlobalVariable(name: "quux", {{.*}}, type: ![[L12:[0-9]+]], {{.*}}) +// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L13:[0-9]+]]) +// CHECK: ![[L13]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L14:[0-9]+]]) +// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L10]]} +// CHECK: ![[L15]] = !{!"btf:type_tag", !"tag3"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c index 29ca5f58e4b812..b713179caee626 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c +++ b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c @@ -8,8 +8,10 @@ int foo(struct t *arg) { return arg->a; } -// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f" -// CHECK-SAME: baseType: ![[L18:[0-9]+]] -// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]]) -// CHECK: ![[L21]] = !{![[L22:[0-9]+]]} -// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"} +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]]) +// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]], annotations: ![[L3:[0-9]+]]) +// CHECK: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L4:[0-9]+]]) +// CHECK: ![[L4]] = !{![[L5:[0-9]+]]} +// CHECK: ![[L5]] = !{!"btf:type_tag", !"rcu"} +// CHECK: ![[L3]] = !{![[L6:[0-9]+]]} +// CHECK: ![[L6]] = !{!"btf_type_tag", !"rcu"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-func.c b/clang/test/CodeGen/attr-btf_type_tag-func.c index c573d1147ccd7e..53ec039a5653e9 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-func.c +++ b/clang/test/CodeGen/attr-btf_type_tag-func.c @@ -15,14 +15,17 @@ int __tag1 * __tag2 *foo(int __tag1 * __tag2 *arg) { return arg; } -// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L9:[0-9]+]] -// CHECK: ![[L9]] = !DISubroutineType(types: ![[L10:[0-9]+]] -// CHECK: ![[L10]] = !{![[L11:[0-9]+]], ![[L11]]} -// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L12:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]] -// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]] -// CHECK: ![[L13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed -// CHECK: ![[L14]] = !{![[L15:[0-9]+]]} -// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag1"} -// CHECK: ![[L16]] = !{![[L17:[0-9]+]]} -// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag2"} -// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L11]]) +// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], {{.*}}) +// CHECK: ![[L01]] = !DISubroutineType(types: ![[L02:[0-9]+]]) +// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L03]]} +// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L04:[0-9]+]], size: [[#]], annotations: ![[L05:[0-9]+]]) +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]]) +// CHECK: ![[L06]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L08:[0-9]+]]) +// CHECK: ![[L08]] = !{![[L09:[0-9]+]]} +// CHECK: ![[L09]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L07]] = !{![[L10:[0-9]+]], ![[L11:[0-9]+]]} +// CHECK: ![[L10]] = !{!"btf:type_tag", !"tag2"} +// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag1"} +// CHECK: ![[L05]] = !{![[L12:[0-9]+]]} +// CHECK: ![[L12]] = !{!"btf_type_tag", !"tag2"} +// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L03]]) diff --git a/clang/test/CodeGen/attr-btf_type_tag-restrict.c b/clang/test/CodeGen/attr-btf_type_tag-restrict.c new file mode 100644 index 00000000000000..6c65c87ce1380c --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-restrict.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 \ +// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \ +// RUN: -S -emit-llvm -o - %s | FileCheck %s + +// See attr-btf_type_tag-const.c for reasoning behind this test. +// Alternatively, see the following method: +// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile) + +#define __tag1 __attribute__((btf_type_tag("tag1"))) + +void foo(int * restrict bar, typeof(bar) __tag1 buz) {} + +// CHECK: ![[#]] = !DISubroutineType(types: ![[L1:[0-9]+]]) +// CHECK: ![[L1]] = !{null, ![[L2:[0-9]+]], ![[L3:[0-9]+]]} +// CHECK: ![[L2]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: ![[L4:[0-9]+]]) +// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], {{.*}}) +// CHECK: ![[L5]] = !DIBasicType(name: "int", {{.*}}, encoding: DW_ATE_signed) +// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: ![[L6:[0-9]+]]) +// CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5]], {{.*}}, annotations: ![[L7:[0-9]+]]) +// CHECK: ![[L7]] = !{![[L8:[0-9]+]]} +// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-similar-type.c b/clang/test/CodeGen/attr-btf_type_tag-similar-type.c index ad9d16f3f6314d..30e0d1477e5468 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-similar-type.c +++ b/clang/test/CodeGen/attr-btf_type_tag-similar-type.c @@ -12,15 +12,23 @@ int test(struct map_value *arg) return *arg->a; } -// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L14:[0-9]+]] -// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L20:[0-9]+]]} -// CHECK: ![[L15]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]] -// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L17:[0-9]+]] -// CHECK: ![[L17]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]} -// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag1"} -// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag3"} -// CHECK: ![[L20]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L21:[0-9]+]] -// CHECK: ![[L21:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L22:[0-9]+]] -// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]} -// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"} -// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"} +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L01:[0-9]+]]) +// CHECK: ![[L01]] = !{![[L02:[0-9]+]], ![[L03:[0-9]+]]} +// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L04:[0-9]+]], size: [[#]]) +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05:[0-9]+]], size: [[#]], annotations: ![[L06:[0-9]+]]) +// CHECK: ![[L05]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L07:[0-9]+]]) +// CHECK: ![[L07]] = !{![[L08:[0-9]+]], ![[L09:[0-9]+]]} +// CHECK: ![[L08]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L09]] = !{!"btf:type_tag", !"tag3"} +// CHECK: ![[L06]] = !{![[L10:[0-9]+]], ![[L11:[0-9]+]]} +// CHECK: ![[L10]] = !{!"btf_type_tag", !"tag1"} +// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag3"} +// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L12:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]]) +// CHECK: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L15:[0-9]+]]) +// CHECK: ![[L15]] = !{![[L16:[0-9]+]], ![[L17:[0-9]+]]} +// CHECK: ![[L16]] = !{!"btf:type_tag", !"tag2"} +// CHECK: ![[L17]] = !{!"btf:type_tag", !"tag4"} +// CHECK: ![[L14]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]} +// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"} +// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag4"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c index c80c7e9b45d96f..74427e5b342646 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c +++ b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c @@ -14,22 +14,27 @@ int *foo1(struct t *a1) { return (int *)a1->c; } -// CHECK: ![[L4:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L16:[0-9]+]]) -// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L24:[0-9]+]], ![[L31:[0-9]+]]} -// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L18:[0-9]+]], size: [[#]]) -// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L19:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]]) -// CHECK: ![[L19]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4]], size: [[#]], annotations: ![[L20:[0-9]+]]) -// CHECK: ![[L20]] = !{![[L21:[0-9]+]]} -// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag1"} -// CHECK: ![[L22]] = !{![[L23:[0-9]+]]} -// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"} -// CHECK: ![[L24]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L25:[0-9]+]] -// CHECK: ![[L25]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L26:[0-9]+]]) -// CHECK: ![[L26]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L27:[0-9]+]], size: [[#]], annotations: ![[L30:[0-9]+]]) -// CHECK: ![[L27]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L28:[0-9]+]]) -// CHECK: ![[L28]] = !DISubroutineType(types: ![[L29:[0-9]+]]) -// CHECK: ![[L29]] = !{null, ![[L4]]} -// CHECK: ![[L30]] = !{![[L21]], ![[L23]]} -// CHECK: ![[L31]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]]1, baseType: ![[L32:[0-9]+]] -// CHECK: ![[L32]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed) +// CHECK: ![[L01:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed) +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L02:[0-9]+]]) +// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L04:[0-9]+]], ![[L05:[0-9]+]]} +// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L06:[0-9]+]], size: [[#]]) +// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L07:[0-9]+]], size: [[#]], annotations: ![[L08:[0-9]+]]) +// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L09:[0-9]+]], size: [[#]], annotations: ![[L10:[0-9]+]]) +// CHECK: ![[L09]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L11:[0-9]+]]) +// CHECK: ![[L11]] = !{![[L12:[0-9]+]]} +// CHECK: ![[L12]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L10]] = !{![[L13:[0-9]+]], ![[L14:[0-9]+]]} +// CHECK: ![[L13]] = !{!"btf:type_tag", !"tag2"} +// CHECK: ![[L14]] = !{!"btf_type_tag", !"tag1"} +// CHECK: ![[L08]] = !{![[L15:[0-9]+]]} +// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag2"} +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L17:[0-9]+]]) +// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L18:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]]) +// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L20:[0-9]+]], annotations: ![[L21:[0-9]+]]) +// CHECK: ![[L20]] = !DISubroutineType(types: ![[L22:[0-9]+]]) +// CHECK: ![[L22]] = !{null, ![[L01]]} +// CHECK: ![[L21]] = !{![[L12]], ![[L13]]} +// CHECK: ![[L19]] = !{![[L14]], ![[L15]]} +// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L23:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L23]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed) diff --git a/clang/test/CodeGen/attr-btf_type_tag-var.c b/clang/test/CodeGen/attr-btf_type_tag-var.c index ccc4edd22c1ccb..4e1a91cbe3fe49 100644 --- a/clang/test/CodeGen/attr-btf_type_tag-var.c +++ b/clang/test/CodeGen/attr-btf_type_tag-var.c @@ -21,23 +21,30 @@ const volatile int __tag1 __tag2 * __tag3 __tag4 const volatile * __tag5 __tag6 const int __tag1 __tag2 volatile * const __tag3 __tag4 volatile * __tag5 __tag6 const volatile * g; #endif -// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L6:[0-9]+]] -// CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L7:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]] -// CHECK: ![[L7]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L8:[0-9]+]] -// CHECK: ![[L8]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L9:[0-9]+]] -// CHECK: ![[L9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]] -// CHECK: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L11:[0-9]+]] -// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L12:[0-9]+]] -// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]] -// CHECK: ![[L13]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L14:[0-9]+]] -// CHECK: ![[L14]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L15:[0-9]+]] -// CHECK: ![[L15]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed -// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]} -// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag1"} -// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"} -// CHECK: ![[L19]] = !{![[L20:[0-9]+]], ![[L21:[0-9]+]]} -// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag3"} -// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag4"} -// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]} -// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag5"} -// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag6"} +// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], isLocal: false, isDefinition: true) +// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L02:[0-9]+]], size: [[#]], annotations: ![[L03:[0-9]+]]) +// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L04:[0-9]+]]) +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L05:[0-9]+]]) +// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]]) +// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]]) +// CHECK: ![[L08]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L09:[0-9]+]]) +// CHECK: ![[L09]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L11:[0-9]+]]) +// CHECK: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L12:[0-9]+]]) +// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L13:[0-9]+]]) +// CHECK: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L14:[0-9]+]]) +// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L16:[0-9]+]]} +// CHECK: ![[L15]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L16]] = !{!"btf:type_tag", !"tag2"} +// CHECK: ![[L11]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]], ![[L19:[0-9]+]], ![[L20:[0-9]+]]} +// CHECK: ![[L17]] = !{!"btf:type_tag", !"tag3"} +// CHECK: ![[L18]] = !{!"btf:type_tag", !"tag4"} +// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag1"} +// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag2"} +// CHECK: ![[L07]] = !{![[L21:[0-9]+]], ![[L22:[0-9]+]], ![[L23:[0-9]+]], ![[L24:[0-9]+]]} +// CHECK: ![[L21]] = !{!"btf:type_tag", !"tag5"} +// CHECK: ![[L22]] = !{!"btf:type_tag", !"tag6"} +// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag3"} +// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"} +// CHECK: ![[L03]] = !{![[L25:[0-9]+]], ![[L26:[0-9]+]]} +// CHECK: ![[L25]] = !{!"btf_type_tag", !"tag5"} +// CHECK: ![[L26]] = !{!"btf_type_tag", !"tag6"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-void.c b/clang/test/CodeGen/attr-btf_type_tag-void.c new file mode 100644 index 00000000000000..0b373591d54eb2 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-void.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -S -emit-llvm -o - %s | FileCheck %s + +#define __tag1 __attribute__((btf_type_tag("tag1"))) +void __tag1 *g; + +// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true) +// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]], annotations: ![[L3:[0-9]+]]) +// CHECK: ![[L2]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: ![[L4:[0-9]+]]) +// CHECK: ![[L4]] = !{![[L5:[0-9]+]]} +// CHECK: ![[L5]] = !{!"btf:type_tag", !"tag1"} +// CHECK: ![[L3]] = !{![[L6:[0-9]+]]} +// CHECK: ![[L6]] = !{!"btf_type_tag", !"tag1"} diff --git a/clang/test/CodeGen/attr-btf_type_tag-volatile.c b/clang/test/CodeGen/attr-btf_type_tag-volatile.c new file mode 100644 index 00000000000000..57a0e4096e95ef --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-volatile.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 \ +// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \ +// RUN: -S -emit-llvm -o - %s | FileCheck %s + +// See attr-btf_type_tag-const.c for reasoning behind this test. +// Alternatively, see the following method: +// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile) + +#define __tag1 __attribute__((btf_type_tag("tag1"))) + +volatile int foo; +typeof(foo) __tag1 bar; + +// CHECK: ![[#]] = distinct !DIGlobalVariable(name: "bar", {{.*}}, type: ![[L1:[0-9]+]], {{.*}}) +// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L2:[0-9]+]]) +// CHECK: ![[L2]] = !DIBasicType(name: "int", size: [[#]], {{.*}}, annotations: ![[L3:[0-9]+]]) +// CHECK: ![[L3]] = !{![[L4:[0-9]+]]} +// CHECK: ![[L4]] = !{!"btf:type_tag", !"tag1"} diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index ecd6dd7b0a4f82..c7737b46d0b6c0 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -294,6 +294,8 @@ namespace llvm { DINode::DIFlags Flags = DINode::FlagZero, DINodeArray Annotations = nullptr); + DIDerivedType *createAnnotationsPlaceholder(); + /// Create debugging information entry for a 'friend'. DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 1ce8c17f8a880f..9bce8f0b27cfdc 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -342,6 +342,17 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name, Annotations); } +DIDerivedType * +DIBuilder::createAnnotationsPlaceholder() { + auto *RetTy = + DIDerivedType::getTemporary( + VMContext, dwarf::DW_TAG_LLVM_annotation, "", nullptr, 0, nullptr, nullptr, + 0, 0, 0, std::nullopt, DINode::FlagZero, nullptr, {}) + .release(); + trackIfUnresolved(RetTy); + return RetTy; +} + DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { assert(Ty && "Invalid type!"); assert(FriendTy && "Invalid friend type!");