[llvm] 3ca1744 - [DebugInfo][BPF] Add 'annotations' field for DIBasicType & DISubroutineType (#91422)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 18 00:23:29 PDT 2024


Author: eddyz87
Date: 2024-06-18T10:23:25+03:00
New Revision: 3ca17443ef4af21bdb1f3b4fbcfff672cbc6176c

URL: https://github.com/llvm/llvm-project/commit/3ca17443ef4af21bdb1f3b4fbcfff672cbc6176c
DIFF: https://github.com/llvm/llvm-project/commit/3ca17443ef4af21bdb1f3b4fbcfff672cbc6176c.diff

LOG: [DebugInfo][BPF] Add 'annotations' field for DIBasicType & DISubroutineType (#91422)

Extend `DIBasicType` and `DISubroutineType` with additional field
`annotations`, e.g. as below:

```
  !5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !6)
  !6 = !{!7}
  !7 = !{!"btf:type_tag", !"tag1"}
```

The field would be used by BPF backend to generate DWARF attributes
corresponding to `btf_type_tag` type attributes, e.g.:

```
  0x00000029:   DW_TAG_base_type
                  DW_AT_name	("int")
                  DW_AT_encoding	(DW_ATE_signed)
                  DW_AT_byte_size	(0x04)

  0x0000002d:     DW_TAG_LLVM_annotation
                    DW_AT_name	("btf:type_tag")
                    DW_AT_const_value	("tag1")
```

Such DWARF entries would be used to generate BTF definitions by tools
like [pahole](https://github.com/acmel/dwarves).

Note: similar fields with similar purposes are already present in
DIDerivedType and DICompositeType.

Currently "btf_type_tag" attributes are represented in debug information
as 'annotations' fields in DIDerivedType with DW_TAG_pointer_type tag.
The annotation on a pointer corresponds to pointee having the attributes
in the final BTF.

The discussion in
[thread](https://lore.kernel.org/bpf/87r0w9jjoq.fsf@oracle.com/) came to
conclusion, that such annotations should apply to the annotated type
itself. Hence the necessity to extend `DIBasicType` & `DISubroutineType`
types with 'annotations' field to represent cases like below:

```
  int __attribute__((btf_type_tag("foo"))) bar;
```

This was previously tracked as differential revision:
https://reviews.llvm.org/D143966

Added: 
    llvm/test/Bitcode/attr-btf_tag-dibasic.ll
    llvm/test/Bitcode/attr-btf_tag-disubroutine.ll

Modified: 
    llvm/include/llvm/IR/DebugInfoMetadata.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/Bitcode/Reader/MetadataLoader.cpp
    llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
    llvm/lib/IR/AsmWriter.cpp
    llvm/lib/IR/DebugInfoMetadata.cpp
    llvm/lib/IR/LLVMContextImpl.h
    llvm/test/DebugInfo/attr-btf_type_tag.ll

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 524945862e8d4..848e7c57938e3 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -828,40 +828,45 @@ class DIBasicType : public DIType {
   static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
                               StringRef Name, uint64_t SizeInBits,
                               uint32_t AlignInBits, unsigned Encoding,
-                              DIFlags Flags, StorageType Storage,
-                              bool ShouldCreate = true) {
+                              DIFlags Flags, DINodeArray Annotations,
+                              StorageType Storage, bool ShouldCreate = true) {
     return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
-                   SizeInBits, AlignInBits, Encoding, Flags, Storage,
-                   ShouldCreate);
+                   SizeInBits, AlignInBits, Encoding, Flags, Annotations.get(),
+                   Storage, ShouldCreate);
   }
   static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
                               MDString *Name, uint64_t SizeInBits,
                               uint32_t AlignInBits, unsigned Encoding,
-                              DIFlags Flags, StorageType Storage,
-                              bool ShouldCreate = true);
+                              DIFlags Flags, Metadata *Annotations,
+                              StorageType Storage, bool ShouldCreate = true);
 
   TempDIBasicType cloneImpl() const {
     return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
-                        getAlignInBits(), getEncoding(), getFlags());
+                        getAlignInBits(), getEncoding(), getFlags(),
+                        getAnnotations());
   }
 
 public:
   DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
