Skip to content

Commit fbc598b

Browse files
committed
[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. This feature is mostly used by Linux Kernel in combination with tool named pahole [2]. Reasonably recent versions of pahole generate errors (1.23, 1.24) or warnings (1.25) when `DW_TAG_LLVM_annotation` is attached to `DW_TAG_base_type` or `DW_TAG_unspecified_type`. Hence the `btf:type_tag` generation is controlled by a hidden option `-mllvm -btf-type-tag-v2`. The goal is to provide a way for tooling to work on adding support `btf:type_tag` and eventually replace `btf_type_tag` by `btf:type_tag`, removing the above option. 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/ [2] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/ This was previously tracked as differential revision: https://reviews.llvm.org/D143967
1 parent 4b35b0a commit fbc598b

14 files changed

+493
-97
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 180 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@
5656
using namespace clang;
5757
using namespace clang::CodeGen;
5858

59+
// Temporarily hide new format for btf_type_tags / DW_TAG_LLVM_annotation
60+
// behind an option to allow transitory period for tooling dependent on
61+
// this annotation. The goal is to remove this flag after transitory period.
62+
static llvm::cl::opt<bool> BTFTypeTagV2(
63+
"btf-type-tag-v2", llvm::cl::Hidden,
64+
llvm::cl::desc("For __attribute__((btf_type_tag(...))) generate "
65+
"DW_TAG_LLVM_annotation tags with DW_AT_name 'btf:type_tag' "
66+
"attached to annotated type itself"),
67+
llvm::cl::init(false));
68+
5969
static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
6070
auto TI = Ctx.getTypeInfo(Ty);
6171
return TI.isAlignRequired() ? TI.Align : 0;
@@ -1185,6 +1195,129 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
11851195
return RetTy;
11861196
}
11871197

