diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -4891,19 +4891,27 @@ llvm::FoldingSetNodeID ID; BTFTagAttributedType::Profile(ID, Wrapped, BTFAttr); + // Split away local CVR qualifiers to make sure that + // BTFTagAttributedType is always applied to non-CVR qualified type. + // Apply CVR to a resulting QualType. + QualType WrappedNoCVR = Wrapped; + WrappedNoCVR.removeLocalCVRQualifiers(Qualifiers::CVRMask); + unsigned CVR = Wrapped.getLocalCVRQualifiers(); + void *InsertPos = nullptr; BTFTagAttributedType *Ty = BTFTagAttributedTypes.FindNodeOrInsertPos(ID, InsertPos); if (Ty) - return QualType(Ty, 0); + return QualType(Ty, CVR); QualType Canon = getCanonicalType(Wrapped); - Ty = new (*this, TypeAlignment) BTFTagAttributedType(Canon, Wrapped, BTFAttr); + Ty = new (*this, TypeAlignment) + BTFTagAttributedType(Canon, WrappedNoCVR, BTFAttr); Types.push_back(Ty); BTFTagAttributedTypes.InsertNode(Ty, InsertPos); - return QualType(Ty, 0); + return QualType(Ty, CVR); } /// Retrieve a substitution-result type. diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -212,6 +212,7 @@ 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/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1156,6 +1156,56 @@ return RetTy; } +llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty, + llvm::DIFile *Unit) { + SmallVector Annots; + auto *BTFAttrTy = Ty; + QualType WrappedTy; + + do { + StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag(); + if (!Tag.empty()) { + auto *TagCode = + llvm::ConstantInt::get(llvm::Type::getInt16Ty(CGM.getLLVMContext()), + llvm::dwarf::Tag::DW_TAG_LLVM_type_annotation); + llvm::Metadata *Ops[3] = { + llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")), + llvm::MDString::get(CGM.getLLVMContext(), Tag), + llvm::ValueAsMetadata::getConstant(TagCode), + }; + Annots.insert(Annots.begin(), + llvm::MDNode::get(CGM.getLLVMContext(), Ops)); + } + WrappedTy = BTFAttrTy->getWrappedType(); + BTFAttrTy = dyn_cast(WrappedTy); + } while (BTFAttrTy); + + llvm::DIType *WrappedDI = getOrCreateType(WrappedTy, Unit); + if (Annots.size() == 0) + return WrappedDI; + + if (!WrappedDI) + WrappedDI = DBuilder.createUnspecifiedType("void"); + + auto AddAnnotations = [](auto *Type, llvm::DINodeArray Annotations) { + auto Clone = Type->clone(); + Clone->replaceAnnotations(Annotations); + return llvm::MDNode::replaceWithPermanent(std::move(Clone)); + }; + + llvm::DINodeArray Annotations = DBuilder.getOrCreateArray(Annots); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty, Annotations); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty, Annotations); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty, Annotations); + if (auto *Ty = dyn_cast(WrappedDI)) + return AddAnnotations(Ty, Annotations); + + return WrappedDI; +} + llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag, const Type *Ty, QualType PointeeTy, @@ -1168,32 +1218,13 @@ 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 (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()); } llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name, @@ -3319,9 +3350,6 @@ case Type::Attributed: T = cast(T)->getEquivalentType(); break; - case Type::BTFTagAttributed: - T = cast(T)->getWrappedType(); - break; case Type::Elaborated: T = cast(T)->getNamedType(); break; @@ -3477,6 +3505,8 @@ return CreateType(cast(Ty)); case Type::Pointer: return CreateType(cast(Ty), Unit); + case Type::BTFTagAttributed: + return CreateType(cast(Ty), Unit); case Type::BlockPointer: return CreateType(cast(Ty), Unit); case Type::Typedef: @@ -3514,7 +3544,6 @@ case Type::Auto: case Type::Attributed: - case Type::BTFTagAttributed: case Type::Adjusted: case Type::Decayed: case Type::DeducedTemplateSpecialization: diff --git a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c --- a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c +++ b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c @@ -9,7 +9,8 @@ } // 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-SAME: baseType: ![[ptr:[0-9]+]] +// CHECK: ![[ptr]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[sub:[0-9]+]], size: [[#]]) +// CHECK: ![[sub]] = !DISubroutineType(types: ![[#]], annotations: ![[sub_annots:[0-9]+]]) +// CHECK: ![[sub_annots]] = !{![[sub_rcu_tag:[0-9]+]]} +// CHECK: ![[sub_rcu_tag]] = !{!"btf_type_tag", !"rcu", i16 24577} diff --git a/clang/test/CodeGen/attr-btf_type_tag-func.c b/clang/test/CodeGen/attr-btf_type_tag-func.c --- a/clang/test/CodeGen/attr-btf_type_tag-func.c +++ b/clang/test/CodeGen/attr-btf_type_tag-func.c @@ -15,14 +15,14 @@ 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: ![[L0:[0-9]+]] +// CHECK: ![[L0]] = !DISubroutineType(types: ![[L1:[0-9]+]]) +// CHECK: ![[L1]] = !{![[L2:[0-9]+]], ![[L2]]} +// CHECK: ![[L2]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L3:[0-9]+]], size: [[#]]) +// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4:[0-9]+]], size: [[#]], annotations: ![[L5:[0-9]+]]) +// CHECK: ![[L4]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L6:[0-9]+]]) +// CHECK: ![[L6]] = !{![[L7:[0-9]+]]} +// CHECK: ![[L7]] = !{!"btf_type_tag", !"tag1", i16 24577} +// CHECK: ![[L5]] = !{![[L8:[0-9]+]]} +// CHECK: ![[L8]] = !{!"btf_type_tag", !"tag2", i16 24577} +// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L2]]) diff --git a/clang/test/CodeGen/attr-btf_type_tag-similar-type.c b/clang/test/CodeGen/attr-btf_type_tag-similar-type.c --- 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,17 @@ 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: ![[L0:[0-9]+]] +// CHECK: ![[L0]] = !{![[L1:[0-9]+]], ![[L2:[0-9]+]]} +// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L3:[0-9]+]] +// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4:[0-9]+]] +// CHECK: ![[L4]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L5:[0-9]+]] +// CHECK: ![[L5]] = !{![[L6:[0-9]+]], ![[L7:[0-9]+]]} +// CHECK: ![[L6]] = !{!"btf_type_tag", !"tag1", i16 24577} +// CHECK: ![[L7]] = !{!"btf_type_tag", !"tag3", i16 24577} +// CHECK: ![[L2]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L8:[0-9]+]] +// CHECK: ![[L8]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L9:[0-9]+]] +// CHECK: ![[L9]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L10:[0-9]+]] +// CHECK: ![[L10]] = !{![[L11:[0-9]+]], ![[L12:[0-9]+]]} +// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag2", i16 24577} +// CHECK: ![[L12]] = !{!"btf_type_tag", !"tag4", i16 24577} diff --git a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c --- a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c +++ b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c @@ -5,31 +5,38 @@ typedef void __fn_t(int); typedef __fn_t __tag1 __tag2 *__fn2_t; +typedef __fn_t *__fn3_t; struct t { int __tag1 * __tag2 *a; __fn2_t b; - long c; + __fn3_t c; + long d; }; 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: ![[L00:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed) +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L01:[0-9]+]]) +// CHECK: ![[L01]] = !{![[L02:[0-9]+]], ![[L03:[0-9]+]], ![[L04:[0-9]+]], ![[L05:[0-9]+]]} +// CHECK: ![[L02]] = !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: [[#]]) +// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L08:[0-9]+]], size: [[#]], annotations: ![[L09:[0-9]+]]) +// CHECK: ![[L08]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L10:[0-9]+]]) +// CHECK: ![[L10]] = !{![[L11:[0-9]+]]} +// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag1", i16 24577} +// CHECK: ![[L09]] = !{![[L12:[0-9]+]]} +// CHECK: ![[L12]] = !{!"btf_type_tag", !"tag2", i16 24577} +// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L13:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L13]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L14:[0-9]+]]) +// CHECK: ![[L14]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L15:[0-9]+]], size: [[#]]) +// CHECK: ![[L15]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]], annotations: ![[L17:[0-9]+]]) +// CHECK: ![[L16]] = !DISubroutineType(types: ![[L18:[0-9]+]]) +// CHECK: ![[L18]] = !{null, ![[L00]]} +// CHECK: ![[L17]] = !{![[L11]], ![[L12]]} +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L19:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L19]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn3_t", file: ![[#]], line: [[#]], baseType: ![[L20:[0-9]+]]) +// CHECK: ![[L20]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L21:[0-9]+]], size: [[#]]) +// CHECK: ![[L21]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L16]]) +// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L22:[0-9]+]], size: [[#]], offset: [[#]]) +// CHECK: ![[L22]] = !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 --- a/clang/test/CodeGen/attr-btf_type_tag-var.c +++ b/clang/test/CodeGen/attr-btf_type_tag-var.c @@ -21,23 +21,23 @@ 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: [[#]]) +// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L03:[0-9]+]]) +// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L04:[0-9]+]]) +// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05:[0-9]+]], size: [[#]], annotations: ![[L06:[0-9]+]]) +// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L07:[0-9]+]]) +// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L08:[0-9]+]]) +// CHECK: ![[L08]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L09:[0-9]+]], size: [[#]], annotations: ![[L10:[0-9]+]]) +// CHECK: ![[L09]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L11:[0-9]+]]) +// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L12:[0-9]+]]) +// CHECK: ![[L12]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L13:[0-9]+]]) +// CHECK: ![[L13]] = !{![[L14:[0-9]+]], ![[L15:[0-9]+]]} +// CHECK: ![[L14]] = !{!"btf_type_tag", !"tag1", i16 24577} +// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag2", i16 24577} +// CHECK: ![[L10]] = !{![[L16:[0-9]+]], ![[L17:[0-9]+]]} +// CHECK: ![[L16]] = !{!"btf_type_tag", !"tag3", i16 24577} +// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag4", i16 24577} +// CHECK: ![[L06]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]} +// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag5", i16 24577} +// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag6", i16 24577} 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 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_type_tag-void.c @@ -0,0 +1,10 @@ +// 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: [[#]]) +// CHECK: ![[L2]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: ![[L3:[0-9]+]]) +// CHECK: ![[L3]] = !{![[L4:[0-9]+]]} +// CHECK: ![[L4]] = !{!"btf_type_tag", !"tag1", i16 24577} diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -253,6 +253,7 @@ // LLVM HANDLE_DW_TAG(0x6000, LLVM_annotation, 0, LLVM, DW_KIND_NONE) +HANDLE_DW_TAG(0x6001, LLVM_type_annotation, 0, LLVM, DW_KIND_NONE) // Green Hills. HANDLE_DW_TAG(0x8004, GHS_namespace, 0, GHS, DW_KIND_NONE) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -861,8 +861,15 @@ const MDNode *MD = cast(Annotation); const MDString *Name = cast(MD->getOperand(0)); const auto &Value = MD->getOperand(1); + unsigned Tag = dwarf::DW_TAG_LLVM_annotation; + if (MD->getNumOperands() == 3) { + const auto *TagValue = dyn_cast(MD->getOperand(2)); + if (!TagValue) + assert(false && "Unsupported annotation tag type"); + Tag = TagValue->getValue()->getUniqueInteger().getZExtValue(); + } - DIE &AnnotationDie = createAndAddDIE(dwarf::DW_TAG_LLVM_annotation, Buffer); + DIE &AnnotationDie = createAndAddDIE(static_cast(Tag), Buffer); addString(AnnotationDie, dwarf::DW_AT_name, Name->getString()); if (const auto *Data = dyn_cast(Value)) addString(AnnotationDie, dwarf::DW_AT_const_value, Data->getString()); diff --git a/llvm/lib/Target/BPF/BPF.h b/llvm/lib/Target/BPF/BPF.h --- a/llvm/lib/Target/BPF/BPF.h +++ b/llvm/lib/Target/BPF/BPF.h @@ -42,6 +42,7 @@ void initializeBPFMIPreEmitPeepholePass(PassRegistry &); void initializeBPFMISimplifyPatchablePass(PassRegistry &); void initializeBPFPreserveDITypePass(PassRegistry &); +void initializeBTFCopyTypeTagsPass(PassRegistry &); class BPFAbstractMemberAccessPass : public PassInfoMixin { @@ -72,6 +73,19 @@ public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); }; + +class BTFCopyTypeTagsPass : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +class BTFUtils { +public: + static void CollectBTFTypeTags(const DIType *Ty, + SmallVectorImpl &Tags); + static bool HasBTFTypeTags(const DIType *Ty); +}; + } // namespace llvm #endif diff --git a/llvm/lib/Target/BPF/BPFTargetMachine.cpp b/llvm/lib/Target/BPF/BPFTargetMachine.cpp --- a/llvm/lib/Target/BPF/BPFTargetMachine.cpp +++ b/llvm/lib/Target/BPF/BPFTargetMachine.cpp @@ -111,6 +111,7 @@ FPM.addPass(BPFPreserveDITypePass()); FPM.addPass(BPFIRPeepholePass()); MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + MPM.addPass(BTFCopyTypeTagsPass()); }); PB.registerPeepholeEPCallback([=](FunctionPassManager &FPM, OptimizationLevel Level) { diff --git a/llvm/lib/Target/BPF/BTFCopyTypeTags.cpp b/llvm/lib/Target/BPF/BTFCopyTypeTags.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/BPF/BTFCopyTypeTags.cpp @@ -0,0 +1,128 @@ +//===------ BTFCopyTypeTags.cpp - re-introduce old-style btf_type_tag -----===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// "btf_type_tag"s are encoded as "annotations" field of the +// DIDerivedType metadata objects. The record format for each +// "btf_type_tag" entry is: +// +// <"btf_type_tag", numeric_value, dwarf_tag> +// +// Where "dwarf_tag" is one of the following: +// - DW_TAG_LLVM_type_annotation - meaning that tag applies to the +// derived type itself; +// - DW_TAG_LLVM_annotation - meaning that tag applies to the *base* +// type of the derived type. +// +// These annotations are reflected in the generated DWARF as tags +// attached to appropriate DIE type objects. The LLVM_type_annotation +// is more generic but LLVM_annotation is used historically by BTF +// aware DWARF consumers, e.g. old versions pahole BTF generation tool [1]. +// +// CGDebugInfo generates annotations encoded with +// LLVM_type_annotation, the BTFCopyTypeTags pass infers +// LLVM_annotation values on the parent types using +// LLVM_type_annotation values on the base types. This allows to +// generate DWARF that could be consumed by old versions of the tools. +// +// The goal is to deprecate LLVM_annotation some day. When this +// happens, changes to LLVM would be contained to a removal of the +// BTFCopyTypeTags pass. +// +// [1] https://github.com/acmel/dwarves +// +//===----------------------------------------------------------------------===// + +#include "BPF.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" + +using namespace llvm; + +namespace { + +class BTFCopyTypeTags final : public ModulePass { +public: + static char ID; + + BTFCopyTypeTags() : ModulePass(ID) {} + bool runOnModule(Module &M) override; +}; + +} // End anonymous namespace + +char BTFCopyTypeTags::ID = 0; + +static void AddTypeTags(LLVMContext &Ctx, DIDerivedType *Type, + SmallVectorImpl &TypeTags) { + SmallVector NewAnnotations; + DINodeArray OldAnnotations = Type->getAnnotations(); + if (OldAnnotations) + for (Metadata *Node : OldAnnotations->operands()) + NewAnnotations.push_back(Node); + for (auto *Tag : TypeTags) { + auto *TagCode = ConstantInt::get(Type::getInt16Ty(Ctx), + dwarf::Tag::DW_TAG_LLVM_annotation); + Metadata *Ops[3] = { + MDString::get(Ctx, StringRef("btf_type_tag")), + MDString::get(Ctx, Tag->getString()), + ConstantAsMetadata::get(TagCode), + }; + NewAnnotations.push_back(MDNode::get(Ctx, Ops)); + } + Type->replaceOperandWith(5, MDNode::get(Ctx, NewAnnotations)); +} + +static DIType *SkipQualifiers(DIType *Type) { + while (auto *Derived = dyn_cast_or_null(Type)) { + switch (Derived->getTag()) { + case dwarf::DW_TAG_const_type: + case dwarf::DW_TAG_volatile_type: + case dwarf::DW_TAG_restrict_type: + Type = Derived->getBaseType(); + break; + default: + return Type; + } + } + return Type; +} + +bool BTFCopyTypeTags::runOnModule(Module &M) { + std::map ReplacementMap; + DIBuilder DIBuilder(M); + DebugInfoFinder Finder; + + Finder.processModule(M); + + for (DIType *Type : Finder.types()) { + auto *DerivedType = dyn_cast(Type); + if (!DerivedType || + DerivedType->getTag() != llvm::dwarf::DW_TAG_pointer_type) + continue; + + SmallVector TypeTags; + if (auto *BaseType = SkipQualifiers(DerivedType->getBaseType())) + BTFUtils::CollectBTFTypeTags(BaseType, TypeTags); + if (TypeTags.empty()) + continue; + + AddTypeTags(M.getContext(), DerivedType, TypeTags); + } + + // Keep analysis results, only debug info might be updated by this pass. + return false; +} + +PreservedAnalyses BTFCopyTypeTagsPass::run(Module &M, + ModuleAnalysisManager &AM) { + return BTFCopyTypeTags().runOnModule(M) ? PreservedAnalyses::none() + : PreservedAnalyses::all(); +} diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h --- a/llvm/lib/Target/BPF/BTFDebug.h +++ b/llvm/lib/Target/BPF/BTFDebug.h @@ -14,6 +14,7 @@ #ifndef LLVM_LIB_TARGET_BPF_BTFDEBUG_H #define LLVM_LIB_TARGET_BPF_BTFDEBUG_H +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/DebugHandlerBase.h" #include @@ -285,6 +286,29 @@ uint32_t RelocKind; ///< What to patch the instruction }; +struct BTFTypeDedupKey { + const dwarf::Tag Kind; + const StringRef Name; + const uint64_t BasicTypeRepr; + + BTFTypeDedupKey(dwarf::Tag Kind, StringRef Name, uint64_t BasicTypeRepr) + : Kind(Kind), Name(Name), BasicTypeRepr(BasicTypeRepr) {} + + bool operator ==(const BTFTypeDedupKey &Other) const { + return Kind == Other.Kind && + Name == Other.Name && + BasicTypeRepr == Other.BasicTypeRepr; + } + + struct Hash { + size_t operator()(BTFTypeDedupKey const& Key) const { + return hash_combine(hash_value(Key.Kind), + hash_value(Key.Name), + hash_value(Key.BasicTypeRepr)); + } + }; +}; + /// Collect and emit BTF information. class BTFDebug : public DebugHandlerBase { MCStreamer &OS; @@ -296,6 +320,8 @@ BTFStringTable StringTable; std::vector> TypeEntries; std::unordered_map DIToIdMap; + std::unordered_map + DIDedupMap; std::map> FuncInfoTable; std::map> LineInfoTable; std::map> FieldRelocTable; @@ -311,11 +337,14 @@ /// Add types to TypeEntries. /// @{ /// Add types to TypeEntries and DIToIdMap. - uint32_t addType(std::unique_ptr TypeEntry, const DIType *Ty); + uint32_t addType(std::unique_ptr TypeEntry, const DIType *Ty, + uint32_t *RealId = nullptr); /// Add types to TypeEntries only and return type id. uint32_t addType(std::unique_ptr TypeEntry); /// @} + std::optional lookupType(const DIType *Ty); + /// IR type visiting functions. /// @{ void visitTypeEntry(const DIType *Ty); @@ -365,7 +394,7 @@ /// the base type of DTy. Return the type id of the first BTF type_tag /// in the chain. If no type_tag's are generated, a negative value /// is returned. - int genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId); + uint32_t genBTFTypeTags(const DIType *Ty, uint32_t BaseId); /// Generate one field relocation record. void generatePatchImmReloc(const MCSymbol *ORSym, uint32_t RootId, diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -510,13 +510,56 @@ addString("\0"); } +/// Generate btf_type_tag chains. +uint32_t BTFDebug::genBTFTypeTags(const DIType *Ty, uint32_t BaseId) { + SmallVector MDStrs; + BTFUtils::CollectBTFTypeTags(Ty, MDStrs); + // With MDStrs [__tag1, __tag2], the output type chain looks like + // PTR -> __tag2 -> __tag1 -> BaseType + // In the below, we construct BTF types with the order of __tag1, __tag2 + // and PTR. + for (unsigned I = 0; I < MDStrs.size(); I++) { + const MDString *Value = MDStrs[I]; + auto TagEntry = std::make_unique(BaseId, Value->getString()); + BaseId = addType(std::move(TagEntry)); + } + return BaseId; +} + +static std::optional MakeDedupKey(const DIType *Ty) { + if (Ty->getName().empty()) + return std::nullopt; + + if (auto *BTy = dyn_cast(Ty)) { + uint32_t Repr = BTy->getEncoding() << 24 | + BTy->getOffsetInBits() << 16 | + BTy->getSizeInBits(); + return std::optional(BTFTypeDedupKey(Ty->getTag(), Ty->getName(), Repr)); + } + + switch (Ty->getTag()) { + case dwarf::Tag::DW_TAG_enumeration_type: + case dwarf::Tag::DW_TAG_structure_type: + case dwarf::Tag::DW_TAG_union_type: + case dwarf::Tag::DW_TAG_typedef: + return std::optional(BTFTypeDedupKey(Ty->getTag(), Ty->getName(), 0)); + default: + return std::nullopt; + } +} + uint32_t BTFDebug::addType(std::unique_ptr TypeEntry, - const DIType *Ty) { - TypeEntry->setId(TypeEntries.size() + 1); - uint32_t Id = TypeEntry->getId(); - DIToIdMap[Ty] = Id; - TypeEntries.push_back(std::move(TypeEntry)); - return Id; + const DIType *Ty, + uint32_t *RealId) { + uint32_t Id = TypeEntry ? addType(std::move(TypeEntry)) : 0; + auto Key = MakeDedupKey(Ty); + if (Key.has_value()) + DIDedupMap[*Key] = Id; + uint32_t TagId = genBTFTypeTags(Ty, Id); + DIToIdMap[Ty] = TagId; + if (RealId) + *RealId = Id; + return TagId; } uint32_t BTFDebug::addType(std::unique_ptr TypeEntry) { @@ -526,7 +569,30 @@ return Id; } +std::optional BTFDebug::lookupType(const DIType *Ty) { + if (DIToIdMap.find(Ty) != DIToIdMap.end()) + return std::optional(DIToIdMap[Ty]); + + auto Key = MakeDedupKey(Ty); + if (!Key.has_value() || (DIDedupMap.find(*Key) == DIDedupMap.end())) + return std::nullopt; + + SmallVector MDStrs; + BTFUtils::CollectBTFTypeTags(Ty, MDStrs); + auto TagId = genBTFTypeTags(Ty, DIDedupMap[*Key]); + DIToIdMap[Ty] = TagId; + return TagId; +} + void BTFDebug::visitBasicType(const DIBasicType *BTy, uint32_t &TypeId) { + // Such "void" entries might arise from use btf_type_tag, e.g.: + // void __attribute__((btf_type_tag("foo"))) *p; + if (BTy->getTag() == dwarf::DW_TAG_unspecified_type && + BTy->getName() == "void") { + TypeId = addType(nullptr, BTy); + return; + } + // Only int and binary floating point types are supported in BTF. uint32_t Encoding = BTy->getEncoding(); std::unique_ptr TypeEntry; @@ -616,44 +682,58 @@ return FuncId; } -/// Generate btf_type_tag chains. -int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) { - SmallVector MDStrs; - DINodeArray Annots = DTy->getAnnotations(); - if (Annots) { - // For type with "int __tag1 __tag2 *p", the MDStrs will have +static DINodeArray LookupAnnotations(const DIType *Ty) { + DINodeArray Annots = {}; + if (auto *SubTy = dyn_cast(Ty)) + Annots = SubTy->getAnnotations(); + else if (auto *SubTy = dyn_cast(Ty)) + Annots = SubTy->getAnnotations(); + else if (auto *SubTy = dyn_cast(Ty)) + Annots = SubTy->getAnnotations(); + else if (auto *SubTy = dyn_cast(Ty)) + Annots = SubTy->getAnnotations(); + return Annots; +} + +static bool IsBTFTypeTag(const MDNode *MD) { + const MDString *Name = cast(MD->getOperand(0)); + if (!Name->getString().equals("btf_type_tag")) + return false; + if (MD->getNumOperands() != 3) + return false; + auto *TagCode = dyn_cast(MD->getOperand(2)); + auto TagValue = TagCode->getValue()->getUniqueInteger().getZExtValue(); + return TagValue == dwarf::DW_TAG_LLVM_type_annotation; +} + +void BTFUtils::CollectBTFTypeTags(const DIType *Ty, + SmallVectorImpl &Tags) { + DINodeArray Annots = LookupAnnotations(Ty); + if (!Annots) + return; + + for (const Metadata *Annotations : Annots->operands()) { + const MDNode *MD = cast(Annotations); + if (!IsBTFTypeTag(MD)) + continue; + // For type with "int __tag1 __tag2 *p", the Tags will have // content: [__tag1, __tag2]. - for (const Metadata *Annotations : Annots->operands()) { - const MDNode *MD = cast(Annotations); - const MDString *Name = cast(MD->getOperand(0)); - if (!Name->getString().equals("btf_type_tag")) - continue; - MDStrs.push_back(cast(MD->getOperand(1))); - } + Tags.push_back(cast(MD->getOperand(1))); } +} - if (MDStrs.size() == 0) - return -1; - - // With MDStrs [__tag1, __tag2], the output type chain looks like - // PTR -> __tag2 -> __tag1 -> BaseType - // In the below, we construct BTF types with the order of __tag1, __tag2 - // and PTR. - unsigned TmpTypeId; - std::unique_ptr TypeEntry; - if (BaseTypeId >= 0) - TypeEntry = - std::make_unique(BaseTypeId, MDStrs[0]->getString()); - else - TypeEntry = std::make_unique(DTy, MDStrs[0]->getString()); - TmpTypeId = addType(std::move(TypeEntry)); +bool BTFUtils::HasBTFTypeTags(const DIType *Ty) { + DINodeArray Annots = LookupAnnotations(Ty); + if (!Annots) + return false; - for (unsigned I = 1; I < MDStrs.size(); I++) { - const MDString *Value = MDStrs[I]; - TypeEntry = std::make_unique(TmpTypeId, Value->getString()); - TmpTypeId = addType(std::move(TypeEntry)); + for (const Metadata *Annotations : Annots->operands()) { + const MDNode *MD = cast(Annotations); + if (IsBTFTypeTag(MD)) + return true; } - return TmpTypeId; + + return false; } /// Handle structure/union types. @@ -677,17 +757,18 @@ auto TypeEntry = std::make_unique(CTy, IsStruct, HasBitField, VLen); StructTypes.push_back(TypeEntry.get()); - TypeId = addType(std::move(TypeEntry), CTy); + uint32_t StructId; + TypeId = addType(std::move(TypeEntry), CTy, &StructId); // Check struct/union annotations - processDeclAnnotations(CTy->getAnnotations(), TypeId, -1); + processDeclAnnotations(CTy->getAnnotations(), StructId, -1); // Visit all struct members. int FieldNo = 0; for (const auto *Element : Elements) { const auto Elem = cast(Element); visitTypeEntry(Elem); - processDeclAnnotations(Elem->getAnnotations(), TypeId, FieldNo); + processDeclAnnotations(Elem->getAnnotations(), StructId, FieldNo); FieldNo++; } } @@ -814,19 +895,11 @@ } } - if (Tag == dwarf::DW_TAG_pointer_type) { - int TmpTypeId = genBTFTypeTags(DTy, -1); - if (TmpTypeId >= 0) { - auto TypeDEntry = - std::make_unique(TmpTypeId, Tag, DTy->getName()); - TypeId = addType(std::move(TypeDEntry), DTy); - } else { - auto TypeEntry = std::make_unique(DTy, Tag, false); - TypeId = addType(std::move(TypeEntry), DTy); - } - } else if (Tag == dwarf::DW_TAG_typedef || Tag == dwarf::DW_TAG_const_type || - Tag == dwarf::DW_TAG_volatile_type || - Tag == dwarf::DW_TAG_restrict_type) { + if (Tag == dwarf::DW_TAG_pointer_type || + Tag == dwarf::DW_TAG_typedef || + Tag == dwarf::DW_TAG_const_type || + Tag == dwarf::DW_TAG_volatile_type || + Tag == dwarf::DW_TAG_restrict_type) { auto TypeEntry = std::make_unique(DTy, Tag, false); TypeId = addType(std::move(TypeEntry), DTy); if (Tag == dwarf::DW_TAG_typedef) @@ -846,8 +919,14 @@ void BTFDebug::visitTypeEntry(const DIType *Ty, uint32_t &TypeId, bool CheckPointer, bool SeenPointer) { - if (!Ty || DIToIdMap.find(Ty) != DIToIdMap.end()) { + // TODO: why is this needed? + if (!Ty) { TypeId = DIToIdMap[Ty]; + return; + } + + if (auto OptTypeId = lookupType(Ty)) { + TypeId = *OptTypeId; // To handle the case like the following: // struct t; @@ -878,14 +957,14 @@ // We will traverse const/ptr/volatile which already have corresponding // BTF types and generate type for 'struct' which might be in Fixup // state. - if (Ty && (!CheckPointer || !SeenPointer)) { + if (!CheckPointer || !SeenPointer) { if (const auto *DTy = dyn_cast(Ty)) { while (DTy) { const DIType *BaseTy = DTy->getBaseType(); if (!BaseTy) break; - if (DIToIdMap.find(BaseTy) != DIToIdMap.end()) { + if (lookupType(BaseTy)) { DTy = dyn_cast(BaseTy); } else { uint32_t TmpTypeId; @@ -1579,27 +1658,17 @@ // Search through struct types uint32_t StructTypeId = 0; - for (const auto &StructType : StructTypes) { - if (StructType->getName() == TypeName) { - StructTypeId = StructType->getId(); - break; - } - } + if (auto OptId = lookupType(CTy)) + StructTypeId = *OptId; if (StructTypeId == 0) { auto FwdTypeEntry = std::make_unique(TypeName, IsUnion); - StructTypeId = addType(std::move(FwdTypeEntry)); + StructTypeId = addType(std::move(FwdTypeEntry), CTy); } for (auto &TypeInfo : Fixup.second) { - const DIDerivedType *DTy = TypeInfo.first; BTFTypeDerived *BDType = TypeInfo.second; - - int TmpTypeId = genBTFTypeTags(DTy, StructTypeId); - if (TmpTypeId >= 0) - BDType->setPointeeType(TmpTypeId); - else - BDType->setPointeeType(StructTypeId); + BDType->setPointeeType(StructTypeId); } } diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt --- a/llvm/lib/Target/BPF/CMakeLists.txt +++ b/llvm/lib/Target/BPF/CMakeLists.txt @@ -33,6 +33,7 @@ BPFMIPeephole.cpp BPFMIChecking.cpp BPFMISimplifyPatchable.cpp + BTFCopyTypeTags.cpp BTFDebug.cpp LINK_COMPONENTS diff --git a/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-fwd.ll b/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-fwd.ll --- a/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-fwd.ll +++ b/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-fwd.ll @@ -18,21 +18,18 @@ ; Compilation flag: ; clang -target bpf -O2 -g -S -emit-llvm test.c -%struct.map_value = type { %struct.foo* } -%struct.foo = type opaque +%struct.map_value = type { ptr } ; Function Attrs: nounwind define dso_local void @test() local_unnamed_addr #0 !dbg !7 { entry: %v = alloca %struct.map_value, align 8 - %0 = bitcast %struct.map_value* %v to i8*, !dbg !20 - call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) #4, !dbg !20 - call void @llvm.dbg.declare(metadata %struct.map_value* %v, metadata !11, metadata !DIExpression()), !dbg !21 - %1 = bitcast %struct.map_value* %v to i64*, !dbg !21 - store i64 0, i64* %1, align 8, !dbg !21 - call void @func(%struct.map_value* noundef nonnull %v) #4, !dbg !22 - call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) #4, !dbg !23 - ret void, !dbg !23 + call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %v) #4, !dbg !23 + call void @llvm.dbg.declare(metadata ptr %v, metadata !11, metadata !DIExpression()), !dbg !24 + store i64 0, ptr %v, align 8, !dbg !24 + call void @func(ptr noundef nonnull %v) #4, !dbg !25 + call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %v) #4, !dbg !26 + ret void, !dbg !26 } ; CHECK: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) @@ -49,50 +46,50 @@ ; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 4) ; CHECK-NEXT: .long 33554432 # 0x2000000 ; CHECK-NEXT: .long 5 -; CHECK-NEXT: .long 62 # BTF_KIND_STRUCT(id = 5) +; CHECK-NEXT: .long 39 # BTF_KIND_STRUCT(id = 5) ; CHECK-NEXT: .long 67108865 # 0x4000001 ; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 72 -; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 0 # 0x0 -; CHECK-NEXT: .long 76 # BTF_KIND_TYPE_TAG(id = 6) -; CHECK-NEXT: .long 301989888 # 0x12000000 -; CHECK-NEXT: .long 9 -; CHECK-NEXT: .long 81 # BTF_KIND_TYPE_TAG(id = 7) -; CHECK-NEXT: .long 301989888 # 0x12000000 +; CHECK-NEXT: .long 49 ; CHECK-NEXT: .long 6 -; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 8) +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 6) ; CHECK-NEXT: .long 33554432 # 0x2000000 -; CHECK-NEXT: .long 7 -; CHECK-NEXT: .long 86 # BTF_KIND_FWD(id = 9) +; CHECK-NEXT: .long 9 +; CHECK-NEXT: .long 53 # BTF_KIND_FWD(id = 7) ; CHECK-NEXT: .long 117440512 # 0x7000000 ; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 90 # BTF_KIND_FUNC(id = 10) +; CHECK-NEXT: .long 57 # BTF_KIND_TYPE_TAG(id = 8) +; CHECK-NEXT: .long 301989888 # 0x12000000 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long 62 # BTF_KIND_TYPE_TAG(id = 9) +; CHECK-NEXT: .long 301989888 # 0x12000000 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 67 # BTF_KIND_FUNC(id = 10) ; CHECK-NEXT: .long 201326594 # 0xc000002 ; CHECK-NEXT: .long 3 ; CHECK: .ascii "test" # string offset=1 -; CHECK: .ascii "map_value" # string offset=62 -; CHECK: .ascii "ptr" # string offset=72 -; CHECK: .ascii "tag2" # string offset=76 -; CHECK: .ascii "tag1" # string offset=81 -; CHECK: .ascii "foo" # string offset=86 -; CHECK: .ascii "func" # string offset=90 +; CHECK: .ascii "map_value" # string offset=39 +; CHECK: .ascii "ptr" # string offset=49 +; CHECK: .ascii "foo" # string offset=53 +; CHECK: .ascii "tag2" # string offset=57 +; CHECK: .ascii "tag1" # string offset=62 +; CHECK: .ascii "func" # string offset=67 -; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn -declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 -; Function Attrs: mustprogress nofree nosync nounwind readnone speculatable willreturn +; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 -declare !dbg !24 dso_local void @func(%struct.map_value* noundef) local_unnamed_addr #3 +declare !dbg !27 dso_local void @func(ptr noundef) local_unnamed_addr #3 -; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn -declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 -attributes #0 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn } -attributes #2 = { mustprogress nofree nosync nounwind readnone speculatable willreturn } +attributes #0 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #2 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } attributes #4 = { nounwind } @@ -100,13 +97,13 @@ !llvm.module.flags = !{!2, !3, !4, !5} !llvm.ident = !{!6} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 15.0.0 (https://github.com/llvm/llvm-project.git 25e8505f515bc9ef6c13527ffc4a902bae3a9071)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/btf_tag_type", checksumkind: CSK_MD5, checksum: "7735a89e98603fee29d352a8e9db5acb") +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "7735a89e98603fee29d352a8e9db5acb") !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 1, !"wchar_size", i32 4} !5 = !{i32 7, !"frame-pointer", i32 2} -!6 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git 25e8505f515bc9ef6c13527ffc4a902bae3a9071)"} +!6 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"} !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 9, type: !8, scopeLine: 10, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) !8 = !DISubroutineType(types: !9) !9 = !{null} @@ -115,17 +112,21 @@ !12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: !1, line: 5, size: 64, elements: !13) !13 = !{!14} !14 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !12, file: !1, line: 6, baseType: !15, size: 64) -!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, annotations: !17) -!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 4, flags: DIFlagFwdDecl) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, annotations: !20) +!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 4, flags: DIFlagFwdDecl, annotations: !17) !17 = !{!18, !19} -!18 = !{!"btf_type_tag", !"tag2"} -!19 = !{!"btf_type_tag", !"tag1"} -!20 = !DILocation(line: 11, column: 9, scope: !7) -!21 = !DILocation(line: 11, column: 26, scope: !7) -!22 = !DILocation(line: 12, column: 9, scope: !7) -!23 = !DILocation(line: 13, column: 1, scope: !7) -!24 = !DISubprogram(name: "func", scope: !1, file: !1, line: 8, type: !25, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !28) -!25 = !DISubroutineType(types: !26) -!26 = !{null, !27} -!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) -!28 = !{} +!18 = !{!"btf_type_tag", !"tag2", i16 24577} +!19 = !{!"btf_type_tag", !"tag1", i16 24577} +!20 = !{!21, !22} +!21 = !{!"btf_type_tag", !"tag2", i16 24576} +!22 = !{!"btf_type_tag", !"tag1", i16 24576} +!23 = !DILocation(line: 11, column: 9, scope: !7) +!24 = !DILocation(line: 11, column: 26, scope: !7) +!25 = !DILocation(line: 12, column: 9, scope: !7) +!26 = !DILocation(line: 13, column: 1, scope: !7) +!27 = !DISubprogram(name: "func", scope: !1, file: !1, line: 8, type: !28, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !31) +!28 = !DISubroutineType(types: !29) +!29 = !{null, !30} +!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!31 = !{!32} +!32 = !DILocalVariable(arg: 1, scope: !27, file: !1, line: 8, type: !30) diff --git a/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-resolved.ll b/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-resolved.ll --- a/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-resolved.ll +++ b/llvm/test/CodeGen/BPF/BTF/type-tag-fixup-resolved.ll @@ -20,21 +20,18 @@ ; Compilation flag: ; clang -target bpf -O2 -g -S -emit-llvm test.c -%struct.map_value = type { %struct.foo* } -%struct.foo = type { i32 } +%struct.map_value = type { ptr } ; Function Attrs: nounwind define dso_local void @test() local_unnamed_addr #0 !dbg !7 { entry: %v = alloca %struct.map_value, align 8 - %0 = bitcast %struct.map_value* %v to i8*, !dbg !23 - call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %0) #4, !dbg !23 - call void @llvm.dbg.declare(metadata %struct.map_value* %v, metadata !11, metadata !DIExpression()), !dbg !24 - %1 = bitcast %struct.map_value* %v to i64*, !dbg !24 - store i64 0, i64* %1, align 8, !dbg !24 - call void @func(%struct.map_value* noundef nonnull %v, %struct.foo* noundef null) #4, !dbg !25 - call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %0) #4, !dbg !26 - ret void, !dbg !26 + call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %v) #4, !dbg !27 + call void @llvm.dbg.declare(metadata ptr %v, metadata !11, metadata !DIExpression()), !dbg !28 + store i64 0, ptr %v, align 8, !dbg !28 + call void @func(ptr noundef nonnull %v, ptr noundef null) #4, !dbg !29 + call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %v) #4, !dbg !30 + ret void, !dbg !30 } ; CHECK: .long 0 # BTF_KIND_FUNC_PROTO(id = 1) @@ -53,10 +50,10 @@ ; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 4) ; CHECK-NEXT: .long 33554432 # 0x2000000 ; CHECK-NEXT: .long 5 -; CHECK-NEXT: .long 63 # BTF_KIND_STRUCT(id = 5) +; CHECK-NEXT: .long 137 # BTF_KIND_STRUCT(id = 5) ; CHECK-NEXT: .long 67108865 # 0x4000001 ; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 73 +; CHECK-NEXT: .long 147 ; CHECK-NEXT: .long 6 ; CHECK-NEXT: .long 0 # 0x0 ; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 6) @@ -65,50 +62,50 @@ ; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 7) ; CHECK-NEXT: .long 33554432 # 0x2000000 ; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 77 # BTF_KIND_STRUCT(id = 8) +; CHECK-NEXT: .long 151 # BTF_KIND_STRUCT(id = 8) ; CHECK-NEXT: .long 67108865 # 0x4000001 ; CHECK-NEXT: .long 4 -; CHECK-NEXT: .long 81 +; CHECK-NEXT: .long 155 ; CHECK-NEXT: .long 9 ; CHECK-NEXT: .long 0 # 0x0 -; CHECK-NEXT: .long 83 # BTF_KIND_INT(id = 9) +; CHECK-NEXT: .long 157 # BTF_KIND_INT(id = 9) ; CHECK-NEXT: .long 16777216 # 0x1000000 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long 16777248 # 0x1000020 -; CHECK-NEXT: .long 87 # BTF_KIND_FUNC(id = 10) +; CHECK-NEXT: .long 161 # BTF_KIND_FUNC(id = 10) ; CHECK-NEXT: .long 201326594 # 0xc000002 ; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long 92 # BTF_KIND_TYPE_TAG(id = 11) +; CHECK-NEXT: .long 166 # BTF_KIND_TYPE_TAG(id = 11) ; CHECK-NEXT: .long 301989888 # 0x12000000 ; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 97 # BTF_KIND_TYPE_TAG(id = 12) +; CHECK-NEXT: .long 171 # BTF_KIND_TYPE_TAG(id = 12) ; CHECK-NEXT: .long 301989888 # 0x12000000 ; CHECK-NEXT: .long 11 ; CHECK: .ascii "test" # string offset=1 -; CHECK: .ascii "map_value" # string offset=63 -; CHECK: .ascii "ptr" # string offset=73 -; CHECK: .ascii "foo" # string offset=77 -; CHECK: .byte 105 # string offset=81 -; CHECK: .ascii "int" # string offset=83 -; CHECK: .ascii "func" # string offset=87 -; CHECK: .ascii "tag2" # string offset=92 -; CHECK: .ascii "tag1" # string offset=97 +; CHECK: .ascii "map_value" # string offset=137 +; CHECK: .ascii "ptr" # string offset=147 +; CHECK: .ascii "foo" # string offset=151 +; CHECK: .byte 105 # string offset=155 +; CHECK: .ascii "int" # string offset=157 +; CHECK: .ascii "func" # string offset=161 +; CHECK: .ascii "tag2" # string offset=166 +; CHECK: .ascii "tag1" # string offset=171 -; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn -declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1 +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1 -; Function Attrs: mustprogress nofree nosync nounwind readnone speculatable willreturn +; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 -declare !dbg !27 dso_local void @func(%struct.map_value* noundef, %struct.foo* noundef) local_unnamed_addr #3 +declare !dbg !31 dso_local void @func(ptr noundef, ptr noundef) local_unnamed_addr #3 -; Function Attrs: argmemonly mustprogress nofree nosync nounwind willreturn -declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1 +; Function Attrs: mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1 -attributes #0 = { nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } -attributes #1 = { argmemonly mustprogress nofree nosync nounwind willreturn } -attributes #2 = { mustprogress nofree nosync nounwind readnone speculatable willreturn } +attributes #0 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } +attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } +attributes #2 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) } attributes #3 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } attributes #4 = { nounwind } @@ -116,13 +113,13 @@ !llvm.module.flags = !{!2, !3, !4, !5} !llvm.ident = !{!6} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 15.0.0 (https://github.com/llvm/llvm-project.git 25e8505f515bc9ef6c13527ffc4a902bae3a9071)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) -!1 = !DIFile(filename: "test.c", directory: "/tmp//home/yhs/work/tests/llvm/btf_tag_type", checksumkind: CSK_MD5, checksum: "8b3b8281c3b4240403467e0c9461251d") +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "t1.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "8b3b8281c3b4240403467e0c9461251d") !2 = !{i32 7, !"Dwarf Version", i32 5} !3 = !{i32 2, !"Debug Info Version", i32 3} !4 = !{i32 1, !"wchar_size", i32 4} !5 = !{i32 7, !"frame-pointer", i32 2} -!6 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git 25e8505f515bc9ef6c13527ffc4a902bae3a9071)"} +!6 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"} !7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 11, type: !8, scopeLine: 12, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) !8 = !DISubroutineType(types: !9) !9 = !{null} @@ -131,21 +128,27 @@ !12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: !1, line: 7, size: 64, elements: !13) !13 = !{!14} !14 = !DIDerivedType(tag: DW_TAG_member, name: "ptr", scope: !12, file: !1, line: 8, baseType: !15, size: 64) -!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, annotations: !20) -!16 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 4, size: 32, elements: !17) +!15 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64, annotations: !24) +!16 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 4, size: 32, elements: !17, annotations: !21) !17 = !{!18} -!18 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !16, file: !1, line: 5, baseType: !19, size: 32) -!19 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!20 = !{!21, !22} -!21 = !{!"btf_type_tag", !"tag2"} -!22 = !{!"btf_type_tag", !"tag1"} -!23 = !DILocation(line: 13, column: 9, scope: !7) -!24 = !DILocation(line: 13, column: 26, scope: !7) -!25 = !DILocation(line: 14, column: 9, scope: !7) -!26 = !DILocation(line: 15, column: 1, scope: !7) -!27 = !DISubprogram(name: "func", scope: !1, file: !1, line: 10, type: !28, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !32) -!28 = !DISubroutineType(types: !29) -!29 = !{null, !30, !31} -!30 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) -!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !16, size: 64) -!32 = !{} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 5, baseType: !20, size: 32) +!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !1, line: 4, size: 32, elements: !17) +!20 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!21 = !{!22, !23} +!22 = !{!"btf_type_tag", !"tag2", i16 24577} +!23 = !{!"btf_type_tag", !"tag1", i16 24577} +!24 = !{!25, !26} +!25 = !{!"btf_type_tag", !"tag2", i16 24576} +!26 = !{!"btf_type_tag", !"tag1", i16 24576} +!27 = !DILocation(line: 13, column: 9, scope: !7) +!28 = !DILocation(line: 13, column: 26, scope: !7) +!29 = !DILocation(line: 14, column: 9, scope: !7) +!30 = !DILocation(line: 15, column: 1, scope: !7) +!31 = !DISubprogram(name: "func", scope: !1, file: !1, line: 10, type: !32, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !36) +!32 = !DISubroutineType(types: !33) +!33 = !{null, !34, !35} +!34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!35 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64) +!36 = !{!37, !38} +!37 = !DILocalVariable(arg: 1, scope: !31, file: !1, line: 10, type: !34) +!38 = !DILocalVariable(arg: 2, scope: !31, file: !1, line: 10, type: !35) diff --git a/llvm/test/CodeGen/BPF/BTF/type-tag-var.ll b/llvm/test/CodeGen/BPF/BTF/type-tag-var.ll --- a/llvm/test/CodeGen/BPF/BTF/type-tag-var.ll +++ b/llvm/test/CodeGen/BPF/BTF/type-tag-var.ll @@ -11,53 +11,62 @@ @g = dso_local local_unnamed_addr global ptr null, align 8, !dbg !0 !llvm.dbg.cu = !{!2} -!llvm.module.flags = !{!12, !13, !14, !15} -!llvm.ident = !{!16} +!llvm.module.flags = !{!15, !16, !17, !18} +!llvm.ident = !{!19} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 3, 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 077b2e0cf1e97c4d97ca5ceab3ec0192ed11c66e)", isOptimized: true, 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") +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "9ae91fe3dd8e44985841816e35923786") !4 = !{!0} -!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !10) -!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, annotations: !8) -!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !13) +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, annotations: !10) +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !8) !8 = !{!9} -!9 = !{!"btf_type_tag", !"tag1"} -!10 = !{!9, !11} -!11 = !{!"btf_type_tag", !"tag2"} +!9 = !{!"btf_type_tag", !"tag1", i16 24577} +!10 = !{!9, !11, !12} +!11 = !{!"btf_type_tag", !"tag2", i16 24577} +!12 = !{!"btf_type_tag", !"tag1", i16 24576} +!13 = !{!12, !14} +!14 = !{!"btf_type_tag", !"tag2", i16 24576} -; CHECK: .long 1 # BTF_KIND_TYPE_TAG(id = 1) -; CHECK-NEXT: .long 301989888 # 0x12000000 -; CHECK-NEXT: .long 5 -; CHECK-NEXT: .long 6 # BTF_KIND_TYPE_TAG(id = 2) -; CHECK-NEXT: .long 301989888 # 0x12000000 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 3) +; CHECK: .long 0 # BTF_KIND_PTR(id = 1) ; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 2) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 1 # BTF_KIND_TYPE_TAG(id = 3) +; CHECK-NEXT: .long 301989888 # 0x12000000 ; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 1 # BTF_KIND_TYPE_TAG(id = 4) +; CHECK-NEXT: .long 6 # BTF_KIND_TYPE_TAG(id = 4) ; CHECK-NEXT: .long 301989888 # 0x12000000 -; CHECK-NEXT: .long 6 -; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 5) -; CHECK-NEXT: .long 33554432 # 0x2000000 -; CHECK-NEXT: .long 4 -; CHECK-NEXT: .long 11 # BTF_KIND_INT(id = 6) +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 11 # BTF_KIND_INT(id = 5) ; CHECK-NEXT: .long 16777216 # 0x1000000 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 1 # BTF_KIND_TYPE_TAG(id = 6) +; CHECK-NEXT: .long 301989888 # 0x12000000 +; CHECK-NEXT: .long 5 ; CHECK-NEXT: .long 15 # BTF_KIND_VAR(id = 7) ; CHECK-NEXT: .long 234881024 # 0xe000000 -; CHECK-NEXT: .long 3 ; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 17 # BTF_KIND_DATASEC(id = 8) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long g +; CHECK-NEXT: .long 8 ; CHECK: .ascii "tag1" # string offset=1 ; CHECK: .ascii "tag2" # string offset=6 ; CHECK: .ascii "int" # string offset=11 ; CHECK: .byte 103 # string offset=15 -!12 = !{i32 7, !"Dwarf Version", i32 4} -!13 = !{i32 2, !"Debug Info Version", i32 3} -!14 = !{i32 1, !"wchar_size", i32 4} -!15 = !{i32 7, !"frame-pointer", i32 2} -!16 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 077b2e0cf1e97c4d97ca5ceab3ec0192ed11c66e)"} +!15 = !{i32 7, !"Dwarf Version", i32 5} +!16 = !{i32 2, !"Debug Info Version", i32 3} +!17 = !{i32 1, !"wchar_size", i32 4} +!18 = !{i32 7, !"frame-pointer", i32 2} +!19 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"} diff --git a/llvm/test/CodeGen/BPF/BTF/type-tag-void.ll b/llvm/test/CodeGen/BPF/BTF/type-tag-void.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/type-tag-void.ll @@ -0,0 +1,47 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; +; Source: +; #define __tag1 __attribute__((btf_type_tag("tag1"))) +; void __tag1 *g; +; Compilation flag: +; clang -S -g -emit-llvm test.c -o test.ll + +@foo = dso_local global ptr null, align 8, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!9, !10, !11, !12, !13, !14, !15} +!llvm.ident = !{!16} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "d51e2505a6f475a2c1811fd5e5fa9c49") +!4 = !{!0} +!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64) +!6 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: !7) +!7 = !{!8} +!8 = !{!"btf_type_tag", !"tag1", i16 24577} +!9 = !{i32 7, !"Dwarf Version", i32 5} +!10 = !{i32 2, !"Debug Info Version", i32 3} +!11 = !{i32 1, !"wchar_size", i32 4} +!12 = !{i32 8, !"PIC Level", i32 2} +!13 = !{i32 7, !"PIE Level", i32 2} +!14 = !{i32 7, !"uwtable", i32 2} +!15 = !{i32 7, !"frame-pointer", i32 2} +!16 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"} + +; CHECK: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_TYPE_TAG(id = 2) +; CHECK-NEXT: .long 301989888 # 0x12000000 +; CHECK-NEXT: .long 0 +; ^^^ void type id +; CHECK-NEXT: .long 6 # BTF_KIND_VAR(id = 3) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 1 + +; CHECK: .ascii "tag1" # string offset=1 +; CHECK: .ascii "foo" # string offset=6