Skip to content

Commit

Permalink
Reland "[Attr] support btf_type_tag attribute"
Browse files Browse the repository at this point in the history
This is to revert commit f95bd18 (Revert "[Attr] support
btf_type_tag attribute") plus a bug fix.

Previous change failed to handle cases like below:
    $ cat reduced.c
    void a(*);
    void a() {}
    $ clang -c reduced.c -O2 -g

In such cases, during clang IR generation, for function a(),
CGCodeGen has numParams = 1 for FunctionType. But for
FunctionTypeLoc we have FuncTypeLoc.NumParams = 0. By using
FunctionType.numParams as the bound to access FuncTypeLoc
params, a random crash is triggered. The bug fix is to
check against FuncTypeLoc.NumParams before accessing
FuncTypeLoc.getParam(Idx).

Differential Revision: https://reviews.llvm.org/D111199
  • Loading branch information
yonghong-song committed Nov 5, 2021
1 parent f64580f commit 3466e00
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 55 deletions.
187 changes: 152 additions & 35 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,8 +929,28 @@ static llvm::dwarf::Tag getNextQualifier(Qualifiers &Q) {
return (llvm::dwarf::Tag)0;
}

llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
llvm::DIFile *Unit) {
// Strip MacroQualifiedTypeLoc and AttributedTypeLoc
// as their corresponding types will be ignored
// during code generation. Stripping them allows
// to maintain proper TypeLoc for a given type
// during code generation.
static TypeLoc StripMacroAttributed(TypeLoc TL) {
if (!TL)
return TL;

while (true) {
if (auto MTL = TL.getAs<MacroQualifiedTypeLoc>())
TL = MTL.getInnerLoc();
else if (auto ATL = TL.getAs<AttributedTypeLoc>())
TL = ATL.getModifiedLoc();
else
break;
}
return TL;
}

llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit,
TypeLoc TL) {
QualifierCollector Qc;
const Type *T = Qc.strip(Ty);

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

auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
QualType NextTy = Qc.apply(CGM.getContext(), T);
TypeLoc NextTL;
if (NextTy.hasQualifiers())
NextTL = TL;
else if (TL) {
if (auto QTL = TL.getAs<QualifiedTypeLoc>())
NextTL = StripMacroAttributed(QTL.getNextTypeLoc());
}
auto *FromTy = getOrCreateType(NextTy, Unit, NextTL);

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

llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty,
llvm::DIFile *Unit) {
llvm::DIType *CGDebugInfo::CreateType(const PointerType *Ty, llvm::DIFile *Unit,
TypeLoc TL) {
return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
Ty->getPointeeType(), Unit, TL);
}

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

llvm::DINodeArray Annotations = nullptr;
TypeLoc NextTL;
if (TL) {
SmallVector<llvm::Metadata *, 4> Annots;
NextTL = TL.getNextTypeLoc();
if (NextTL) {
// Traverse all MacroQualifiedTypeLoc, QualifiedTypeLoc and
// AttributedTypeLoc type locations so we can collect
// BTFTypeTag attributes for this pointer.
while (true) {
if (auto MTL = NextTL.getAs<MacroQualifiedTypeLoc>()) {
NextTL = MTL.getInnerLoc();
} else if (auto QTL = NextTL.getAs<QualifiedTypeLoc>()) {
NextTL = QTL.getNextTypeLoc();
} else if (auto ATL = NextTL.getAs<AttributedTypeLoc>()) {
if (const auto *A = ATL.getAttrAs<BTFTypeTagAttr>()) {
StringRef BTFTypeTag = A->getBTFTypeTag();
if (!BTFTypeTag.empty()) {
llvm::Metadata *Ops[2] = {
llvm::MDString::get(CGM.getLLVMContext(),
StringRef("btf_type_tag")),
llvm::MDString::get(CGM.getLLVMContext(), BTFTypeTag)};
Annots.insert(Annots.begin(),
llvm::MDNode::get(CGM.getLLVMContext(), Ops));
}
}
NextTL = ATL.getModifiedLoc();
} else {
break;
}
}
}

NextTL = StripMacroAttributed(TL.getNextTypeLoc());
if (Annots.size() > 0)
Annotations = DBuilder.getOrCreateArray(Annots);
}

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);
return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit, NextTL),
Size, Align, DWARFAddressSpace,
StringRef(), Annotations);
}

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

llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
llvm::DIFile *Unit) {
TypeLoc TL;
if (const TypeSourceInfo *TSI = Ty->getDecl()->getTypeSourceInfo())
TL = TSI->getTypeLoc();
llvm::DIType *Underlying =
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, TL);

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

llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
llvm::DIFile *Unit) {
llvm::DIFile *Unit, TypeLoc TL) {
const auto *FPT = dyn_cast<FunctionProtoType>(Ty);
if (FPT) {
if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit))
Expand All @@ -1352,17 +1423,43 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
SmallVector<llvm::Metadata *, 16> EltTys;

// Add the result type at least.
EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit));
TypeLoc RetTL;
if (TL) {
if (auto FTL = TL.getAs<FunctionTypeLoc>())
RetTL = FTL.getReturnLoc();
}
EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit, RetTL));

llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
// Set up remainder of arguments if there is a prototype.
// otherwise emit it as a variadic function.
if (!FPT)
if (!FPT) {
EltTys.push_back(DBuilder.createUnspecifiedParameter());
else {
} else {
Flags = getRefFlags(FPT);
for (const QualType &ParamType : FPT->param_types())
EltTys.push_back(getOrCreateType(ParamType, Unit));
bool DoneWithTL = false;
if (TL) {
if (auto FTL = TL.getAs<FunctionTypeLoc>()) {
DoneWithTL = true;
unsigned Idx = 0;
unsigned FTL_NumParams = FTL.getNumParams();
for (const QualType &ParamType : FPT->param_types()) {
TypeLoc ParamTL;
if (Idx < FTL_NumParams) {
ParmVarDecl *Param = FTL.getParam(Idx);
if (const TypeSourceInfo *TSI = Param->getTypeSourceInfo())
ParamTL = TSI->getTypeLoc();
}
EltTys.push_back(getOrCreateType(ParamType, Unit, ParamTL));
Idx++;
}
}
}

if (!DoneWithTL) {
for (const QualType &ParamType : FPT->param_types())
EltTys.push_back(getOrCreateType(ParamType, Unit));
}
if (FPT->isVariadic())
EltTys.push_back(DBuilder.createUnspecifiedParameter());
}
Expand Down Expand Up @@ -1433,11 +1530,13 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
Flags, DebugType, Annotations);
}

llvm::DIType *CGDebugInfo::createFieldType(
StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
llvm::DIScope *scope, const RecordDecl *RD, llvm::DINodeArray Annotations) {
llvm::DIType *debugType = getOrCreateType(type, tunit);
llvm::DIType *
CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
AccessSpecifier AS, uint64_t offsetInBits,
uint32_t AlignInBits, llvm::DIFile *tunit,
llvm::DIScope *scope, const RecordDecl *RD,
llvm::DINodeArray Annotations, TypeLoc TL) {
llvm::DIType *debugType = getOrCreateType(type, tunit, TL);

// Get the location for the field.
llvm::DIFile *file = getOrCreateFile(loc);
Expand Down Expand Up @@ -1545,9 +1644,12 @@ void CGDebugInfo::CollectRecordNormalField(
} else {
auto Align = getDeclAlignIfRequired(field, CGM.getContext());
llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
FieldType =
createFieldType(name, type, field->getLocation(), field->getAccess(),
OffsetInBits, Align, tunit, RecordTy, RD, Annotations);
TypeLoc TL;
if (const TypeSourceInfo *TSI = field->getTypeSourceInfo())
TL = TSI->getTypeLoc();
FieldType = createFieldType(name, type, field->getLocation(),
field->getAccess(), OffsetInBits, Align, tunit,
RecordTy, RD, Annotations, TL);
}

elements.push_back(FieldType);
Expand Down Expand Up @@ -3305,7 +3407,8 @@ void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
}

llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit,
TypeLoc TL) {
if (Ty.isNull())
return nullptr;

Expand All @@ -3322,7 +3425,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
if (auto *T = getTypeOrNull(Ty))
return T;

llvm::DIType *Res = CreateTypeNode(Ty, Unit);
llvm::DIType *Res = CreateTypeNode(Ty, Unit, TL);
void *TyPtr = Ty.getAsOpaquePtr();

// And update the type cache.
Expand Down Expand Up @@ -3366,10 +3469,11 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
return nullptr;
}

llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit,
TypeLoc TL) {
// Handle qualifiers, which recursively handles what they refer to.
if (Ty.hasLocalQualifiers())
return CreateQualifiedType(Ty, Unit);
return CreateQualifiedType(Ty, Unit, TL);

// Work out details of type.
switch (Ty->getTypeClass()) {
Expand Down Expand Up @@ -3398,7 +3502,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::Complex:
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
return CreateType(cast<PointerType>(Ty), Unit, TL);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
Expand All @@ -3409,7 +3513,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
return CreateEnumType(cast<EnumType>(Ty));
case Type::FunctionProto:
case Type::FunctionNoProto:
return CreateType(cast<FunctionType>(Ty), Unit);
return CreateType(cast<FunctionType>(Ty), Unit, TL);
case Type::ConstantArray:
case Type::VariableArray:
case Type::IncompleteArray:
Expand Down Expand Up @@ -3954,7 +4058,12 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
getDwarfCC(CC));
}

return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
TypeLoc TL;
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo())
TL = TSI->getTypeLoc();
}
return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F, TL));
}

QualType
Expand Down Expand Up @@ -4356,8 +4465,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
else
Ty = getOrCreateType(VD->getType(), Unit);
else {
TypeLoc TL;
if (const TypeSourceInfo *TSI = VD->getTypeSourceInfo())
TL = TSI->getTypeLoc();
Ty = getOrCreateType(VD->getType(), Unit, TL);
}

// If there is no debug info for this type then do not emit debug info
// for this variable.
Expand Down Expand Up @@ -5081,10 +5194,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
}
AppendAddressSpaceXDeref(AddressSpace, Expr);

TypeLoc TL;
if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
TL = TSI->getTypeLoc();

llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
GVE = DBuilder.createGlobalVariableExpression(
DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
Var->hasLocalLinkage(), true,
DContext, DeclName, LinkageName, Unit, LineNo,
getOrCreateType(T, Unit, TL), Var->hasLocalLinkage(), true,
Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
Align, Annotations);
Expand Down
21 changes: 14 additions & 7 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,16 +178,19 @@ class CGDebugInfo {
llvm::DIType *CreateType(const ComplexType *Ty);
llvm::DIType *CreateType(const AutoType *Ty);
llvm::DIType *CreateType(const ExtIntType *Ty);
llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg);
llvm::DIType *CreateQualifiedType(QualType Ty, llvm::DIFile *Fg,
TypeLoc TL = TypeLoc());
llvm::DIType *CreateQualifiedType(const FunctionProtoType *Ty,
llvm::DIFile *Fg);
llvm::DIType *CreateType(const TypedefType *Ty, llvm::DIFile *Fg);
llvm::DIType *CreateType(const TemplateSpecializationType *Ty,
llvm::DIFile *Fg);
llvm::DIType *CreateType(const ObjCObjectPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PointerType *Ty, llvm::DIFile *F,
TypeLoc TL = TypeLoc());
llvm::DIType *CreateType(const BlockPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const FunctionType *Ty, llvm::DIFile *F,
TypeLoc TL = TypeLoc());
/// Get structure or union type.
llvm::DIType *CreateType(const RecordType *Tyg);
llvm::DIType *CreateTypeDefinition(const RecordType *Ty);
Expand Down Expand Up @@ -242,7 +245,8 @@ class CGDebugInfo {
/// \return namespace descriptor for the given namespace decl.
llvm::DINamespace *getOrCreateNamespace(const NamespaceDecl *N);
llvm::DIType *CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty,
QualType PointeeTy, llvm::DIFile *F);
QualType PointeeTy, llvm::DIFile *F,
TypeLoc TL = TypeLoc());
llvm::DIType *getOrCreateStructPtrType(StringRef Name, llvm::DIType *&Cache);

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

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

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

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

/// Create type metadata for a source language type.
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg);
llvm::DIType *CreateTypeNode(QualType Ty, llvm::DIFile *Fg,
TypeLoc TL = TypeLoc());

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

0 comments on commit 3466e00

Please sign in to comment.