[clang] 3466e00 - Reland "[Attr] support btf_type_tag attribute"

Yonghong Song via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 5 11:26:05 PDT 2021


Author: Yonghong Song
Date: 2021-11-05T11:25:17-07:00
New Revision: 3466e00716e12e32fdb100e3fcfca5c2b3e8d784

URL: https://github.com/llvm/llvm-project/commit/3466e00716e12e32fdb100e3fcfca5c2b3e8d784
DIFF: https://github.com/llvm/llvm-project/commit/3466e00716e12e32fdb100e3fcfca5c2b3e8d784.diff

LOG: Reland "[Attr] support btf_type_tag attribute"

This is to revert commit f95bd18b5faa (Revert "[Attr] support
btf_type_tag attribute") plus a bug fix.

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

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

Differential Revision: https://reviews.llvm.org/D111199

Added: 
    clang/test/CodeGen/attr-btf_type_tag-func.c
    clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
    clang/test/CodeGen/attr-btf_type_tag-var.c
    llvm/test/Bitcode/attr-btf_type_tag.ll
    llvm/test/DebugInfo/attr-btf_type_tag.ll

Modified: 
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/CodeGen/CGDebugInfo.h
    llvm/include/llvm/IR/DIBuilder.h
    llvm/lib/IR/DIBuilder.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 64dd70f837f7b..2b9532534e3aa 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<MacroQualifiedTypeLoc>())
+      TL = MTL.getInnerLoc();
+    else if (auto ATL = TL.getAs<AttributedTypeLoc>())
+      TL = ATL.getModifiedLoc();
+    else
+      break;
+  }
+  return TL;
+}
+
+llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile *Unit,
+                                               TypeLoc TL) {
   QualifierCollector Qc;
   const Type *T = Qc.strip(Ty);
 
@@ -944,7 +964,15 @@ llvm::DIType *CGDebugInfo::CreateQualifiedType(QualType Ty,
     return getOrCreateType(QualType(T, 0), Unit);
   }
 
-  auto *FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit);
+  QualType NextTy = Qc.apply(CGM.getContext(), T);
+  TypeLoc NextTL;
+  if (NextTy.hasQualifiers())
+    NextTL = TL;
+  else if (TL) {
+    if (auto QTL = TL.getAs<QualifiedTypeLoc>())
+      NextTL = StripMacroAttributed(QTL.getNextTypeLoc());
+  }
+  auto *FromTy = getOrCreateType(NextTy, Unit, NextTL);
 
   // No need to fill in the Name, Line, Size, Alignment, Offset in case of
   // CVR derived types.
@@ -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<unsigned> DWARFAddressSpace =
       CGM.getTarget().getDWARFAddressSpace(AddressSpace);
 
+  llvm::DINodeArray Annotations = nullptr;
+  TypeLoc NextTL;
+  if (TL) {
+    SmallVector<llvm::Metadata *, 4> Annots;
+    NextTL = TL.getNextTypeLoc();
+    if (NextTL) {
+      // Traverse all MacroQualifiedTypeLoc, QualifiedTypeLoc and
+      // AttributedTypeLoc type locations so we can collect
+      // BTFTypeTag attributes for this pointer.
+      while (true) {
+        if (auto MTL = NextTL.getAs<MacroQualifiedTypeLoc>()) {
+          NextTL = MTL.getInnerLoc();
+        } else if (auto QTL = NextTL.getAs<QualifiedTypeLoc>()) {
+          NextTL = QTL.getNextTypeLoc();
+        } else if (auto ATL = NextTL.getAs<AttributedTypeLoc>()) {
+          if (const auto *A = ATL.getAttrAs<BTFTypeTagAttr>()) {
+            StringRef BTFTypeTag = A->getBTFTypeTag();
+            if (!BTFTypeTag.empty()) {
+              llvm::Metadata *Ops[2] = {
+                  llvm::MDString::get(CGM.getLLVMContext(),
+                                      StringRef("btf_type_tag")),
+                  llvm::MDString::get(CGM.getLLVMContext(), BTFTypeTag)};
+              Annots.insert(Annots.begin(),
+                            llvm::MDNode::get(CGM.getLLVMContext(), Ops));
+            }
+          }
+          NextTL = ATL.getModifiedLoc();
+        } else {
+          break;
+        }
+      }
+    }
+
+    NextTL = StripMacroAttributed(TL.getNextTypeLoc());
+    if (Annots.size() > 0)
+      Annotations = DBuilder.getOrCreateArray(Annots);
+  }
+
   if (Tag == llvm::dwarf::DW_TAG_reference_type ||
       Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
     return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
                                         Size, Align, DWARFAddressSpace);
   else
-    return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
-                                      Align, DWARFAddressSpace);
+    return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit, NextTL),
+                                      Size, Align, DWARFAddressSpace,
+                                      StringRef(), Annotations);
 }
 
 llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -1265,8 +1333,11 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
 
 llvm::DIType *CGDebugInfo::CreateType(const TypedefType *Ty,
                                       llvm::DIFile *Unit) {
+  TypeLoc TL;
+  if (const TypeSourceInfo *TSI = Ty->getDecl()->getTypeSourceInfo())
+    TL = TSI->getTypeLoc();
   llvm::DIType *Underlying =
-      getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+      getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit, TL);
 
   if (Ty->getDecl()->hasAttr<NoDebugAttr>())
     return Underlying;
