Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -1823,6 +1823,23 @@ std::tie(Var, Value) = Attr.split('='); FuncAttrs.addAttribute(Var, Value); } + + if (CodeGenOpts.BranchTargetEnforcement) { + FuncAttrs.addAttribute("branch-target-enforcement", "true"); + } + + auto RASignKind = CodeGenOpts.getSignReturnAddress(); + if (RASignKind != CodeGenOptions::SignReturnAddressScope::None) { + FuncAttrs.addAttribute( + "sign-return-address", + RASignKind == CodeGenOptions::SignReturnAddressScope::All ? "all" + : "non-leaf"); + auto RASignKey = CodeGenOpts.getSignReturnAddressKey(); + FuncAttrs.addAttribute( + "sign-return-address-key", + RASignKey == CodeGenOptions::SignReturnAddressKeyValue::AKey ? "a_key" + : "b_key"); + } } void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { Index: clang/lib/CodeGen/CGDeclCXX.cpp =================================================================== --- clang/lib/CodeGen/CGDeclCXX.cpp +++ clang/lib/CodeGen/CGDeclCXX.cpp @@ -406,7 +406,7 @@ } if (getCodeGenOpts().BranchTargetEnforcement) - Fn->addFnAttr("branch-target-enforcement"); + Fn->addFnAttr("branch-target-enforcement", "true"); return Fn; } Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -583,6 +583,27 @@ 1); } + if (CodeGenOpts.BranchTargetEnforcement) { + getModule().addModuleFlag(llvm::Module::Override, + "branch-target-enforcement", 1); + } + + CodeGenOptions::SignReturnAddressScope Scope = + CodeGenOpts.getSignReturnAddress(); + if (Scope != CodeGenOptions::SignReturnAddressScope::None) { + getModule().addModuleFlag( + llvm::Module::Override, "sign-return-address", + Scope == CodeGenOptions::SignReturnAddressScope::All + ? llvm::MDString::get(VMContext, "all") + : llvm::MDString::get(VMContext, "non-leaf")); + getModule().addModuleFlag( + llvm::Module::Override, "sign-return-address-key", + CodeGenOpts.getSignReturnAddressKey() == + CodeGenOptions::SignReturnAddressKeyValue::AKey + ? 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 @@ -5106,38 +5106,53 @@ if (!FD) return; - CodeGenOptions::SignReturnAddressScope Scope = CGM.getCodeGenOpts().getSignReturnAddress(); - CodeGenOptions::SignReturnAddressKeyValue Key = CGM.getCodeGenOpts().getSignReturnAddressKey(); - bool BranchTargetEnforcement = CGM.getCodeGenOpts().BranchTargetEnforcement; if (const auto *TA = FD->getAttr()) { ParsedTargetAttr Attr = TA->parse(); if (!Attr.BranchProtection.empty()) { TargetInfo::BranchProtectionInfo BPI; StringRef Error; + + CodeGenOptions::SignReturnAddressScope Scope = + CGM.getCodeGenOpts().getSignReturnAddress(); + CodeGenOptions::SignReturnAddressKeyValue Key = + CGM.getCodeGenOpts().getSignReturnAddressKey(); + bool BranchTargetEnforcement = + CGM.getCodeGenOpts().BranchTargetEnforcement; + (void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection, BPI, Error); assert(Error.empty()); - Scope = BPI.SignReturnAddr; - Key = BPI.SignKey; - BranchTargetEnforcement = BPI.BranchTargetEnforcement; + auto *Fn = cast(GV); + + // Update flags only when differ from the codegen flags. + if (Scope != BPI.SignReturnAddr || Key != BPI.SignKey) { + Scope = BPI.SignReturnAddr; + Key = BPI.SignKey; + if (Scope != CodeGenOptions::SignReturnAddressScope::None) { + Fn->addFnAttr("sign-return-address", + Scope == CodeGenOptions::SignReturnAddressScope::All + ? "all" + : "non-leaf"); + + Fn->addFnAttr("sign-return-address-key", + Key == CodeGenOptions::SignReturnAddressKeyValue::AKey + ? "a_key" + : "b_key"); + } else { + Fn->removeAttribute(llvm::AttributeList::FunctionIndex, + "sign-return-address"); + Fn->removeAttribute(llvm::AttributeList::FunctionIndex, + "sign-return-address-key"); + } + } + if (BranchTargetEnforcement != BPI.BranchTargetEnforcement) { + if (BPI.BranchTargetEnforcement) + Fn->addFnAttr("branch-target-enforcement", "true"); + else + Fn->addFnAttr("branch-target-enforcement", "false"); + } } } - - auto *Fn = cast(GV); - if (Scope != CodeGenOptions::SignReturnAddressScope::None) { - Fn->addFnAttr("sign-return-address", - Scope == CodeGenOptions::SignReturnAddressScope::All - ? "all" - : "non-leaf"); - - Fn->addFnAttr("sign-return-address-key", - Key == CodeGenOptions::SignReturnAddressKeyValue::AKey - ? "a_key" - : "b_key"); - } - - if (BranchTargetEnforcement) - Fn->addFnAttr("branch-target-enforcement"); } llvm::Value *decodeReturnAddress(CodeGen::CodeGenFunction &CGF, llvm::Value *Address) const override { Index: clang/test/CodeGen/aarch64-branch-protection-attr.c =================================================================== --- clang/test/CodeGen/aarch64-branch-protection-attr.c +++ clang/test/CodeGen/aarch64-branch-protection-attr.c @@ -64,18 +64,18 @@ // NO-OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]] // OVERRIDE: define void @btileaf() #[[#BTIPACLEAF:]] -// CHECK-DAG: attributes #[[#NONE]] +// CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" -// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#BTI]] = { {{.*}}"branch-target-enforcement" +// CHECK-DAG: attributes #[[#BTI]] = { {{.*}} "branch-target-enforcement"="true" -// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PAC]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#PACLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" -// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" +// CHECK-DAG: attributes #[[#PACBKEY]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="b_key" -// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" +// CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" -// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" +// CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" Index: clang/test/CodeGen/aarch64-sign-return-address.c =================================================================== --- clang/test/CodeGen/aarch64-sign-return-address.c +++ clang/test/CodeGen/aarch64-sign-return-address.c @@ -18,7 +18,7 @@ // ALL: "sign-return-address"="all" -// BTE: "branch-target-enforcement" +// BTE: "branch-target-enforcement"="true" // A-KEY: "sign-return-address-key"="a_key" Index: clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/aarch64-branch-target_clang_call_terminate.cpp @@ -0,0 +1,34 @@ +// RUN: %clang -target aarch64-linux-android -mbranch-protection=none -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+leaf -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key+leaf -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NONE +// RUN: %clang -target aarch64-linux-android -mbranch-protection=standard -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI +// RUN: %clang -target aarch64-linux-android -mbranch-protection=bti -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI +// RUN: %clang -target aarch64-linux-android -mbranch-protection=pac-ret+b-key+leaf+bti -c %s -o - | \ +// RUN: llvm-objdump -d -mattr=+bti - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-BTI + +void a(); +void d(); + +void c() { + try { + d(); + } catch (...) { + a(); + } +} + +// CHECK-BTI: 0000000000000000 __clang_call_terminate: +// CHECK-BTI-NEXT: bti c +// CHECK-BTI-NEXT: str x30, [sp, #-16]! + +// CHECK-NONE: 0000000000000000 __clang_call_terminate: +// CHECK-NONE-NEXT: str x30, [sp, #-16]! Index: clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp =================================================================== --- clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp +++ clang/test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp @@ -38,4 +38,4 @@ // CHECK-ALL: "sign-return-address"="all" // CHECK-A-KEY: "sign-return-address-key"="a_key" // CHECK-B-KEY: "sign-return-address-key"="b_key" -// CHECK-BTE: "branch-target-enforcement" +// CHECK-BTE: "branch-target-enforcement"="true" Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -187,19 +187,29 @@ 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; + unsigned Flags = 0; + 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 (any_of(M, [](const Function &F) { - return !F.isDeclaration() && - !F.hasFnAttribute("branch-target-enforcement"); + if (F.isDeclaration()) + return false; + return F.getFnAttribute("branch-target-enforcement") + .getValueAsString() == "false"; })) { 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"); + if (F.isDeclaration()) + return false; + if (!F.hasFnAttribute("branch-target-enforcement")) + return false; + return F.getFnAttribute("branch-target-enforcement") + .getValueAsString() == "true"; })) { errs() << "warning: some functions compiled with BTI and some compiled " "without BTI\n" Index: llvm/lib/Target/AArch64/AArch64BranchTargets.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64BranchTargets.cpp +++ llvm/lib/Target/AArch64/AArch64BranchTargets.cpp @@ -58,8 +58,18 @@ bool AArch64BranchTargets::runOnMachineFunction(MachineFunction &MF) { const Function &F = MF.getFunction(); - if (!F.hasFnAttribute("branch-target-enforcement")) - return false; + + // LLVM emmited function won't have the attribute. + if (!F.hasFnAttribute("branch-target-enforcement")) { + // Fall back to the module flag, add BTI if the module is compiled with it. + if (!MF.getMMI().getModule()->getModuleFlag("branch-target-enforcement")) + return false; + } else { + // Explicitly requested to not generate BTI. + if (F.getFnAttribute("branch-target-enforcement").getValueAsString() == + "false") + return false; + } LLVM_DEBUG( dbgs() << "********** AArch64 Branch Targets **********\n" Index: llvm/lib/Target/AArch64/AArch64CallLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64CallLowering.cpp +++ llvm/lib/Target/AArch64/AArch64CallLowering.cpp @@ -762,7 +762,8 @@ // When BTI is enabled, we need to use TCRETURNriBTI to make sure that we use // x16 or x17. - if (CallerF.hasFnAttribute("branch-target-enforcement")) + if (CallerF.getFnAttribute("branch-target-enforcement").getValueAsString() == + "true") return AArch64::TCRETURNriBTI; return AArch64::TCRETURNri; @@ -782,7 +783,8 @@ // TODO: Right now, regbankselect doesn't know how to handle the rtcGPR64 // register class. Until we can do that, we should fall back here. - if (F.hasFnAttribute("branch-target-enforcement")) { + if (F.getFnAttribute("branch-target-enforcement").getValueAsString() == + "true") { LLVM_DEBUG( dbgs() << "Cannot lower indirect tail calls with BTI enabled yet.\n"); return false; Index: llvm/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -5859,7 +5859,10 @@ NumBytesToCreateFrame += 4; bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) { - return C.getMF()->getFunction().hasFnAttribute("branch-target-enforcement"); + return C.getMF() + ->getFunction() + .getFnAttribute("branch-target-enforcement") + .getValueAsString() == "true"; }); // Returns true if an instructions is safe to fix up, false otherwise. Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -570,8 +570,8 @@ // Avoid generating STRQro if it is slow, unless we're optimizing for code size. def UseSTRQro : Predicate<"!Subtarget->isSTRQroSlow() || shouldOptForSize(MF)">; - def UseBTI : Predicate<[{ MF->getFunction().hasFnAttribute("branch-target-enforcement") }]>; - def NotUseBTI : Predicate<[{ !MF->getFunction().hasFnAttribute("branch-target-enforcement") }]>; + def UseBTI : Predicate<[{ MF->getFunction().getFnAttribute("branch-target-enforcement").getValueAsString() == "true" }]>; + def NotUseBTI : Predicate<[{ !(MF->getFunction().getFnAttribute("branch-target-enforcement").getValueAsString() == "true") }]>; // Toggles patterns which aren't beneficial in GlobalISel when we aren't // optimizing. This allows us to selectively use patterns without impacting Index: llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll =================================================================== --- llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll +++ llvm/test/CodeGen/AArch64/branch-target-enforcement-indirect-calls.ll @@ -20,7 +20,7 @@ ret void } -define void @bti_enabled(void ()* %p) "branch-target-enforcement" { +define void @bti_enabled(void ()* %p) "branch-target-enforcement"="true" { entry: tail call void %p() ; CHECK: br {{x16|x17}} Index: llvm/test/CodeGen/AArch64/branch-target-enforcement.mir =================================================================== --- llvm/test/CodeGen/AArch64/branch-target-enforcement.mir +++ llvm/test/CodeGen/AArch64/branch-target-enforcement.mir @@ -3,29 +3,29 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" target triple = "aarch64-arm-none-eabi" - define hidden i32 @simple_external() "branch-target-enforcement" { + define hidden i32 @simple_external() "branch-target-enforcement"="true" { entry: ret i32 0 } - define internal i32 @simple_internal() "branch-target-enforcement" { + define internal i32 @simple_internal() "branch-target-enforcement"="true" { entry: ret i32 0 } - define hidden i32 @ptr_auth() "branch-target-enforcement" { + define hidden i32 @ptr_auth() "branch-target-enforcement"="true" { entry: tail call void asm sideeffect "", "~{lr}"() ret i32 0 } - define hidden i32 @ptr_auth_b() "branch-target-enforcement" { + define hidden i32 @ptr_auth_b() "branch-target-enforcement"="true" { entry: tail call void asm sideeffect "", "~{lr}"() ret i32 0 } - define hidden i32 @jump_table(i32 %a) "branch-target-enforcement" { + define hidden i32 @jump_table(i32 %a) "branch-target-enforcement"="true" { entry: switch i32 %a, label %sw.epilog [ i32 1, label %sw.bb @@ -61,7 +61,7 @@ @label_address.addr = internal unnamed_addr global i8* blockaddress(@label_address, %return), align 8 - define hidden i32 @label_address() "branch-target-enforcement" { + define hidden i32 @label_address() "branch-target-enforcement"="true" { entry: %0 = load i8*, i8** @label_address.addr, align 8 indirectbr i8* %0, [label %return, label %lab2] @@ -79,7 +79,7 @@ ret i32 %merge2 } - define hidden i32 @label_address_entry() "branch-target-enforcement" { + define hidden i32 @label_address_entry() "branch-target-enforcement"="true" { entry: %0 = load i8*, i8** @label_address.addr, align 8 indirectbr i8* %0, [label %return, label %lab2] @@ -97,7 +97,7 @@ ret i32 %merge2 } - define hidden i32 @debug_ptr_auth() "branch-target-enforcement" { + define hidden i32 @debug_ptr_auth() "branch-target-enforcement"="true" { entry: tail call void asm sideeffect "", "~{lr}"() ret i32 0 Index: llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll =================================================================== --- llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll +++ llvm/test/CodeGen/AArch64/bti-branch-relaxation.ll @@ -61,4 +61,4 @@ declare dso_local i64 @llvm.aarch64.space(i32, i64) local_unnamed_addr #0 -attributes #0 = { nounwind "branch-target-enforcement" "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+v8.5a" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #0 = { nounwind "branch-target-enforcement"="true" "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon,+v8.5a" "unsafe-fp-math"="false" "use-soft-float"="false" } Index: llvm/test/CodeGen/AArch64/machine-outliner-bti.mir =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-bti.mir +++ llvm/test/CodeGen/AArch64/machine-outliner-bti.mir @@ -15,7 +15,7 @@ --- | @g = hidden local_unnamed_addr global i32 0, align 4 - define hidden void @bar(void ()* nocapture %f) "branch-target-enforcement" { + define hidden void @bar(void ()* nocapture %f) "branch-target-enforcement"="true" { entry: ret void } Index: llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll =================================================================== --- llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll +++ llvm/test/CodeGen/AArch64/machine-outliner-outline-bti.ll @@ -5,7 +5,7 @@ @g = hidden global i32 0, align 4 -define hidden void @foo() minsize "branch-target-enforcement" { +define hidden void @foo() minsize "branch-target-enforcement"="true" { entry: ; CHECK: hint #34 ; CHECK: b OUTLINED_FUNCTION_0 @@ -13,10 +13,10 @@ ret void } -define hidden void @bar() minsize "branch-target-enforcement" { +define hidden void @bar() minsize "branch-target-enforcement"="true" { entry: ; CHECK: hint #34 ; CHECK: b OUTLINED_FUNCTION_0 store volatile i32 1, i32* @g, align 4 ret void -} +} \ No newline at end of file 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,12 @@ ; RUN: llvm-readelf --notes | FileCheck %s --check-prefix=OBJ @x = common dso_local global i32 0, align 4 -attributes #0 = { "branch-target-enforcement" } +attributes #0 = { "branch-target-enforcement"="true" } + +!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 @@ -8,7 +8,11 @@ ret i32 0 } -attributes #0 = { "branch-target-enforcement" } +attributes #0 = { "branch-target-enforcement"="true" } + +!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 @@ -10,6 +10,10 @@ attributes #0 = { "sign-return-address"="all" } +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"sign-return-address", !"all"} + ; PAC attribute present ; ASM: .word 3221225472 ; ASM-NEXT: .word 4 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 @@ -8,7 +8,12 @@ ret i32 0 } -attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } +attributes #0 = { "branch-target-enforcement"="true" "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 @@ -13,9 +13,13 @@ ret i32 0 } -attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } +attributes #0 = { "branch-target-enforcement"="true" "sign-return-address"="non-leaf" } -attributes #1 = { "branch-target-enforcement" } +attributes #1 = { "branch-target-enforcement"="true" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} ; Only the common atttribute (BTI) ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-5.ll @@ -13,9 +13,15 @@ ret i32 0 } -attributes #0 = { "branch-target-enforcement" "sign-return-address"="non-leaf" } +attributes #0 = { "branch-target-enforcement"="true" "sign-return-address"="non-leaf" } + +attributes #1 = { "branch-target-enforcement"="false" "sign-return-address"="all" } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} +!1 = !{i32 4, !"sign-return-address", !"all"} -attributes #1 = { "sign-return-address"="all" } ; Only the common atttribute (PAC) ; ASM: warning: not setting BTI in feature flags Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-6.ll @@ -17,6 +17,11 @@ attributes #1 = { "sign-return-address"="none" } +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"sign-return-address", !"non-leaf"} + + ; 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 +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-7.ll @@ -13,9 +13,13 @@ ret i32 0 } -attributes #0 = { "sign-return-address"="non-leaf" } +attributes #0 = { "branch-target-enforcement"="false" "sign-return-address"="non-leaf" } -attributes #1 = { "branch-target-enforcement" } +attributes #1 = { "branch-target-enforcement"="true" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} ; No common attribute, no note section ; ASM: warning: not setting BTI in feature flags Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll =================================================================== --- llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-8.ll @@ -11,7 +11,11 @@ declare dso_local i32 @g() -attributes #0 = { "branch-target-enforcement" } +attributes #0 = { "branch-target-enforcement"="true" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} ; Declarations don't prevent setting BTI ; ASM: .word 3221225472 Index: llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-9.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/note-gnu-property-pac-bti-9.ll @@ -0,0 +1,27 @@ +; 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() { +entry: + ret i32 0 +} + +attributes #0 = { "branch-target-enforcement"="true" } + +!llvm.module.flags = !{!0} + +!0 = !{i32 4, !"branch-target-enforcement", i32 1} + +; Only the common atttribute (BTI) +; ASM: .word 3221225472 +; ASM-NEXT: .word 4 +; ASM-NEXT .word 1 + +; OBJ: Properties: aarch64 feature: BTI Index: llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll =================================================================== --- llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll +++ llvm/test/CodeGen/AArch64/patchable-function-entry-bti.ll @@ -1,6 +1,6 @@ ; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s -define void @f0() "patchable-function-entry"="0" "branch-target-enforcement" { +define void @f0() "patchable-function-entry"="0" "branch-target-enforcement"="true" { ; CHECK-LABEL: f0: ; CHECK-NEXT: .Lfunc_begin0: ; CHECK: // %bb.0: @@ -12,7 +12,7 @@ ;; -fpatchable-function-entry=1 -mbranch-protection=bti ;; For M=0, place the label .Lpatch0 after the initial BTI. -define void @f1() "patchable-function-entry"="1" "branch-target-enforcement" { +define void @f1() "patchable-function-entry"="1" "branch-target-enforcement"="true" { ; CHECK-LABEL: f1: ; CHECK-NEXT: .Lfunc_begin1: ; CHECK-NEXT: .cfi_startproc @@ -28,7 +28,7 @@ } ;; -fpatchable-function-entry=2,1 -mbranch-protection=bti -define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="1" "branch-target-enforcement" { +define void @f2_1() "patchable-function-entry"="1" "patchable-function-prefix"="1" "branch-target-enforcement"="true" { ; CHECK-LABEL: .type f2_1,@function ; CHECK-NEXT: .Ltmp0: ; CHECK-NEXT: nop @@ -50,7 +50,7 @@ ;; -fpatchable-function-entry=1 -mbranch-protection=bti ;; For M=0, don't create .Lpatch0 if the initial instruction is not BTI, ;; even if other basic blocks may have BTI. -define internal void @f1i(i64 %v) "patchable-function-entry"="1" "branch-target-enforcement" { +define internal void @f1i(i64 %v) "patchable-function-entry"="1" "branch-target-enforcement"="true" { ; CHECK-LABEL: f1i: ; CHECK-NEXT: .Lfunc_begin3: ; CHECK: // %bb.0: