Skip to content

[ARM][AArch64] Change module flags values. #84804

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1171,22 +1171,29 @@ void CodeGenModule::Release() {
"tag-stack-memory-buildattr", 1);

if (T.isARM() || T.isThumb() || T.isAArch64()) {
// Previously 1 is used and meant for the backed to derive the function
// attribute form it. 2 now means function attributes already set for all
// functions in this module, so no need to propagate those from the module
// flag. Value is only used in case of LTO module merge because the backend
// will see all required function attribute set already. Value is used
// before modules got merged. Any posive value means the feature is active
// and required binary markings need to be emit accordingly.
if (LangOpts.BranchTargetEnforcement)
getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
1);
2);
if (LangOpts.BranchProtectionPAuthLR)
getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr",
1);
2);
if (LangOpts.GuardedControlStack)
getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 1);
getModule().addModuleFlag(llvm::Module::Min, "guarded-control-stack", 2);
if (LangOpts.hasSignReturnAddress())
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1);
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 2);
if (LangOpts.isSignReturnAddressScopeAll())
getModule().addModuleFlag(llvm::Module::Min, "sign-return-address-all",
1);
2);
if (!LangOpts.isSignReturnAddressWithAKey())
getModule().addModuleFlag(llvm::Module::Min,
"sign-return-address-with-bkey", 1);
"sign-return-address-with-bkey", 2);
}

if (CodeGenOpts.StackClashProtector)
Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGen/aarch64-sign-return-address.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@
// NONE-NOT: !"branch-target-enforcement"
// ALL-NOT: !"branch-target-enforcement"
// PART-NOT: !"branch-target-enforcement"
// BTE: !{i32 8, !"branch-target-enforcement", i32 1}
// BTE: !{i32 8, !"branch-target-enforcement", i32 2}
// B-KEY-NOT: !"branch-target-enforcement"

// NONE-NOT: !"sign-return-address"
// ALL: !{i32 8, !"sign-return-address", i32 1}
// PART: !{i32 8, !"sign-return-address", i32 1}
// ALL: !{i32 8, !"sign-return-address", i32 2}
// PART: !{i32 8, !"sign-return-address", i32 2}
// BTE-NOT: !"sign-return-address"
// B-KEY: !{i32 8, !"sign-return-address", i32 1}
// B-KEY: !{i32 8, !"sign-return-address", i32 2}

// NONE-NOT: !"sign-return-address-all"
// ALL: !{i32 8, !"sign-return-address-all", i32 1}
// ALL: !{i32 8, !"sign-return-address-all", i32 2}
// PART-NOT: !"sign-return-address-all"
// BTE-NOT: !"sign-return-address-all"
// B-KEY-NOT: !"sign-return-address-all"
Expand All @@ -41,6 +41,6 @@
// ALL-NOT: !"sign-return-address-with-bkey"
// PART-NOT: !"sign-return-address-with-bkey"
// BTE-NOT: !"sign-return-address-with-bkey"
// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 1}
// B-KEY: !{i32 8, !"sign-return-address-with-bkey", i32 2}

void foo() {}
8 changes: 4 additions & 4 deletions clang/test/CodeGen/arm-branch-protection-attr-2.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
// NONE-NOT: !"branch-target-enforcement"
// PART-NOT: !"branch-target-enforcement"
// ALL-NOT: !"branch-target-enforcement"
// BTE: !{i32 8, !"branch-target-enforcement", i32 1}
// BTE: !{i32 8, !"branch-target-enforcement", i32 2}

// NONE-NOT: !"sign-return-address"
// PART: !{i32 8, !"sign-return-address", i32 1}
// ALL: !{i32 8, !"sign-return-address", i32 1}
// PART: !{i32 8, !"sign-return-address", i32 2}
// ALL: !{i32 8, !"sign-return-address", i32 2}
// BTE-NOT: !"sign-return-address"

// NONE-NOT: !"sign-return-address-all", i32 0}
// PART-NOT: !"sign-return-address-all", i32 0}
// ALL: !{i32 8, !"sign-return-address-all", i32 1}
// ALL: !{i32 8, !"sign-return-address-all", i32 2}
// BTE-NOT: !"sign-return-address-all", i32 0}

void foo() {}
2 changes: 1 addition & 1 deletion clang/test/Frontend/arm-ignore-branch-protection-option.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ __attribute__((target("arch=cortex-m0"))) void f() {}
// CHECK-NOT: attributes { {{.*}} "branch-target-enforcement"

/// Check that there are branch protection module attributes despite the warning.
// CHECK: !{i32 8, !"branch-target-enforcement", i32 1}
// CHECK: !{i32 8, !"branch-target-enforcement", i32 2}
71 changes: 71 additions & 0 deletions lld/test/ELF/lto/aarch64_inline.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
; REQUIRES: aarch64
;; Test verifies inlining happens cross module when module flags are upgraded
;; by the thin-lto linker/IRMover.
;; Regression test for #82763

