Skip to content

Commit c82cb02

Browse files
[Clang][ARM][AArch64] Emit attributes for functions always.
Branch protection, sign return address, guarded control stack flags are only emitted as module flags if not specified per function. The inliner might inline functions with different set of flags as it doesn't see the flags. In case of LTO build the module flags get merged with the `min` rule which means if one of the modules is not build with PAC/BTI then the features will be turned off on all functions due to the functions takes the branch-protection and sign-return-address features from the module flags. The sign-return-address is function level option therefore it is expected functions from files that are compiled with -mbranch-protection=pac-ret to be protected but in LTO case this might not happen. This patch adds the flags to functions in case of an LTO build therefore they don't need to rely on the module flag.
1 parent c5c2d72 commit c82cb02

File tree

12 files changed

+195
-98
lines changed

12 files changed

+195
-98
lines changed

clang/include/clang/Basic/TargetInfo.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,21 @@ class TargetInfo : public TransferrableTargetInfo,
13771377

13781378
BranchProtectionInfo() = default;
13791379

1380+
BranchProtectionInfo(const LangOptions &LangOpts) {
1381+
SignReturnAddr =
1382+
LangOpts.hasSignReturnAddress()
1383+
? (LangOpts.isSignReturnAddressScopeAll()
1384+
? LangOptions::SignReturnAddressScopeKind::All
1385+
: LangOptions::SignReturnAddressScopeKind::NonLeaf)
1386+
: LangOptions::SignReturnAddressScopeKind::None;
1387+
SignKey = LangOpts.isSignReturnAddressWithAKey()
1388+
? LangOptions::SignReturnAddressKeyKind::AKey
1389+
: LangOptions::SignReturnAddressKeyKind::BKey;
1390+
BranchTargetEnforcement = LangOpts.BranchTargetEnforcement;
1391+
BranchProtectionPAuthLR = LangOpts.BranchProtectionPAuthLR;
1392+
GuardedControlStack = LangOpts.GuardedControlStack;
1393+
}
1394+
13801395
const char *getSignReturnAddrStr() const {
13811396
static const char *SignReturnAddrStr[] = {"none", "non-leaf", "all"};
13821397
assert(static_cast<unsigned>(SignReturnAddr) <= 2 &&

clang/lib/CodeGen/Targets/AArch64.cpp

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -109,21 +109,18 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo {
109109
if (!FD)
110110
return;
111111

112-
const auto *TA = FD->getAttr<TargetAttr>();
113-
if (TA == nullptr)
114-
return;
115-
116-
ParsedTargetAttr Attr =
117-
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
118-
if (Attr.BranchProtection.empty())
119-
return;
120-
121-
TargetInfo::BranchProtectionInfo BPI;
122-
StringRef Error;
123-
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
124-
Attr.CPU, BPI, Error);
125-
assert(Error.empty());
126-
112+
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
113+
114+
if (const auto *TA = FD->getAttr<TargetAttr>()) {
115+
ParsedTargetAttr Attr =
116+
CGM.getTarget().parseTargetAttr(TA->getFeaturesStr());
117+
if (!Attr.BranchProtection.empty()) {
118+
StringRef Error;
119+
(void)CGM.getTarget().validateBranchProtection(Attr.BranchProtection,
120+
Attr.CPU, BPI, Error);
121+
assert(Error.empty());
122+
}
123+
}
127124
auto *Fn = cast<llvm::Function>(GV);
128125
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
129126

clang/lib/CodeGen/Targets/ARM.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ class ARMTargetCodeGenInfo : public TargetCodeGenInfo {
167167
diag::warn_target_unsupported_branch_protection_attribute)
168168
<< Attr.CPU;
169169
}
170+
} else if (CGM.getTarget().isBranchProtectionSupportedArch(
171+
CGM.getTarget().getTargetOpts().CPU)) {
172+
TargetInfo::BranchProtectionInfo BPI(CGM.getLangOpts());
173+
Fn->addFnAttr("sign-return-address", BPI.getSignReturnAddrStr());
174+
175+
Fn->addFnAttr("branch-target-enforcement",
176+
BPI.BranchTargetEnforcement ? "true" : "false");
170177
}
171178

172179
const ARMInterruptAttr *Attr = FD->getAttr<ARMInterruptAttr>();

clang/test/CodeGen/aarch64-cpu-supports-target.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,6 @@ int test_versions() {
4747
else
4848
return code();
4949
}
50-
// CHECK: attributes #0 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
51-
// CHECK: attributes #1 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+neon" }
52-
// CHECK: attributes #2 = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
50+
// CHECK: attributes #0 = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="false" "guarded-control-stack"="false" "no-trapping-math"="true" "sign-return-address"="none" "stack-protector-buffer-size"="8" }
51+
// CHECK: attributes #1 = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="false" "guarded-control-stack"="false" "no-trapping-math"="true" "sign-return-address"="none" "stack-protector-buffer-size"="8" "target-features"="+neon" }
52+
// CHECK: attributes #2 = { noinline nounwind optnone "branch-protection-pauth-lr"="false" "branch-target-enforcement"="false" "guarded-control-stack"="false" "no-trapping-math"="true" "sign-return-address"="none" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }

clang/test/CodeGen/aarch64-sign-return-address.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,33 @@
77
// RUN: %clang -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=B-KEY
88
// RUN: %clang -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
99

10+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK-LTO
11+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK-LTO
12+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK-LTO
13+
14+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=none %s | FileCheck %s --check-prefix=CHECK-LTO
15+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | FileCheck %s --check-prefix=CHECK-LTO
16+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK-LTO
17+
// RUN: %clang -flto -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK-LTO
18+
19+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK-LTO
20+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK-LTO
21+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK-LTO
22+
23+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=none %s | FileCheck %s --check-prefix=CHECK-LTO
24+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=pac-ret+leaf %s | FileCheck %s --check-prefix=CHECK-LTO
25+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK-LTO
26+
// RUN: %clang -flto=thin -target aarch64-none-elf -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK-LTO
27+
1028
// REQUIRES: aarch64-registered-target
1129

12-
// Check there are no branch protection function attributes
30+
// Branch protection function attributes are always expected.
1331

1432
// CHECK-LABEL: @foo() #[[#ATTR:]]
33+
// CHECK-LTO-LABEL: @foo() #[[#ATTR:]]
1534

16-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
17-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
18-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
35+
// CHECK: attributes #[[#ATTR]] = { {{.*}} "branch-protection-pauth-lr"{{.*}}"branch-target-enforcement"{{.*}}"guarded-control-stack"{{.*}}"sign-return-address"
36+
// CHECK-LTO: attributes #[[#ATTR]] = { {{.*}} "branch-protection-pauth-lr"{{.*}}"branch-target-enforcement"{{.*}}"guarded-control-stack"{{.*}}"sign-return-address"
1937

2038
// Check module attributes
2139

clang/test/CodeGen/aarch64-sme-intrinsics/aarch64-sme-attrs.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -278,18 +278,18 @@ int test_variadic_template() __arm_inout("za") {
278278
preserves_za_decl);
279279
}
280280

281-
// CHECK: attributes #[[SM_ENABLED]] = { mustprogress noinline nounwind "aarch64_pstate_sm_enabled" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
282-
// CHECK: attributes #[[NORMAL_DECL]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
283-
// CHECK: attributes #[[SM_ENABLED_DECL]] = { "aarch64_pstate_sm_enabled" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
284-
// CHECK: attributes #[[SM_COMPATIBLE]] = { mustprogress noinline nounwind "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
285-
// CHECK: attributes #[[SM_COMPATIBLE_DECL]] = { "aarch64_pstate_sm_compatible" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
286-
// CHECK: attributes #[[SM_BODY]] = { mustprogress noinline nounwind "aarch64_pstate_sm_body" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
287-
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
288-
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_inout_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
289-
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
290-
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_preserves_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
291-
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_new_za" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
292-
// CHECK: attributes #[[NORMAL_DEF]] = { mustprogress noinline nounwind "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
281+
// CHECK: attributes #[[SM_ENABLED]] = { mustprogress noinline nounwind "aarch64_pstate_sm_enabled" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
282+
// CHECK: attributes #[[NORMAL_DECL]] = { {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
283+
// CHECK: attributes #[[SM_ENABLED_DECL]] = { "aarch64_pstate_sm_enabled" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
284+
// CHECK: attributes #[[SM_COMPATIBLE]] = { mustprogress noinline nounwind "aarch64_pstate_sm_compatible" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
285+
// CHECK: attributes #[[SM_COMPATIBLE_DECL]] = { "aarch64_pstate_sm_compatible" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
286+
// CHECK: attributes #[[SM_BODY]] = { mustprogress noinline nounwind "aarch64_pstate_sm_body" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
287+
// CHECK: attributes #[[ZA_SHARED]] = { mustprogress noinline nounwind "aarch64_inout_za" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
288+
// CHECK: attributes #[[ZA_SHARED_DECL]] = { "aarch64_inout_za" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
289+
// CHECK: attributes #[[ZA_PRESERVED]] = { mustprogress noinline nounwind "aarch64_preserves_za" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
290+
// CHECK: attributes #[[ZA_PRESERVED_DECL]] = { "aarch64_preserves_za" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
291+
// CHECK: attributes #[[ZA_NEW]] = { mustprogress noinline nounwind "aarch64_new_za" {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
292+
// CHECK: attributes #[[NORMAL_DEF]] = { mustprogress noinline nounwind {{.*}} "no-trapping-math"="true" {{.*}} "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme" }
293293
// CHECK: attributes #[[SM_ENABLED_CALL]] = { "aarch64_pstate_sm_enabled" }
294294
// CHECK: attributes #[[SM_COMPATIBLE_CALL]] = { "aarch64_pstate_sm_compatible" }
295295
// CHECK: attributes #[[SM_BODY_CALL]] = { "aarch64_pstate_sm_body" }

clang/test/CodeGen/arm-branch-protection-attr-2.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=pac-ret+b-key %s | FileCheck %s --check-prefix=CHECK --check-prefix=PART
66
// RUN: %clang -target arm-arm-none-eabi -march=armv8.1-m.main -S -emit-llvm -o - -mbranch-protection=bti %s | FileCheck %s --check-prefix=CHECK --check-prefix=BTE
77

8-
// Check there are no branch protection function attributes
8+
// Check there is branch protection function attributes
99

1010
// CHECK-LABEL: @foo() #[[#ATTR:]]
1111

12-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address"
13-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "sign-return-address-key"
14-
// CHECK-NOT: attributes #[[#ATTR]] = { {{.*}} "branch-target-enforcement"
12+
// CHECK: attributes #[[#ATTR]] = { {{.*}} {{.*}} "branch-target-enforcement"{{.*}}"sign-return-address"
1513

1614
// Check module attributes
1715

0 commit comments

Comments
 (0)