yonghong-song created this revision.
yonghong-song added a reviewer: dblaikie.
yonghong-song added a project: debug-info.
Herald added subscribers: dexonsmith, dang, ormris, hiraditya.
yonghong-song requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Add a new LLVM custom attribute DWARF_AT_LLVM_annotation
so attributes with __attribute__((annotate("..."))) can be
passed to the dwarf debug_info. Please see
https://reviews.llvm.org/D103549 on why BPF community
wants this feature.

This patch added supports for annotation attributes
for global/local variables (including parameters),
static/global functions, record (struct/union) types
and record fields.

This is still work-in-progress. I would like to get feedback
on my current approach.

First, I named the new attribute as DWARF_AT_LLVM_annotations.
I avoided to use BTF/BPF in the name as this doesn't need
to be BPF specific and some other tools might find this useful
in the future.

Second, we don't want to emit DWARF_AT_LLVM_annotations by
default. Two reasons, first, the initial implementation will
be incomplete and heavily geared to BPF use case; second,
this is unlikely to be used outside BPF community initially.
So exposing to other users sounds unnecessary. So I added
a flag -gannotations to control the feature.
If -gannotations is not specified, DWARF_AT_LLVM_annotations
will not be generated.

Third, it is desirable to add IR/BitCode read/write support for
annotations. This will help writing tests too. I only
implemented for DIGlobalVariable. I am pretty sure that
my implementation may have some issues. It
be good to get some feedback before I continues.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103667

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/CodeGen/annotation-1.c
  clang/test/CodeGen/annotation-2.c
  llvm/include/llvm/BinaryFormat/Dwarf.def
  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/DwarfCompileUnit.cpp
  llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
  llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
  llvm/lib/IR/AsmWriter.cpp
  llvm/lib/IR/DIBuilder.cpp
  llvm/lib/IR/DebugInfoMetadata.cpp
  llvm/lib/IR/LLVMContextImpl.h
  llvm/test/DebugInfo/annotation-1.ll

Index: llvm/test/DebugInfo/annotation-1.ll
===================================================================
--- /dev/null
+++ llvm/test/DebugInfo/annotation-1.ll
@@ -0,0 +1,57 @@
+; REQUIRES: x86_64-linux
+; RUN: llc -march=x86 -filetype=asm %s -o - | FileCheck %s
+
+@s1 = internal global i32 0, align 4, !dbg !0
+@g1 = dso_local global i32 0, align 4, !dbg !6
+@.str = private unnamed_addr constant [8 x i8] c"static1\00", section "llvm.metadata"
+@.str.1 = private unnamed_addr constant [8 x i8] c"test3.c\00", section "llvm.metadata"
+@.str.2 = private unnamed_addr constant [8 x i8] c"global1\00", section "llvm.metadata"
+@.str.3 = private unnamed_addr constant [8 x i8] c"global2\00", section "llvm.metadata"
+@llvm.global.annotations = appending global [3 x { i8*, i8*, i8*, i32, i8* }] [{ i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @s1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 1, i8* null }, { i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @g1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 2, i8* null }, { i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @g1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 2, i8* null }], section "llvm.metadata"
+
+; Function Attrs: noinline nounwind optnone uwtable
+define dso_local i32 @test1() #0 !dbg !16 {
+entry:
+  %0 = load volatile i32, i32* @s1, align 4, !dbg !19
+  %1 = load i32, i32* @g1, align 4, !dbg !20
+  %add = add nsw i32 %0, %1, !dbg !21
+  ret i32 %add, !dbg !22
+}
+
+attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11, !12, !13, !14}
+!llvm.ident = !{!15}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "s1", scope: !2, file: !3, line: 1, type: !9, isLocal: true, isDefinition: true, annotations: "static1")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 829c6b7c4cdcd57972e23d7aca4be65b1bd11eaf)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test3.c", directory: "/tmp/home/yhs/work/tests/llvm/annot")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "g1", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true, annotations: "global1,global2")
+
+; CHECK:        .long   .Linfo_string5                  # DW_AT_LLVM_annotations
+; CHECK:        .long   .Linfo_string7                  # DW_AT_LLVM_annotations
+; CHECK:        .Linfo_string5:
+; CHECK-NEXT:           .asciz  "static1"
+; CHECK:        .Linfo_string7:
+; CHECK-NEXT:           .asciz  "global1,global2"
+
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !8)
+!10 = !{i32 7, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!13 = !{i32 7, !"uwtable", i32 1}
+!14 = !{i32 7, !"frame-pointer", i32 2}
+!15 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 829c6b7c4cdcd57972e23d7aca4be65b1bd11eaf)"}
+!16 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 3, type: !17, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
+!17 = !DISubroutineType(types: !18)
+!18 = !{!8}
+!19 = !DILocation(line: 4, column: 10, scope: !16)
+!20 = !DILocation(line: 4, column: 15, scope: !16)
+!21 = !DILocation(line: 4, column: 13, scope: !16)
+!22 = !DILocation(line: 4, column: 3, scope: !16)
Index: llvm/lib/IR/LLVMContextImpl.h
===================================================================
--- llvm/lib/IR/LLVMContextImpl.h
+++ llvm/lib/IR/LLVMContextImpl.h
@@ -981,7 +981,7 @@
                 Metadata *File, unsigned Line, Metadata *Type,
                 bool IsLocalToUnit, bool IsDefinition,
                 Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