; RUN: split-file %s %t
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %t/foo.s -o %t/foo.o
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %t/bar.s -o %t/bar.o
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -unified-lto %t/main.s -o %t/main.o
; RUN: ld.lld -O2 --lto=thin --entry=main %t/main.o %t/foo.o %t/bar.o -o %t/exe
; RUN: llvm-objdump -d %t/exe | FileCheck %s


; CHECK-LABEL: <main>:
; CHECK-NEXT: pacibsp
; CHECK-NEXT: mov w0, #0x23
; CHECK-NEXT: autibsp
; CHECK-NEXT: ret

;--- foo.s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

define dso_local noundef i32 @foo() local_unnamed_addr #0 {
entry:
ret i32 34
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
!llvm.module.flags = !{!0, !1, !2, !3 }
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 1}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}

;--- bar.s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

define dso_local noundef i32 @bar() local_unnamed_addr #0 {
entry:
ret i32 1
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) "branch-target-enforcement"="true" "sign-return-address"="all" "sign-return-address-key"="b_key" }
!llvm.module.flags = !{!0, !1, !2, !3 }
!0 = !{i32 8, !"branch-target-enforcement", i32 2}
!1 = !{i32 8, !"sign-return-address", i32 2}
!2 = !{i32 8, !"sign-return-address-all", i32 2}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}

;--- main.s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

declare i32 @foo();
declare i32 @bar();

define i32 @main() {
entry:
%1 = call i32 @foo()
%2 = call i32 @bar()
%3 = add i32 %1, %2
ret i32 %3
}

!llvm.module.flags = !{!0, !1, !2, !3 }
!0 = !{i32 8, !"branch-target-enforcement", i32 1}
!1 = !{i32 8, !"sign-return-address", i32 1}
!2 = !{i32 8, !"sign-return-address-all", i32 1}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 1}
3 changes: 3 additions & 0 deletions llvm/include/llvm/IR/AutoUpgrade.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ namespace llvm {
/// info. Return true if module is modified.
bool UpgradeDebugInfo(Module &M);

/// Copies module attributes to the functions in the module.
void CopyModuleAttrToFunctions(Module &M);

/// Check whether a string looks like an old loop attachment tag.
inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
return Name.starts_with("llvm.vectorizer.");
Expand Down
52 changes: 52 additions & 0 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5178,6 +5178,58 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
}

// Check if the module attribute is present and set to one.
static bool isModuleAttributeOne(Module &M, const StringRef &ModAttr) {
const auto *Attr =
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr));
return Attr && Attr->isOne();
}

// Check if the function attribute is not present and set it.
static void SetFunctionAttrIfNotSet(Function &F, StringRef FnAttrName,
StringRef Value) {
if (!F.hasFnAttribute(FnAttrName))
F.addFnAttr(FnAttrName, Value);
}

void llvm::CopyModuleAttrToFunctions(Module &M) {
Triple T(M.getTargetTriple());
if (!T.isThumb() && !T.isARM() && !T.isAArch64())
return;

bool BTE = isModuleAttributeOne(M, "branch-target-enforcement");
bool BPPLR = isModuleAttributeOne(M, "branch-protection-pauth-lr");
bool GCS = isModuleAttributeOne(M, "guarded-control-stack");
bool SRA = isModuleAttributeOne(M, "sign-return-address");

if (!BTE && !BPPLR && !GCS && !SRA)
return;

StringRef SignTypeValue = "non-leaf";
if (SRA && isModuleAttributeOne(M, "sign-return-address-all"))
SignTypeValue = "all";

StringRef SignKeyValue = "a_key";
if (SRA && isModuleAttributeOne(M, "sign-return-address-with-bkey"))
SignKeyValue = "b_key";

for (Function &F : M.getFunctionList()) {
if (F.isDeclaration())
continue;

if (SRA) {
SetFunctionAttrIfNotSet(F, "sign-return-address", SignTypeValue);
SetFunctionAttrIfNotSet(F, "sign-return-address-key", SignKeyValue);
}
if (BTE)
SetFunctionAttrIfNotSet(F, "branch-target-enforcement", "true");
if (BPPLR)
SetFunctionAttrIfNotSet(F, "branch-protection-pauth-lr", "true");
if (GCS)
SetFunctionAttrIfNotSet(F, "guarded-control-stack", "true");
}
}