-                    (Tag, Name, 0, 0, 0, FlagZero))
+                    (Tag, Name, 0, 0, 0, FlagZero, {}))
   DEFINE_MDNODE_GET(DIBasicType,
                     (unsigned Tag, StringRef Name, uint64_t SizeInBits),
-                    (Tag, Name, SizeInBits, 0, 0, FlagZero))
+                    (Tag, Name, SizeInBits, 0, 0, FlagZero, {}))
   DEFINE_MDNODE_GET(DIBasicType,
                     (unsigned Tag, MDString *Name, uint64_t SizeInBits),
-                    (Tag, Name, SizeInBits, 0, 0, FlagZero))
+                    (Tag, Name, SizeInBits, 0, 0, FlagZero, {}))
   DEFINE_MDNODE_GET(DIBasicType,
                     (unsigned Tag, StringRef Name, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
-                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
+                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
+                     DINodeArray Annotations = {}),
+                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,
+                     Annotations))
   DEFINE_MDNODE_GET(DIBasicType,
                     (unsigned Tag, MDString *Name, uint64_t SizeInBits,
-                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
-                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
+                     uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
+                     Metadata *Annotations = nullptr),
+                    (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,
+                     Annotations))
 
   TempDIBasicType clone() const { return cloneImpl(); }
 
@@ -873,6 +878,16 @@ class DIBasicType : public DIType {
   /// neither signed nor unsigned.
   std::optional<Signedness> getSignedness() const;
 
+  Metadata *getRawAnnotations() const { return getOperand(3); }
+
+  DINodeArray getAnnotations() const {
+    return cast_or_null<MDTuple>(getRawAnnotations());
+  }
+
+  void replaceAnnotations(DINodeArray Annotations) {
+    replaceOperandWith(3, Annotations.get());
+  }
+
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == DIBasicTypeKind;
   }
@@ -1112,6 +1127,10 @@ class DIDerivedType : public DIType {
   }
   Metadata *getRawAnnotations() const { return getOperand(5); }
 
+  void replaceAnnotations(DINodeArray Annotations) {
+    replaceOperandWith(5, Annotations.get());
+  }
+
   /// Get casted version of extra data.
   /// @{
   DIType *getClassType() const;
@@ -1339,6 +1358,10 @@ class DICompositeType : public DIType {
     return cast_or_null<MDTuple>(getRawAnnotations());
   }
 
+  void replaceAnnotations(DINodeArray Annotations) {
+    replaceOperandWith(13, Annotations.get());
+  }
+
   /// Replace operands.
   ///
   /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision
@@ -1385,26 +1408,30 @@ class DISubroutineType : public DIType {
 
   static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags,
                                    uint8_t CC, DITypeRefArray TypeArray,
-                                   StorageType Storage,
+                                   DINodeArray Annotations, StorageType Storage,
                                    bool ShouldCreate = true) {
-    return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate);
+    return getImpl(Context, Flags, CC, TypeArray.get(), Annotations.get(),
+                   Storage, ShouldCreate);
   }
   static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags,
                                    uint8_t CC, Metadata *TypeArray,
-                                   StorageType Storage,
+                                   Metadata *Annotations, StorageType Storage,
                                    bool ShouldCreate = true);
 
   TempDISubroutineType cloneImpl() const {
-    return getTemporary(getContext(), getFlags(), getCC(), getTypeArray());
+    return getTemporary(getContext(), getFlags(), getCC(), getTypeArray(),
+                        getAnnotations());
   }
 
 public:
   DEFINE_MDNODE_GET(DISubroutineType,
-                    (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray),
-                    (Flags, CC, TypeArray))
+                    (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray,
+                     DINodeArray Annotations = nullptr),
+                    (Flags, CC, TypeArray, Annotations))
   DEFINE_MDNODE_GET(DISubroutineType,
-                    (DIFlags Flags, uint8_t CC, Metadata *TypeArray),
-                    (Flags, CC, TypeArray))
+                    (DIFlags Flags, uint8_t CC, Metadata *TypeArray,
+                     Metadata *Annotations = nullptr),
+                    (Flags, CC, TypeArray, Annotations))
 
   TempDISubroutineType clone() const { return cloneImpl(); }
   // Returns a new temporary DISubroutineType with updated CC
@@ -1422,6 +1449,15 @@ class DISubroutineType : public DIType {
 
   Metadata *getRawTypeArray() const { return getOperand(3); }
 
+  Metadata *getRawAnnotations() const { return getOperand(4); }
+  DINodeArray getAnnotations() const {
+    return cast_or_null<MDTuple>(getRawAnnotations());
+  }
+
+  void replaceAnnotations(DINodeArray Annotations) {
+    replaceOperandWith(4, Annotations.get());
+  }
+
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == DISubroutineTypeKind;
   }

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index eb1e3e494a42f..6ca80e34907fc 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5250,7 +5250,7 @@ bool LLParser::parseDIEnumerator(MDNode *&Result, bool IsDistinct) {
 
 /// parseDIBasicType:
 ///   ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32,
-///                    encoding: DW_ATE_encoding, flags: 0)
+///                    encoding: DW_ATE_encoding, flags: 0, annotations: !1)
 bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type));                     \
@@ -5258,12 +5258,14 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX));                            \
   OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));                           \
   OPTIONAL(encoding, DwarfAttEncodingField, );                                 \
-  OPTIONAL(flags, DIFlagField, );
+  OPTIONAL(flags, DIFlagField, );                                              \
+  OPTIONAL(annotations, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
-  Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val,
-                                         align.Val, encoding.Val, flags.Val));
+  Result = GET_OR_DISTINCT(DIBasicType,
+                           (Context, tag.Val, name.Val, size.Val, align.Val,
+                            encoding.Val, flags.Val, annotations.Val));
   return false;
 }
 
@@ -5400,12 +5402,13 @@ bool LLParser::parseDISubroutineType(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(cc, DwarfCCField, );                                                \
-  REQUIRED(types, MDField, );
+  REQUIRED(types, MDField, );                                                  \
+  OPTIONAL(annotations, MDField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
-  Result = GET_OR_DISTINCT(DISubroutineType,
-                           (Context, flags.Val, cc.Val, types.Val));
+  Result = GET_OR_DISTINCT(DISubroutineType, (Context, flags.Val, cc.Val,
+                                              types.Val, annotations.Val));
   return false;
 }
 

diff  --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 9102f3a60cffc..bc06c55f1662c 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1527,7 +1527,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     break;
   }
   case bitc::METADATA_BASIC_TYPE: {
-    if (Record.size() < 6 || Record.size() > 7)
+    if (Record.size() < 6 || Record.size() > 8)
       return error("Invalid record");
 
     IsDistinct = Record[0];
@@ -1535,10 +1535,14 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
                                 ? static_cast<DINode::DIFlags>(Record[6])
                                 : DINode::FlagZero;
 
+    Metadata *Annotations = nullptr;
+    if (Record.size() > 7 && Record[7])
+      Annotations = getMDOrNull(Record[7]);
+
     MetadataList.assignValue(
         GET_OR_DISTINCT(DIBasicType,
                         (Context, Record[1], getMDString(Record[2]), Record[3],
-                         Record[4], Record[5], Flags)),
+                         Record[4], Record[5], Flags, Annotations)),
         NextMetadataNo);
     NextMetadataNo++;
     break;
@@ -1703,7 +1707,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     break;
   }
   case bitc::METADATA_SUBROUTINE_TYPE: {
-    if (Record.size() < 3 || Record.size() > 4)
+    if (Record.size() < 3 || Record.size() > 5)
       return error("Invalid record");
     bool IsOldTypeRefArray = Record[0] < 2;
     unsigned CC = (Record.size() > 3) ? Record[3] : 0;
@@ -1713,9 +1717,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
     Metadata *Types = getMDOrNull(Record[2]);
     if (LLVM_UNLIKELY(IsOldTypeRefArray))
       Types = MetadataList.upgradeTypeRefArray(Types);
+    Metadata *Annotations = nullptr;
+    if (Record.size() > 4 && Record[4])
+      Annotations = getMDOrNull(Record[4]);
 
     MetadataList.assignValue(
-        GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)),
+        GET_OR_DISTINCT(DISubroutineType,
+                        (Context, Flags, CC, Types, Annotations)),
         NextMetadataNo);
     NextMetadataNo++;
     break;