-                uint32_t AlignInBits)
+                uint32_t AlignInBits, MDString *Annotations)
       : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
         Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
         IsDefinition(IsDefinition),
Index: llvm/lib/IR/DebugInfoMetadata.cpp
===================================================================
--- llvm/lib/IR/DebugInfoMetadata.cpp
+++ llvm/lib/IR/DebugInfoMetadata.cpp
@@ -977,13 +977,15 @@
                           Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
                           Metadata *StaticDataMemberDeclaration,
                           Metadata *TemplateParams, uint32_t AlignInBits,
-                          StorageType Storage, bool ShouldCreate) {
+                          MDString *Annotations, StorageType Storage,
+                          bool ShouldCreate) {
   assert(isCanonical(Name) && "Expected canonical MDString");
   assert(isCanonical(LinkageName) && "Expected canonical MDString");
   DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, (Scope, Name, LinkageName, File, Line,
                                            Type, IsLocalToUnit, IsDefinition,
                                            StaticDataMemberDeclaration,
-                                           TemplateParams, AlignInBits));
+                                           TemplateParams, AlignInBits,
+                                           Annotations));
   Metadata *Ops[] = {Scope,
                      Name,
                      File,
@@ -991,9 +993,12 @@
                      Name,
                      LinkageName,
                      StaticDataMemberDeclaration,
-                     TemplateParams};
+                     TemplateParams,
+                     Annotations};
   DEFINE_GETIMPL_STORE(DIGlobalVariable,
-                       (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops);
+                       (Line, IsLocalToUnit, IsDefinition, AlignInBits,
+                        Annotations),
+                       Ops);
 }
 
 DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope,
Index: llvm/lib/IR/DIBuilder.cpp
===================================================================
--- llvm/lib/IR/DIBuilder.cpp
+++ llvm/lib/IR/DIBuilder.cpp
@@ -704,7 +704,7 @@
   auto *GV = DIGlobalVariable::getDistinct(
       VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F,
       LineNumber, Ty, IsLocalToUnit, isDefined, cast_or_null<DIDerivedType>(Decl),
-      TemplateParams, AlignInBits);
+      TemplateParams, AlignInBits, StringRef());
   if (!Expr)
     Expr = createExpression();
   auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr);
@@ -721,7 +721,8 @@
   return DIGlobalVariable::getTemporary(
              VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F,
              LineNumber, Ty, IsLocalToUnit, false,
-             cast_or_null<DIDerivedType>(Decl), TemplateParams, AlignInBits)
+             cast_or_null<DIDerivedType>(Decl), TemplateParams, AlignInBits,
+             StringRef())
       .release();
 }
 
Index: llvm/lib/IR/AsmWriter.cpp
===================================================================
--- llvm/lib/IR/AsmWriter.cpp
+++ llvm/lib/IR/AsmWriter.cpp
@@ -2051,6 +2051,7 @@
   if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace())
     Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
                      /* ShouldSkipZero */ false);
+  Printer.printString("annotations", N->getAnnotations());
   Out << ")";
 }
 
@@ -2084,6 +2085,7 @@
                      /* ShouldSkipZero */ false);
   else
     Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true);
+  Printer.printString("annotations", N->getAnnotations());
   Out << ")";
 }
 
@@ -2170,6 +2172,7 @@
   Printer.printMetadata("declaration", N->getRawDeclaration());
   Printer.printMetadata("retainedNodes", N->getRawRetainedNodes());
   Printer.printMetadata("thrownTypes", N->getRawThrownTypes());
+  Printer.printString("annotations", N->getAnnotations());
   Out << ")";
 }
 
@@ -2308,6 +2311,7 @@
   Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration());
   Printer.printMetadata("templateParams", N->getRawTemplateParams());
   Printer.printInt("align", N->getAlignInBits());
+  Printer.printString("annotations", N->getAnnotations());
   Out << ")";
 }
 
@@ -2324,6 +2328,7 @@
   Printer.printMetadata("type", N->getRawType());
   Printer.printDIFlags("flags", N->getFlags());
   Printer.printInt("align", N->getAlignInBits());
+  Printer.printString("annotations", N->getAnnotations());
   Out << ")";
 }
 
Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -297,6 +297,9 @@
   /// Get context owner's DIE.
   DIE *createTypeDIE(const DICompositeType *Ty);
 
+  /// Add annotations.
+  void addAnnotations(DIE &Die, const DINode *DN);
+
 protected:
   ~DwarfUnit();
 
Index: llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -957,6 +957,9 @@
   if (!Name.empty())
     addString(Buffer, dwarf::DW_AT_name, Name);
 
+  if (!CTy->getAnnotations().empty())
+    addAnnotations(Buffer, CTy);
+
   if (Tag == dwarf::DW_TAG_enumeration_type ||
       Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
       Tag == dwarf::DW_TAG_union_type) {
@@ -1191,6 +1194,9 @@
   if (!SP->getName().empty())
     addString(SPDie, dwarf::DW_AT_name, SP->getName());
 
+  if (!SP->getAnnotations().empty())
+    addAnnotations(SPDie, SP);
+
   if (!SkipSPSourceLocation)
     addSourceLine(SPDie, SP);
 
@@ -1541,6 +1547,9 @@
   if (!Name.empty())
     addString(MemberDie, dwarf::DW_AT_name, Name);
 
+  if (!DT->getAnnotations().empty())
+    addAnnotations(MemberDie, DT);
+
   if (DIType *Resolved = DT->getBaseType())
     addType(MemberDie, Resolved);
 
@@ -1794,6 +1803,10 @@
                   TLOF.getDwarfRnglistsSection()->getBeginSymbol());
 }
 
+void DwarfUnit::addAnnotations(DIE& D, const DINode *Ty) {
+  addString(D, dwarf::DW_AT_LLVM_annotations, Ty->getAnnotations());
+}
+
 void DwarfTypeUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) {
   addFlag(D, dwarf::DW_AT_declaration);
   StringRef Name = CTy->getName();
Index: llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
===================================================================
--- llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -183,6 +183,9 @@
   else
     addGlobalName(GV->getName(), *VariableDIE, DeclContext);
 
+  if (!GV->getAnnotations().empty())
+    addAnnotations(*VariableDIE, GV);
+
   if (uint32_t AlignInBytes = GV->getAlignInBytes())
     addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
             AlignInBytes);
@@ -1479,11 +1482,15 @@
   if (!Name.empty())
     addString(VariableDie, dwarf::DW_AT_name, Name);
   const auto *DIVar = Var.getVariable();
-  if (DIVar)
+  if (DIVar) {
     if (uint32_t AlignInBytes = DIVar->getAlignInBytes())
       addUInt(VariableDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
               AlignInBytes);
 
+    if (!DIVar->getAnnotations().empty())
+      addAnnotations(VariableDie, DIVar);
+  }
+
   addSourceLine(VariableDie, DIVar);
   addType(VariableDie, Var.getType());
   if (Var.isArtificial())
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1956,6 +1956,7 @@
   Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration()));
   Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams()));
   Record.push_back(N->getAlignInBits());
+  Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations()));
 
   Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev);
   Record.clear();
