Skip to content

Commit 737e421

Browse files
committed
[Attr] support btf_type_tag attribute
This patch added clang codegen and llvm support for btf_type_tag support. Currently, btf_type_tag attribute info is preserved in DebugInfo IR only for pointer types associated with typedef, global variable and function declaration. Eventually, such information is emitted to dwarf. The following is an example: $ cat test.c #define __tag __attribute__((btf_type_tag("tag"))) int __tag *g; $ clang -O2 -g -c test.c $ llvm-dwarfdump --debug-info test.o ... 0x0000001e: DW_TAG_variable DW_AT_name ("g") DW_AT_type (0x00000033 "int *") DW_AT_external (true) DW_AT_decl_file ("/home/yhs/test.c") DW_AT_decl_line (2) DW_AT_location (DW_OP_addr 0x0) 0x00000033: DW_TAG_pointer_type DW_AT_type (0x00000042 "int") 0x00000038: DW_TAG_LLVM_annotation DW_AT_name ("btf_type_tag") DW_AT_const_value ("tag") 0x00000041: NULL 0x00000042: DW_TAG_base_type DW_AT_name ("int") DW_AT_encoding (DW_ATE_signed) DW_AT_byte_size (0x04) 0x00000049: NULL Basically, a DW_TAG_LLVM_annotation tag will be inserted under DW_TAG_pointer_type tag if that pointer has a btf_type_tag associated with it. Differential Revision: https://reviews.llvm.org/D111199
1 parent 453fdeb commit 737e421

File tree

9 files changed

+361
-55
lines changed

9 files changed

+361
-55
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 150 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -929,8 +929,28 @@ static llvm::dwarf::Tag getNextQualifier(Qualifiers &Q) {
929929
return (llvm::dwarf::Tag)0;
930930
}
931931

932-
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
933-
llvm::DIFile *Unit) {
932+
// Strip MacroQualifiedTypeLoc and AttributedTypeLoc
933+
// as their corresponding types will be ignored
934+
// during code generation. Stripping them allows
935+
// to maintain proper TypeLoc for a given type
936+
// during code generation.
937+
static TypeLoc StripMacroAttributed(TypeLoc TL) {
938+
if (!TL)
939+
return TL;
940+
941+
while (true) {
942+
if (auto MTL = TL.getAs<MacroQualifiedTypeLoc>())
943+
TL = MTL.getInnerLoc();
944+
else if (auto ATL = TL.getAs<AttributedTypeLoc>())
945+
TL = ATL.getModifiedLoc();
946+
else
947+
break;
948+
}
949+
return TL;
950+
}
951+
952+
llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit,
953+
TypeLoc TL) {
934954
QualifierCollector Qc;
935955
const Type *T = Qc.strip(Ty);
936956

@@ -944,7 +964,15 @@ llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
944964
return getOrCreateType(QualType(T, 0), Unit);
945965
}
946966

947-
auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
967+
QualType NextTy = Qc.apply(CGM.getContext(), T);
968+
TypeLoc NextTL;
969+
if (NextTy.hasQualifiers())
970+
NextTL = TL;
971+
else if (TL) {
972+
if (auto QTL = TL.getAs<QualifiedTypeLoc>())
973+
NextTL = StripMacroAttributed(QTL.getNextTypeLoc());
974+
}
975+
auto *FromTy = getOrCreateType(NextTy, Unit, NextTL);
948976

949977
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
950978
// CVR derived types.
@@ -988,10 +1016,10 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
9881016
Ty->getPointeeType(), Unit);
9891017
}
9901018

991-
llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
992-
llvm::DIFile *Unit) {
1019+
llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIFile *Unit,
1020+
TypeLoc TL) {
9931021
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
994-
Ty->getPointeeType(), Unit);
1022+
Ty->getPointeeType(), Unit, TL);
9951023
}
9961024

