about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-10-20 23:13:48 -0400
committerDaniel Micay <danielmicay@gmail.com>2013-10-28 15:34:50 -0400
commit541e5f84d7ccbf02f8fdab6da0ff92f7ffbf0866 (patch)
tree322f1b094fe96327906dc66349d069c3d31cf745 /src
parentd664ca26357fad84b4bc48f903f4795d491ccfd1 (diff)
downloadrust-541e5f84d7ccbf02f8fdab6da0ff92f7ffbf0866.tar.gz
rust-541e5f84d7ccbf02f8fdab6da0ff92f7ffbf0866.zip
add support for the `cold` function attribute
This allows a function to marked as infrequently called, resulting in
any branch calling it to be considered colder.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lib/llvm.rs2
-rw-r--r--src/librustc/middle/trans/base.rs18
-rw-r--r--src/libstd/rt/borrowck.rs1
-rw-r--r--src/libstd/unstable/lang.rs2
-rw-r--r--src/rustllvm/RustWrapper.cpp5
-rw-r--r--src/rustllvm/rustllvm.def.in1
6 files changed, 23 insertions, 6 deletions
diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs
index aa899239d8b..64c6678ec5f 100644
--- a/src/librustc/lib/llvm.rs
+++ b/src/librustc/lib/llvm.rs
@@ -693,6 +693,8 @@ pub mod llvm {
         pub fn LLVMAddReturnAttribute(Fn: ValueRef, PA: c_uint);
         pub fn LLVMRemoveReturnAttribute(Fn: ValueRef, PA: c_uint);
 
+        pub fn LLVMAddColdAttribute(Fn: ValueRef);
+
         pub fn LLVMRemoveFunctionAttr(Fn: ValueRef,
                                       PA: c_ulonglong,
                                       HighPA: c_ulonglong);
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 74f9e2114e1..2f60b2bebce 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -202,19 +202,21 @@ pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
     f
 }
 
-pub fn get_extern_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
-                          name: &str) -> ValueRef {
+fn get_extern_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
+                      name: &str, did: ast::DefId) -> ValueRef {
     match ccx.externs.find_equiv(&name) {
         Some(n) => return *n,
         None => ()
     }
     let f = decl_rust_fn(ccx, inputs, output, name);
+    do csearch::get_item_attrs(ccx.tcx.cstore, did) |meta_items| {
+        set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f)
+    }
     ccx.externs.insert(name.to_owned(), f);
     f
 }
 
-pub fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t,
-                    name: &str) -> ValueRef {
+fn decl_rust_fn(ccx: &mut CrateContext, inputs: &[ty::t], output: ty::t, name: &str) -> ValueRef {
     let llfty = type_of_rust_fn(ccx, inputs, output);
     let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
 
@@ -481,6 +483,10 @@ pub fn set_llvm_fn_attrs(attrs: &[ast::Attribute], llfn: ValueRef) {
     if contains_name(attrs, "no_split_stack") {
         set_no_split_stack(llfn);
     }
+
+    if contains_name(attrs, "cold") {
+        unsafe { llvm::LLVMAddColdAttribute(llfn) }
+    }
 }
 
 pub fn set_always_inline(f: ValueRef) {
@@ -840,7 +846,7 @@ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) ->
         ty::ty_bare_fn(ref fn_ty) => {
             match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
                 Some(Rust) | Some(RustIntrinsic) => {
-                    get_extern_rust_fn(ccx, fn_ty.sig.inputs, fn_ty.sig.output, name)
+                    get_extern_rust_fn(ccx, fn_ty.sig.inputs, fn_ty.sig.output, name, did)
                 }
                 Some(*) | None => {
                     let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
@@ -851,7 +857,7 @@ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t) ->
             }
         }
         ty::ty_closure(ref f) => {
-            get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name)
+            get_extern_rust_fn(ccx, f.sig.inputs, f.sig.output, name, did)
         }
         _ => {
             let llty = type_of(ccx, t);
diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs
index 9d13e79464a..7fcd674009d 100644
--- a/src/libstd/rt/borrowck.rs
+++ b/src/libstd/rt/borrowck.rs
@@ -57,6 +57,7 @@ pub fn clear_task_borrow_list() {
     let _ = try_take_task_borrow_list();
 }
 
+#[cold]
 unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) -> ! {
     debug_borrow("fail_borrowed: ", box, 0, 0, file, line);
 
diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs
index 6dfb319d592..89126bf9c9c 100644
--- a/src/libstd/unstable/lang.rs
+++ b/src/libstd/unstable/lang.rs
@@ -16,11 +16,13 @@ use libc::{c_char, size_t, uintptr_t};
 use rt::task;
 use rt::borrowck;
 
+#[cold]
 #[lang="fail_"]
 pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
     task::begin_unwind(expr, file, line);
 }
 
+#[cold]
 #[lang="fail_bounds_check"]
 pub fn fail_bounds_check(file: *c_char, line: size_t, index: size_t, len: size_t) -> ! {
     let msg = format!("index out of bounds: the len is {} but the index is {}",
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index f8d56f4e892..0a148d334ab 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -365,6 +365,11 @@ extern "C" void LLVMRemoveReturnAttribute(LLVMValueRef Fn, LLVMAttribute PA) {
                       AttributeSet::get(A->getContext(), AttributeSet::ReturnIndex,  B));
 }
 
+extern "C" void LLVMAddColdAttribute(LLVMValueRef Fn) {
+  Function *A = unwrap<Function>(Fn);
+  A->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
+}
+
 extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
                                             LLVMValueRef source,
                                             const char* Name,
diff --git a/src/rustllvm/rustllvm.def.in b/src/rustllvm/rustllvm.def.in
index c1f1444fb4f..a6b887f058a 100644
--- a/src/rustllvm/rustllvm.def.in
+++ b/src/rustllvm/rustllvm.def.in
@@ -629,3 +629,4 @@ LLVMRustAddAlwaysInlinePass
 LLVMAddReturnAttribute
 LLVMRemoveReturnAttribute
 LLVMTypeToString
+LLVMAddColdAttribute