diff  --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index b08d5c50e5ae3..f3e87310310ec 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1816,6 +1816,7 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N,
   Record.push_back(N->getAlignInBits());
   Record.push_back(N->getEncoding());
   Record.push_back(N->getFlags());
+  Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations()));
 
   Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev);
   Record.clear();
@@ -1911,6 +1912,7 @@ void ModuleBitcodeWriter::writeDISubroutineType(
   Record.push_back(N->getFlags());
   Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get()));
   Record.push_back(N->getCC());
+  Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations()));
 
   Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev);
   Record.clear();

diff  --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 6c04fa1c67a95..08be3a51862ca 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -712,7 +712,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
   if (!Name.empty())
     addString(Buffer, dwarf::DW_AT_name, Name);
 
-  // An unspecified type only has a name attribute.
+  addAnnotation(Buffer, BTy->getAnnotations());
+
+  // An unspecified type only has a name attribute & annotations.
   if (BTy->getTag() == dwarf::DW_TAG_unspecified_type)
     return;
 
@@ -881,6 +883,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
 
   if (CTy->isRValueReference())
     addFlag(Buffer, dwarf::DW_AT_rvalue_reference);
+
+  addAnnotation(Buffer, CTy->getAnnotations());
 }
 
 void DwarfUnit::addAnnotation(DIE &Buffer, DINodeArray Annotations) {

diff  --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 0bf8be9ac55f9..16e51307ddb71 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2122,9 +2122,9 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
 }
 
 static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
-                             AsmWriterContext &) {
+                             AsmWriterContext &WriterCtx) {
   Out << "!DIBasicType(";
-  MDFieldPrinter Printer(Out);
+  MDFieldPrinter Printer(Out, WriterCtx);
   if (N->getTag() != dwarf::DW_TAG_base_type)
     Printer.printTag(N);
   Printer.printString("name", N->getName());
@@ -2133,6 +2133,7 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
   Printer.printDwarfEnum("encoding", N->getEncoding(),
                          dwarf::AttributeEncodingString);
   Printer.printDIFlags("flags", N->getFlags());
+  Printer.printMetadata("annotations", N->getRawAnnotations());
   Out << ")";
 }
 
@@ -2228,6 +2229,7 @@ static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N,
   Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
   Printer.printMetadata("types", N->getRawTypeArray(),
                         /* ShouldSkipNull */ false);
+  Printer.printMetadata("annotations", N->getRawAnnotations());
   Out << ")";
 }
 

diff  --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 161a30dfb3828..7c677b78c577a 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -663,12 +663,12 @@ DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,
 DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
                                   MDString *Name, uint64_t SizeInBits,
                                   uint32_t AlignInBits, unsigned Encoding,
-                                  DIFlags Flags, StorageType Storage,
-                                  bool ShouldCreate) {
+                                  DIFlags Flags, Metadata *Annotations,
+                                  StorageType Storage, bool ShouldCreate) {
   assert(isCanonical(Name) && "Expected canonical MDString");
-  DEFINE_GETIMPL_LOOKUP(DIBasicType,
-                        (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags));
-  Metadata *Ops[] = {nullptr, nullptr, Name};
+  DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, SizeInBits, AlignInBits,
+                                      Encoding, Flags, Annotations));
+  Metadata *Ops[] = {nullptr, nullptr, Name, Annotations};
   DEFINE_GETIMPL_STORE(DIBasicType,
                        (Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops);
 }
@@ -872,10 +872,11 @@ DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage,
 
 DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
                                             uint8_t CC, Metadata *TypeArray,
+                                            Metadata *Annotations,
                                             StorageType Storage,
                                             bool ShouldCreate) {
-  DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));
-  Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray};
+  DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray, Annotations));
+  Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray, Annotations};
   DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
 }
 

