diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 64dd70f837f7bc..9813c01beef3eb 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -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()) + TL = MTL.getInnerLoc(); + else if (auto ATL = TL.getAs()) + 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); @@ -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()) + 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. @@ -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. @@ -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. @@ -1142,13 +1171,52 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, Optional DWARFAddressSpace = CGM.getTarget().getDWARFAddressSpace(AddressSpace); + llvm::DINodeArray Annotations = nullptr; + TypeLoc NextTL; + if (TL) { + SmallVector 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()) { + NextTL = MTL.getInnerLoc(); + } else if (auto QTL = NextTL.getAs()) { + NextTL = QTL.getNextTypeLoc(); + } else if (auto ATL = NextTL.getAs()) { + if (const auto *A = ATL.getAttrAs()) { + 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, @@ -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()) return Underlying; @@ -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(Ty); if (FPT) { if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit)) @@ -1352,17 +1423,41 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty, SmallVector EltTys; // Add the result type at least. - EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit)); + TypeLoc RetTL; + if (TL) { + if (auto FTL = TL.getAs()) + 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()) { + DoneWithTL = true; + int Idx = 0; + for (const QualType &ParamType : FPT->param_types()) { + TypeLoc ParamTL; + if (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()); } @@ -1433,11 +1528,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); @@ -1545,9 +1642,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); @@ -3305,7 +3405,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; @@ -3322,7 +3423,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. @@ -3366,10 +3467,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()) { @@ -3398,7 +3500,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { case Type::Complex: return CreateType(cast(Ty)); case Type::Pointer: - return CreateType(cast(Ty), Unit); + return CreateType(cast(Ty), Unit, TL); case Type::BlockPointer: return CreateType(cast(Ty), Unit); case Type::Typedef: @@ -3409,7 +3511,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) { return CreateEnumType(cast(Ty)); case Type::FunctionProto: case Type::FunctionNoProto: - return CreateType(cast(Ty), Unit); + return CreateType(cast(Ty), Unit, TL); case Type::ConstantArray: case Type::VariableArray: case Type::IncompleteArray: @@ -3954,7 +4056,12 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D, getDwarfCC(CC)); } - return cast(getOrCreateType(FnType, F)); + TypeLoc TL; + if (const auto *FD = dyn_cast(D)) { + if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo()) + TL = TSI->getTypeLoc(); + } + return cast(getOrCreateType(FnType, F, TL)); } QualType @@ -4356,8 +4463,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD, uint64_t XOffset = 0; if (VD->hasAttr()) 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. @@ -5081,10 +5192,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); diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index d6b9bdd4839cc7..a7b72fa5f5a656 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -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); @@ -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 @@ -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, @@ -628,7 +633,8 @@ class CGDebugInfo { Optional 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. @@ -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, diff --git a/clang/test/CodeGen/attr-btf_type_tag-func.c b/clang/test/CodeGen/attr-btf_type_tag-func.c new file mode 100644 index 00000000000000..016e1064eb861a --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-func.c @@ -0,0 +1,20 @@ +// 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"))) +#define __tag2 __attribute__((btf_type_tag("tag2"))) +#define __tag3 __attribute__((btf_type_tag("tag3"))) +#define __tag4 __attribute__((btf_type_tag("tag4"))) + +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]]) diff --git a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c new file mode 100644 index 00000000000000..c80c7e9b45d96f --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c @@ -0,0 +1,35 @@ +// 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"))) +#define __tag2 __attribute__((btf_type_tag("tag2"))) + +typedef void __fn_t(int); +typedef __fn_t __tag1 __tag2 *__fn2_t; +struct t { + int __tag1 * __tag2 *a; + __fn2_t b; + long c; +}; +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) diff --git a/clang/test/CodeGen/attr-btf_type_tag-var.c b/clang/test/CodeGen/attr-btf_type_tag-var.c new file mode 100644 index 00000000000000..3493d8f6d36669 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-var.c @@ -0,0 +1,31 @@ +// 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"))) +#define __tag2 __attribute__((btf_type_tag("tag2"))) +#define __tag3 __attribute__((btf_type_tag("tag3"))) +#define __tag4 __attribute__((btf_type_tag("tag4"))) +#define __tag5 __attribute__((btf_type_tag("tag5"))) +#define __tag6 __attribute__((btf_type_tag("tag6"))) + +const int __tag1 __tag2 volatile * const __tag3 __tag4 volatile * __tag5 __tag6 const volatile * g; + +// 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"} diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 90165095bb0c0a..61c6dd885980e9 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -219,11 +219,12 @@ namespace llvm { /// \param AlignInBits Alignment. (optional) /// \param DWARFAddressSpace DWARF address space. (optional) /// \param Name Pointer type name. (optional) - DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, - uint32_t AlignInBits = 0, - Optional DWARFAddressSpace = - None, - StringRef Name = ""); + /// \param Annotations Member annotations. + DIDerivedType * + createPointerType(DIType *PointeeTy, uint64_t SizeInBits, + uint32_t AlignInBits = 0, + Optional DWARFAddressSpace = None, + StringRef Name = "", DINodeArray Annotations = nullptr); /// Create debugging information entry for a pointer to member. /// \param PointeeTy Type pointed to by this pointer. diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index de4ab5981883d7..12320cf4af9f7b 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -287,17 +287,16 @@ DIDerivedType *DIBuilder::createQualifiedType(unsigned Tag, DIType *FromTy) { 0, 0, None, DINode::FlagZero); } -DIDerivedType *DIBuilder::createPointerType( - DIType *PointeeTy, - uint64_t SizeInBits, - uint32_t AlignInBits, - Optional DWARFAddressSpace, - StringRef Name) { +DIDerivedType * +DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits, + uint32_t AlignInBits, + Optional DWARFAddressSpace, + StringRef Name, DINodeArray Annotations) { // FIXME: Why is there a name here? return DIDerivedType::get(VMContext, dwarf::DW_TAG_pointer_type, Name, nullptr, 0, nullptr, PointeeTy, SizeInBits, - AlignInBits, 0, DWARFAddressSpace, - DINode::FlagZero); + AlignInBits, 0, DWARFAddressSpace, DINode::FlagZero, + nullptr, Annotations); } DIDerivedType *DIBuilder::createMemberPointerType(DIType *PointeeTy, diff --git a/llvm/test/Bitcode/attr-btf_type_tag.ll b/llvm/test/Bitcode/attr-btf_type_tag.ll new file mode 100644 index 00000000000000..ab0634bb147a05 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_type_tag.ll @@ -0,0 +1,36 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; +; Source: +; #define __tag1 __attribute__((btf_type_tag("tag1"))) +; int __tag1 *g; +; Compilation flag: +; clang -S -g -emit-llvm test.c + +@g = dso_local global i32* null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 248122328bfefe82608a2e110af3a3ff04279ddf)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/btf_tag_type") +!4 = !{!0} +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !7) +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = !{!8} +!8 = !{!"btf_type_tag", !"tag1"} + +; CHECK: distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5 +; CHECK: !5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !7) +; CHECK-NEXT: !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +; CHECK-NEXT: !7 = !{!8} +; CHECK-NEXT: !8 = !{!"btf_type_tag", !"tag1"} + +!9 = !{i32 7, !"Dwarf Version", i32 4} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{i32 7, !"uwtable", i32 1} +!13 = !{i32 7, !"frame-pointer", i32 2} +!14 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 248122328bfefe82608a2e110af3a3ff04279ddf)"} diff --git a/llvm/test/DebugInfo/attr-btf_type_tag.ll b/llvm/test/DebugInfo/attr-btf_type_tag.ll new file mode 100644 index 00000000000000..6cf72a899cd0a8 --- /dev/null +++ b/llvm/test/DebugInfo/attr-btf_type_tag.ll @@ -0,0 +1,62 @@ +; REQUIRES: x86-registered-target +; RUN: llc -filetype=obj -o %t %s +; RUN: llvm-dwarfdump -debug-info %t | FileCheck %s +; Source: +; #define __tag1 __attribute__((btf_type_tag("tag1"))) +; #define __tag2 __attribute__((btf_type_tag("tag2"))) +; +; int * __tag1 * __tag2 *g; +; Compilation flag: +; clang -target x86_64 -g -S -emit-llvm t.c + +@g = dso_local global i32*** null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!13, !14, !15, !16, !17} +!llvm.ident = !{!18} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/work/tests/llvm/btf_tag_type") +!4 = !{!0} +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !11) +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, annotations: !9) +!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64) +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !{!10} +!10 = !{!"btf_type_tag", !"tag1"} +!11 = !{!12} +!12 = !{!"btf_type_tag", !"tag2"} + +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_name ("g") +; CHECK-NEXT: DW_AT_type (0x[[T1:[0-9]+]] "int ***") + +; CHECK: 0x[[T1]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type (0x[[T2:[0-9]+]] "int **") + +; CHECK: DW_TAG_LLVM_annotation +; CHECK-NEXT: DW_AT_name ("btf_type_tag") +; CHECK-NEXT: DW_AT_const_value ("tag2") + +; CHECK: NULL + +; CHECK: 0x[[T2]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type (0x[[T3:[0-9]+]] "int *") + +; CHECK: DW_TAG_LLVM_annotation +; CHECK-NEXT: DW_AT_name ("btf_type_tag") +; CHECK-NEXT: DW_AT_const_value ("tag1") + +; CHECK: NULL + +; CHECK: 0x[[T3]]: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type (0x[[#]] "int") + +!13 = !{i32 7, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{i32 7, !"uwtable", i32 1} +!17 = !{i32 7, !"frame-pointer", i32 2} +!18 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)"}