about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-09-16 01:30:52 -0700
committerbors <bors@rust-lang.org>2013-09-16 01:30:52 -0700
commit610c0cdf11ea350793fa9a7b9d0af96f8ed5ab94 (patch)
tree93700681637cc30564f991d31fca07abcd252df8
parentb05dccacaeb5986897aa132e4fd9c07426106f49 (diff)
parent297ac739d8e7891bfaa4d73f8126371c2c13425f (diff)
downloadrust-610c0cdf11ea350793fa9a7b9d0af96f8ed5ab94.tar.gz
rust-610c0cdf11ea350793fa9a7b9d0af96f8ed5ab94.zip
auto merge of #9196 : alexcrichton/rust/attempting-9055, r=cmr
Beforehand it was assumed that the standard cdecl abi was used for all extern
fns of extern crates, but this reads the abi of the extern fn type and declares
the function in the local crate with the appropriate type.

I was trying to think of how to write a test for this, but I was just drawing up blanks :(. Are there standard functions in libc which are not of the cdecl abi? If so we could try linking to them and make sure that the cal completes successfully.

Otherwise, I manually verified that the function was declared correctly by looking at the llvm assembly.

cc #9055 (I'm not sure if this will fix that issue)
-rw-r--r--src/librustc/middle/trans/base.rs33
-rw-r--r--src/librustc/middle/trans/foreign.rs5
2 files changed, 25 insertions, 13 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 4d1ea783c39..c06fcbea222 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -86,7 +86,7 @@ use syntax::parse::token;
 use syntax::parse::token::{special_idents};
 use syntax::print::pprust::stmt_to_str;
 use syntax::{ast, ast_util, codemap, ast_map};
-use syntax::abi::{X86, X86_64, Arm, Mips};
+use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
 use syntax::visit;
 use syntax::visit::Visitor;
 
@@ -813,15 +813,28 @@ pub fn trans_external_path(ccx: &mut CrateContext, did: ast::DefId, t: ty::t)
     -> ValueRef {
     let name = csearch::get_symbol(ccx.sess.cstore, did);
     match ty::get(t).sty {
-      ty::ty_bare_fn(_) | ty::ty_closure(_) => {
-        let llty = type_of_fn_from_ty(ccx, t);
-        return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
-                             lib::llvm::CCallConv, llty);
-      }
-      _ => {
-        let llty = type_of(ccx, t);
-        return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
-      }
+        ty::ty_bare_fn(ref fn_ty) => {
+            // Currently llvm_calling_convention triggers unimpl/bug on
+            // Rust/RustIntrinsic, so those two are handled specially here.
+            let cconv = match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
+                Some(Rust) | Some(RustIntrinsic) => lib::llvm::CCallConv,
+                Some(*) | None => {
+                    let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
+                    c.unwrap_or(lib::llvm::CCallConv)
+                }
+            };
+            let llty = type_of_fn_from_ty(ccx, t);
+            return get_extern_fn(&mut ccx.externs, ccx.llmod, name, cconv, llty);
+        }
+        ty::ty_closure(_) => {
+            let llty = type_of_fn_from_ty(ccx, t);
+            return get_extern_fn(&mut ccx.externs, ccx.llmod, name,
+            lib::llvm::CCallConv, llty);
+        }
+        _ => {
+            let llty = type_of(ccx, t);
+            return get_extern_const(&mut ccx.externs, ccx.llmod, name, llty);
+        }
     };
 }
 
diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs
index 87755b4431c..1ebe402bbb9 100644
--- a/src/librustc/middle/trans/foreign.rs
+++ b/src/librustc/middle/trans/foreign.rs
@@ -74,9 +74,8 @@ struct LlvmSignature {
 ///////////////////////////////////////////////////////////////////////////
 // Calls to external functions
 
-fn llvm_calling_convention(ccx: @mut CrateContext,
-                           abis: AbiSet)
-                           -> Option<CallConv> {
+pub fn llvm_calling_convention(ccx: &mut CrateContext,
+                               abis: AbiSet) -> Option<CallConv> {
     let arch = ccx.sess.targ_cfg.arch;
     abis.for_arch(arch).map(|abi| {
         match *abi {