Skip to content

Commit 472c79c

Browse files
authored
[IR] Check that arguments of naked function are not used (llvm#104757)
Verify that the arguments of a naked function are not used. They can only be referenced via registers/stack in inline asm, not as IR values. Doing so will result in assertion failures in the backend. There's probably more that we should verify, though I'm not completely sure what the constraints are (would it be correct to require that naked functions are exactly an inline asm call + unreachable, or is more allowed?) Fixes llvm#104718.
1 parent 08a0dec commit 472c79c

File tree

7 files changed

+21
-13
lines changed

7 files changed

+21
-13
lines changed

llvm/docs/LangRef.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2046,7 +2046,8 @@ example:
20462046
attributes.
20472047
``naked``
20482048
This attribute disables prologue / epilogue emission for the
2049-
function. This can have very system-specific consequences.
2049+
function. This can have very system-specific consequences. The arguments of
2050+
a ``naked`` function can not be referenced through IR values.
20502051
``"no-inline-line-tables"``
20512052
When this attribute is set to true, the inliner discards source locations
20522053
when inlining code and instead uses the source location of the call site.

llvm/lib/IR/Verifier.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2777,6 +2777,10 @@ void Verifier::visitFunction(const Function &F) {
27772777
Check(!Attrs.hasAttrSomewhere(Attribute::ElementType),
27782778
"Attribute 'elementtype' can only be applied to a callsite.", &F);
27792779

2780+
if (Attrs.hasFnAttr(Attribute::Naked))
2781+
for (const Argument &Arg : F.args())
2782+
Check(Arg.use_empty(), "cannot use argument of naked function", &Arg);
2783+
27802784
// Check that this function meets the restrictions on this calling convention.
27812785
// Sometimes varargs is used for perfectly forwarding thunks, so some of these
27822786
// restrictions can be lifted.

llvm/test/Instrumentation/ThreadSanitizer/tsan_basic.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,12 @@ define void @SwiftErrorCall(ptr swifterror) sanitize_thread {
9898
ret void
9999
}
100100

101-
; CHECK-LABEL: @NakedTest(ptr %a)
102-
; CHECK-NEXT: call void @foo()
103-
; CHECK-NEXT: %tmp1 = load i32, ptr %a, align 4
104-
; CHECK-NEXT: ret i32 %tmp1
105-
define i32 @NakedTest(ptr %a) naked sanitize_thread {
106-
call void @foo()
101+
; CHECK-LABEL: @NakedTest()
102+
; CHECK-NEXT: %a = call ptr @foo()
103+
; CHECK-NEXT: %tmp1 = load i32, ptr %a, align 4
104+
; CHECK-NEXT: ret i32 %tmp1
105+
define i32 @NakedTest() naked sanitize_thread {
106+
%a = call ptr @foo()
107107
%tmp1 = load i32, ptr %a, align 4
108108
ret i32 %tmp1
109109
}

llvm/test/Transforms/Attributor/nonnull.ll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,10 +1048,8 @@ define internal void @naked(ptr dereferenceable(4) %a) naked {
10481048
; CHECK: Function Attrs: naked
10491049
; CHECK-LABEL: define {{[^@]+}}@naked
10501050
; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {
1051-
; CHECK-NEXT: call void @use_i32_ptr(ptr nocapture nofree noundef nonnull [[A]])
10521051
; CHECK-NEXT: ret void
10531052
;
1054-
call void @use_i32_ptr(ptr %a)
10551053
ret void
10561054
}
10571055
; Avoid nonnull as we do not touch optnone

llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ attributes #0 = {
8181

8282
; attributes to drop
8383
attributes #1 = {
84-
alignstack=16 convergent inaccessiblememonly inaccessiblemem_or_argmemonly naked
84+
alignstack=16 convergent inaccessiblememonly inaccessiblemem_or_argmemonly
8585
noreturn readonly argmemonly returns_twice speculatable "thunk"
8686
}

llvm/test/Transforms/FunctionAttrs/nonnull.ll

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,15 +1079,12 @@ define internal void @control(ptr dereferenceable(4) %a) {
10791079
define internal void @naked(ptr dereferenceable(4) %a) naked {
10801080
; FNATTRS-LABEL: define internal void @naked(
10811081
; FNATTRS-SAME: ptr dereferenceable(4) [[A:%.*]]) #[[ATTR10:[0-9]+]] {
1082-
; FNATTRS-NEXT: call void @use_i32_ptr(ptr [[A]])
10831082
; FNATTRS-NEXT: ret void
10841083
;
10851084
; ATTRIBUTOR-LABEL: define internal void @naked(
10861085
; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {
1087-
; ATTRIBUTOR-NEXT: call void @use_i32_ptr(ptr [[A]])
10881086
; ATTRIBUTOR-NEXT: ret void
10891087
;
1090-
call void @use_i32_ptr(ptr %a)
10911088
ret void
10921089
}
10931090
; Avoid nonnull as we do not touch optnone

llvm/test/Verifier/naked.ll

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
; CHECK: cannot use argument of naked function
4+
define void @test(ptr %ptr) naked {
5+
getelementptr i8, ptr %ptr, i64 1
6+
call void @llvm.trap()
7+
unreachable
8+
}

0 commit comments

Comments
 (0)