diff  --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 392e0d16f1761..8fb55d9c719d1 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -465,25 +465,29 @@ template <> struct MDNodeKeyImpl<DIBasicType> {
   uint32_t AlignInBits;
   unsigned Encoding;
   unsigned Flags;
+  Metadata *Annotations;
 
   MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,
-                uint32_t AlignInBits, unsigned Encoding, unsigned Flags)
+                uint32_t AlignInBits, unsigned Encoding, unsigned Flags,
+                Metadata *Annotations)
       : Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
-        Encoding(Encoding), Flags(Flags) {}
+        Encoding(Encoding), Flags(Flags), Annotations(Annotations) {}
   MDNodeKeyImpl(const DIBasicType *N)
       : Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),
         AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()),
-        Flags(N->getFlags()) {}
+        Flags(N->getFlags()), Annotations(N->getRawAnnotations()) {}
 
   bool isKeyOf(const DIBasicType *RHS) const {
     return Tag == RHS->getTag() && Name == RHS->getRawName() &&
            SizeInBits == RHS->getSizeInBits() &&
            AlignInBits == RHS->getAlignInBits() &&
-           Encoding == RHS->getEncoding() && Flags == RHS->getFlags();
+           Encoding == RHS->getEncoding() && Flags == RHS->getFlags() &&
+           Annotations == RHS->getRawAnnotations();
   }
 
   unsigned getHashValue() const {
-    return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
+    return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding,
+                        Annotations);
   }
 };
 
@@ -712,18 +716,24 @@ template <> struct MDNodeKeyImpl<DISubroutineType> {
   unsigned Flags;
   uint8_t CC;
   Metadata *TypeArray;
+  Metadata *Annotations;
 
-  MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
-      : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
+  MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray,
+                Metadata *Annotations)
+      : Flags(Flags), CC(CC), TypeArray(TypeArray), Annotations(Annotations) {}
   MDNodeKeyImpl(const DISubroutineType *N)
-      : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
+      : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()),
+        Annotations(N->getRawAnnotations()) {}
 
   bool isKeyOf(const DISubroutineType *RHS) const {
     return Flags == RHS->getFlags() && CC == RHS->getCC() &&
-           TypeArray == RHS->getRawTypeArray();
+           TypeArray == RHS->getRawTypeArray() &&
+           Annotations == RHS->getRawAnnotations();
   }
 
-  unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
+  unsigned getHashValue() const {
+    return hash_combine(Flags, CC, TypeArray, Annotations);
+  }
 };
 
 template <> struct MDNodeKeyImpl<DIFile> {

diff  --git a/llvm/test/Bitcode/attr-btf_tag-dibasic.ll b/llvm/test/Bitcode/attr-btf_tag-dibasic.ll
new file mode 100644
index 0000000000000..7a73f921466d9
--- /dev/null
+++ b/llvm/test/Bitcode/attr-btf_tag-dibasic.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 0, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9, !10, !11, !12, !13, !14}
+!llvm.ident = !{!15}
+
+!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_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: "79feb01d60b549b43abc493c324fe2a8")
+!4 = !{!0}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !6)
+!6 = !{!7}
+!7 = !{!"btf:type_tag", !"tag1"}
+
+; CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+; CHECK: ![[L1]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L2:[0-9]+]])
+; CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
+; CHECK: ![[L3]] = !{!"btf:type_tag", !"tag1"}
+
+!8 = !{i32 7, !"Dwarf Version", i32 5}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"wchar_size", i32 4}
+!11 = !{i32 8, !"PIC Level", i32 2}
+!12 = !{i32 7, !"PIE Level", i32 2}
+!13 = !{i32 7, !"uwtable", i32 2}
+!14 = !{i32 7, !"frame-pointer", i32 2}
+!15 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"}