Index: llvm/lib/Bitcode/Reader/MetadataLoader.cpp
===================================================================
--- llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1866,7 +1866,8 @@
               (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
                getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
                getDITypeRefOrNull(Record[6]), Record[7], Record[8],
-               getMDOrNull(Record[9]), getMDOrNull(Record[10]), Record[11])),
+               getMDOrNull(Record[9]), getMDOrNull(Record[10]), Record[11],
+               Record.size() == 13 ? getMDString(Record[12]) : nullptr)),
           NextMetadataNo);
 
       NextMetadataNo++;
@@ -1879,7 +1880,8 @@
                            getMDString(Record[2]), getMDString(Record[3]),
                            getMDOrNull(Record[4]), Record[5],
                            getDITypeRefOrNull(Record[6]), Record[7], Record[8],
-                           getMDOrNull(Record[10]), nullptr, Record[11])),
+                           getMDOrNull(Record[10]), nullptr, Record[11],
+                           nullptr)),
           NextMetadataNo);
 
       NextMetadataNo++;
@@ -1912,7 +1914,7 @@
           (Context, getMDOrNull(Record[1]), getMDString(Record[2]),
            getMDString(Record[3]), getMDOrNull(Record[4]), Record[5],
            getDITypeRefOrNull(Record[6]), Record[7], Record[8],
-           getMDOrNull(Record[10]), nullptr, AlignInBits));
+           getMDOrNull(Record[10]), nullptr, AlignInBits, nullptr));
 
       DIGlobalVariableExpression *DGVE = nullptr;
       if (Attach || Expr)
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -4880,7 +4880,7 @@
 ///   ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0,
 ///                      line: 7, scope: !1, baseType: !2, size: 32,
 ///                      align: 32, offset: 0, flags: 0, extraData: !3,
-///                      dwarfAddressSpace: 3)
+///                      dwarfAddressSpace: 3, annotations: "bar")
 bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   REQUIRED(tag, DwarfTagField, );                                              \
@@ -4894,7 +4894,8 @@
   OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX));                          \
   OPTIONAL(flags, DIFlagField, );                                              \
   OPTIONAL(extraData, MDField, );                                              \
-  OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX));
+  OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX));      \
+  OPTIONAL(annotations, MDStringField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -4931,7 +4932,8 @@
   OPTIONAL(dataLocation, MDField, );                                           \
   OPTIONAL(associated, MDField, );                                             \
   OPTIONAL(allocated, MDField, );                                              \
-  OPTIONAL(rank, MDSignedOrMDField, );
+  OPTIONAL(rank, MDSignedOrMDField, );                                         \
+  OPTIONAL(annotations, MDStringField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -5062,7 +5064,8 @@
 ///                     virtuality: DW_VIRTUALTIY_pure_virtual,
 ///                     virtualIndex: 10, thisAdjustment: 4, flags: 11,
 ///                     spFlags: 10, isOptimized: false, templateParams: !4,
-///                     declaration: !5, retainedNodes: !6, thrownTypes: !7)
+///                     declaration: !5, retainedNodes: !6, thrownTypes: !7,
+///                     annotations: "bar")
 bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) {
   auto Loc = Lex.getLoc();
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
@@ -5086,7 +5089,8 @@
   OPTIONAL(templateParams, MDField, );                                         \
   OPTIONAL(declaration, MDField, );                                            \
   OPTIONAL(retainedNodes, MDField, );                                          \
-  OPTIONAL(thrownTypes, MDField, );
+  OPTIONAL(thrownTypes, MDField, );                                            \
+  OPTIONAL(annotations, MDStringField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -5269,7 +5273,7 @@
 ///   ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo",
 ///                         file: !1, line: 7, type: !2, isLocal: false,
 ///                         isDefinition: true, templateParams: !3,
-///                         declaration: !4, align: 8)
+///                         declaration: !4, align: 8, annotations: "bar")
 bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   REQUIRED(name, MDStringField, (/* AllowEmpty */ false));                     \
@@ -5282,7 +5286,8 @@
   OPTIONAL(isDefinition, MDBoolField, (true));                                 \
   OPTIONAL(templateParams, MDField, );                                         \
   OPTIONAL(declaration, MDField, );                                            \
-  OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));
+  OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(annotations, MDStringField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
@@ -5290,17 +5295,18 @@
       GET_OR_DISTINCT(DIGlobalVariable,
                       (Context, scope.Val, name.Val, linkageName.Val, file.Val,
                        line.Val, type.Val, isLocal.Val, isDefinition.Val,
-                       declaration.Val, templateParams.Val, align.Val));
+                       declaration.Val, templateParams.Val, align.Val,
+                       annotations.Val));
   return false;
 }
 
 /// parseDILocalVariable:
 ///   ::= !DILocalVariable(arg: 7, scope: !0, name: "foo",
 ///                        file: !1, line: 7, type: !2, arg: 2, flags: 7,