1198+
static QualType collectBTFTypeTagAnnotations(
1199+
llvm::LLVMContext &Context, llvm::DIBuilder &DBuilder,
1200+
llvm::SmallVectorImpl<llvm::Metadata *> &Annots,
1201+
const BTFTagAttributedType *BTFAttrTy, const char *TagName) {
1202+
QualType WrappedTy;
1203+
1204+
do {
1205+
StringRef TagValue = BTFAttrTy->getAttr()->getBTFTypeTag();
1206+
if (!TagValue.empty()) {
1207+
llvm::Metadata *Ops[] = {
1208+
llvm::MDString::get(Context, TagName),
1209+
llvm::MDString::get(Context, TagValue),
1210+
};
1211+
Annots.insert(Annots.begin(), llvm::MDNode::get(Context, Ops));
1212+
}
1213+
WrappedTy = BTFAttrTy->getWrappedType();
1214+
BTFAttrTy = dyn_cast<BTFTagAttributedType>(WrappedTy);
1215+
} while (BTFAttrTy);
1216+
1217+
return WrappedTy;
1218+
}
1219+
1220+
static bool retreiveCVR(llvm::DIDerivedType *DTy, QualifierCollector &Qc) {
1221+
switch (DTy->getTag()) {
1222+
case llvm::dwarf::DW_TAG_const_type:
1223+
Qc.addConst();
1224+
return true;
1225+
case llvm::dwarf::DW_TAG_volatile_type:
1226+
Qc.addVolatile();
1227+
return true;
1228+
case llvm::dwarf::DW_TAG_restrict_type:
1229+
Qc.addRestrict();
1230+
return true;
1231+
default:
1232+
return false;
1233+
}
1234+
}
1235+
1236+
// Tags returned by QualifierCollector::getNextQualifier() should be
1237+
// applied in the reverse order, thus use recursive function.
1238+
static llvm::DIType *applyQualifiers(llvm::DIBuilder &DBuilder,
1239+
llvm::DIType *Ty, QualifierCollector &Qc) {
1240+
llvm::dwarf::Tag Tag = getNextQualifier(Qc);
1241+
if (!Tag)
1242+
return Ty;
1243+
Ty = applyQualifiers(DBuilder, Ty, Qc);
1244+
return DBuilder.createQualifiedType(Tag, Ty);
1245+
}
1246+
1247+
static bool isAnnotationsPlaceholder(llvm::DIDerivedType *DTy) {
1248+
return DTy->isTemporary() &&
1249+
DTy->getTag() == llvm::dwarf::DW_TAG_LLVM_annotation;
1250+
}
1251+
1252+
llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty,
1253+
llvm::DIFile *Unit) {
1254+
SmallVector<llvm::Metadata *, 4> Annotations;
1255+
auto WrappedTy = collectBTFTypeTagAnnotations(
1256+
CGM.getLLVMContext(), DBuilder, Annotations, Ty, "btf:type_tag");
1257+
1258+
if (!BTFTypeTagV2 || Annotations.empty())
1259+
return getOrCreateType(WrappedTy, Unit);
1260+
1261+
// After discussion with GCC BPF team in [1] it was decided to avoid
1262+
// attaching BTF type tags to const/volatile/restrict DWARF DIEs.
1263+
// So, strip qualifiers from WrappedTy and apply those to a final
1264+
// annotations placeholder instance at the end of this function.
1265+
//
1266+
// [1] https://reviews.llvm.org/D143967
1267+
QualifierCollector Qc;
1268+
Qc.addCVRQualifiers(WrappedTy.getLocalCVRQualifiers());
1269+
WrappedTy.removeLocalFastQualifiers(Qualifiers::CVRMask);
1270+
1271+
llvm::DIType *WrappedDI = getOrCreateType(WrappedTy, Unit);
1272+
if (!WrappedDI)
1273+
WrappedDI = DBuilder.createUnspecifiedType("void");
1274+
1275+
// Stripping local CVR qualifiers might not be enough in cases like this:
1276+
//
1277+
// #define __tag __attribute__((btf_type_tag("tag")))
1278+
// const int *foo;
1279+
// const int *bar(void) {
1280+
// return (typeof(*foo) __tag *)(0);
1281+
// }
1282+
//
1283+
// Here the AST looks like:
1284+
//
1285+
// BTFTagAttributedType
1286+
// | 'typeof (*foo) __attribute__((btf_type_tag("tag")))' sugar
1287+
// `-TypeOfExprType 'typeof (*foo)' sugar
1288+
// |-ParenExpr 'const int' lvalue
1289+
// | `- ...
1290+
// `-QualType 'const int' const
1291+
// `-BuiltinType 'int'
1292+
//
1293+
// The BTFTagAttributedType is applied to TypeOfExpr.
1294+
// For TypeOfExpr the getOrCreateType(), would return instance of
1295+
// DIDerivedType with tag DW_TAG_const_type.
1296+
//
1297+
// To avoid repeating UnwrapTypeForDebugInfo() logic here just
1298+
// rebuild CVR metadata nodes if necessary.
1299+
// The above local CVR qualifiers processing is redundant,
1300+
// but avoids rebuilding metadata nodes in the most common case.
1301+
while (auto *DTy = dyn_cast<llvm::DIDerivedType>(WrappedDI)) {
1302+
if (!retreiveCVR(DTy, Qc))
1303+
break;
1304+
WrappedDI = DTy->getBaseType();
1305+
}
1306+
1307+
if (auto *DTy = dyn_cast<llvm::DIDerivedType>(WrappedDI))
1308+
if (isAnnotationsPlaceholder(DTy)) {
1309+
WrappedDI = DTy->getBaseType();
1310+
for (llvm::Metadata *O : DTy->getAnnotations()->operands())
1311+
Annotations.push_back(O);
1312+
}
1313+
1314+
auto *Placeholder = DBuilder.createAnnotationsPlaceholder(
1315+
WrappedDI, DBuilder.getOrCreateArray(Annotations));
1316+
AnnotationPlaceholders.push_back(Placeholder);
1317+
1318+
return applyQualifiers(DBuilder, Placeholder, Qc);
1319+
}
1320+
11881321
llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
11891322
const Type *Ty,
11901323
QualType PointeeTy,
@@ -1197,32 +1330,23 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
11971330
CGM.getTarget().getDWARFAddressSpace(
11981331
CGM.getTypes().getTargetAddressSpace(PointeeTy));
11991332

1200-
SmallVector<llvm::Metadata *, 4> Annots;
1201-
auto *BTFAttrTy = dyn_cast<BTFTagAttributedType>(PointeeTy);
1202-
while (BTFAttrTy) {
1203-
StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag();
1204-
if (!Tag.empty()) {
1205-
llvm::Metadata *Ops[2] = {
1206-
llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")),
1207-
llvm::MDString::get(CGM.getLLVMContext(), Tag)};
1208-
Annots.insert(Annots.begin(),
1209-
llvm::MDNode::get(CGM.getLLVMContext(), Ops));
1210-
}
1211-
BTFAttrTy = dyn_cast<BTFTagAttributedType>(BTFAttrTy->getWrappedType());
1212-
}
1213-
12141333
llvm::DINodeArray Annotations = nullptr;
1215-
if (Annots.size() > 0)
1216-
Annotations = DBuilder.getOrCreateArray(Annots);
1334+
auto *BTFAttrTy = dyn_cast<BTFTagAttributedType>(PointeeTy.getTypePtr());
1335+
if (!BTFTypeTagV2 && BTFAttrTy) {
1336+
SmallVector<llvm::Metadata *, 4> AnnotationsVec;
1337+
collectBTFTypeTagAnnotations(CGM.getLLVMContext(), DBuilder, AnnotationsVec,
1338+
BTFAttrTy, "btf_type_tag");
1339+
Annotations = DBuilder.getOrCreateArray(AnnotationsVec);
1340+
}
12171341