diff  --git a/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll
new file mode 100644
index 0000000000000..277348c3eb461
--- /dev/null
+++ b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll
@@ -0,0 +1,41 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+;
+; Source:
+;   #define __tag1 __attribute__((btf_type_tag("tag1")))
+;   int (__tag1 * g)(void);
+
+; Compilation flag:
+;   clang -S -g -emit-llvm test.c
+
+ at g = dso_local global ptr null, align 8, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!11, !12, !13, !14, !15, !16, !17}
+!llvm.ident = !{!18}
+
+!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_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: "2ed8742fd12b44b948de1ac5e433bd63")
+!4 = !{!0}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DISubroutineType(types: !7, annotations: !9)
+!7 = !{!8}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{!10}
+!10 = !{!"btf:type_tag", !"tag1"}
+
+; 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]] = !DISubroutineType(types: ![[#]], annotations: ![[L3:[0-9]+]])
+; CHECK: ![[L3]] = !{![[L4:[0-9]+]]}
+; CHECK: ![[L4]] = !{!"btf:type_tag", !"tag1"}
+
+!11 = !{i32 7, !"Dwarf Version", i32 5}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{i32 8, !"PIC Level", i32 2}
+!15 = !{i32 7, !"PIE Level", i32 2}
+!16 = !{i32 7, !"uwtable", i32 2}
+!17 = !{i32 7, !"frame-pointer", i32 2}
+!18 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"}

diff  --git a/llvm/test/DebugInfo/attr-btf_type_tag.ll b/llvm/test/DebugInfo/attr-btf_type_tag.ll
index 47a2aa59106d1..329b95cb5d63b 100644
--- a/llvm/test/DebugInfo/attr-btf_type_tag.ll
+++ b/llvm/test/DebugInfo/attr-btf_type_tag.ll
@@ -4,59 +4,121 @@
 ; Source:
 ;   #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  a;
+;   int * __tag2  b;
+;   void  __tag3 *c;
+;   void (__tag4 *d)(void);
+;
 ;
-;   int * __tag1 * __tag2 *g;
 ; Compilation flag:
 ;   clang -target x86_64 -g -S -emit-llvm t.c
+;
+; Note: only "btf:type_tag" annotations are checked for brevity.
 
- at g = dso_local global ptr null, align 8, !dbg !0
+ at a = dso_local global i32 0, align 4, !dbg !0
+ at b = dso_local global ptr null, align 8, !dbg !5
+ at c = dso_local global ptr null, align 8, !dbg !11
+ at d = dso_local global ptr null, align 8, !dbg !19
 
 !llvm.dbg.cu = !{!2}
-!llvm.module.flags = !{!13, !14, !15, !16, !17}
-!llvm.ident = !{!18}
+!llvm.module.flags = !{!31, !32, !33, !34, !35}
+!llvm.ident = !{!36}
 
 !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)
+!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 6, type: !28, 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 ffde01565bce81795ba0442108742557a9a4562d)", 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: "71845c02e58f6b1a8b0162797b4d3f37")
+!4 = !{!0, !5, !11, !19}
+!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
+
+; CHECK:                 DW_TAG_variable
+; CHECK-NEXT:               DW_AT_name      ("a")
+; CHECK-NEXT:               DW_AT_type      (0x[[T1:[0-9a-f]+]] "int")
+
+; CHECK:      0x[[T1]]:  DW_TAG_base_type
+; CHECK-NEXT:               DW_AT_name      ("int")
+
+; CHECK:                    DW_TAG_LLVM_annotation
+; CHECK-NEXT:                 DW_AT_name    ("btf:type_tag")
+; CHECK-NEXT:                 DW_AT_const_value     ("tag1")
+
+!6 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true)
+!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, annotations: !9)
 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
 !9 = !{!10}
-!10 = !{!"btf_type_tag", !"tag1"}
-!11 = !{!12}
-!12 = !{!"btf_type_tag", !"tag2"}
+!10 = !{!"btf:type_tag", !"tag2"}
+!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())
+
+; CHECK:                DW_TAG_variable
+; CHECK-NEXT:               DW_AT_name      ("b")
+; CHECK-NEXT:               DW_AT_type      (0x[[T2:[0-9a-f]+]] "int *")
+
+; 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     ("tag2")
+
+; CHECK:      0x[[T3]]:   DW_TAG_base_type
+; CHECK-NEXT:               DW_AT_name      ("int")
+; CHECK-NEXT:               DW_AT_encoding  (DW_ATE_signed)
+
+!12 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 8, type: !13, isLocal: false, isDefinition: true)
+!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, annotations: !17)
+!14 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: !15)
+!15 = !{!16}
+!16 = !{!"btf:type_tag", !"tag3"}
+!17 = !{!18}
+!18 = !{!"btf_type_tag", !"tag3"}
+
+; CHECK:                DW_TAG_variable
+; CHECK-NEXT:             DW_AT_name      ("c")
+; CHECK-NEXT:             DW_AT_type      (0x[[T4:[0-9a-f]+]] "void *")
 
-; CHECK:      DW_TAG_variable
-; CHECK-NEXT:   DW_AT_name      ("g")
-; CHECK-NEXT:   DW_AT_type      (0x[[T1:[0-9a-f]+]] "int ***")
+; CHECK:      0x[[T4]]: DW_TAG_pointer_type
+; CHECK-NEXT:             DW_AT_type      (0x[[T5:[0-9a-f]+]] "void")
 
-; CHECK:      0x[[T1]]: DW_TAG_pointer_type
-; CHECK-NEXT:   DW_AT_type      (0x[[T2:[0-9a-f]+]] "int **")
+; CHECK:      0x[[T5]]: DW_TAG_unspecified_type
+; CHECK-NEXT:             DW_AT_name      ("void")
 
-; CHECK:        DW_TAG_LLVM_annotation
-; CHECK-NEXT:     DW_AT_name    ("btf_type_tag")
-; CHECK-NEXT:     DW_AT_const_value     ("tag2")
+; CHECK:                  DW_TAG_LLVM_annotation
+; CHECK-NEXT:               DW_AT_name    ("btf:type_tag")
+; CHECK-NEXT:               DW_AT_const_value     ("tag3")
 
-; CHECK:        NULL
+!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
+!20 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 9, type: !21, isLocal: false, isDefinition: true)
+!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64, annotations: !26)
+!22 = !DISubroutineType(types: !23, annotations: !24)
+!23 = !{null}
+!24 = !{!25}
+!25 = !{!"btf:type_tag", !"tag4"}
+!26 = !{!27}
+!27 = !{!"btf_type_tag", !"tag4"}
+!28 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !29)
+!29 = !{!30}
+!30 = !{!"btf:type_tag", !"tag1"}
 
-; CHECK:      0x[[T2]]: DW_TAG_pointer_type
-; CHECK-NEXT:   DW_AT_type      (0x[[T3:[0-9a-f]+]] "int *")
+; CHECK:                DW_TAG_variable
+; CHECK-NEXT:             DW_AT_name      ("d")
+; CHECK-NEXT:             DW_AT_type      (0x[[T6:[0-9a-f]+]] "void (*)(")
 
-; CHECK:        DW_TAG_LLVM_annotation
-; CHECK-NEXT:     DW_AT_name    ("btf_type_tag")
-; CHECK-NEXT:     DW_AT_const_value     ("tag1")
+; CHECK:      0x[[T6]]: DW_TAG_pointer_type
+; CHECK-NEXT:             DW_AT_type      (0x[[T7:[0-9a-f]+]] "void (")
 
-; CHECK:        NULL
+; CHECK:      0x[[T7]]: DW_TAG_subroutine_type
+; CHECK-NEXT:             DW_AT_prototyped        (true)
 
-; CHECK:      0x[[T3]]: DW_TAG_pointer_type
-; CHECK-NEXT:   DW_AT_type      (0x{{[0-9a-f]+}} "int")
+; CHECK:                  DW_TAG_LLVM_annotation
+; CHECK-NEXT:               DW_AT_name    ("btf:type_tag")
+; CHECK-NEXT:               DW_AT_const_value     ("tag4")
 
-!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)"}
+!31 = !{i32 7, !"Dwarf Version", i32 5}
+!32 = !{i32 2, !"Debug Info Version", i32 3}
+!33 = !{i32 1, !"wchar_size", i32 4}
+!34 = !{i32 7, !"uwtable", i32 2}
+!35 = !{i32 7, !"frame-pointer", i32 2}
+!36 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git ffde01565bce81795ba0442108742557a9a4562d)"}


        


More information about the llvm-commits mailing list