-///                        align: 8)
+///                        align: 8, annotations: "bar")
 ///   ::= !DILocalVariable(scope: !0, name: "foo",
 ///                        file: !1, line: 7, type: !2, arg: 2, flags: 7,
-///                        align: 8)
+///                        align: 8, annotations: "bar")
 bool LLParser::parseDILocalVariable(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   REQUIRED(scope, MDField, (/* AllowNull */ false));                           \
@@ -5310,7 +5316,8 @@
   OPTIONAL(line, LineField, );                                                 \
   OPTIONAL(type, MDField, );                                                   \
   OPTIONAL(flags, DIFlagField, );                                              \
-  OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));
+  OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX));                           \
+  OPTIONAL(annoations, MDStringField, );
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
Index: llvm/include/llvm/IR/DebugInfoMetadata.h
===================================================================
--- llvm/include/llvm/IR/DebugInfoMetadata.h
+++ llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -128,12 +128,16 @@
   friend class LLVMContextImpl;
   friend class MDNode;
 
+  std::string Annotations;
+
 protected:
   DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
-         ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None)
+         ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None,
+         StringRef Annotations = StringRef())
       : MDNode(C, ID, Storage, Ops1, Ops2) {
     assert(Tag < 1u << 16);
     SubclassData16 = Tag;
+    this->Annotations = Annotations.str();
   }
   ~DINode() = default;
 
@@ -183,6 +187,19 @@
   static DIFlags splitFlags(DIFlags Flags,
                             SmallVectorImpl<DIFlags> &SplitFlags);
 
+  /// Add annotations.
+  ///
+  /// If there are multiple annotations for a particular DINode,
+  /// merge all these annotations into one string separated with ','.
+  void addAnnotation(StringRef Annotation) {
+    if (Annotations.empty())
+      this->Annotations = Annotation.str();
+    else
+      this->Annotations = this->Annotations + std::string(",") +
+                          Annotation.str();
+  }
+  const StringRef getAnnotations() const { return Annotations; }
+
   static bool classof(const Metadata *MD) {
     switch (MD->getMetadataID()) {
     default:
@@ -2489,9 +2506,10 @@
 
 protected:
   DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line,
-             ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0)
-      : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line),
-        AlignInBits(AlignInBits) {}
+             ArrayRef<Metadata *> Ops, uint32_t AlignInBits = 0,
+             StringRef Annotations = StringRef())
+      : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops, None, Annotations),
+        Line(Line), AlignInBits(AlignInBits) {}
   ~DIVariable() = default;
 
 public:
@@ -2914,8 +2932,9 @@
 
   DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line,
                    bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits,
-                   ArrayRef<Metadata *> Ops)
-      : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits),
+                   MDString *Annotations, ArrayRef<Metadata *> Ops)
+      : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits,
+                   Annotations ? Annotations->getString() : StringRef()),
         IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
   ~DIGlobalVariable() = default;
 
@@ -2924,11 +2943,13 @@
           StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type,
           bool IsLocalToUnit, bool IsDefinition,
           DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams,
-          uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) {
+          uint32_t AlignInBits, StringRef Annotations, StorageType Storage,
+          bool ShouldCreate = true) {
     return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
                    getCanonicalMDString(Context, LinkageName), File, Line, Type,
                    IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration,
-                   cast_or_null<Metadata>(TemplateParams), AlignInBits, Storage,
+                   cast_or_null<Metadata>(TemplateParams), AlignInBits,
+                   getCanonicalMDString(Context, Annotations), Storage,
                    ShouldCreate);
   }
   static DIGlobalVariable *
@@ -2936,13 +2957,15 @@
           MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type,
           bool IsLocalToUnit, bool IsDefinition,
           Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,
-          uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true);
+          uint32_t AlignInBits, MDString *Annotations, StorageType Storage,
+          bool ShouldCreate = true);
 
   TempDIGlobalVariable cloneImpl() const {
     return getTemporary(getContext(), getScope(), getName(), getLinkageName(),
                         getFile(), getLine(), getType(), isLocalToUnit(),
                         isDefinition(), getStaticDataMemberDeclaration(),
-                        getTemplateParams(), getAlignInBits());
+                        getTemplateParams(), getAlignInBits(),
+                        getAnnotations());
   }
 
 public:
@@ -2951,19 +2974,21 @@
                      DIFile *File, unsigned Line, DIType *Type,
                      bool IsLocalToUnit, bool IsDefinition,
                      DIDerivedType *StaticDataMemberDeclaration,
-                     MDTuple *TemplateParams, uint32_t AlignInBits),
+                     MDTuple *TemplateParams, uint32_t AlignInBits,
+                     StringRef Annotations),
                     (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
                      IsDefinition, StaticDataMemberDeclaration, TemplateParams,
-                     AlignInBits))
+                     AlignInBits, Annotations))
   DEFINE_MDNODE_GET(DIGlobalVariable,
                     (Metadata * Scope, MDString *Name, MDString *LinkageName,
                      Metadata *File, unsigned Line, Metadata *Type,
                      bool IsLocalToUnit, bool IsDefinition,
                      Metadata *StaticDataMemberDeclaration,
-                     Metadata *TemplateParams, uint32_t AlignInBits),
+                     Metadata *TemplateParams, uint32_t AlignInBits,
+                     MDString *Annotations),
                     (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
                      IsDefinition, StaticDataMemberDeclaration, TemplateParams,
-                     AlignInBits))
+                     AlignInBits, Annotations))
 
   TempDIGlobalVariable clone() const { return cloneImpl(); }
 
@@ -2979,6 +3004,7 @@
   Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); }
   Metadata *getRawTemplateParams() const { return getOperand(7); }
   MDTuple *getTemplateParams() const { return getOperandAs<MDTuple>(7); }
+  MDString *getRawAnnotations() const { return getOperandAs<MDString>(8); }
 
   static bool classof(const Metadata *MD) {
     return MD->getMetadataID() == DIGlobalVariableKind;
Index: llvm/include/llvm/BinaryFormat/Dwarf.def
===================================================================
--- llvm/include/llvm/BinaryFormat/Dwarf.def
+++ llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -595,6 +595,7 @@
 HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM)
 // The missing numbers here are reserved for ptrauth support.
 HANDLE_DW_AT(0x3e07, LLVM_apinotes, 0, APPLE)
+HANDLE_DW_AT(0x3e08, LLVM_annotations, 0, LLVM)
 
 // Apple extensions.
 
Index: clang/test/CodeGen/annotation-2.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/annotation-2.c
@@ -0,0 +1,14 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang %s -g -target x86_64 -gannotations -S -emit-llvm -o - | FileCheck %s
+
+struct t {
+  int a __attribute__((annotate("gfield")));
+} __attribute__((annotate("gstruct")));
+int test(struct t *arg) {
+  return arg->a;
+}
+
+// CHECK:      distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t"
+// CHECK-SAME: annotations: "gstruct"
+// CHECK:      !DIDerivedType(tag: DW_TAG_member, name: "a"
+// CHECK-SAME: annotations: "gfield"
Index: clang/test/CodeGen/annotation-1.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/annotation-1.c
@@ -0,0 +1,30 @@
+// REQUIRES: x86-registered-target
+// RUN: %clang %s -g -target x86_64 -gannotations -S -emit-llvm -o - | FileCheck %s
+
+static volatile int s1 __attribute__((annotate("static1")));
+int g1 __attribute__((annotate("global1"))) __attribute__((annotate("global2")));
+int test1() {
+  return s1 + g1;
+}
+
+// CHECK:      distinct !DIGlobalVariable(name: "s1"
+// CHECK-SAME: annotations: "static1"
+// CHECK:      distinct !DIGlobalVariable(name: "g1"
+// CHECK-SAME: annotations: "global1,global2"
+
+static int __attribute__((annotate("sfunc"))) __attribute__((noinline))
+func1(int a, int b) {
+  return a + b;
+}
+
+int __attribute__((annotate("gfunc")))
+func2(int a __attribute__((annotate("param"))), int b) {
+  return func1(a, b);
+}
+
+// CHECK:      distinct !DISubprogram(name: "func2"
+// CHECK-SAME: annotations: "gfunc"
+// CHECK:      !DILocalVariable(name: "a"
+// CHECK-SAME: annotations: "param"
+// CHECK:      distinct !DISubprogram(name: "func1"
+// CHECK-SAME: annotations: "sfunc"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -3968,6 +3968,11 @@
     }
   }
 
