eddyz87 created this revision.
Herald added a subscriber: hiraditya.
Herald added a project: All.
eddyz87 retitled this revision from "This series of patches adds support for 
"btf_decl_tag" annotations
for arguments of extern functions. Patch descriptions follow.

[BPF] Triple::isBPF() utility method" to "[BPF] Support for "btf_decl_tag" 
annotations for arguments of extern functions".
eddyz87 edited the summary of this revision.
eddyz87 published this revision for review.
eddyz87 added a reviewer: yonghong-song.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

This adds support for "btf_decl_tag" annotations for arguments of extern 
functions. The changes are split into several commits:

- `Triple::isBPF() utility method` -- adds a simple utility method for 
llvm::Triple class;
- `preserve btf_decl_tag for parameters of extern functions` -- modifies CLang 
frontend to generate DILocalVariable entries with attached "btf_dec_tag" 
annotations for parameters of extern functions;
- `generate btf_decl_tag records for params of extern functions` -- modifies 
BPF backend to process "btf_decl_tag" annotations for parameters of extern 
functions.

Below are descriptions for the last two commits:

Preserve btf_decl_tag for parameters of extern functions
--------------------------------------------------------

Generate DILocalVariable entries for parameters of extern functions, the 
"annotations" field of DILocalVariable is used to link "btf_decl_tag" 
annotation with the parameter.

Do this only for BPF backend as there are no other users for this information. 
Final DWARF is valid as "Appendix A" is very much lax in
what is allowed as attributes for "DW_TAG_formal_parameter":

> DWARF does not in general require that a given debugging information entry 
> contain a particular attribute or set of attributes. Instead, a DWARF 
> producer is free to generate any, all, or none of the attributes ... other 
> attributes ... may also appear in a given  debugging information entry.

DWARF Debugging Information Format Version 5,
Appendix A: Attributes by Tag Value (Informative)
Page 251, Line 3.

Generate btf_decl_tag records for params of extern functions
------------------------------------------------------------

After frontend changes in the following commit: "BPF: preserve btf_decl_tag for 
parameters of extern functions" same mechanics could be used to get the list of 
function parameters and associated btf_decl_tag entries for both extern and 
non-extern functions.

This commit extracts this mechanics as a separate auxiliary function 
BTFDebug::processDISubprogram(). The function is called for both
extern and non-extern functions in order to generated corresponding 
BTF_DECL_TAG records.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D140929

Files:
  clang/lib/CodeGen/CGDebugInfo.cpp
  clang/test/CodeGen/bpf-decl-tag-extern-func-args.c
  llvm/include/llvm/TargetParser/Triple.h
  llvm/lib/Target/BPF/BTFDebug.cpp
  llvm/lib/Target/BPF/BTFDebug.h
  llvm/test/CodeGen/BPF/BTF/tag-extern-func.ll

