From 14e72c19daefd09b6cfe7e99865b89afa8c5a4d8 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 25 Jun 2024 19:16:01 -0700 Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?= =?UTF-8?q?itial=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created using spr 1.3.6-beta.1 --- clang/lib/CodeGen/CodeGenAction.cpp | 6 ++++++ clang/test/CodeGen/coverage-target-attr.c | 17 +++++++++++++++++ llvm/include/llvm/IR/Function.h | 6 +++++- llvm/include/llvm/IR/LLVMContext.h | 20 ++++++++++++++++++++ llvm/lib/IR/Function.cpp | 6 ++++++ llvm/lib/IR/LLVMContext.cpp | 16 ++++++++++++++++ llvm/lib/IR/LLVMContextImpl.h | 3 +++ 7 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/coverage-target-attr.c diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 6d3efdb5ffe34..7766383fdc890 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -299,6 +299,9 @@ void BackendConsumer::HandleTranslationUnit(ASTContext &C) { Ctx.setDiagnosticHandler(std::make_unique( CodeGenOpts, this)); + Ctx.setDefaultTargetCPU(TargetOpts.CPU); + Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); + Expected> OptRecordFileOrErr = setupLLVMOptimizationRemarks( Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, @@ -1205,6 +1208,9 @@ void CodeGenAction::ExecuteAction() { Ctx.setDiagnosticHandler( std::make_unique(CodeGenOpts, &Result)); + Ctx.setDefaultTargetCPU(TargetOpts.CPU); + Ctx.setDefaultTargetFeatures(llvm::join(TargetOpts.Features, ",")); + Expected> OptRecordFileOrErr = setupLLVMOptimizationRemarks( Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, diff --git a/clang/test/CodeGen/coverage-target-attr.c b/clang/test/CodeGen/coverage-target-attr.c new file mode 100644 index 0000000000000..3929d7b43df69 --- /dev/null +++ b/clang/test/CodeGen/coverage-target-attr.c @@ -0,0 +1,17 @@ +// RUN: %clang -S -emit-llvm --coverage --target=aarch64-linux-android30 -fsanitize=hwaddress %s -o %t +// RUN: FileCheck %s < %t + +// CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr [[ATTR:#[0-9]+]] +// CHECK: define internal void @__llvm_gcov_reset() unnamed_addr [[ATTR]] +// CHECK: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] +// CHECK: define internal void @hwasan.module_ctor() [[ATTR2:#[0-9]+]] +// CHECK: attributes [[ATTR]] = {{.*}} "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+fp-armv8,+neon,+outline-atomics,+tagged-globals,+v8a" +// CHECK: attributes [[ATTR2]] = {{.*}} "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+fp-armv8,+neon,+outline-atomics,+tagged-globals,+v8a" + +__attribute__((weak)) int foo = 0; + +__attribute__((weak)) void bar() {} + +int main() { + if (foo) bar(); +} diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 5468cedb0815a..6bd997b7ac75a 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -181,10 +181,14 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject, const Twine &N, Module &M); /// Creates a function with some attributes recorded in llvm.module.flags - /// applied. + /// and the LLVMContext applied. /// /// Use this when synthesizing new functions that need attributes that would /// have been set by command line options. + /// + /// This function should not be called from backends or the LTO pipeline. If + /// it is called from one of those places, some default attributes will not be + /// applied to the function. static Function *createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N = "", diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index 89ad6f1572c67..177d6e1817089 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -327,6 +327,26 @@ class LLVMContext { [[deprecated("Always returns false")]] bool supportsTypedPointers() const; + /// Get the current "default" target CPU (target-cpu function attribute). The + /// intent is that compiler frontends will set this to a value that reflects + /// the attribute that a function would get "by default" without any specific + /// function attributes, and compiler passes will attach the attribute to + /// newly created functions that are not associated with a particular + /// function, such as global initializers. Function::createWithDefaultAttr() + /// will create functions with this attribute. This function should only be + /// called by passes that run at compile time and not by the backend or LTO + /// passes. + StringRef getDefaultTargetCPU(); + + /// See getDefaultTargetCPU(). + void setDefaultTargetCPU(StringRef CPU); + + /// Similar to getDefaultTargetCPU() but for default target-features instead. + StringRef getDefaultTargetFeatures(); + + /// See getDefaultTargetFeatures(). + void setDefaultTargetFeatures(StringRef Features); + private: // Module needs access to the add/removeModule methods. friend class Module; diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 9360e6d7d274c..1190a3fb9be23 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -397,6 +397,12 @@ Function *Function::createWithDefaultAttr(FunctionType *Ty, } if (M->getModuleFlag("function_return_thunk_extern")) B.addAttribute(Attribute::FnRetThunkExtern); + StringRef DefaultCPU = F->getContext().getDefaultTargetCPU(); + if (!DefaultCPU.empty()) + B.addAttribute("target-cpu", DefaultCPU); + StringRef DefaultFeatures = F->getContext().getDefaultTargetFeatures(); + if (!DefaultFeatures.empty()) + B.addAttribute("target-features", DefaultFeatures); F->addFnAttrs(B); return F; } diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index 8120cccace40b..194c7e7581cfb 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -390,3 +390,19 @@ void LLVMContext::setOpaquePointers(bool Enable) const { bool LLVMContext::supportsTypedPointers() const { return false; } + +StringRef LLVMContext::getDefaultTargetCPU() { + return pImpl->DefaultTargetCPU; +} + +void LLVMContext::setDefaultTargetCPU(StringRef CPU) { + pImpl->DefaultTargetCPU = CPU; +} + +StringRef LLVMContext::getDefaultTargetFeatures() { + return pImpl->DefaultTargetFeatures; +} + +void LLVMContext::setDefaultTargetFeatures(StringRef Features) { + pImpl->DefaultTargetFeatures = Features; +} diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 5f8df87149f04..937a87d686175 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1723,6 +1723,9 @@ class LLVMContextImpl { } void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDbgRecords.erase(B); } + + std::string DefaultTargetCPU; + std::string DefaultTargetFeatures; }; } // end namespace llvm From e307fbab2ecb83d9a0fca0c4247b43aacb4e8fca Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Tue, 25 Jun 2024 20:38:17 -0700 Subject: [PATCH 2/2] Address review comments Created using spr 1.3.6-beta.1 --- clang/test/CodeGen/asan-frame-pointer.cpp | 6 ++--- clang/test/CodeGen/asan-globals.cpp | 4 ++-- clang/test/CodeGen/coverage-target-attr.c | 6 ++--- .../CodeGen/sanitize-metadata-nosanitize.c | 2 +- llvm/include/llvm/IR/LLVMContext.h | 24 ++++++++----------- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/clang/test/CodeGen/asan-frame-pointer.cpp b/clang/test/CodeGen/asan-frame-pointer.cpp index ed3624f3146eb..ecc1a18c11daa 100644 --- a/clang/test/CodeGen/asan-frame-pointer.cpp +++ b/clang/test/CodeGen/asan-frame-pointer.cpp @@ -8,12 +8,12 @@ int global; // NONE: define internal void @asan.module_ctor() #[[#ATTR:]] { // NONE: define internal void @asan.module_dtor() #[[#ATTR]] { -// NONE: attributes #[[#ATTR]] = { nounwind } +// NONE: attributes #[[#ATTR]] = { nounwind // NONLEAF: define internal void @asan.module_ctor() #[[#ATTR:]] { // NONLEAF: define internal void @asan.module_dtor() #[[#ATTR]] { -// NONLEAF: attributes #[[#ATTR]] = { nounwind "frame-pointer"="non-leaf" } +// NONLEAF: attributes #[[#ATTR]] = { nounwind "frame-pointer"="non-leaf" // ALL: define internal void @asan.module_ctor() #[[#ATTR:]] { // ALL: define internal void @asan.module_dtor() #[[#ATTR]] { -// ALL: attributes #[[#ATTR]] = { nounwind "frame-pointer"="all" } +// ALL: attributes #[[#ATTR]] = { nounwind "frame-pointer"="all" diff --git a/clang/test/CodeGen/asan-globals.cpp b/clang/test/CodeGen/asan-globals.cpp index 4a370cbd44650..be52ea99de969 100644 --- a/clang/test/CodeGen/asan-globals.cpp +++ b/clang/test/CodeGen/asan-globals.cpp @@ -67,13 +67,13 @@ void func() { // CHECK-NEXT: call void @__asan_unregister_globals // CHECK-NEXT: ret void -// CHECK: attributes #[[#ATTR]] = { nounwind } +// CHECK: attributes #[[#ATTR]] = { nounwind /// If -fasynchronous-unwind-tables, set the module flag "uwtable". ctor/dtor /// will thus get the uwtable attribute. // RUN: %clang_cc1 -emit-llvm -fsanitize=address -funwind-tables=2 -o - %s | FileCheck %s --check-prefixes=UWTABLE // UWTABLE: define internal void @asan.module_dtor() #[[#ATTR:]] { -// UWTABLE: attributes #[[#ATTR]] = { nounwind uwtable } +// UWTABLE: attributes #[[#ATTR]] = { nounwind uwtable // UWTABLE: ![[#]] = !{i32 7, !"uwtable", i32 2} // IGNORELIST-SRC: @{{.*}}extra_global{{.*}} ={{.*}} global diff --git a/clang/test/CodeGen/coverage-target-attr.c b/clang/test/CodeGen/coverage-target-attr.c index 3929d7b43df69..8c8e6ee1c3b69 100644 --- a/clang/test/CodeGen/coverage-target-attr.c +++ b/clang/test/CodeGen/coverage-target-attr.c @@ -1,12 +1,12 @@ -// RUN: %clang -S -emit-llvm --coverage --target=aarch64-linux-android30 -fsanitize=hwaddress %s -o %t +// RUN: %clang_cc1 -emit-llvm -coverage-notes-file=test.gcno -coverage-data-file=test.gcda -triple aarch64-linux-android30 -target-cpu generic -target-feature +tagged-globals -fsanitize=hwaddress %s -o %t // RUN: FileCheck %s < %t // CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr [[ATTR:#[0-9]+]] // CHECK: define internal void @__llvm_gcov_reset() unnamed_addr [[ATTR]] // CHECK: define internal void @__llvm_gcov_init() unnamed_addr [[ATTR]] // CHECK: define internal void @hwasan.module_ctor() [[ATTR2:#[0-9]+]] -// CHECK: attributes [[ATTR]] = {{.*}} "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+fp-armv8,+neon,+outline-atomics,+tagged-globals,+v8a" -// CHECK: attributes [[ATTR2]] = {{.*}} "target-cpu"="generic" "target-features"="+fix-cortex-a53-835769,+fp-armv8,+neon,+outline-atomics,+tagged-globals,+v8a" +// CHECK: attributes [[ATTR]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" +// CHECK: attributes [[ATTR2]] = {{.*}} "target-cpu"="generic" "target-features"="+tagged-globals" __attribute__((weak)) int foo = 0; diff --git a/clang/test/CodeGen/sanitize-metadata-nosanitize.c b/clang/test/CodeGen/sanitize-metadata-nosanitize.c index 60f93476b050f..6414956fb6796 100644 --- a/clang/test/CodeGen/sanitize-metadata-nosanitize.c +++ b/clang/test/CodeGen/sanitize-metadata-nosanitize.c @@ -93,7 +93,7 @@ __attribute__((no_sanitize("all"))) int test_no_sanitize_all(int *x, int *y) { // CHECK: attributes #1 = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } // CHECK: attributes #2 = { disable_sanitizer_instrumentation mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } // CHECK: attributes #3 = { mustprogress nofree norecurse nounwind willreturn memory(write, argmem: readwrite, inaccessiblemem: none) "min-legal-vector-width"="0" "no-trapping-math"="true" "no_sanitize_thread" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } -// CHECK: attributes #4 = { nounwind } +// CHECK: attributes #4 = { nounwind "target-features"="+cx8,+mmx,+sse,+sse2,+x87" } //. // CHECK: !2 = !{!"sanmd_covered!C", !3} // CHECK: !3 = !{i64 0} diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index 177d6e1817089..6ffa2bdaa319a 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -327,24 +327,20 @@ class LLVMContext { [[deprecated("Always returns false")]] bool supportsTypedPointers() const; - /// Get the current "default" target CPU (target-cpu function attribute). The - /// intent is that compiler frontends will set this to a value that reflects - /// the attribute that a function would get "by default" without any specific - /// function attributes, and compiler passes will attach the attribute to - /// newly created functions that are not associated with a particular - /// function, such as global initializers. Function::createWithDefaultAttr() - /// will create functions with this attribute. This function should only be - /// called by passes that run at compile time and not by the backend or LTO - /// passes. + /// Get or set the current "default" target CPU (target-cpu function + /// attribute). The intent is that compiler frontends will set this to a value + /// that reflects the attribute that a function would get "by default" without + /// any specific function attributes, and compiler passes will attach the + /// attribute to newly created functions that are not associated with a + /// particular function, such as global initializers. + /// Function::createWithDefaultAttr() will create functions with this + /// attribute. This function should only be called by passes that run at + /// compile time and not by the backend or LTO passes. StringRef getDefaultTargetCPU(); - - /// See getDefaultTargetCPU(). void setDefaultTargetCPU(StringRef CPU); - /// Similar to getDefaultTargetCPU() but for default target-features instead. + /// Similar to {get,set}DefaultTargetCPU() but for default target-features. StringRef getDefaultTargetFeatures(); - - /// See getDefaultTargetFeatures(). void setDefaultTargetFeatures(StringRef Features); private: