Auto merge of #32410 - Ticki:master, r=eddyb
Add support for naked functions See https://github.com/rust-lang/rfcs/pull/1201#issuecomment-199442239 This PR adds `#[naked]` for marking naked functions.
This commit is contained in:
commit
26cfc269a0
@ -1905,6 +1905,8 @@ type int8_t = i8;
|
||||
- `should_panic` - indicates that this test function should panic, inverting the success condition.
|
||||
- `cold` - The function is unlikely to be executed, so optimize it (and calls
|
||||
to it) differently.
|
||||
- `naked` - The function utilizes a custom ABI or custom inline ASM that requires
|
||||
epilogue and prologue to be skipped.
|
||||
|
||||
### Static-only attributes
|
||||
|
||||
|
@ -81,6 +81,18 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue.
|
||||
#[inline]
|
||||
pub fn naked(val: ValueRef, is_naked: bool) {
|
||||
if is_naked {
|
||||
llvm::SetFunctionAttribute(val, llvm::Attribute::Naked);
|
||||
} else {
|
||||
unsafe {
|
||||
llvm::LLVMRemoveFunctionAttr(val, llvm::Attribute::Naked.bits() as c_ulonglong);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
|
||||
/// attributes.
|
||||
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
|
||||
if attr.check_name("cold") {
|
||||
llvm::Attributes::default().set(llvm::Attribute::Cold)
|
||||
.apply_llfn(llvm::FunctionIndex as usize, llfn)
|
||||
} else if attr.check_name("naked") {
|
||||
naked(llfn, true);
|
||||
} else if attr.check_name("allocator") {
|
||||
llvm::Attributes::default().set(llvm::Attribute::NoAlias)
|
||||
.apply_llfn(llvm::ReturnIndex as usize, llfn)
|
||||
|
@ -212,6 +212,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
|
||||
// rust runtime internal
|
||||
("unwind_attributes", "1.4.0", None, Active),
|
||||
|
||||
// allow the use of `#[naked]` on functions.
|
||||
("naked_functions", "1.9.0", None, Active),
|
||||
|
||||
// allow empty structs and enum variants with braces
|
||||
("braced_empty_structs", "1.5.0", Some(29720), Accepted),
|
||||
|
||||
@ -376,6 +379,9 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
|
||||
// FIXME: #14406 these are processed in trans, which happens after the
|
||||
// lint pass
|
||||
("cold", Whitelisted, Ungated),
|
||||
("naked", Whitelisted, Gated("naked_functions",
|
||||
"the `#[naked]` attribute \
|
||||
is an experimental feature")),
|
||||
("export_name", Whitelisted, Ungated),
|
||||
("inline", Whitelisted, Ungated),
|
||||
("link", Whitelisted, Ungated),
|
||||
|
69
src/test/codegen/naked-functions.rs
Normal file
69
src/test/codegen/naked-functions.rs
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// compile-flags: -C no-prepopulate-passes
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(naked_functions)]
|
||||
|
||||
// CHECK: Function Attrs: naked uwtable
|
||||
// CHECK-NEXT: define internal void @naked_empty()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
fn naked_empty() {
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked uwtable
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
// CHECK-NEXT: define internal void @naked_with_args(i{{[0-9]+}})
|
||||
fn naked_with_args(a: isize) {
|
||||
// CHECK: %a = alloca i{{[0-9]+}}
|
||||
// CHECK: ret void
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked uwtable
|
||||
// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_return()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
fn naked_with_return() -> isize {
|
||||
// CHECK: ret i{{[0-9]+}} 0
|
||||
0
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked uwtable
|
||||
// CHECK-NEXT: define internal i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}})
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
fn naked_with_args_and_return(a: isize) -> isize {
|
||||
// CHECK: %a = alloca i{{[0-9]+}}
|
||||
// CHECK: ret i{{[0-9]+}} %{{[0-9]+}}
|
||||
a
|
||||
}
|
||||
|
||||
// CHECK: Function Attrs: naked uwtable
|
||||
// CHECK-NEXT: define internal void @naked_recursive()
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
fn naked_recursive() {
|
||||
// CHECK: call void @naked_empty()
|
||||
naked_empty();
|
||||
// CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return()
|
||||
naked_with_args(
|
||||
// CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}})
|
||||
naked_with_args_and_return(
|
||||
// CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}})
|
||||
naked_with_return()
|
||||
)
|
||||
);
|
||||
}
|
19
src/test/compile-fail/gated-naked_functions.rs
Normal file
19
src/test/compile-fail/gated-naked_functions.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#[naked]
|
||||
//~^ the `#[naked]` attribute is an experimental feature
|
||||
fn naked() {}
|
||||
|
||||
#[naked]
|
||||
//~^ the `#[naked]` attribute is an experimental feature
|
||||
fn naked_2() -> isize {
|
||||
0
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user