Index: llvm/test/CodeGen/BPF/BTF/tag-extern-func.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/BPF/BTF/tag-extern-func.ll
@@ -0,0 +1,96 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+
+; Source code:
+;   #define __tag(x) __attribute__((btf_decl_tag(x)))
+;
+;   extern void foo(int x __tag("x_tag"), int y __tag("y_tag")) __tag("foo_tag");
+;
+;   void root(void) {
+;     foo(0, 0);
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+
+; Function Attrs: nounwind
+define dso_local void @root() local_unnamed_addr #0 !dbg !7 {
+entry:
+  tail call void @foo(i32 noundef 0, i32 noundef 0) #2, !dbg !12
+  ret void, !dbg !13
+}
+
+declare !dbg !14 dso_local void @foo(i32 noundef, i32 noundef) local_unnamed_addr #1
+
+attributes #0 = { nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 16.0.0 (https://github.com/llvm/llvm-project.git 603e8490729e477680f0bc8284e136ceeb66e7f4)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "/home/eddy/work/tasks/llvm-decl-tags/test.c", directory: "/home/eddy/work/tasks/llvm-decl-tags", checksumkind: CSK_MD5, checksum: "0a768161d04f21ca6734ef31f6258656")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 7, !"frame-pointer", i32 2}
+!6 = !{!"clang version 16.0.0 (https://github.com/llvm/llvm-project.git 603e8490729e477680f0bc8284e136ceeb66e7f4)"}
+!7 = distinct !DISubprogram(name: "root", scope: !8, file: !8, line: 5, type: !9, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!8 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tasks/llvm-decl-tags", checksumkind: CSK_MD5, checksum: "0a768161d04f21ca6734ef31f6258656")
+!9 = !DISubroutineType(types: !10)
+!10 = !{null}
+!11 = !{}
+!12 = !DILocation(line: 6, column: 3, scope: !7)
+!13 = !DILocation(line: 7, column: 1, scope: !7)
+!14 = !DISubprogram(name: "foo", scope: !8, file: !8, line: 3, type: !15, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !18, annotations: !25)
+!15 = !DISubroutineType(types: !16)
+!16 = !{null, !17, !17}
+!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!18 = !{!19, !22}
+!19 = !DILocalVariable(name: "x", arg: 1, scope: !14, file: !8, line: 3, type: !17, annotations: !20)
+!20 = !{!21}
+!21 = !{!"btf_decl_tag", !"x_tag"}
+!22 = !DILocalVariable(name: "y", arg: 2, scope: !14, file: !8, line: 3, type: !17, annotations: !23)
+!23 = !{!24}
+!24 = !{!"btf_decl_tag", !"y_tag"}
+!25 = !{!26}
+!26 = !{!"btf_decl_tag", !"foo_tag"}
+
+; CHECK: 	.long	0                               # BTF_KIND_FUNC_PROTO(id = 1)
+; CHECK-NEXT: 	.long	218103808                       # 0xd000000
+; CHECK-NEXT: 	.long	0
+; CHECK-NEXT: 	.long	1                               # BTF_KIND_FUNC(id = 2)
+; CHECK-NEXT: 	.long	201326593                       # 0xc000001
+; CHECK-NEXT: 	.long	1
+; CHECK-NEXT: 	.long	0                               # BTF_KIND_FUNC_PROTO(id = 3)
+; CHECK-NEXT: 	.long	218103810                       # 0xd000002
+; CHECK-NEXT: 	.long	0
+; CHECK-NEXT: 	.long	0
+; CHECK-NEXT: 	.long	4
+; CHECK-NEXT: 	.long	0
+; CHECK-NEXT: 	.long	4
+; CHECK-NEXT: 	.long	71                              # BTF_KIND_INT(id = 4)
+; CHECK-NEXT: 	.long	16777216                        # 0x1000000
+; CHECK-NEXT: 	.long	4
+; CHECK-NEXT: 	.long	16777248                        # 0x1000020
+; CHECK-NEXT: 	.long	75                              # BTF_KIND_FUNC(id = 5)
+; CHECK-NEXT: 	.long	201326594                       # 0xc000002
+; CHECK-NEXT: 	.long	3
+; CHECK-NEXT: 	.long	79                              # BTF_KIND_DECL_TAG(id = 6)
+; CHECK-NEXT: 	.long	285212672                       # 0x11000000
+; CHECK-NEXT: 	.long	5
+; CHECK-NEXT: 	.long	0
+; CHECK-NEXT: 	.long	85                              # BTF_KIND_DECL_TAG(id = 7)
+; CHECK-NEXT: 	.long	285212672                       # 0x11000000
+; CHECK-NEXT: 	.long	5
+; CHECK-NEXT: 	.long	1
+; CHECK-NEXT: 	.long	91                              # BTF_KIND_DECL_TAG(id = 8)
+; CHECK-NEXT: 	.long	285212672                       # 0x11000000
+; CHECK-NEXT: 	.long	5
+; CHECK-NEXT: 	.long	4294967295
+
+; CHECK: 	.ascii	"x_tag"                         # string offset=79
+; CHECK: 	.ascii	"y_tag"                         # string offset=85
+; CHECK: 	.ascii	"foo_tag"                       # string offset=91
Index: llvm/lib/Target/BPF/BTFDebug.h
===================================================================
--- llvm/lib/Target/BPF/BTFDebug.h
+++ llvm/lib/Target/BPF/BTFDebug.h
@@ -356,6 +356,11 @@
   void processDeclAnnotations(DINodeArray Annotations, uint32_t BaseTypeId,
                               int ComponentId);
 
+  /// Generate types for DISubprogram and it's arguments.
+  uint32_t processDISubprogram(const DISubprogram *SP,
+                               uint32_t ProtoTypeId,
+                               uint8_t Scope);
+
   /// Generate BTF type_tag's. If BaseTypeId is nonnegative, the last
   /// BTF type_tag in the chain points to BaseTypeId. Otherwise, it points to
   /// the base type of DTy. Return the type id of the first BTF type_tag
Index: llvm/lib/Target/BPF/BTFDebug.cpp
===================================================================
--- llvm/lib/Target/BPF/BTFDebug.cpp
+++ llvm/lib/Target/BPF/BTFDebug.cpp
@@ -596,6 +596,26 @@
   }
 }
 