@@ -1340,7 +1411,7 @@ static llvm::DINode::DIFlags getRefFlags(const FunctionProtoType *Func) {
 }
 
 llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
-                                      llvm::DIFile *Unit) {
+                                      llvm::DIFile *Unit, TypeLoc TL) {
   const auto *FPT = dyn_cast<FunctionProtoType>(Ty);
   if (FPT) {
     if (llvm::DIType *QTy = CreateQualifiedType(FPT, Unit))
@@ -1352,17 +1423,43 @@ llvm::DIType *CGDebugInfo::CreateType(const FunctionType *Ty,
   SmallVector<llvm::Metadata *, 16> EltTys;
 
   // Add the result type at least.
-  EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit));
+  TypeLoc RetTL;
+  if (TL) {
+    if (auto FTL = TL.getAs<FunctionTypeLoc>())
+      RetTL = FTL.getReturnLoc();
+  }
+  EltTys.push_back(getOrCreateType(Ty->getReturnType(), Unit, RetTL));
 
   llvm::DINode::DIFlags Flags = llvm::DINode::FlagZero;
   // Set up remainder of arguments if there is a prototype.
   // otherwise emit it as a variadic function.
-  if (!FPT)
+  if (!FPT) {
     EltTys.push_back(DBuilder.createUnspecifiedParameter());
-  else {
+  } else {
     Flags = getRefFlags(FPT);
-    for (const QualType &ParamType : FPT->param_types())
-      EltTys.push_back(getOrCreateType(ParamType, Unit));
+    bool DoneWithTL = false;
+    if (TL) {
+      if (auto FTL = TL.getAs<FunctionTypeLoc>()) {
+        DoneWithTL = true;
+        unsigned Idx = 0;
+        unsigned FTL_NumParams = FTL.getNumParams();
+        for (const QualType &ParamType : FPT->param_types()) {
+          TypeLoc ParamTL;
+          if (Idx < FTL_NumParams) {
+            ParmVarDecl *Param = FTL.getParam(Idx);
+            if (const TypeSourceInfo *TSI = Param->getTypeSourceInfo())
+              ParamTL = TSI->getTypeLoc();
+          }
+          EltTys.push_back(getOrCreateType(ParamType, Unit, ParamTL));
+          Idx++;
+        }
+      }
+    }
+
+    if (!DoneWithTL) {
+      for (const QualType &ParamType : FPT->param_types())
+        EltTys.push_back(getOrCreateType(ParamType, Unit));
+    }
     if (FPT->isVariadic())
       EltTys.push_back(DBuilder.createUnspecifiedParameter());
   }
@@ -1433,11 +1530,13 @@ llvm::DIType *CGDebugInfo::createBitFieldType(const FieldDecl *BitFieldDecl,
       Flags, DebugType, Annotations);
 }
 
-llvm::DIType *CGDebugInfo::createFieldType(
-    StringRef name, QualType type, SourceLocation loc, AccessSpecifier AS,
-    uint64_t offsetInBits, uint32_t AlignInBits, llvm::DIFile *tunit,
-    llvm::DIScope *scope, const RecordDecl *RD, llvm::DINodeArray Annotations) {
-  llvm::DIType *debugType = getOrCreateType(type, tunit);
+llvm::DIType *
+CGDebugInfo::createFieldType(StringRef name, QualType type, SourceLocation loc,
+                             AccessSpecifier AS, uint64_t offsetInBits,
+                             uint32_t AlignInBits, llvm::DIFile *tunit,
+                             llvm::DIScope *scope, const RecordDecl *RD,
+                             llvm::DINodeArray Annotations, TypeLoc TL) {
+  llvm::DIType *debugType = getOrCreateType(type, tunit, TL);
 
   // Get the location for the field.
   llvm::DIFile *file = getOrCreateFile(loc);
@@ -1545,9 +1644,12 @@ void CGDebugInfo::CollectRecordNormalField(
   } else {
     auto Align = getDeclAlignIfRequired(field, CGM.getContext());
     llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(field);
-    FieldType =
-        createFieldType(name, type, field->getLocation(), field->getAccess(),
-                        OffsetInBits, Align, tunit, RecordTy, RD, Annotations);
+    TypeLoc TL;
+    if (const TypeSourceInfo *TSI = field->getTypeSourceInfo())
+      TL = TSI->getTypeLoc();
+    FieldType = createFieldType(name, type, field->getLocation(),
+                                field->getAccess(), OffsetInBits, Align, tunit,
+                                RecordTy, RD, Annotations, TL);
   }
 
   elements.push_back(FieldType);
@@ -3305,7 +3407,8 @@ void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
   RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
 }
 
-llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
+llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit,
+                                           TypeLoc TL) {
   if (Ty.isNull())
     return nullptr;
 
@@ -3322,7 +3425,7 @@ llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
   if (auto *T = getTypeOrNull(Ty))
     return T;
 
-  llvm::DIType *Res = CreateTypeNode(Ty, Unit);
+  llvm::DIType *Res = CreateTypeNode(Ty, Unit, TL);
   void *TyPtr = Ty.getAsOpaquePtr();
 
   // And update the type cache.
@@ -3366,10 +3469,11 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
   return nullptr;
 }
 
-llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
+llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit,
+                                          TypeLoc TL) {
   // Handle qualifiers, which recursively handles what they refer to.
   if (Ty.hasLocalQualifiers())
-    return CreateQualifiedType(Ty, Unit);
+    return CreateQualifiedType(Ty, Unit, TL);
 
   // Work out details of type.
   switch (Ty->getTypeClass()) {
@@ -3398,7 +3502,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
   case Type::Complex:
     return CreateType(cast<ComplexType>(Ty));
   case Type::Pointer:
-    return CreateType(cast<PointerType>(Ty), Unit);
+    return CreateType(cast<PointerType>(Ty), Unit, TL);
   case Type::BlockPointer:
     return CreateType(cast<BlockPointerType>(Ty), Unit);
   case Type::Typedef:
@@ -3409,7 +3513,7 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
     return CreateEnumType(cast<EnumType>(Ty));
   case Type::FunctionProto:
   case Type::FunctionNoProto:
-    return CreateType(cast<FunctionType>(Ty), Unit);
+    return CreateType(cast<FunctionType>(Ty), Unit, TL);
   case Type::ConstantArray:
   case Type::VariableArray:
   case Type::IncompleteArray:
@@ -3954,7 +4058,12 @@ llvm::DISubroutineType *CGDebugInfo::getOrCreateFunctionType(const Decl *D,
                                            getDwarfCC(CC));
     }
 
-  return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F));
+  TypeLoc TL;
+  if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+    if (const TypeSourceInfo *TSI = FD->getTypeSourceInfo())
+      TL = TSI->getTypeLoc();
+  }
+  return cast<llvm::DISubroutineType>(getOrCreateType(FnType, F, TL));
 }
 
 QualType