+  if (const Arg *A = Args.getLastArg(options::OPT_gannotations)) {
+    if (checkDebugInfoOption(A, Args, D, TC))
+      CmdArgs.push_back("-gannotations");
+  }
+
   unsigned RequestedDWARFVersion = 0; // DWARF version requested by the user
   unsigned EffectiveDWARFVersion = 0; // DWARF version TC can generate. It may
                                       // be lower than what the user wanted.
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1516,6 +1516,11 @@
     FieldType =
         createFieldType(name, type, field->getLocation(), field->getAccess(),
                         OffsetInBits, Align, tunit, RecordTy, RD);
+    if (CGM.getCodeGenOpts().EmitAnnotations &&
+        field->hasAttr<AnnotateAttr>()) {
+      for (const auto *I : field->specific_attrs<AnnotateAttr>())
+        FieldType->addAnnotation(I->getAnnotation());
+    }
   }
 
   elements.push_back(FieldType);
@@ -3487,6 +3492,11 @@
     break;
   }
 
+  if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr<AnnotateAttr>()) {
+    for (const auto *I : D->specific_attrs<AnnotateAttr>())
+      RealDecl->addAnnotation(I->getAnnotation());
+  }
+
   RegionMap[Ty->getDecl()].reset(RealDecl);
   TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl);
 
@@ -3977,6 +3987,11 @@
   if (HasDecl && isa<FunctionDecl>(D))
     DeclCache[D->getCanonicalDecl()].reset(SP);
 
+  if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr<AnnotateAttr>()) {
+    for (const auto *I : D->specific_attrs<AnnotateAttr>())
+      SP->addAnnotation(I->getAnnotation());
+  }
+
   // Push the function onto the lexical block stack.
   LexicalBlockStack.emplace_back(SP);
 
@@ -4375,6 +4390,10 @@
   if (ArgNo) {
     D = DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, Ty,
                                          CGM.getLangOpts().Optimize, Flags);
+    if (CGM.getCodeGenOpts().EmitAnnotations && VD->hasAttr<AnnotateAttr>()) {
+      for (const auto *I : VD->specific_attrs<AnnotateAttr>())
+        D->addAnnotation(I->getAnnotation());
+    }
   } else {
     // For normal local variable, we will try to find out whether 'VD' is the
     // copy parameter of coroutine.
@@ -4833,6 +4852,12 @@
         getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters,
         Align);
     Var->addDebugInfo(GVE);
+
+    if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr<AnnotateAttr>()) {
+      auto DIVar = GVE->getVariable();
+      for (const auto *I : D->specific_attrs<AnnotateAttr>())
+        DIVar->addAnnotation(I->getAnnotation());
+    }
   }
   DeclCache[D->getCanonicalDecl()].reset(GVE);
 }
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2898,6 +2898,10 @@
 def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>,
     Flags<[NoXarchOption]>,
     HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">;
+def gannotations : Flag<["-"], "gannotations">, Group<g_flags_Group>,
+    MarshallingInfoFlag<CodeGenOpts<"EmitAnnotations">>,
+    Flags<[CC1Option]>,
+    HelpText<"Emit annotations in DWARF debug sections">;
 def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">;
 def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option,
     FlangOption]>, HelpText<"Display available options">,
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -432,6 +432,9 @@
 /// propagate signaling NaN inputs per IEEE 754-2008 (AMDGPU Only)
 CODEGENOPT(EmitIEEENaNCompliantInsts, 1, 1)
 
+/// Whether to emit Annotations in dwarf sections
+CODEGENOPT(EmitAnnotations, 1, 0)
+
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
 #undef VALUE_CODEGENOPT
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to