9971025
/// \return whether a C++ mangling exists for the type defined by TD.
@@ -1132,7 +1160,8 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
11321160
llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
11331161
const Type *Ty,
11341162
QualType PointeeTy,
1135-
llvm::DIFile *Unit) {
1163+
llvm::DIFile *Unit,
1164+
TypeLoc TL) {
11361165
// Bit size, align and offset of the type.
11371166
// Size is always the size of a pointer. We can't use getTypeSize here
11381167
// because that does not return the correct value for references.
@@ -1142,13 +1171,52 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
11421171
Optional<unsigned> DWARFAddressSpace =
11431172
CGM.getTarget().getDWARFAddressSpace(AddressSpace);
11441173

1174+
llvm::DINodeArray Annotations = nullptr;
1175+
TypeLoc NextTL;
1176+
if (TL) {
1177+
SmallVector<llvm::Metadata *, 4> Annots;
1178+
NextTL = TL.getNextTypeLoc();
1179+
if (NextTL) {
1180+
// Traverse all MacroQualifiedTypeLoc, QualifiedTypeLoc and
1181+
// AttributedTypeLoc type locations so we can collect
1182+
// BTFTypeTag attributes for this pointer.
1183+
while (true) {
1184+
if (auto MTL = NextTL.getAs<MacroQualifiedTypeLoc>()) {
1185+
NextTL = MTL.getInnerLoc();
1186+
} else if (auto QTL = NextTL.getAs<QualifiedTypeLoc>()) {
1187+
NextTL = QTL.getNextTypeLoc();
1188+
} else if (auto ATL = NextTL.getAs<AttributedTypeLoc>()) {
1189+
if (const auto *A = ATL.getAttrAs<BTFTypeTagAttr>()) {
1190+
StringRef BTFTypeTag = A->getBTFTypeTag();
1191+
if (!BTFTypeTag.empty()) {
1192+
llvm::Metadata *Ops[2] = {
1193+
llvm::MDString::get(CGM.getLLVMContext(),
1194+
StringRef("btf_type_tag")),
1195+
llvm::MDString::get(CGM.getLLVMContext(), BTFTypeTag)};
1196+
Annots.insert(Annots.begin(),
1197+
llvm::MDNode::get(CGM.getLLVMContext(), Ops));
1198+
}
1199+
}
1200+
NextTL = ATL.getModifiedLoc();
1201+
} else {
1202+
break;
1203+
}
1204+
}
1205+
}
1206+
1207+
NextTL = StripMacroAttributed(TL.getNextTypeLoc());
1208+
if (Annots.size() > 0)
1209+
Annotations = DBuilder.getOrCreateArray(Annots);
1210+
}
1211+
11451212
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
11461213
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
11471214
return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
11481215
Size, Align, DWARFAddressSpace);
11491216
else
1150-
return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
1151-
Align, DWARFAddressSpace);
1217+
return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit, NextTL),
1218+
Size, Align, DWARFAddressSpace,
1219+
StringRef(), Annotations);
11521220
}
11531221

11541222
llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -1265,8 +1333,11 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
12651333

12661334
llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
12671335
llvm::DIFile *Unit) {
1336+
TypeLoc TL;
1337+
if (const TypeSourceInfo *TSI = Ty->getDecl()->getTypeSourceInfo())
1338+
TL = TSI->getTypeLoc();
12681339
llvm::DIType *Underlying =
1269-
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
1340+
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, TL);
12701341

12711342
if (Ty->getDecl()->hasAttr<NoDebugAttr>())
12721343
return Underlying;
@@ -1340,7 +1411,7 @@ static llvm::DINode::DIFlags getRefFlags(const FunctionProtoType *Func) {
13401411
}
13411412

13421413
llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
1343-
llvm::DIFile *Unit) {
1414+
llvm::DIFile *Unit, TypeLoc TL) {
13441415
const auto *FPT = dyn_cast<FunctionProtoType>(Ty);
13451416
if (FPT) {
13461417
if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit))
@@ -1352,17 +1423,41 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
13521423
SmallVector<llvm::Metadata *, 16> EltTys;
13531424

13541425
// Add the result type at least.
1355-
EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit));
1426+
TypeLoc RetTL;
1427+
if (TL) {
1428+
if (auto FTL = TL.getAs<FunctionTypeLoc>())
1429+
RetTL = FTL.getReturnLoc();
1430+
}
1431+
EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit, RetTL));
13561432

13571433
llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
13581434
// Set up remainder of arguments if there is a prototype.
13591435
// otherwise emit it as a variadic function.
1360-
if (!FPT)
1436+
if (!FPT) {
13611437
EltTys.push_back(DBuilder.createUnspecifiedParameter());
1362-
else {
1438+
} else {
13631439
Flags = getRefFlags(FPT);
1364-
for (const QualType &ParamType : FPT->param_types())
1365-
EltTys.push_back(getOrCreateType(ParamType, Unit));
1440+
bool DoneWithTL = false;
1441+
if (TL) {
1442+
if (auto FTL = TL.getAs<FunctionTypeLoc>()) {
1443+
DoneWithTL = true;
1444+
int Idx = 0;
1445+
for (const QualType &ParamType : FPT->param_types()) {
1446+
TypeLoc ParamTL;
1447+
if (ParmVarDecl *Param = FTL.getParam(Idx)) {
1448+
if (const TypeSourceInfo *TSI = Param->getTypeSourceInfo())
1449+
ParamTL = TSI->getTypeLoc();
1450+
}
1451+
EltTys.push_back(getOrCreateType(ParamType, Unit, ParamTL));
1452+
Idx++;
1453+
}
1454+
}
1455+
}
1456+
1457+
if (!DoneWithTL) {
1458+
for (const QualType &ParamType : FPT->param_types())
1459+
EltTys.push_back(getOrCreateType(ParamType, Unit));
1460+
}
13661461
if (FPT->isVariadic())
13671462
EltTys.push_back(DBuilder.createUnspecifiedParameter());
13681463
}
@@ -1433,11 +1528,13 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
14331528
Flags, DebugType, Annotations);
14341529
}
14351530

1436-
llvm::DIType *CGDebugInfo::createFieldType(
1437-
StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
1438-
uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
1439-
llvm::DIScope *scope, const RecordDecl *RD, llvm::DINodeArray Annotations) {
1440-
llvm::DIType *debugType = getOrCreateType(type, tunit);
1531+
llvm::DIType *
1532+
CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
1533+
AccessSpecifier AS, uint64_t offsetInBits,
1534+
uint32_t AlignInBits, llvm::DIFile *tunit,
1535+
llvm::DIScope *scope, const RecordDecl *RD,
1536+
llvm::DINodeArray Annotations, TypeLoc TL) {
1537+
llvm::DIType *debugType = getOrCreateType(type, tunit, TL);
14411538

14421539
// Get the location for the field.
14431540
llvm::DIFile *file = getOrCreateFile(loc);
@@ -1545,9 +1642,12 @@ void CGDebugInfo::CollectRecordNormalField(
15451642
} else {
15461643
auto Align = getDeclAlignIfRequired(field, CGM.getContext());
15471644
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
1548-
FieldType =
1549-
createFieldType(name, type, field->getLocation(), field->getAccess(),
1550-
OffsetInBits, Align, tunit, RecordTy, RD, Annotations);
1645+
TypeLoc TL;
1646+
if (const TypeSourceInfo *TSI = field->getTypeSourceInfo())
1647+
TL = TSI->getTypeLoc();
1648+
FieldType = createFieldType(name, type, field->getLocation(),
1649+
field->getAccess(), OffsetInBits, Align, tunit,
1650+
RecordTy, RD, Annotations, TL);
15511651
}
15521652

15531653
elements.push_back(FieldType);
@@ -3305,7 +3405,8 @@ void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
33053405
RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
33063406
}
33073407

3308-
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
3408+
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit,
3409+
TypeLoc TL) {
33093410
if (Ty.isNull())
33103411
return nullptr;
33113412

@@ -3322,7 +3423,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
33223423
if (auto *T = getTypeOrNull(Ty))
33233424
return T;
33243425

3325-
llvm::DIType *Res = CreateTypeNode(Ty, Unit);
3426+
llvm::DIType *Res = CreateTypeNode(Ty, Unit, TL);
33263427
void *TyPtr = Ty.getAsOpaquePtr();
33273428

33283429
// And update the type cache.
@@ -3366,10 +3467,11 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
33663467
return nullptr;
33673468
}
33683469

3369-
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
3470+
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit,
3471+
TypeLoc TL) {
33703472
// Handle qualifiers, which recursively handles what they refer to.
33713473
if (Ty.hasLocalQualifiers())
3372-
return CreateQualifiedType(Ty, Unit);
3474+
return CreateQualifiedType(Ty, Unit, TL);
33733475

33743476
// Work out details of type.
33753477
switch (Ty->getTypeClass()) {
@@ -3398,7 +3500,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
33983500
case Type::Complex:
33993501
return CreateType(cast<ComplexType>(Ty));
34003502
case Type::Pointer:
3401-
return CreateType(cast<PointerType>(Ty), Unit);
3503+
return CreateType(cast<PointerType>(Ty), Unit, TL);
34023504
case Type::BlockPointer:
34033505
return CreateType(cast<BlockPointerType>(Ty), Unit);
34043506
case Type::Typedef:
@@ -3409,7 +3511,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
34093511
return CreateEnumType(cast<EnumType>(Ty));
34103512
case Type::FunctionProto:
34113513
case Type::FunctionNoProto:
3412-
return CreateType(cast<FunctionType>(Ty), Unit);
3514+
return CreateType(cast<FunctionType>(Ty), Unit, TL);
34133515
case Type::ConstantArray:
34143516
case Type::VariableArray:
34153517
case Type::IncompleteArray:
@@ -3954,7 +4056,12 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
39544056
getDwarfCC(CC));
39554057
}
39564058