static bool isOldLoopArgument(Metadata *MD) {
auto *T = dyn_cast_or_null<MDTuple>(MD);
if (!T)
Expand Down
10 changes: 10 additions & 0 deletions llvm/lib/Linker/IRMover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1623,6 +1623,11 @@ Error IRLinker::run() {
// Loop over all of the linked values to compute type mappings.
computeTypeMapping();

// Convert module level attributes to function level attributes because
// after merging modules the attributes might change and would have different
// effect on the functions as the original module would have.
CopyModuleAttrToFunctions(*SrcM);

std::reverse(Worklist.begin(), Worklist.end());
while (!Worklist.empty()) {
GlobalValue *GV = Worklist.back();
Expand Down Expand Up @@ -1787,6 +1792,11 @@ IRMover::IRMover(Module &M) : Composite(M) {
for (const auto *MD : StructTypes.getVisitedMetadata()) {
SharedMDs[MD].reset(const_cast<MDNode *>(MD));
}

// Convert module level attributes to function level attributes because
// after merging modules the attributes might change and would have different
// effect on the functions as the original module would have.
CopyModuleAttrToFunctions(M);
}

Error IRMover::move(std::unique_ptr<Module> Src,
Expand Down
22 changes: 22 additions & 0 deletions llvm/test/LTO/AArch64/Inputs/bar.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

define dso_local void @bar() #0 {
entry:
ret void
}

define dso_local void @baz() #1 {
entry:
ret void
}

attributes #0 = { noinline nounwind optnone uwtable }
attributes #1 = { noinline nounwind optnone uwtable "branch-target-enforcement"="true" }

!llvm.module.flags = !{!0, !1, !2, !3}

!0 = !{i32 8, !"branch-target-enforcement", i32 2}
!1 = !{i32 8, !"sign-return-address", i32 2}
!2 = !{i32 8, !"sign-return-address-all", i32 2}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 2}
3 changes: 3 additions & 0 deletions llvm/test/LTO/AArch64/link-branch-target-enforcement.ll
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ entry:

; CHECK-NOT: linking module flags 'branch-target-enforcement': IDs have conflicting values in
; CHECK-DUMP: <main>:
; CHECK-DUMP: paciasp
; CHECK-DUMP: str
; CHECK-DUMP: bl 0x8 <main+0x8>
; CHECK-DUMP: <foo>:
; CHECK-DUMP: pacibsp

; `main` doesn't support BTI while `foo` does, so in the binary
; we should see only PAC which is supported by both.
Expand Down
56 changes: 56 additions & 0 deletions llvm/test/LTO/AArch64/link-sign-return-address.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
; Testcase to check that module with different sign return address can
; be mixed.
;
; RUN: llvm-as %s -o %t1.bc
; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc
; RUN: llvm-as %p/Inputs/bar.ll -o %t3.bc
; RUN: llvm-lto -exported-symbol main \
; RUN: -exported-symbol foo \
; RUN: -filetype=obj \
; RUN: %t3.bc %t2.bc %t1.bc \
; RUN: -o %t1.exe 2>&1
; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s

target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64-unknown-linux-gnu"

declare i32 @foo();
declare void @baz();
declare void @bar();

define i32 @main() {
entry:
%add = call i32 @foo()
call void @bar()
call void @baz()
ret i32 %add
}

!llvm.module.flags = !{!0, !1, !2, !3 }
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
!1 = !{i32 8, !"sign-return-address", i32 0}
!2 = !{i32 8, !"sign-return-address-all", i32 0}
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}


; CHECK-DUMP: <bar>:
; CHECK-DUMP: ret
; CHECK-DUMP: <baz>:
; CHECK-DUMP: bti c
; CHECK-DUMP: ret
; CHECK-DUMP: <foo>:
; CHECK-DUMP: pacibsp
; CHECK-DUMP: mov w0, #0x2a
; CHECK-DUMP: autibsp
; CHECK-DUMP: ret
; CHECK-DUMP: <main>:
; CHECK-DUMP-NOT: paciasp
; CHECK-DUMP: str x30,
; CHECK-DUMP: bl 0x20 <main+0x4>
; CHECK-DUMP: bl 0x0 <bar>
; CHECK-DUMP: bl 0x4 <baz>

; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
; we should not see anything.
; CHECK-PROP-NOT: Properties: aarch64 feature: PAC
6 changes: 3 additions & 3 deletions llvm/test/Linker/link-arm-and-thumb.ll
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ entry:
ret i32 %add
}

; CHECK: define i32 @main() {
; CHECK: define i32 @main()
; CHECK: define i32 @foo(i32 %a, i32 %b) [[ARM_ATTRS:#[0-9]+]]
; CHECK: define i32 @bar(i32 %a, i32 %b) [[THUMB_ATTRS:#[0-9]+]]

; CHECK: attributes [[ARM_ATTRS]] = { "target-features"="-thumb-mode" }
; CHECK: attributes [[THUMB_ATTRS]] = { "target-features"="+thumb-mode" }
; CHECK: attributes [[ARM_ATTRS]] = {{{.*}}"target-features"="-thumb-mode" }
; CHECK: attributes [[THUMB_ATTRS]] = {{{.*}}"target-features"="+thumb-mode" }

; STDERR-NOT: warning: Linking two modules of different target triples: