Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -51,6 +51,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" @@ -590,6 +591,25 @@ 1); } + if (Context.getLangOpts().BranchTargetEnforcement) { + getModule().setModuleFlag( + llvm::Module::Override, "branch-target-enforcement", + llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(Int32Ty, 1))); + } + + if (Context.getLangOpts().hasSignReturnAddress()) { + getModule().setModuleFlag( + llvm::Module::Override, "sign-return-address", + Context.getLangOpts().isSignReturnAddressScopeAll() + ? llvm::MDString::get(VMContext, "all") + : llvm::MDString::get(VMContext, "non-leaf")); + getModule().setModuleFlag( + llvm::Module::Override, "sign-return-address-key", + Context.getLangOpts().isSignReturnAddressWithAKey() + ? llvm::MDString::get(VMContext, "a_key") + : llvm::MDString::get(VMContext, "b_key")); + } + if (LangOpts.CUDAIsDevice && getTriple().isNVPTX()) { // Indicate whether __nvvm_reflect should be configured to flush denormal // floating point values to 0. (This corresponds to its "__CUDA_FTZ" Index: clang/lib/CodeGen/TargetInfo.cpp =================================================================== --- clang/lib/CodeGen/TargetInfo.cpp +++ clang/lib/CodeGen/TargetInfo.cpp @@ -5534,6 +5534,7 @@ } auto *Fn = cast(GV); + auto *M = Fn->getParent(); if (Scope != LangOptions::SignReturnAddressScopeKind::None) { Fn->addFnAttr("sign-return-address", Scope == LangOptions::SignReturnAddressScopeKind::All @@ -5544,10 +5545,25 @@ Key == LangOptions::SignReturnAddressKeyKind::AKey ? "a_key" : "b_key"); + if (!M->getModuleFlag("sign-return-address")) { + auto &VMContext = CGM.getLLVMContext(); + M->addModuleFlag(llvm::Module::Override, "sign-return-address", + Scope == LangOptions::SignReturnAddressScopeKind::All + ? llvm::MDString::get(VMContext, "all") + : llvm::MDString::get(VMContext, "non-leaf")); + M->addModuleFlag(llvm::Module::Override, "sign-return-address-key", + Key == LangOptions::SignReturnAddressKeyKind::AKey + ? llvm::MDString::get(VMContext, "a_key") + : llvm::MDString::get(VMContext, "b_key")); + } } - if (BranchTargetEnforcement) + if (BranchTargetEnforcement) { Fn->addFnAttr("branch-target-enforcement"); + if (!M->getModuleFlag("branch-target-enforcement")) + M->addModuleFlag(llvm::Module::Override, "branch-target-enforcement", + 1); + } } }; Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -189,33 +189,12 @@ return; // Assemble feature flags that may require creation of a note section. - unsigned Flags = ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI | - ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC; - - if (any_of(M, [](const Function &F) { - return !F.isDeclaration() && - !F.hasFnAttribute("branch-target-enforcement"); - })) { - Flags &= ~ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI; - } - - if ((Flags & ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI) == 0 && - any_of(M, [](const Function &F) { - return F.hasFnAttribute("branch-target-enforcement"); - })) { - errs() << "warning: some functions compiled with BTI and some compiled " - "without BTI\n" - << "warning: not setting BTI in feature flags\n"; - } + unsigned Flags = 0; - if (any_of(M, [](const Function &F) { - if (F.isDeclaration()) - return false; - Attribute A = F.getFnAttribute("sign-return-address"); - return !A.isStringAttribute() || A.getValueAsString() == "none"; - })) { - Flags &= ~ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC; - } + if (M.getModuleFlag("branch-target-enforcement")) + Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI; + if (M.getModuleFlag("sign-return-address")) + Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC; if (Flags == 0) return; Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-0.ll @@ -4,7 +4,10 @@ ; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ @x = common dso_local global i32 0, align 4 -attributes #0 = { "branch-target-enforcement" } +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} +!1 = !{i32 4, !"sign-return-address", !"all"} ; Both attributes present in a file with no functions. ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-1.ll @@ -3,12 +3,14 @@ ; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ ; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ -define dso_local i32 @f() #0 { +define dso_local i32 @f() { entry: ret i32 0 } -attributes #0 = { "branch-target-enforcement" } +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} ; BTI attribute present ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-2.ll @@ -3,12 +3,14 @@ ; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ ; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ -define dso_local i32 @f() #0 { +define dso_local i32 @f() { entry: ret i32 0 } -attributes #0 = { "sign-return-address"="all" } +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"sign-return-address", !"all"} ; PAC attribute present ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-3.ll @@ -3,12 +3,15 @@ ; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ ; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ -define dso_local i32 @f() #0 { +define dso_local i32 @f() { entry: ret i32 0 } -attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} +!1 = !{i32 4, !"sign-return-address", !"non-leaf"} ; Both attribute present ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-4.ll @@ -1,25 +1,12 @@ ; RUN: llc -mtriple=aarch64-linux %s -o - | \ ; RUN: FileCheck %s --check-prefix=ASM -; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ -; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ define dso_local i32 @f() #0 { entry: ret i32 0 } -define dso_local i32 @g() #1 { -entry: - ret i32 0 -} - attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } -attributes #1 = { "branch-target-enforcement" } - -; Only the common atttribute (BTI) -; ASM: .word 3221225472 -; ASM-NEXT: .word 4 -; ASM-NEXT: .word 1 - -; OBJ: Properties: aarch64 feature: BTI +; Note is not emited if module has no properties +; ASM-NOT: .note.gnu.property Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll +++ /dev/null @@ -1,26 +0,0 @@ -; RUN: llc -mtriple=aarch64-linux %s -o - 2>&1 | \ -; RUN: FileCheck %s --check-prefix=ASM -; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ -; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ - -define dso_local i32 @f() #0 { -entry: - ret i32 0 -} - -define dso_local i32 @g() #1 { -entry: - ret i32 0 -} - -attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } - -attributes #1 = { "sign-return-address"="all" } - -; Only the common atttribute (PAC) -; ASM: warning: not setting BTI in feature flags -; ASM: .word 3221225472 -; ASM-NEXT: .word 4 -; ASM-NEXT: .word 2 - -; OBJ: Properties: aarch64 feature: PAC Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll +++ /dev/null @@ -1,22 +0,0 @@ -; RUN: llc -mtriple=aarch64-linux %s -o - | \ -; RUN: FileCheck %s --check-prefix=ASM -; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ -; RUN: llvm-readelf -S - | FileCheck %s --check-prefix=OBJ - -define dso_local i32 @f() #0 { -entry: - ret i32 0 -} - -define dso_local i32 @g() #1 { -entry: - ret i32 0 -} - -attributes #0 = { "sign-return-address"="non-leaf" } - -attributes #1 = { "sign-return-address"="none" } - -; No common attribute, no note section -; ASM-NOT: .note.gnu.property -; OBJ-NOT: .note.gnu.property Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll +++ /dev/null @@ -1,23 +0,0 @@ -; RUN: llc -mtriple=aarch64-linux %s -o - 2>&1 | \ -; RUN: FileCheck %s --check-prefix=ASM -; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ -; RUN: llvm-readelf -S - | FileCheck %s --check-prefix=OBJ - -define dso_local i32 @f() #0 { -entry: - ret i32 0 -} - -define dso_local i32 @g() #1 { -entry: - ret i32 0 -} - -attributes #0 = { "sign-return-address"="non-leaf" } - -attributes #1 = { "branch-target-enforcement" } - -; No common attribute, no note section -; ASM: warning: not setting BTI in feature flags -; ASM-NOT: .note.gnu.property -; OBJ-NOT: .note.gnu.property Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll +++ /dev/null @@ -1,21 +0,0 @@ -; RUN: llc -mtriple=aarch64-linux %s -o - | \ -; RUN: FileCheck %s --check-prefix=ASM -; RUN: llc -mtriple=aarch64-linux %s -filetype=obj -o - | \ -; RUN: llvm-readelf --notes - | FileCheck %s --check-prefix=OBJ - -define dso_local i32 @f() #0 { -entry: - %r = tail call i32 @g() - ret i32 %r -} - -declare dso_local i32 @g() - -attributes #0 = { "branch-target-enforcement" } - -; Declarations don't prevent setting BTI -; ASM: .word 3221225472 -; ASM-NEXT: .word 4 -; ASM-NEXT: .word 1 - -; OBJ: Properties: aarch64 feature: BTI