about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/middle/trans/base.rs87
-rw-r--r--src/librustc/middle/trans/foreign.rs20
-rw-r--r--src/librustc/middle/trans/glue.rs2
-rw-r--r--src/librustc/middle/trans/intrinsic.rs7
4 files changed, 59 insertions, 57 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 6fa3764fb37..37893c7fd4c 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -177,32 +177,57 @@ impl<'a> Drop for StatRecorder<'a> {
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
+fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
+           ty: Type, output: ty::t) -> ValueRef {
     let llfn: ValueRef = name.with_c_str(|buf| {
         unsafe {
             llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
         }
     });
 
+    match ty::get(output).sty {
+        // functions returning bottom may unwind, but can never return normally
+        ty::ty_bot => {
+            unsafe {
+                llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
+            }
+        }
+        // `~` pointer return values never alias because ownership is transferred
+        // FIXME #6750 ~Trait cannot be directly marked as
+        // noalias because the actual object pointer is nested.
+        ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
+        ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
+            unsafe {
+                llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
+            }
+        }
+        _ => {}
+    }
+
     lib::llvm::SetFunctionCallConv(llfn, cc);
     // Function addresses in Rust are never significant, allowing functions to be merged.
     lib::llvm::SetUnnamedAddr(llfn, true);
-    return llfn;
+
+    llfn
 }
 
 // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
-pub fn decl_cdecl_fn(llmod: ModuleRef, name: &str, ty: Type) -> ValueRef {
-    return decl_fn(llmod, name, lib::llvm::CCallConv, ty);
+pub fn decl_cdecl_fn(llmod: ModuleRef,
+                     name: &str,
+                     ty: Type,
+                     output: ty::t) -> ValueRef {
+    decl_fn(llmod, name, lib::llvm::CCallConv, ty, output)
 }
 
 // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
-pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef, name: &str,
-                     cc: lib::llvm::CallConv, ty: Type) -> ValueRef {
+pub fn get_extern_fn(externs: &mut ExternMap, llmod: ModuleRef,
+                     name: &str, cc: lib::llvm::CallConv,
+                     ty: Type, output: ty::t) -> ValueRef {
     match externs.find_equiv(&name) {
         Some(n) => return *n,
-        None => ()
+        None => {}
     }
-    let f = decl_fn(llmod, name, cc, ty);
+    let f = decl_fn(llmod, name, cc, ty, output);
     externs.insert(name.to_owned(), f);
     f
 }
@@ -233,24 +258,7 @@ fn decl_rust_fn(ccx: &CrateContext,
                 output: ty::t,
                 name: &str) -> ValueRef {
     let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
-    let llfn = decl_cdecl_fn(ccx.llmod, name, llfty);
-
-    match ty::get(output).sty {
-        // functions returning bottom may unwind, but can never return normally
-        ty::ty_bot => {
-            unsafe {
-                llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
-            }
-        }
-        // `~` pointer return values never alias because ownership is transferred
-        ty::ty_uniq(..) |
-        ty::ty_vec(_, ty::vstore_uniq) => {
-            unsafe {
-                llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
-            }
-        }
-        _ => ()
-    }
+    let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
 
     let uses_outptr = type_of::return_uses_outptr(ccx, output);
     let offset = if uses_outptr { 2 } else { 1 };
@@ -259,8 +267,10 @@ fn decl_rust_fn(ccx: &CrateContext,
         let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
         match ty::get(arg_ty).sty {
             // `~` pointer parameters never alias because ownership is transferred
-            ty::ty_uniq(..) |
-            ty::ty_vec(_, ty::vstore_uniq) |
+            // FIXME #6750 ~Trait cannot be directly marked as
+            // noalias because the actual object pointer is nested.
+            ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
+            ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
             ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, ..}) => {
                 unsafe {
                     llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
@@ -584,11 +594,8 @@ pub fn get_res_dtor(ccx: @CrateContext,
 
         {
             let mut externs = ccx.externs.borrow_mut();
-            get_extern_fn(externs.get(),
-                          ccx.llmod,
-                          name,
-                          lib::llvm::CCallConv,
-                          llty)
+            get_extern_fn(externs.get(), ccx.llmod, name,
+                          lib::llvm::CCallConv, llty, ty::mk_nil())
         }
     }
 }
@@ -919,7 +926,8 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
                     let cconv = c.unwrap_or(lib::llvm::CCallConv);
                     let llty = type_of_fn_from_ty(ccx, None, t);
                     let mut externs = ccx.externs.borrow_mut();
-                    get_extern_fn(externs.get(), ccx.llmod, name, cconv, llty)
+                    get_extern_fn(externs.get(), ccx.llmod, name,
+                                  cconv, llty, fn_ty.sig.output)
                 }
             }
         }