12181342
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
12191343
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
12201344
return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
12211345
Size, Align, DWARFAddressSpace);
1222-
else
1223-
return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
1224-
Align, DWARFAddressSpace, StringRef(),
1225-
Annotations);
1346+
1347+
return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
1348+
Align, DWARFAddressSpace, StringRef(),
1349+
Annotations);
12261350
}
12271351

12281352
llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -3543,9 +3667,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
35433667
case Type::Attributed:
35443668
T = cast<AttributedType>(T)->getEquivalentType();
35453669
break;
3546-
case Type::BTFTagAttributed:
3547-
T = cast<BTFTagAttributedType>(T)->getWrappedType();
3548-
break;
35493670
case Type::CountAttributed:
35503671
T = cast<CountAttributedType>(T)->desugar();
35513672
break;
@@ -3745,10 +3866,12 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
37453866
case Type::TemplateSpecialization:
37463867
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
37473868

3869+
case Type::BTFTagAttributed:
3870+
return CreateType(cast<BTFTagAttributedType>(Ty), Unit);
3871+
37483872
case Type::CountAttributed:
37493873
case Type::Auto:
37503874
case Type::Attributed:
3751-
case Type::BTFTagAttributed:
37523875
case Type::Adjusted:
37533876
case Type::Decayed:
37543877
case Type::DeducedTemplateSpecialization:
@@ -6005,6 +6128,35 @@ void CGDebugInfo::setDwoId(uint64_t Signature) {
60056128
TheCU->setDWOId(Signature);
60066129
}
60076130

