Skip to content

Commit 9253536

Browse files
[llvm][AArch64] Autoupgrade function attributes from Module attributes. (#80640)
Refactored.
1 parent 335d34d commit 9253536

File tree

6 files changed

+122
-3
lines changed

6 files changed

+122
-3
lines changed

llvm/include/llvm/IR/AutoUpgrade.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ namespace llvm {
8888
/// info. Return true if module is modified.
8989
bool UpgradeDebugInfo(Module &M);
9090

91+
/// Copies module attributes to the functions in the module.
92+
void CopyModuleAttrToFunctions(Module &M);
93+
9194
/// Check whether a string looks like an old loop attachment tag.
9295
inline bool mayBeOldLoopAttachmentTag(StringRef Name) {
9396
return Name.starts_with("llvm.vectorizer.");

llvm/lib/IR/AutoUpgrade.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5169,6 +5169,72 @@ void llvm::UpgradeFunctionAttributes(Function &F) {
51695169
Arg.removeAttrs(AttributeFuncs::typeIncompatible(Arg.getType()));
51705170
}
51715171

5172+
// Check if the module attribute is present and not zero.
5173+
static bool isModuleAttributeSet(Module &M, const StringRef &ModAttr) {
5174+
const auto *Attr =
5175+
mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(ModAttr));
5176+
return Attr && Attr->getZExtValue();
5177+
}
5178+
5179+
// Copy an attribute from module to the function if exists.
5180+
// First value of the pair is used when the module attribute is not zero
5181+
// the second otherwise.
5182+
static void
5183+
CopyModuleAttributeToFunction(Function &F, StringRef FnAttrName,
5184+
StringRef ModAttrName,
5185+
std::pair<StringRef, StringRef> Values) {
5186+
if (F.hasFnAttribute(FnAttrName))
5187+
return;
5188+
F.addFnAttr(FnAttrName, isModuleAttributeSet(*F.getParent(), ModAttrName)
5189+
? Values.first
5190+
: Values.second);
5191+
}
5192+
5193+
// Copy a boolean attribute from module to the function if exists.
5194+
// Module attribute treated false if zero otherwise true.
5195+
static void CopyModuleAttributeToFunction(Function &F, StringRef AttrName) {
5196+
CopyModuleAttributeToFunction(
5197+
F, AttrName, AttrName,
5198+
std::make_pair<StringRef, StringRef>("true", "false"));
5199+
}
5200+
5201+
// Copy an attribute from module to the function if exists.
5202+
// First value of the pair is used when the module attribute is not zero
5203+
// the second otherwise.
5204+
static void
5205+
CopyModuleAttributeToFunction(Function &F, StringRef AttrName,
5206+
std::pair<StringRef, StringRef> Values) {
5207+
CopyModuleAttributeToFunction(F, AttrName, AttrName, Values);
5208+
}
5209+
5210+
void llvm::CopyModuleAttrToFunctions(Module &M) {
5211+
Triple T(M.getTargetTriple());
5212+
if (!T.isThumb() && !T.isARM() && !T.isAArch64())
5213+
return;
5214+
5215+
for (Function &F : M.getFunctionList()) {
5216+
if (F.isDeclaration())
5217+
continue;
5218+
5219+
if (!F.hasFnAttribute("sign-return-address")) {
5220+
StringRef SignType = "none";
5221+
if (isModuleAttributeSet(M, "sign-return-address"))
5222+
SignType = "non-leaf";
5223+
5224+
if (isModuleAttributeSet(M, "sign-return-address-all"))
5225+
SignType = "all";
5226+
5227+
F.addFnAttr("sign-return-address", SignType);
5228+
}
5229+
CopyModuleAttributeToFunction(F, "branch-target-enforcement");
5230+
CopyModuleAttributeToFunction(F, "branch-protection-pauth-lr");
5231+
CopyModuleAttributeToFunction(F, "guarded-control-stack");
5232+
CopyModuleAttributeToFunction(
5233+
F, "sign-return-address-key",
5234+
std::make_pair<StringRef, StringRef>("b_key", "a_key"));
5235+
}
5236+
}
5237+
51725238
static bool isOldLoopArgument(Metadata *MD) {
51735239
auto *T = dyn_cast_or_null<MDTuple>(MD);
51745240
if (!T)

llvm/lib/Linker/IRMover.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,11 @@ Error IRLinker::run() {
16061606
// Loop over all of the linked values to compute type mappings.
16071607
computeTypeMapping();
16081608

1609+
// Convert module level attributes to function level attributes because
1610+
// after merging modules the attributes might change and would have different
1611+
// effect on the functions as the original module would have.
1612+
CopyModuleAttributesToFunction(*SrcM);
1613+
16091614
std::reverse(Worklist.begin(), Worklist.end());
16101615
while (!Worklist.empty()) {
16111616
GlobalValue *GV = Worklist.back();

llvm/test/LTO/AArch64/link-branch-target-enforcement.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ entry:
3232
; CHECK-DUMP: <main>:
3333
; CHECK-DUMP: bl 0x8 <main+0x8>
3434
; CHECK-DUMP: <foo>:
35+
; CHECK-DUMP: paciasp
3536

3637
; `main` doesn't support BTI while `foo` does, so in the binary
3738
; we should see only PAC which is supported by both.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; Testcase to check that module with different branch-target-enforcement can
2+
; be mixed.
3+
;
4+
; RUN: llvm-as %s -o %t1.bc
5+
; RUN: llvm-as %p/Inputs/foo.ll -o %t2.bc
6+
; RUN: llvm-lto -exported-symbol main \
7+
; RUN: -exported-symbol foo \
8+
; RUN: -filetype=obj \
9+
; RUN: %t2.bc %t1.bc \
10+
; RUN: -o %t1.exe 2>&1
11+
; RUN: llvm-objdump -d %t1.exe | FileCheck --check-prefix=CHECK-DUMP %s
12+
; RUN: llvm-readelf -n %t1.exe | FileCheck --allow-empty --check-prefix=CHECK-PROP %s
13+
14+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
15+
target triple = "aarch64-unknown-linux-gnu"
16+
17+
declare i32 @foo();
18+
19+
define i32 @main() {
20+
entry:
21+
%add = call i32 @foo()
22+
ret i32 %add
23+
}
24+
25+
!llvm.module.flags = !{!0, !1, !2, !3 }
26+
!0 = !{i32 8, !"branch-target-enforcement", i32 0}
27+
!1 = !{i32 8, !"sign-return-address", i32 0}
28+
!2 = !{i32 8, !"sign-return-address-all", i32 0}
29+
!3 = !{i32 8, !"sign-return-address-with-bkey", i32 0}
30+
31+
; CHECK-DUMP: <foo>:
32+
; CHECK-DUMP: paciasp
33+
; CHECK-DUMP: mov w0, #0x2a
34+
; CHECK-DUMP: autiasp
35+
; CHECK-DUMP: ret
36+
; CHECK-DUMP: <main>:
37+
; CHECK-DUMP-NOT: paciasp
38+
; CHECK-DUMP: str x30,
39+
; CHECK-DUMP: bl 0x14 <main+0x4>
40+
41+
; `main` doesn't support PAC sign-return-address while `foo` does, so in the binary
42+
; we should not see anything.
43+
; CHECK-PROP-NOT: Properties: aarch64 feature: PAC

llvm/test/Linker/link-arm-and-thumb.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,12 @@ entry:
1313
ret i32 %add
1414
}
1515

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

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

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

0 commit comments

Comments
 (0)