about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTicki <Ticki@users.noreply.github.com>2016-03-21 21:01:08 +0100
committerTicki <Ticki@users.noreply.github.com>2016-03-21 21:01:08 +0100
commit1605ab377bc2c9be97df2cfbab00e011d526e316 (patch)
treefa2e1a73245bd8a3ea2da7a1af6c1b68d2b362eb
parent0215681744bb1156ef686ab265ed71e4d5705b64 (diff)
downloadrust-1605ab377bc2c9be97df2cfbab00e011d526e316.tar.gz
rust-1605ab377bc2c9be97df2cfbab00e011d526e316.zip
Add support for naked functions
-rw-r--r--src/doc/reference.md2
-rw-r--r--src/librustc_trans/trans/attributes.rs14
-rw-r--r--src/libsyntax/feature_gate.rs6
3 files changed, 22 insertions, 0 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 4c5fd31b96e..3325749d94c 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -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
 
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index 99dc3ade823..4ea920c57aa 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -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)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index a017e62d546..ebd8db1b25c 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -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),