Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 26cfc26

Browse files
committedMar 23, 2016
Auto merge of #32410 - Ticki:master, r=eddyb
Add support for naked functions See rust-lang/rfcs#1201 (comment) This PR adds `#[naked]` for marking naked functions.
2 parents d6af19b + 4869417 commit 26cfc26

File tree

5 files changed

+110
-0
lines changed

5 files changed

+110
-0
lines changed
 

‎src/doc/reference.md

+2
Original file line numberDiff line numberDiff line change
@@ -1905,6 +1905,8 @@ type int8_t = i8;
19051905
- `should_panic` - indicates that this test function should panic, inverting the success condition.
19061906
- `cold` - The function is unlikely to be executed, so optimize it (and calls
19071907
to it) differently.
1908+
- `naked` - The function utilizes a custom ABI or custom inline ASM that requires
1909+
epilogue and prologue to be skipped.
19081910

19091911
### Static-only attributes
19101912

‎src/librustc_trans/trans/attributes.rs

+14
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
8181
}
8282
}
8383

84+
/// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
85+
#[inline]
86+
pub fn naked(val: ValueRef, is_naked: bool) {
87+
if is_naked {
88+
llvm::SetFunctionAttribute(val, llvm::Attribute::Naked);
89+
} else {
90+
unsafe {
91+
llvm::LLVMRemoveFunctionAttr(val, llvm::Attribute::Naked.bits() as c_ulonglong);
92+
}
93+
}
94+
}
95+
8496
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
8597
/// attributes.
8698
pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
@@ -105,6 +117,8 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
105117
if attr.check_name("cold") {
106118
llvm::Attributes::default().set(llvm::Attribute::Cold)
107119
.apply_llfn(llvm::FunctionIndex as usize, llfn)
120+
} else if attr.check_name("naked") {
121+
naked(llfn, true);
108122
} else if attr.check_name("allocator") {
109123
llvm::Attributes::default().set(llvm::Attribute::NoAlias)
110124
.apply_llfn(llvm::ReturnIndex as usize, llfn)

‎src/libsyntax/feature_gate.rs

+6
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
212212
// rust runtime internal
213213
("unwind_attributes", "1.4.0", None, Active),
214214

215+
// allow the use of `#[naked]` on functions.
216+
("naked_functions", "1.9.0", None, Active),
217+
215218
// allow empty structs and enum variants with braces
216219
("braced_empty_structs", "1.5.0", Some(29720), Accepted),
217220

@@ -376,6 +379,9 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
376379
// FIXME: #14406 these are processed in trans, which happens after the
377380
// lint pass
378381
("cold", Whitelisted, Ungated),
382+
("naked", Whitelisted, Gated("naked_functions",
383+
"the `#[naked]` attribute \
384+
is an experimental feature")),
379385
("export_name", Whitelisted, Ungated),
380386
("inline", Whitelisted, Ungated),
381387
("link", Whitelisted, Ungated),

‎src/test/codegen/naked-functions.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
13+
// compile-flags: -C no-prepopulate-passes
14+
15+
#![crate_type = "lib"]
16+
#![feature(naked_functions)]
17+
18+
// CHECK: Function Attrs: naked uwtable
19+
// CHECK-NEXT: define internal void @naked_empty()
20+
#[no_mangle]
21+
#[naked]
22+
fn naked_empty() {
23+
// CHECK: ret void
24+
}
25+
26+
// CHECK: Function Attrs: naked uwtable
27+
#[no_mangle]
28+
#[naked]
29+
// CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}})
30+
fn naked_with_args(a: isize) {
31+
// CHECK: %a = alloca i{{[0-9]+}}
32+
// CHECK: ret void
33+
}
34+
35+
// CHECK: Function Attrs: naked uwtable
36+
// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_return()
37+
#[no_mangle]
38+
#[naked]
39+
fn naked_with_return() -> isize {
40+
// CHECK: ret i{{[0-9]+}} 0
41+
0
42+
}
43+
44+
// CHECK: Function Attrs: naked uwtable
45+
// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
46+
#[no_mangle]
47+
#[naked]
48+
fn naked_with_args_and_return(a: isize) -> isize {
49+
// CHECK: %a = alloca i{{[0-9]+}}
50+
// CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
51+
a
52+
}
53+
54+
// CHECK: Function Attrs: naked uwtable
55+
// CHECK-NEXT: define internal void @naked_recursive()
56+
#[no_mangle]
57+
#[naked]
58+
fn naked_recursive() {
59+
// CHECK: call void @naked_empty()
60+
naked_empty();
61+
// CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
62+
naked_with_args(
63+
// CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
64+
naked_with_args_and_return(
65+
// CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
66+
naked_with_return()
67+
)
68+
);
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[naked]
12+
//~^ the `#[naked]` attribute is an experimental feature
13+
fn naked() {}
14+
15+
#[naked]
16+
//~^ the `#[naked]` attribute is an experimental feature
17+
fn naked_2() -> isize {
18+
0
19+
}

0 commit comments

Comments
 (0)
Failed to load comments.