@@ -4356,8 +4465,12 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
   uint64_t XOffset = 0;
   if (VD->hasAttr<BlocksAttr>())
     Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset).WrappedType;
-  else
-    Ty = getOrCreateType(VD->getType(), Unit);
+  else {
+    TypeLoc TL;
+    if (const TypeSourceInfo *TSI = VD->getTypeSourceInfo())
+      TL = TSI->getTypeLoc();
+    Ty = getOrCreateType(VD->getType(), Unit, TL);
+  }
 
   // If there is no debug info for this type then do not emit debug info
   // for this variable.
@@ -5081,10 +5194,14 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
     }
     AppendAddressSpaceXDeref(AddressSpace, Expr);
 
+    TypeLoc TL;
+    if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
+      TL = TSI->getTypeLoc();
+
     llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
     GVE = DBuilder.createGlobalVariableExpression(
-        DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
-        Var->hasLocalLinkage(), true,
+        DContext, DeclName, LinkageName, Unit, LineNo,
+        getOrCreateType(T, Unit, TL), Var->hasLocalLinkage(), true,
         Expr.empty() ? nullptr : DBuilder.createExpression(Expr),
         getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
         Align, Annotations);

diff  --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index d6b9bdd4839cc..a7b72fa5f5a65 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<StringRef> Source);
 
   /// Get the type from the cache or create a new type if necessary.
-  llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg);
+  llvm::DIType *getOrCreateType(QualType Ty, llvm::DIFile *Fg,
+                                TypeLoc TL = TypeLoc());
 
   /// Get a reference to a clang module.  If \p CreateSkeletonCU is true,
   /// this also creates a split dwarf skeleton compile unit.
@@ -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 0000000000000..016e1064eb861
--- /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 0000000000000..c80c7e9b45d96
--- /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 0000000000000..3493d8f6d3666
--- /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 90165095bb0c0..61c6dd885980e 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<unsigned> DWARFAddressSpace =
-                                         None,
-                                     StringRef Name = "");
+    /// \param Annotations       Member annotations.
+    DIDerivedType *
+    createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
+                      uint32_t AlignInBits = 0,
+                      Optional<unsigned> 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 de4ab5981883d..12320cf4af9f7 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<unsigned> DWARFAddressSpace,
-    StringRef Name) {
+DIDerivedType *
+DIBuilder::createPointerType(DIType *PointeeTy, uint64_t SizeInBits,
+                             uint32_t AlignInBits,
+                             Optional<unsigned> 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 0000000000000..ab0634bb147a0
--- /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
+
+ at 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 0000000000000..4561d0512a991
--- /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
+
+ at 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-9a-f]+]] "int ***")
+
+; CHECK:      0x[[T1]]: DW_TAG_pointer_type
+; CHECK-NEXT:   DW_AT_type      (0x[[T2:[0-9a-f]+]] "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-9a-f]+]] "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{{[0-9a-f]+}} "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)"}


        


More information about the cfe-commits mailing list