6131+
static llvm::DIType *copyAnnotations(llvm::DIBuilder &DBuilder,
6132+
llvm::DIDerivedType *Placeholder) {
6133+
auto *WrappedDI = Placeholder->getBaseType();
6134+
SmallVector<llvm::Metadata *, 4> Annotations;
6135+
6136+
for (const llvm::Metadata *O : Placeholder->getAnnotations()->operands())
6137+
Annotations.push_back(const_cast<llvm::Metadata *>(O));
6138+
6139+
auto AddAnnotations = [&](auto *Type) {
6140+
if (llvm::DINodeArray OldAnnotations = Type->getAnnotations())
6141+
for (const llvm::Metadata *O : OldAnnotations->operands())
6142+
Annotations.push_back(const_cast<llvm::Metadata *>(O));
6143+
auto Clone = Type->clone();
6144+
Clone->replaceAnnotations(DBuilder.getOrCreateArray(Annotations));
6145+
return llvm::MDNode::replaceWithPermanent(std::move(Clone));
6146+
};
6147+
6148+
if (auto *Ty = dyn_cast<llvm::DIBasicType>(WrappedDI))
6149+
return AddAnnotations(Ty);
6150+
if (auto *Ty = dyn_cast<llvm::DICompositeType>(WrappedDI))
6151+
return AddAnnotations(Ty);
6152+
if (auto *Ty = dyn_cast<llvm::DIDerivedType>(WrappedDI))
6153+
return AddAnnotations(Ty);
6154+
if (auto *Ty = dyn_cast<llvm::DISubroutineType>(WrappedDI))
6155+
return AddAnnotations(Ty);
6156+
6157+
return WrappedDI;
6158+
}
6159+
60086160
void CGDebugInfo::finalize() {
60096161
// Creating types might create further types - invalidating the current
60106162
// element and the size(), so don't cache/reference them.
@@ -6078,6 +6230,10 @@ void CGDebugInfo::finalize() {
60786230
if (auto MD = TypeCache[RT])
60796231
DBuilder.retainType(cast<llvm::DIType>(MD));
60806232

6233+
for (auto &Placeholder : AnnotationPlaceholders)
6234+
DBuilder.replaceTemporary(llvm::TempDIType(Placeholder),
6235+
copyAnnotations(DBuilder, Placeholder));
6236+
60816237
DBuilder.finalize();
60826238
}
60836239

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ class CGDebugInfo {
171171
/// The key is coroutine real parameters, value is DIVariable in LLVM IR.
172172
Param2DILocTy ParamDbgMappings;
173173

174+
std::vector<llvm::DIDerivedType *> AnnotationPlaceholders;
175+
174176
/// Helper functions for getOrCreateType.
175177
/// @{
176178
/// Currently the checksum of an interface includes the number of
@@ -218,6 +220,7 @@ class CGDebugInfo {
218220
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
219221
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
220222
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
223+
llvm::DIType *CreateType(const BTFTagAttributedType *Ty, llvm::DIFile *F);
221224
/// Get enumeration type.
222225
llvm::DIType *CreateEnumType(const EnumType *Ty);
223226
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang_cc1 \
2+
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
3+
// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
4+
5+
#define __tag1 __attribute__((btf_type_tag("tag1")))
6+
7+
struct st {
8+
struct st __tag1 *self;
9+
} g;
10+
11+
// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
12+
// CHECK: ![[L1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2:[0-9]+]])
13+
// CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
14+
// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_member, name: "self", scope: ![[L1]], file: ![[#]], line: [[#]], baseType: ![[L4:[0-9]+]], size: [[#]])
15+
// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], size: [[#]])
16+
// CHECK: ![[L5]] = !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2]], annotations: ![[L7:[0-9]+]])
17+
// CHECK: ![[L7]] = !{![[L8:[0-9]+]]}
18+
// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %clang_cc1 \
2+
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
3+
// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
4+
5+
// Check that BTF type tags are not attached to DW_TAG_const_type DIEs
6+
// in presence of "sugar" expressions that are transparent for
7+
// CGDebugInfo.cpp:UnwrapTypeForDebugInfo(), but are not transparent
8+
// for local qualifiers.
9+
//
10+
// For details see:
11+
// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile)
12+
13+
#define __tag1 __attribute__((btf_type_tag("tag1")))
14+
#define __tag2 __attribute__((btf_type_tag("tag2")))
15+
#define __tag3 __attribute__((btf_type_tag("tag3")))
16+
17+
const int *foo;
18+
typeof(*foo) __tag1 bar;
19+
20+
// CHECK: distinct !DIGlobalVariable(name: "bar", {{.*}}, type: ![[L01:[0-9]+]], {{.*}})
21+
// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L02:[0-9]+]])
22+
// CHECK: ![[L02]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L03:[0-9]+]])
23+
// CHECK: ![[L03]] = !{![[L04:[0-9]+]]}
24+
// CHECK: ![[L04]] = !{!"btf:type_tag", !"tag1"}
25+
26+
const int __tag2 *buz;
27+
28+
// CHECK: distinct !DIGlobalVariable(name: "buz", {{.*}}, type: ![[L05:[0-9]+]], {{.*}})
29+
// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], {{.*}})
30+
// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]])
31+
// CHECK: ![[L08]] = !DIBasicType(name: "int", size: [[#]], {{.*}}, annotations: ![[L09:[0-9]+]])
32+
// CHECK: ![[L09]] = !{![[L10:[0-9]+]]}
33+
// CHECK: ![[L10]] = !{!"btf:type_tag", !"tag2"}
34+
35+
typeof(*buz) __tag3 quux;
36+
37+
// CHECK: distinct !DIGlobalVariable(name: "quux", {{.*}}, type: ![[L12:[0-9]+]], {{.*}})
38+
// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L13:[0-9]+]])
39+
// CHECK: ![[L13]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L14:[0-9]+]])
40+
// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L10]]}
41+
// CHECK: ![[L15]] = !{!"btf:type_tag", !"tag3"}
Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
2+
// RUN: %clang_cc1 \
3+
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
4+
// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
5+
// RUN: | FileCheck --check-prefix CHECK-V2 %s
26

37
struct t {
48
int (__attribute__((btf_type_tag("rcu"))) *f)();
@@ -8,8 +12,13 @@ int foo(struct t *arg) {
812
return arg->a;
913
}
1014

11-
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f"
12-
// CHECK-SAME: baseType: ![[L18:[0-9]+]]
13-
// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]])
14-
// CHECK: ![[L21]] = !{![[L22:[0-9]+]]}
15-
// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"}
15+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]])
16+
// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L2:[0-9]+]])
17+
// CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
18+
// CHECK: ![[L3]] = !{!"btf_type_tag", !"rcu"}
19+
20+
// CHECK-V2: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]])
21+
// CHECK-V2: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]])
22+
// CHECK-V2: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L4:[0-9]+]])
23+
// CHECK-V2: ![[L4]] = !{![[L5:[0-9]+]]}
24+
// CHECK-V2: ![[L5]] = !{!"btf:type_tag", !"rcu"}

0 commit comments

Comments
 (0)