@@ -2535,13 +2543,13 @@ pub fn register_fn_llvmty(ccx: @CrateContext,
                           sym: ~str,
                           node_id: ast::NodeId,
                           cc: lib::llvm::CallConv,
-                          fn_ty: Type)
-                          -> ValueRef {
+                          fn_ty: Type,
+                          output: ty::t) -> ValueRef {
     debug!("register_fn_fuller creating fn for item {} with path {}",
            node_id,
            ast_map::path_to_str(item_path(ccx, &node_id), token::get_ident_interner()));
 
-    let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty);
+    let llfn = decl_fn(ccx.llmod, sym, cc, fn_ty, output);
     finish_register_fn(ccx, sp, sym, node_id, llfn);
     llfn
 }
@@ -2573,7 +2581,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
         let llfty = Type::func([ccx.int_type, Type::i8().ptr_to().ptr_to()],
                                &ccx.int_type);
 
-        let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty);
+        let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil());
         let llbb = "top".with_c_str(|buf| {
             unsafe {
                 llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf)
@@ -2977,7 +2985,8 @@ pub fn p2i(ccx: &CrateContext, v: ValueRef) -> ValueRef {
 macro_rules! ifn (
     ($intrinsics:ident, $name:expr, $args:expr, $ret:expr) => ({
         let name = $name;
-        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret));
+        // HACK(eddyb) dummy output type, shouln't affect anything.
+        let f = decl_cdecl_fn(llmod, name, Type::func($args, &$ret), ty::mk_nil());
         $intrinsics.insert(name, f);
     })
 )
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 304edb2c312..2b55c0aac0c 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -150,11 +150,8 @@ pub fn register_foreign_item_fn(ccx: @CrateContext,
     let llfn;
     {
         let mut externs = ccx.externs.borrow_mut();
-        llfn = base::get_extern_fn(externs.get(),
-                                   ccx.llmod,
-                                   lname,
-                                   cc,
-                                   llfn_ty);
+        llfn = base::get_extern_fn(externs.get(), ccx.llmod, lname,
+                                   cc, llfn_ty, tys.fn_sig.output);
     };
     add_argument_attributes(&tys, llfn);
 
@@ -417,19 +414,14 @@ pub fn register_rust_fn_with_foreign_abi(ccx: @CrateContext,
     let tys = foreign_types_for_id(ccx, node_id);
     let llfn_ty = lltype_for_fn_from_foreign_types(&tys);
     let t = ty::node_id_to_type(ccx.tcx, node_id);
-    let cconv = match ty::get(t).sty {
+    let (cconv, output) = match ty::get(t).sty {
         ty::ty_bare_fn(ref fn_ty) => {
             let c = llvm_calling_convention(ccx, fn_ty.abis);
-            c.unwrap_or(lib::llvm::CCallConv)
+            (c.unwrap_or(lib::llvm::CCallConv), fn_ty.sig.output)
         }
-        _ => lib::llvm::CCallConv
+        _ => fail!("expected bare fn in register_rust_fn_with_foreign_abi")
     };
-    let llfn = base::register_fn_llvmty(ccx,
-                                        sp,
-                                        sym,
-                                        node_id,
-                                        cconv,
-                                        llfn_ty);
+    let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty, output);
     add_argument_attributes(&tys, llfn);
     debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})",
            node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn));
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index 16a761a44db..2c081751cc8 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -592,7 +592,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type,
     let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
     debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
     note_unique_llvm_symbol(ccx, fn_nm);
-    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty);
+    let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty, ty::mk_nil());
     return llfn;
 }
 
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 126aa9e7be5..ff5c22e726a 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -431,9 +431,10 @@ pub fn trans_intrinsic(ccx: @CrateContext,
             // native function. There should be a general in-language
             // way to do this
             let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
-            let morestack_addr = decl_cdecl_fn(
-                bcx.ccx().llmod, "__morestack", llfty);
-            let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
+            let morestack_addr = decl_cdecl_fn(bcx.ccx().llmod, "__morestack",
+                                               llfty, ty::mk_nil());
+            let morestack_addr = PointerCast(bcx, morestack_addr,
+                                             Type::nil().ptr_to());
             Ret(bcx, morestack_addr);
         }
         "offset" => {