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" <g...@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 5e86668f7a4224c5fba6f00bd2ed1fe027215c90 Mon Sep 17 00:00:00 2001 From: Billy Moses <g...@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 | 10 +++++----- clang/lib/CodeGen/CodeGenFunction.cpp | 11 +++++------ clang/lib/Sema/SemaDeclAttr.cpp | 23 +++++++++++++++++++++++ clang/test/CodeGen/attr-llvmfn.c | 13 +++++++------ clang/test/Sema/attr-llvmfn.c | 10 ++++++++++ 6 files changed, 51 insertions(+), 18 deletions(-) create mode 100644 clang/test/Sema/attr-llvmfn.c 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..4f95c951720f8f 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2466,20 +2466,20 @@ 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..3504a684a8afc3 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -832,21 +832,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, SanOpts.Mask &= ~SanitizerKind::Null; if (D) { - for (auto Attr : - template TargetDecl->specific_attrs<attr::LLVMFuncAttr>()) { + for (auto Attr : 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..7ced0292c9f68b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1689,6 +1689,26 @@ 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) { + if (!isFunctionOrMethod(D)) { + S.Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type) + << AL << AL.isRegularKeywordAttribute() << ExpectedFunctionOrMethod; + return; + } + + 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 +9379,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" diff --git a/clang/test/Sema/attr-llvmfn.c b/clang/test/Sema/attr-llvmfn.c new file mode 100644 index 00000000000000..e3c27d98d49181 --- /dev/null +++ b/clang/test/Sema/attr-llvmfn.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -verify -fsyntax-only + +int a __attribute__((llvm_fn_attr("k", "v"))); // expected-warning {{'llvm_fn_attr' attribute only applies to functions and methods}} + +void t1(void) __attribute__((llvm_fn_attr("k", "v"))); + +void t2(void) __attribute__((llvm_fn_attr(2, "3"))); // expected-error {{expected string literal as argument of 'llvm_fn_attr' attribute}} + +void t3(void) __attribute__((llvm_fn_attr())); // expected-error {{'llvm_fn_attr' attribute requires exactly 2 arguments}} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits