Skip to content

Commit

Permalink
Auto merge of #32410 - Ticki:master, r=eddyb
Browse files Browse the repository at this point in the history
Add support for naked functions

See rust-lang/rfcs#1201 (comment)

This PR adds `#[naked]` for marking naked functions.
  • Loading branch information
bors committed Mar 23, 2016
2 parents d6af19b + 4869417 commit 26cfc26
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 14 additions & 0 deletions src/librustc_trans/trans/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down Expand Up @@ -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),
Expand Down
69 changes: 69 additions & 0 deletions src/test/codegen/naked-functions.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions src/test/compile-fail/gated-naked_functions.rs
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit 26cfc26

Please sign in to comment.