[clang] [Clang][HTO] Add clang attribute for propagating llvm-level information (PR #83059)

William Moses via cfe-commits cfe-commits at lists.llvm.org
Mon Feb 26 16:56:49 PST 2024


https://github.com/wsmoses updated https://github.com/llvm/llvm-project/pull/83059

>From c01b559836ca62648c5f95a6441888514347a1ea Mon Sep 17 00:00:00 2001
From: "William S. Moses" <gh at wsmoses.com>
Date: Mon, 26 Feb 2024 16:17:55 -0500
Subject: [PATCH 1/2] [Clang][HTO] Add clang attribute for propagating
 llvm-level information

---
 clang/include/clang/Basic/Attr.td     |  7 +++++++
 clang/include/clang/Basic/AttrDocs.td | 13 +++++++++++++
 clang/lib/CodeGen/CGCall.cpp          | 16 ++++++++++++++++
 clang/lib/CodeGen/CodeGenFunction.cpp | 19 +++++++++++++++++++
 clang/test/CodeGen/attr-llvmfn.c      | 14 ++++++++++++++
 5 files changed, 69 insertions(+)
 create mode 100644 clang/test/CodeGen/attr-llvmfn.c

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index fa191c7378dba4..044f4fada3590f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2211,6 +2211,13 @@ def AllocAlign : InheritableAttr {
   let Documentation = [AllocAlignDocs];
 }
 
+def LLVMFuncAttr : InheritableAttr {
+  let Spellings = [Clang<"llvm_fn_attr">];
+  let Args = [StringArgument<"LLVMAttrName">, StringArgument<"LLVMAttrValue">];
+  let Documentation = [LLVMFuncAttrDocs];
+  let InheritEvenIfAlreadyPresent = 1;
+}
+
 def NoReturn : InheritableAttr {
   let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
   // FIXME: Does GCC allow this on the function instead?
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index b96fbddd51154c..3f93bb6d6fc648 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -781,6 +781,19 @@ pointer is not sufficiently aligned.
   }];
 }
 
+def LLVMFuncAttrDocs : Documentation {
+  let Category = DocCatFunction;
+  let Content = [{
+Use ``__attribute__((llvm_fn_attr(attr_name, attr_value)))`` on a function to specify an LLVM function attribute that will be added to this function. 
+
+Note that uses of this attribute are highly compiler specific as the meaning and availability of LLVM attributes may change between compiler versions.
+
+This attribute is only intended for advanced users who need to specify specific information only available in LLVM attributes. Use of attributes which are not tied to a specific version of Clang (e.g. pure) should be preferred when available.
+
+The first arugment is a string representing the name of the LLVM attribute to be applied and the second arugment is a string representing its value.
+  }];
+}
+
 def EnableIfDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d05cf1c6e1814e..4725dce607eee9 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2465,6 +2465,22 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
 
     if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
       FuncAttrs.addAttribute("aarch64_pstate_sm_body");
+
+    for (auto Attr : TargetDecl->specific_attrs<attr::LLVMFuncAttr>()) {
+      auto name = Attr->getLLVMAttrName();
+      auto value = Attr->getLLVMAttrValue();
+
+      Attribute Attr;
+      auto EnumAttr = llvm::Attribute::getAttrKindFromName(name);
+      if (EnumAttr == llvm::Attribute::None)
+        Attr = llvm::Attribute::get(getLLVMContext(), name, value);
+      else {
+        assert(value.size() == 0 &&
+               "enum attribute does not support value yet");
+        Attr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
+      }
+      FuncAttrs.addAttribute(Attr);
+    }
   }
 
   // Attach "no-builtins" attributes to:
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 1ad905078d349c..5d0edd4bbf83c7 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -831,6 +831,25 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
         FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass)
       SanOpts.Mask &= ~SanitizerKind::Null;
 
+  if (D) {
+    for (auto Attr :
+         template TargetDecl->specific_attrs<attr::LLVMFuncAttr>()) {
+      auto name = Attr->getLLVMAttrName();
+      auto value = Attr->getLLVMAttrValue();
+
+      Attribute Attr;
+      auto EnumAttr = llvm::Attribute::getAttrKindFromName(name);
+      if (EnumAttr == llvm::Attribute::None)
+        Attr = llvm::Attribute::get(getLLVMContext(), name, value);
+      else {
+        assert(value.size() == 0 &&
+               "enum attribute does not support value yet");
+        Attr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
+      }
+      Fn->addFnAttr(Attr);
+    }
+  }
+
   // Apply xray attributes to the function (as a string, for now)
   bool AlwaysXRayAttr = false;
   if (const auto *XRayAttr = D ? D->getAttr<XRayInstrumentAttr>() : nullptr) {
diff --git a/clang/test/CodeGen/attr-llvmfn.c b/clang/test/CodeGen/attr-llvmfn.c
new file mode 100644
index 00000000000000..72f14a726f795e
--- /dev/null
+++ b/clang/test/CodeGen/attr-llvmfn.c
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - | FileCheck %s
+
+void t1() __attribute__((llvm_fn_attr("custom_attr", "custom_value"), llvm_fn_attr("second_attr", "second_value")));
+
+void t1()
+{
+}
+
+void t2();
+
+void t3() {
+	t2() ____attribute__((llvm_fn_attr("custom_attr", "custom_value"), llvm_fn_attr("second_attr", "second_value")));
+}
+

>From cb87c493905b383b19be82fbf87cef607e659cd6 Mon Sep 17 00:00:00 2001
From: Billy Moses <gh at wsmoses.com>
Date: Mon, 26 Feb 2024 22:39:15 +0000
Subject: [PATCH 2/2] fixup

---
 clang/include/clang/Basic/Attr.td     |  2 +-
 clang/lib/CodeGen/CGCall.cpp          | 12 ++++++------
 clang/lib/CodeGen/CodeGenFunction.cpp | 10 +++++-----
 clang/lib/Sema/SemaDeclAttr.cpp       | 17 +++++++++++++++++
 clang/test/CodeGen/attr-llvmfn.c      | 13 +++++++------
 5 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 044f4fada3590f..5b792db5c7435f 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2211,7 +2211,7 @@ def AllocAlign : InheritableAttr {
   let Documentation = [AllocAlignDocs];
 }
 
-def LLVMFuncAttr : InheritableAttr {
+def LLVMFuncAttr : DeclOrStmtAttr {
   let Spellings = [Clang<"llvm_fn_attr">];
   let Args = [StringArgument<"LLVMAttrName">, StringArgument<"LLVMAttrValue">];
   let Documentation = [LLVMFuncAttrDocs];
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 4725dce607eee9..dcf4aa9ac76708 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -2465,21 +2465,21 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
 
     if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
       FuncAttrs.addAttribute("aarch64_pstate_sm_body");
-
-    for (auto Attr : TargetDecl->specific_attrs<attr::LLVMFuncAttr>()) {
+    
+    for (auto Attr : TargetDecl->specific_attrs<LLVMFuncAttrAttr>()) {
       auto name = Attr->getLLVMAttrName();
       auto value = Attr->getLLVMAttrValue();
 
-      Attribute Attr;
+      llvm::Attribute LLAttr;
       auto EnumAttr = llvm::Attribute::getAttrKindFromName(name);
       if (EnumAttr == llvm::Attribute::None)
-        Attr = llvm::Attribute::get(getLLVMContext(), name, value);
+        LLAttr = llvm::Attribute::get(getLLVMContext(), name, value);
       else {
         assert(value.size() == 0 &&
                "enum attribute does not support value yet");
-        Attr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
+        LLAttr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
       }
-      FuncAttrs.addAttribute(Attr);
+      FuncAttrs.addAttribute(LLAttr);
     }
   }
 
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 5d0edd4bbf83c7..92abff5915abd0 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -833,20 +833,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
 
   if (D) {
     for (auto Attr :
-         template TargetDecl->specific_attrs<attr::LLVMFuncAttr>()) {
+         D->template specific_attrs<LLVMFuncAttrAttr>()) {
       auto name = Attr->getLLVMAttrName();
       auto value = Attr->getLLVMAttrValue();
 
-      Attribute Attr;
+      llvm::Attribute LLAttr;
       auto EnumAttr = llvm::Attribute::getAttrKindFromName(name);
       if (EnumAttr == llvm::Attribute::None)
-        Attr = llvm::Attribute::get(getLLVMContext(), name, value);
+        LLAttr = llvm::Attribute::get(getLLVMContext(), name, value);
       else {
         assert(value.size() == 0 &&
                "enum attribute does not support value yet");
-        Attr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
+        LLAttr = llvm::Attribute::get(getLLVMContext(), EnumAttr);
       }
-      Fn->addFnAttr(Attr);
+      Fn->addFnAttr(LLAttr);
     }
   }
 
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index c1c28a73fd79ce..06a1b4317ac0c3 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -1689,6 +1689,20 @@ static void handleAllocAlignAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   S.AddAllocAlignAttr(D, AL, AL.getArgAsExpr(0));
 }
 
+static void handleLLVMFuncAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  StringRef Name;
+  SourceLocation NameStrLoc;
+  if (!S.checkStringLiteralArgumentAttr(AL, 0, Name, &NameStrLoc))
+    return;
+  
+  StringRef Value;
+  SourceLocation ValueStrLoc;
+  if (!S.checkStringLiteralArgumentAttr(AL, 1, Value, &ValueStrLoc))
+    return;
+
+  D->addAttr(::new (S.Context) LLVMFuncAttrAttr(S.Context, AL, Name, Value));
+}
+
 void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E,
                                 Expr *OE) {
   QualType ResultType = getFunctionOrMethodResultType(D);
@@ -9359,6 +9373,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   case ParsedAttr::AT_AllocAlign:
     handleAllocAlignAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_LLVMFuncAttr:
+    handleLLVMFuncAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_Ownership:
     handleOwnershipAttr(S, D, AL);
     break;
diff --git a/clang/test/CodeGen/attr-llvmfn.c b/clang/test/CodeGen/attr-llvmfn.c
index 72f14a726f795e..14cca30fdfaf85 100644
--- a/clang/test/CodeGen/attr-llvmfn.c
+++ b/clang/test/CodeGen/attr-llvmfn.c
@@ -1,14 +1,15 @@
-// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
 
 void t1() __attribute__((llvm_fn_attr("custom_attr", "custom_value"), llvm_fn_attr("second_attr", "second_value")));
 
+__attribute__((llvm_fn_attr("third_attr", "third_value")))
 void t1()
 {
 }
 
-void t2();
-
-void t3() {
-	t2() ____attribute__((llvm_fn_attr("custom_attr", "custom_value"), llvm_fn_attr("second_attr", "second_value")));
-}
+// CHECK: define dso_local void @t1() #[[t1attrs:[0-9]+]]
 
+// CHECK: #[[t1attrs]]
+// CHECK-SAME: "custom_attr"="custom_value"
+// CHECK-SAME: "second_attr"="second_value"
+// CHECK-SAME: "third_attr"="third_value"



More information about the cfe-commits mailing list