3957-
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
4059+
TypeLoc TL;
4060+
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
4061+
if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo())
4062+
TL = TSI->getTypeLoc();
4063+
}
4064+
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F, TL));
39584065
}
39594066

39604067
QualType
@@ -4356,8 +4463,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
43564463
uint64_t XOffset = 0;
43574464
if (VD->hasAttr<BlocksAttr>())
43584465
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
4359-
else
4360-
Ty = getOrCreateType(VD->getType(), Unit);
4466+
else {
4467+
TypeLoc TL;
4468+
if (const TypeSourceInfo *TSI = VD->getTypeSourceInfo())
4469+
TL = TSI->getTypeLoc();
4470+
Ty = getOrCreateType(VD->getType(), Unit, TL);
4471+
}
43614472

43624473
// If there is no debug info for this type then do not emit debug info
43634474
// for this variable.
@@ -5081,10 +5192,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
50815192
}
50825193
AppendAddressSpaceXDeref(AddressSpace, Expr);
50835194

5195+
TypeLoc TL;
5196+
if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
5197+
TL = TSI->getTypeLoc();
5198+
50845199
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
50855200
GVE = DBuilder.createGlobalVariableExpression(
5086-
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
5087-
Var->hasLocalLinkage(), true,
5201+
DContext, DeclName, LinkageName, Unit, LineNo,
5202+
getOrCreateType(T, Unit, TL), Var->hasLocalLinkage(), true,
50885203
Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
50895204
getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
50905205
Align, Annotations);

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,16 +178,19 @@ class CGDebugInfo {
178178
llvm::DIType *CreateType(const ComplexType *Ty);
179179
llvm::DIType *CreateType(const AutoType *Ty);
180180
llvm::DIType *CreateType(const ExtIntType *Ty);
181-
llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
181+
llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg,
182+
TypeLoc TL = TypeLoc());
182183
llvm::DIType *CreateQualifiedType(const FunctionProtoType *Ty,
183184
llvm::DIFile *Fg);
184185
llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg);
185186
llvm::DIType *CreateType(const TemplateSpecializationType *Ty,
186187
llvm::DIFile *Fg);
187188
llvm::DIType *CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *F);
188-
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F);
189+
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F,
190+
TypeLoc TL = TypeLoc());
189191
llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F);
190-
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F);
192+
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F,
193+
TypeLoc TL = TypeLoc());
191194
/// Get structure or union type.
192195
llvm::DIType *CreateType(const RecordType *Tyg);
193196
llvm::DIType *CreateTypeDefinition(const RecordType *Ty);
@@ -242,7 +245,8 @@ class CGDebugInfo {
242245
/// \return namespace descriptor for the given namespace decl.
243246
llvm::DINamespace *getOrCreateNamespace(const NamespaceDecl *N);
244247
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
245-
QualType PointeeTy, llvm::DIFile *F);
248+
QualType PointeeTy, llvm::DIFile *F,
249+
TypeLoc TL = TypeLoc());
246250
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);
247251

248252
/// A helper function to create a subprogram for a single member
@@ -308,7 +312,8 @@ class CGDebugInfo {
308312
uint64_t offsetInBits, uint32_t AlignInBits,
309313
llvm::DIFile *tunit, llvm::DIScope *scope,
310314
const RecordDecl *RD = nullptr,
311-
llvm::DINodeArray Annotations = nullptr);
315+
llvm::DINodeArray Annotations = nullptr,
316+
TypeLoc TL = TypeLoc());
312317

313318
llvm::DIType *createFieldType(StringRef name, QualType type,
314319
SourceLocation loc, AccessSpecifier AS,
@@ -628,7 +633,8 @@ class CGDebugInfo {
628633
Optional<StringRef> Source);
629634

630635
/// Get the type from the cache or create a new type if necessary.
631-
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
636+
llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg,
637+
TypeLoc TL = TypeLoc());
632638

633639
/// Get a reference to a clang module. If \p CreateSkeletonCU is true,
634640
/// this also creates a split dwarf skeleton compile unit.
@@ -643,7 +649,8 @@ class CGDebugInfo {
643649
llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty);
644650

645651
/// Create type metadata for a source language type.
646-
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
652+
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg,
653+
TypeLoc TL = TypeLoc());
647654

648655
/// Create new member and increase Offset by FType's size.
649656
llvm::DIType *CreateMemberType(llvm::DIFile *Unit, QualType FType,

0 commit comments

Comments
 (0)