about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-08-22 15:20:48 +0000
committerbors <bors@rust-lang.org>2014-08-22 15:20:48 +0000
commit36789fbbc5568b71c1eee85bcc20ffbdcf79f7a4 (patch)
treee06efaa2feae9fffd5a0f178f61869a9c18de2ab
parentc9cf3b3cc4d1d4eed359be54f08ba2b5fe961bf1 (diff)
parent171c54296586bd08f0cfd49098515bef045a059b (diff)
downloadrust-36789fbbc5568b71c1eee85bcc20ffbdcf79f7a4.tar.gz
rust-36789fbbc5568b71c1eee85bcc20ffbdcf79f7a4.zip
auto merge of #16656 : luqmana/rust/ucmla, r=pcwalton
Gets rid of a FIXME in `base::get_fn_llvm_attributes`.

r? @pcwalton
-rw-r--r--src/librustc/middle/trans/base.rs40
1 files changed, 29 insertions, 11 deletions
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index e3dfd4f534d..043636a32c0 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2240,26 +2240,44 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
         ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false),
         ty::ty_unboxed_closure(closure_did, _) => {
             let unboxed_closures = ccx.tcx.unboxed_closures.borrow();
-            let function_type = unboxed_closures.get(&closure_did)
-                                                .closure_type
-                                                .clone();
+            let ref function_type = unboxed_closures.get(&closure_did)
+                                                    .closure_type;
+
             (function_type.sig.clone(), RustCall, true)
         }
-        _ => fail!("expected closure or function.")
+        _ => ccx.sess().bug("expected closure or function.")
     };
 
+
     // Since index 0 is the return value of the llvm func, we start
     // at either 1 or 2 depending on whether there's an env slot or not
     let mut first_arg_offset = if has_env { 2 } else { 1 };
     let mut attrs = llvm::AttrBuilder::new();
     let ret_ty = fn_sig.output;
 
-    // These have an odd calling convention, so we skip them for now.
-    //
-    // FIXME(pcwalton): We don't have to skip them; just untuple the result.
-    if abi == RustCall {
-        return attrs;
-    }
+    // These have an odd calling convention, so we need to manually
+    // unpack the input ty's
+    let input_tys = match ty::get(fn_ty).sty {
+        ty::ty_unboxed_closure(_, _) => {
+            assert!(abi == RustCall);
+
+            match ty::get(fn_sig.inputs[0]).sty {
+                ty::ty_nil => Vec::new(),
+                ty::ty_tup(ref inputs) => inputs.clone(),
+                _ => ccx.sess().bug("expected tuple'd inputs")
+            }
+        },
+        ty::ty_bare_fn(_) if abi == RustCall => {
+            let inputs = vec![fn_sig.inputs[0]];
+
+            match ty::get(fn_sig.inputs[1]).sty {
+                ty::ty_nil => inputs,
+                ty::ty_tup(ref t_in) => inputs.append(t_in.as_slice()),
+                _ => ccx.sess().bug("expected tuple'd inputs")
+            }
+        }
+        _ => fn_sig.inputs.clone()
+    };
 
     // A function pointer is called without the declaration
     // available, so we have to apply any attributes with ABI
@@ -2315,7 +2333,7 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t)
         }
     }
 
-    for (idx, &t) in fn_sig.inputs.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
+    for (idx, &t) in input_tys.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
         match ty::get(t).sty {
             // this needs to be first to prevent fat pointers from falling through
             _ if !type_is_immediate(ccx, t) => {