+uint32_t BTFDebug::processDISubprogram(const DISubprogram *SP,
+                                       uint32_t ProtoTypeId,
+                                       uint8_t Scope) {
+  auto FuncTypeEntry =
+    std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
+  uint32_t FuncId = addType(std::move(FuncTypeEntry));
+
+  // Process argument annotations.
+  for (const DINode *DN : SP->getRetainedNodes()) {
+    if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
+      uint32_t Arg = DV->getArg();
+      if (Arg)
+        processDeclAnnotations(DV->getAnnotations(), FuncId, Arg - 1);
+    }
+  }
+  processDeclAnnotations(SP->getAnnotations(), FuncId, -1);
+
+  return FuncId;
+}
+
 /// Generate btf_type_tag chains.
 int BTFDebug::genBTFTypeTags(const DIDerivedType *DTy, int BaseTypeId) {
   SmallVector<const MDString *, 4> MDStrs;
@@ -1177,20 +1197,7 @@
 
   // Construct subprogram func type
   uint8_t Scope = SP->isLocalToUnit() ? BTF::FUNC_STATIC : BTF::FUNC_GLOBAL;
-  auto FuncTypeEntry =
-      std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
-  uint32_t FuncTypeId = addType(std::move(FuncTypeEntry));
-
-  // Process argument annotations.
-  for (const DINode *DN : SP->getRetainedNodes()) {
-    if (const auto *DV = dyn_cast<DILocalVariable>(DN)) {
-      uint32_t Arg = DV->getArg();
-      if (Arg)
-        processDeclAnnotations(DV->getAnnotations(), FuncTypeId, Arg - 1);
-    }
-  }
-
-  processDeclAnnotations(SP->getAnnotations(), FuncTypeId, -1);
+  uint32_t FuncTypeId = processDISubprogram(SP, ProtoTypeId, Scope);
 
   for (const auto &TypeEntry : TypeEntries)
     TypeEntry->completeType(*this);
@@ -1535,13 +1542,7 @@
   uint32_t ProtoTypeId;
   const std::unordered_map<uint32_t, StringRef> FuncArgNames;
   visitSubroutineType(SP->getType(), false, FuncArgNames, ProtoTypeId);
-
-  uint8_t Scope = BTF::FUNC_EXTERN;
-  auto FuncTypeEntry =
-      std::make_unique<BTFTypeFunc>(SP->getName(), ProtoTypeId, Scope);
-  uint32_t FuncId = addType(std::move(FuncTypeEntry));
-
-  processDeclAnnotations(SP->getAnnotations(), FuncId, -1);
+  uint32_t FuncId = processDISubprogram(SP, ProtoTypeId, BTF::FUNC_EXTERN);
 
   if (F->hasSection()) {
     StringRef SecName = F->getSection();
Index: llvm/include/llvm/TargetParser/Triple.h
===================================================================
--- llvm/include/llvm/TargetParser/Triple.h
+++ llvm/include/llvm/TargetParser/Triple.h
@@ -939,6 +939,11 @@
     return Env == Triple::GNUX32 || Env == Triple::MuslX32;
   }
 
+  /// Tests whether the target is eBPF.
+  bool isBPF() const {
+    return getArch() == Triple::bpfel || getArch() == Triple::bpfeb;
+  }
+
   /// Tests whether the target supports comdat
   bool supportsCOMDAT() const {
     return !(isOSBinFormatMachO() || isOSBinFormatXCOFF() ||
Index: clang/test/CodeGen/bpf-decl-tag-extern-func-args.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/bpf-decl-tag-extern-func-args.c
@@ -0,0 +1,37 @@
+// RUN: %clang -target bpf -S -emit-llvm -g -O2 -o - %s  | FileCheck %s
+
+#define __decl_tag(x) __attribute__((btf_decl_tag(x)))
+
+extern void foo(int aa __decl_tag("aa_tag"), long bb __decl_tag("bb_tag"));
+extern void bar(char cc __decl_tag("cc_tag"));
+extern void buz(int __decl_tag("buz_arg_tag"));
+
+void root(void) {
+  foo(0, 1);
+  bar(0);
+  buz(0);
+}
+// CHECK: [[foo:![0-9]+]] = !DISubprogram(name: "foo", {{.*}}, retainedNodes: [[foo_nodes:![0-9]+]])
+// CHECK: [[foo_nodes]] = !{[[aa:![0-9]+]], [[bb:![0-9]+]]}
+
+// CHECK: [[aa]] = !DILocalVariable(name: "aa", arg: 1, scope: [[foo]], {{.*}}, annotations: [[aa_annot:![0-9]+]])
+// CHECK: [[aa_annot]] = !{[[aa_tag:![0-9]+]]}
+// CHECK: [[aa_tag]] = !{!"btf_decl_tag", !"aa_tag"}
+
+// CHECK: [[bb]] = !DILocalVariable(name: "bb", arg: 2, scope: [[foo]], {{.*}}, annotations: [[bb_annot:![0-9]+]])
+// CHECK: [[bb_annot]] = !{[[bb_tag:![0-9]+]]}
+// CHECK: [[bb_tag]] = !{!"btf_decl_tag", !"bb_tag"}
+
+// CHECK: [[bar:![0-9]+]] = !DISubprogram(name: "bar", {{.*}}, retainedNodes: [[bar_nodes:![0-9]+]])
+// CHECK: [[bar_nodes]] = !{[[cc:![0-9]+]]}
+
+// CHECK: [[cc]] = !DILocalVariable(name: "cc", arg: 1, scope: [[bar]], {{.*}}, annotations: [[cc_annot:![0-9]+]])
+// CHECK: [[cc_annot]] = !{[[cc_tag:![0-9]+]]}
+// CHECK: [[cc_tag]] = !{!"btf_decl_tag", !"cc_tag"}
+
+// CHECK: [[buz:![0-9]+]] = !DISubprogram(name: "buz", {{.*}}, retainedNodes: [[buz_nodes:![0-9]+]])
+// CHECK: [[buz_nodes]] = !{[[buz_arg:![0-9]+]]}
+
+// CHECK: [[buz_arg]] = !DILocalVariable(arg: 1, scope: [[buz]], {{.*}}, annotations: [[buz_arg_annot:![0-9]+]])
+// CHECK: [[buz_arg_annot]] = !{[[buz_arg_tag:![0-9]+]]}
+// CHECK: [[buz_arg_tag]] = !{!"btf_decl_tag", !"buz_arg_tag"}
Index: clang/lib/CodeGen/CGDebugInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGDebugInfo.cpp
+++ clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4206,11 +4206,29 @@
     SPFlags |= llvm::DISubprogram::SPFlagOptimized;
 
   llvm::DINodeArray Annotations = CollectBTFDeclTagAnnotations(D);
+  llvm::DISubroutineType *STy = getOrCreateFunctionType(D, FnType, Unit);
   llvm::DISubprogram *SP = DBuilder.createFunction(
       FDContext, Name, LinkageName, Unit, LineNo,
-      getOrCreateFunctionType(D, FnType, Unit), ScopeLine, Flags, SPFlags,
+      STy, ScopeLine, Flags, SPFlags,
       TParamsArray.get(), getFunctionDeclaration(D), nullptr, Annotations);
 
+  // Preserve btf_decl_tag attributes for parameters of extern functions
+  // for BPF target. The parameters created in this loop are attached as
+  // DISubprogram's retainedNodes in the subsequent finalizeSubprogram call.
+  if (IsDeclForCallSite && CGM.getTarget().getTriple().isBPF()) {
+    if (auto *FD = dyn_cast<FunctionDecl>(D)) {
+      llvm::DITypeRefArray ParamTypes = STy->getTypeArray();
+      unsigned ArgNo = 1;
+      for (ParmVarDecl *PD : FD->parameters()) {
+        llvm::DINodeArray ParamAnnotations = CollectBTFDeclTagAnnotations(PD);
+        DBuilder.createParameterVariable
+          (SP, PD->getName(), ArgNo, Unit, LineNo, ParamTypes[ArgNo], true,
+           llvm::DINode::FlagZero, ParamAnnotations);
+        ++ArgNo;
+      }
+    }
+  }
+
   if (IsDeclForCallSite)
     Fn->setSubprogram(SP);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to