]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/trans/foreign.rs
Auto merge of #22541 - Manishearth:rollup, r=Gankro
[rust.git] / src / librustc_trans / trans / foreign.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use back::{link};
13 use llvm::{ValueRef, CallConv, get_param};
14 use llvm;
15 use middle::weak_lang_items;
16 use trans::base::{llvm_linkage_by_name, push_ctxt};
17 use trans::base;
18 use trans::build::*;
19 use trans::cabi;
20 use trans::common::*;
21 use trans::debuginfo::DebugLoc;
22 use trans::machine;
23 use trans::monomorphize;
24 use trans::type_::Type;
25 use trans::type_of::*;
26 use trans::type_of;
27 use middle::ty::{self, Ty};
28 use middle::subst::Substs;
29
30 use std::ffi::CString;
31 use std::cmp;
32 use libc::c_uint;
33 use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
34 use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
35 use syntax::codemap::Span;
36 use syntax::parse::token::{InternedString, special_idents};
37 use syntax::parse::token;
38 use syntax::{ast};
39 use syntax::{attr, ast_map};
40 use syntax::print::pprust;
41 use util::ppaux::Repr;
42
43 ///////////////////////////////////////////////////////////////////////////
44 // Type definitions
45
46 struct ForeignTypes<'tcx> {
47     /// Rust signature of the function
48     fn_sig: ty::FnSig<'tcx>,
49
50     /// Adapter object for handling native ABI rules (trust me, you
51     /// don't want to know)
52     fn_ty: cabi::FnType,
53
54     /// LLVM types that will appear on the foreign function
55     llsig: LlvmSignature,
56 }
57
58 struct LlvmSignature {
59     // LLVM versions of the types of this function's arguments.
60     llarg_tys: Vec<Type> ,
61
62     // LLVM version of the type that this function returns.  Note that
63     // this *may not be* the declared return type of the foreign
64     // function, because the foreign function may opt to return via an
65     // out pointer.
66     llret_ty: Type,
67
68     /// True if there is a return value (not bottom, not unit)
69     ret_def: bool,
70 }
71
72
73 ///////////////////////////////////////////////////////////////////////////
74 // Calls to external functions
75
76 pub fn llvm_calling_convention(ccx: &CrateContext,
77                                abi: Abi) -> CallConv {
78     match ccx.sess().target.target.adjust_abi(abi) {
79         RustIntrinsic => {
80             // Intrinsics are emitted at the call site
81             ccx.sess().bug("asked to register intrinsic fn");
82         }
83
84         Rust => {
85             // FIXME(#3678) Implement linking to foreign fns with Rust ABI
86             ccx.sess().unimpl("foreign functions with Rust ABI");
87         }
88
89         RustCall => {
90             // FIXME(#3678) Implement linking to foreign fns with Rust ABI
91             ccx.sess().unimpl("foreign functions with RustCall ABI");
92         }
93
94         // It's the ABI's job to select this, not us.
95         System => ccx.sess().bug("system abi should be selected elsewhere"),
96
97         Stdcall => llvm::X86StdcallCallConv,
98         Fastcall => llvm::X86FastcallCallConv,
99         C => llvm::CCallConv,
100         Win64 => llvm::X86_64_Win64,
101
102         // These API constants ought to be more specific...
103         Cdecl => llvm::CCallConv,
104         Aapcs => llvm::CCallConv,
105     }
106 }
107
108 pub fn register_static(ccx: &CrateContext,
109                        foreign_item: &ast::ForeignItem) -> ValueRef {
110     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
111     let llty = type_of::type_of(ccx, ty);
112
113     let ident = link_name(foreign_item);
114     match attr::first_attr_value_str_by_name(&foreign_item.attrs[],
115                                              "linkage") {
116         // If this is a static with a linkage specified, then we need to handle
117         // it a little specially. The typesystem prevents things like &T and
118         // extern "C" fn() from being non-null, so we can't just declare a
119         // static and call it a day. Some linkages (like weak) will make it such
120         // that the static actually has a null value.
121         Some(name) => {
122             let linkage = match llvm_linkage_by_name(&name) {
123                 Some(linkage) => linkage,
124                 None => {
125                     ccx.sess().span_fatal(foreign_item.span,
126                                           "invalid linkage specified");
127                 }
128             };
129             let llty2 = match ty.sty {
130                 ty::ty_ptr(ref mt) => type_of::type_of(ccx, mt.ty),
131                 _ => {
132                     ccx.sess().span_fatal(foreign_item.span,
133                                           "must have type `*T` or `*mut T`");
134                 }
135             };
136             unsafe {
137                 // Declare a symbol `foo` with the desired linkage.
138                 let buf = CString::new(ident.as_bytes()).unwrap();
139                 let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
140                                              buf.as_ptr());
141                 llvm::SetLinkage(g1, linkage);
142
143                 // Declare an internal global `extern_with_linkage_foo` which
144                 // is initialized with the address of `foo`.  If `foo` is
145                 // discarded during linking (for example, if `foo` has weak
146                 // linkage and there are no definitions), then
147                 // `extern_with_linkage_foo` will instead be initialized to
148                 // zero.
149                 let mut real_name = "_rust_extern_with_linkage_".to_string();
150                 real_name.push_str(&ident);
151                 let real_name = CString::new(real_name).unwrap();
152                 let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
153                                              real_name.as_ptr());
154                 llvm::SetLinkage(g2, llvm::InternalLinkage);
155                 llvm::LLVMSetInitializer(g2, g1);
156                 g2
157             }
158         }
159         None => unsafe {
160             // Generate an external declaration.
161             let buf = CString::new(ident.as_bytes()).unwrap();
162             llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
163         }
164     }
165 }
166
167 /// Registers a foreign function found in a library. Just adds a LLVM global.
168 pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
169                                           abi: Abi, fty: Ty<'tcx>,
170                                           name: &str) -> ValueRef {
171     debug!("register_foreign_item_fn(abi={}, \
172             ty={}, \
173             name={})",
174            abi.repr(ccx.tcx()),
175            fty.repr(ccx.tcx()),
176            name);
177
178     let cc = llvm_calling_convention(ccx, abi);
179
180     // Register the function as a C extern fn
181     let tys = foreign_types_for_fn_ty(ccx, fty);
182
183     // Make sure the calling convention is right for variadic functions
184     // (should've been caught if not in typeck)
185     if tys.fn_sig.variadic {
186         assert!(cc == llvm::CCallConv);
187     }
188
189     // Create the LLVM value for the C extern fn
190     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
191
192     let llfn = base::get_extern_fn(ccx,
193                                    &mut *ccx.externs().borrow_mut(),
194                                    name,
195                                    cc,
196                                    llfn_ty,
197                                    fty);
198     add_argument_attributes(&tys, llfn);
199
200     llfn
201 }
202
203 /// Prepares a call to a native function. This requires adapting
204 /// from the Rust argument passing rules to the native rules.
205 ///
206 /// # Parameters
207 ///
208 /// - `callee_ty`: Rust type for the function we are calling
209 /// - `llfn`: the function pointer we are calling
210 /// - `llretptr`: where to store the return value of the function
211 /// - `llargs_rust`: a list of the argument values, prepared
212 ///   as they would be if calling a Rust function
213 /// - `passed_arg_tys`: Rust type for the arguments. Normally we
214 ///   can derive these from callee_ty but in the case of variadic
215 ///   functions passed_arg_tys will include the Rust type of all
216 ///   the arguments including the ones not specified in the fn's signature.
217 pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
218                                      callee_ty: Ty<'tcx>,
219                                      llfn: ValueRef,
220                                      llretptr: ValueRef,
221                                      llargs_rust: &[ValueRef],
222                                      passed_arg_tys: Vec<Ty<'tcx>>,
223                                      call_debug_loc: DebugLoc)
224                                      -> Block<'blk, 'tcx>
225 {
226     let ccx = bcx.ccx();
227     let tcx = bcx.tcx();
228
229     debug!("trans_native_call(callee_ty={}, \
230             llfn={}, \
231             llretptr={})",
232            callee_ty.repr(tcx),
233            ccx.tn().val_to_string(llfn),
234            ccx.tn().val_to_string(llretptr));
235
236     let (fn_abi, fn_sig) = match callee_ty.sty {
237         ty::ty_bare_fn(_, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
238         _ => ccx.sess().bug("trans_native_call called on non-function type")
239     };
240     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
241     let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
242     let fn_type = cabi::compute_abi_info(ccx,
243                                          &llsig.llarg_tys[],
244                                          llsig.llret_ty,
245                                          llsig.ret_def);
246
247     let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys[];
248
249     let mut llargs_foreign = Vec::new();
250
251     // If the foreign ABI expects return value by pointer, supply the
252     // pointer that Rust gave us. Sometimes we have to bitcast
253     // because foreign fns return slightly different (but equivalent)
254     // views on the same type (e.g., i64 in place of {i32,i32}).
255     if fn_type.ret_ty.is_indirect() {
256         match fn_type.ret_ty.cast {
257             Some(ty) => {
258                 let llcastedretptr =
259                     BitCast(bcx, llretptr, ty.ptr_to());
260                 llargs_foreign.push(llcastedretptr);
261             }
262             None => {
263                 llargs_foreign.push(llretptr);
264             }
265         }
266     }
267
268     for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
269         let mut llarg_rust = llarg_rust;
270
271         if arg_tys[i].is_ignore() {
272             continue;
273         }
274
275         // Does Rust pass this argument by pointer?
276         let rust_indirect = type_of::arg_is_indirect(ccx, passed_arg_tys[i]);
277
278         debug!("argument {}, llarg_rust={}, rust_indirect={}, arg_ty={}",
279                i,
280                ccx.tn().val_to_string(llarg_rust),
281                rust_indirect,
282                ccx.tn().type_to_string(arg_tys[i].ty));
283
284         // Ensure that we always have the Rust value indirectly,
285         // because it makes bitcasting easier.
286         if !rust_indirect {
287             let scratch =
288                 base::alloca(bcx,
289                              type_of::type_of(ccx, passed_arg_tys[i]),
290                              "__arg");
291             base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
292             llarg_rust = scratch;
293         }
294
295         debug!("llarg_rust={} (after indirection)",
296                ccx.tn().val_to_string(llarg_rust));
297
298         // Check whether we need to do any casting
299         match arg_tys[i].cast {
300             Some(ty) => llarg_rust = BitCast(bcx, llarg_rust, ty.ptr_to()),
301             None => ()
302         }
303
304         debug!("llarg_rust={} (after casting)",
305                ccx.tn().val_to_string(llarg_rust));
306
307         // Finally, load the value if needed for the foreign ABI
308         let foreign_indirect = arg_tys[i].is_indirect();
309         let llarg_foreign = if foreign_indirect {
310             llarg_rust
311         } else {
312             if ty::type_is_bool(passed_arg_tys[i]) {
313                 let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, llvm::False);
314                 Trunc(bcx, val, Type::i1(bcx.ccx()))
315             } else {
316                 Load(bcx, llarg_rust)
317             }
318         };
319
320         debug!("argument {}, llarg_foreign={}",
321                i, ccx.tn().val_to_string(llarg_foreign));
322
323         // fill padding with undef value
324         match arg_tys[i].pad {
325             Some(ty) => llargs_foreign.push(C_undef(ty)),
326             None => ()
327         }
328         llargs_foreign.push(llarg_foreign);
329     }
330
331     let cc = llvm_calling_convention(ccx, fn_abi);
332
333     // A function pointer is called without the declaration available, so we have to apply
334     // any attributes with ABI implications directly to the call instruction.
335     let mut attrs = llvm::AttrBuilder::new();
336
337     // Add attributes that are always applicable, independent of the concrete foreign ABI
338     if fn_type.ret_ty.is_indirect() {
339         let llret_sz = machine::llsize_of_real(ccx, fn_type.ret_ty.ty);
340
341         // The outptr can be noalias and nocapture because it's entirely
342         // invisible to the program. We also know it's nonnull as well
343         // as how many bytes we can dereference
344         attrs.arg(1, llvm::NoAliasAttribute)
345              .arg(1, llvm::NoCaptureAttribute)
346              .arg(1, llvm::DereferenceableAttribute(llret_sz));
347     };
348
349     // Add attributes that depend on the concrete foreign ABI
350     let mut arg_idx = if fn_type.ret_ty.is_indirect() { 1 } else { 0 };
351     match fn_type.ret_ty.attr {
352         Some(attr) => { attrs.arg(arg_idx, attr); },
353         _ => ()
354     }
355
356     arg_idx += 1;
357     for arg_ty in &fn_type.arg_tys {
358         if arg_ty.is_ignore() {
359             continue;
360         }
361         // skip padding
362         if arg_ty.pad.is_some() { arg_idx += 1; }
363
364         if let Some(attr) = arg_ty.attr {
365             attrs.arg(arg_idx, attr);
366         }
367
368         arg_idx += 1;
369     }
370
371     let llforeign_retval = CallWithConv(bcx,
372                                         llfn,
373                                         &llargs_foreign[..],
374                                         cc,
375                                         Some(attrs),
376                                         call_debug_loc);
377
378     // If the function we just called does not use an outpointer,
379     // store the result into the rust outpointer. Cast the outpointer
380     // type to match because some ABIs will use a different type than
381     // the Rust type. e.g., a {u32,u32} struct could be returned as
382     // u64.
383     if llsig.ret_def && !fn_type.ret_ty.is_indirect() {
384         let llrust_ret_ty = llsig.llret_ty;
385         let llforeign_ret_ty = match fn_type.ret_ty.cast {
386             Some(ty) => ty,
387             None => fn_type.ret_ty.ty
388         };
389
390         debug!("llretptr={}", ccx.tn().val_to_string(llretptr));
391         debug!("llforeign_retval={}", ccx.tn().val_to_string(llforeign_retval));
392         debug!("llrust_ret_ty={}", ccx.tn().type_to_string(llrust_ret_ty));
393         debug!("llforeign_ret_ty={}", ccx.tn().type_to_string(llforeign_ret_ty));
394
395         if llrust_ret_ty == llforeign_ret_ty {
396             match fn_sig.output {
397                 ty::FnConverging(result_ty) => {
398                     base::store_ty(bcx, llforeign_retval, llretptr, result_ty)
399                 }
400                 ty::FnDiverging => {}
401             }
402         } else {
403             // The actual return type is a struct, but the ABI
404             // adaptation code has cast it into some scalar type.  The
405             // code that follows is the only reliable way I have
406             // found to do a transform like i64 -> {i32,i32}.
407             // Basically we dump the data onto the stack then memcpy it.
408             //
409             // Other approaches I tried:
410             // - Casting rust ret pointer to the foreign type and using Store
411             //   is (a) unsafe if size of foreign type > size of rust type and
412             //   (b) runs afoul of strict aliasing rules, yielding invalid
413             //   assembly under -O (specifically, the store gets removed).
414             // - Truncating foreign type to correct integral type and then
415             //   bitcasting to the struct type yields invalid cast errors.
416             let llscratch = base::alloca(bcx, llforeign_ret_ty, "__cast");
417             Store(bcx, llforeign_retval, llscratch);
418             let llscratch_i8 = BitCast(bcx, llscratch, Type::i8(ccx).ptr_to());
419             let llretptr_i8 = BitCast(bcx, llretptr, Type::i8(ccx).ptr_to());
420             let llrust_size = machine::llsize_of_store(ccx, llrust_ret_ty);
421             let llforeign_align = machine::llalign_of_min(ccx, llforeign_ret_ty);
422             let llrust_align = machine::llalign_of_min(ccx, llrust_ret_ty);
423             let llalign = cmp::min(llforeign_align, llrust_align);
424             debug!("llrust_size={}", llrust_size);
425             base::call_memcpy(bcx, llretptr_i8, llscratch_i8,
426                               C_uint(ccx, llrust_size), llalign as u32);
427         }
428     }
429
430     return bcx;
431 }
432
433 // feature gate SIMD types in FFI, since I (huonw) am not sure the
434 // ABIs are handled at all correctly.
435 fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
436     if !tcx.sess.features.borrow().simd_ffi {
437         let check = |ast_ty: &ast::Ty, ty: ty::Ty| {
438             if ty::type_is_simd(tcx, ty) {
439                 tcx.sess.span_err(ast_ty.span,
440                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
441                                         may result in invalid code",
442                                        pprust::ty_to_string(ast_ty))[]);
443                 tcx.sess.span_help(ast_ty.span,
444                                    "add #![feature(simd_ffi)] to the crate attributes to enable");
445             }
446         };
447         let sig = &ty.sig.0;
448         for (input, ty) in decl.inputs.iter().zip(sig.inputs.iter()) {
449             check(&*input.ty, *ty)
450         }
451         if let ast::Return(ref ty) = decl.output {
452             check(&**ty, sig.output.unwrap())
453         }
454     }
455 }
456
457 pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
458     let _icx = push_ctxt("foreign::trans_foreign_mod");
459     for foreign_item in &foreign_mod.items {
460         let lname = link_name(&**foreign_item);
461
462         if let ast::ForeignItemFn(ref decl, _) = foreign_item.node {
463             match foreign_mod.abi {
464                 Rust | RustIntrinsic => {}
465                 abi => {
466                     let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
467                     match ty.sty {
468                         ty::ty_bare_fn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
469                         _ => ccx.tcx().sess.span_bug(foreign_item.span,
470                                                      "foreign fn's sty isn't a bare_fn_ty?")
471                     }
472
473                     register_foreign_item_fn(ccx, abi, ty,
474                                              &lname);
475                     // Unlike for other items, we shouldn't call
476                     // `base::update_linkage` here.  Foreign items have
477                     // special linkage requirements, which are handled
478                     // inside `foreign::register_*`.
479                 }
480             }
481         }
482
483         ccx.item_symbols().borrow_mut().insert(foreign_item.id,
484                                              lname.to_string());
485     }
486 }
487
488 ///////////////////////////////////////////////////////////////////////////
489 // Rust functions with foreign ABIs
490 //
491 // These are normal Rust functions defined with foreign ABIs.  For
492 // now, and perhaps forever, we translate these using a "layer of
493 // indirection". That is, given a Rust declaration like:
494 //
495 //     extern "C" fn foo(i: u32) -> u32 { ... }
496 //
497 // we will generate a function like:
498 //
499 //     S foo(T i) {
500 //         S r;
501 //         foo0(&r, NULL, i);
502 //         return r;
503 //     }
504 //
505 //     #[inline_always]
506 //     void foo0(uint32_t *r, void *env, uint32_t i) { ... }
507 //
508 // Here the (internal) `foo0` function follows the Rust ABI as normal,
509 // where the `foo` function follows the C ABI. We rely on LLVM to
510 // inline the one into the other. Of course we could just generate the
511 // correct code in the first place, but this is much simpler.
512
513 pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
514                                                t: Ty<'tcx>,
515                                                name: &str)
516                                                -> ValueRef {
517     let tys = foreign_types_for_fn_ty(ccx, t);
518     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
519     let cconv = match t.sty {
520         ty::ty_bare_fn(_, ref fn_ty) => {
521             llvm_calling_convention(ccx, fn_ty.abi)
522         }
523         _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
524     };
525     let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil(ccx.tcx())));
526     add_argument_attributes(&tys, llfn);
527     debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
528            ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
529     llfn
530 }
531
532 pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
533                                          sp: Span,
534                                          sym: String,
535                                          node_id: ast::NodeId)
536                                          -> ValueRef {
537     let _icx = push_ctxt("foreign::register_foreign_fn");
538
539     let tys = foreign_types_for_id(ccx, node_id);
540     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
541     let t = ty::node_id_to_type(ccx.tcx(), node_id);
542     let cconv = match t.sty {
543         ty::ty_bare_fn(_, ref fn_ty) => {
544             llvm_calling_convention(ccx, fn_ty.abi)
545         }
546         _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
547     };
548     let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
549     add_argument_attributes(&tys, llfn);
550     debug!("register_rust_fn_with_foreign_abi(node_id={}, llfn_ty={}, llfn={})",
551            node_id, ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
552     llfn
553 }
554
555 pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
556                                                 decl: &ast::FnDecl,
557                                                 body: &ast::Block,
558                                                 attrs: &[ast::Attribute],
559                                                 llwrapfn: ValueRef,
560                                                 param_substs: &'tcx Substs<'tcx>,
561                                                 id: ast::NodeId,
562                                                 hash: Option<&str>) {
563     let _icx = push_ctxt("foreign::build_foreign_fn");
564
565     let fnty = ty::node_id_to_type(ccx.tcx(), id);
566     let mty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fnty);
567     let tys = foreign_types_for_fn_ty(ccx, mty);
568
569     unsafe { // unsafe because we call LLVM operations
570         // Build up the Rust function (`foo0` above).
571         let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
572
573         // Build up the foreign wrapper (`foo` above).
574         return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
575     }
576
577     fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
578                                decl: &ast::FnDecl,
579                                body: &ast::Block,
580                                param_substs: &'tcx Substs<'tcx>,
581                                attrs: &[ast::Attribute],
582                                id: ast::NodeId,
583                                hash: Option<&str>)
584                                -> ValueRef
585     {
586         let _icx = push_ctxt("foreign::foreign::build_rust_fn");
587         let tcx = ccx.tcx();
588         let t = ty::node_id_to_type(tcx, id);
589         let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
590
591         let ps = ccx.tcx().map.with_path(id, |path| {
592             let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
593             link::mangle(path.chain(abi.into_iter()), hash)
594         });
595
596         // Compute the type that the function would have if it were just a
597         // normal Rust function. This will be the type of the wrappee fn.
598         match t.sty {
599             ty::ty_bare_fn(_, ref f) => {
600                 assert!(f.abi != Rust && f.abi != RustIntrinsic);
601             }
602             _ => {
603                 ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {}, \
604                                         expected a bare fn ty",
605                                        ccx.tcx().map.path_to_string(id),
606                                        t.repr(tcx))[]);
607             }
608         };
609
610         debug!("build_rust_fn: path={} id={} t={}",
611                ccx.tcx().map.path_to_string(id),
612                id, t.repr(tcx));
613
614         let llfn = base::decl_internal_rust_fn(ccx, t, &ps[..]);
615         base::set_llvm_fn_attrs(ccx, attrs, llfn);
616         base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]);
617         llfn
618     }
619
620     unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
621                                       llrustfn: ValueRef,
622                                       llwrapfn: ValueRef,
623                                       tys: &ForeignTypes<'tcx>,
624                                       t: Ty<'tcx>) {
625         let _icx = push_ctxt(
626             "foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
627         let tcx = ccx.tcx();
628
629         debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
630                ccx.tn().val_to_string(llrustfn),
631                ccx.tn().val_to_string(llwrapfn),
632                t.repr(ccx.tcx()));
633
634         // Avoid all the Rust generation stuff and just generate raw
635         // LLVM here.
636         //
637         // We want to generate code like this:
638         //
639         //     S foo(T i) {
640         //         S r;
641         //         foo0(&r, NULL, i);
642         //         return r;
643         //     }
644
645         let ptr = "the block\0".as_ptr();
646         let the_block = llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn,
647                                                             ptr as *const _);
648
649         let builder = ccx.builder();
650         builder.position_at_end(the_block);
651
652         // Array for the arguments we will pass to the rust function.
653         let mut llrust_args = Vec::new();
654         let mut next_foreign_arg_counter: c_uint = 0;
655         let mut next_foreign_arg = |pad: bool| -> c_uint {
656             next_foreign_arg_counter += if pad {
657                 2
658             } else {
659                 1
660             };
661             next_foreign_arg_counter - 1
662         };
663
664         // If there is an out pointer on the foreign function
665         let foreign_outptr = {
666             if tys.fn_ty.ret_ty.is_indirect() {
667                 Some(get_param(llwrapfn, next_foreign_arg(false)))
668             } else {
669                 None
670             }
671         };
672
673         let rustfn_ty = Type::from_ref(llvm::LLVMTypeOf(llrustfn)).element_type();
674         let mut rust_param_tys = rustfn_ty.func_params().into_iter();
675         // Push Rust return pointer, using null if it will be unused.
676         let rust_uses_outptr = match tys.fn_sig.output {
677             ty::FnConverging(ret_ty) => type_of::return_uses_outptr(ccx, ret_ty),
678             ty::FnDiverging => false
679         };
680         let return_alloca: Option<ValueRef>;
681         let llrust_ret_ty = if rust_uses_outptr {
682             rust_param_tys.next().expect("Missing return type!").element_type()
683         } else {
684             rustfn_ty.return_type()
685         };
686         if rust_uses_outptr {
687             // Rust expects to use an outpointer. If the foreign fn
688             // also uses an outpointer, we can reuse it, but the types
689             // may vary, so cast first to the Rust type. If the
690             // foreign fn does NOT use an outpointer, we will have to
691             // alloca some scratch space on the stack.
692             match foreign_outptr {
693                 Some(llforeign_outptr) => {
694                     debug!("out pointer, foreign={}",
695                            ccx.tn().val_to_string(llforeign_outptr));
696                     let llrust_retptr =
697                         builder.bitcast(llforeign_outptr, llrust_ret_ty.ptr_to());
698                     debug!("out pointer, foreign={} (casted)",
699                            ccx.tn().val_to_string(llrust_retptr));
700                     llrust_args.push(llrust_retptr);
701                     return_alloca = None;
702                 }
703
704                 None => {
705                     let slot = builder.alloca(llrust_ret_ty, "return_alloca");
706                     debug!("out pointer, \
707                             allocad={}, \
708                             llrust_ret_ty={}, \
709                             return_ty={}",
710                            ccx.tn().val_to_string(slot),
711                            ccx.tn().type_to_string(llrust_ret_ty),
712                            tys.fn_sig.output.repr(tcx));
713                     llrust_args.push(slot);
714                     return_alloca = Some(slot);
715                 }
716             }
717         } else {
718             // Rust does not expect an outpointer. If the foreign fn
719             // does use an outpointer, then we will do a store of the
720             // value that the Rust fn returns.
721             return_alloca = None;
722         };
723
724         // Build up the arguments to the call to the rust function.
725         // Careful to adapt for cases where the native convention uses
726         // a pointer and Rust does not or vice versa.
727         for i in 0..tys.fn_sig.inputs.len() {
728             let rust_ty = tys.fn_sig.inputs[i];
729             let rust_indirect = type_of::arg_is_indirect(ccx, rust_ty);
730             let llty = rust_param_tys.next().expect("Not enough parameter types!");
731             let llrust_ty = if rust_indirect {
732                 llty.element_type()
733             } else {
734                 llty
735             };
736             let llforeign_arg_ty = tys.fn_ty.arg_tys[i];
737             let foreign_indirect = llforeign_arg_ty.is_indirect();
738
739             if llforeign_arg_ty.is_ignore() {
740                 debug!("skipping ignored arg #{}", i);
741                 llrust_args.push(C_undef(llrust_ty));
742                 continue;
743             }
744
745             // skip padding
746             let foreign_index = next_foreign_arg(llforeign_arg_ty.pad.is_some());
747             let mut llforeign_arg = get_param(llwrapfn, foreign_index);
748
749             debug!("llforeign_arg {}{}: {}", "#",
750                    i, ccx.tn().val_to_string(llforeign_arg));
751             debug!("rust_indirect = {}, foreign_indirect = {}",
752                    rust_indirect, foreign_indirect);
753
754             // Ensure that the foreign argument is indirect (by
755             // pointer).  It makes adapting types easier, since we can
756             // always just bitcast pointers.
757             if !foreign_indirect {
758                 llforeign_arg = if ty::type_is_bool(rust_ty) {
759                     let lltemp = builder.alloca(Type::bool(ccx), "");
760                     builder.store(builder.zext(llforeign_arg, Type::bool(ccx)), lltemp);
761                     lltemp
762                 } else {
763                     let lltemp = builder.alloca(val_ty(llforeign_arg), "");
764                     builder.store(llforeign_arg, lltemp);
765                     lltemp
766                 }
767             }
768
769             // If the types in the ABI and the Rust types don't match,
770             // bitcast the llforeign_arg pointer so it matches the types
771             // Rust expects.
772             if llforeign_arg_ty.cast.is_some() {
773                 assert!(!foreign_indirect);
774                 llforeign_arg = builder.bitcast(llforeign_arg, llrust_ty.ptr_to());
775             }
776
777             let llrust_arg = if rust_indirect {
778                 llforeign_arg
779             } else {
780                 if ty::type_is_bool(rust_ty) {
781                     let tmp = builder.load_range_assert(llforeign_arg, 0, 2, llvm::False);
782                     builder.trunc(tmp, Type::i1(ccx))
783                 } else if type_of::type_of(ccx, rust_ty).is_aggregate() {
784                     // We want to pass small aggregates as immediate values, but using an aggregate
785                     // LLVM type for this leads to bad optimizations, so its arg type is an
786                     // appropriately sized integer and we have to convert it
787                     let tmp = builder.bitcast(llforeign_arg,
788                                               type_of::arg_type_of(ccx, rust_ty).ptr_to());
789                     builder.load(tmp)
790                 } else {
791                     builder.load(llforeign_arg)
792                 }
793             };
794
795             debug!("llrust_arg {}{}: {}", "#",
796                    i, ccx.tn().val_to_string(llrust_arg));
797             llrust_args.push(llrust_arg);
798         }
799
800         // Perform the call itself
801         debug!("calling llrustfn = {}, t = {}",
802                ccx.tn().val_to_string(llrustfn), t.repr(ccx.tcx()));
803         let attributes = base::get_fn_llvm_attributes(ccx, t);
804         let llrust_ret_val = builder.call(llrustfn, &llrust_args, Some(attributes));
805
806         // Get the return value where the foreign fn expects it.
807         let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast {
808             Some(ty) => ty,
809             None => tys.fn_ty.ret_ty.ty
810         };
811         match foreign_outptr {
812             None if !tys.llsig.ret_def => {
813                 // Function returns `()` or `bot`, which in Rust is the LLVM
814                 // type "{}" but in foreign ABIs is "Void".
815                 builder.ret_void();
816             }
817
818             None if rust_uses_outptr => {
819                 // Rust uses an outpointer, but the foreign ABI does not. Load.
820                 let llrust_outptr = return_alloca.unwrap();
821                 let llforeign_outptr_casted =
822                     builder.bitcast(llrust_outptr, llforeign_ret_ty.ptr_to());
823                 let llforeign_retval = builder.load(llforeign_outptr_casted);
824                 builder.ret(llforeign_retval);
825             }
826
827             None if llforeign_ret_ty != llrust_ret_ty => {
828                 // Neither ABI uses an outpointer, but the types don't
829                 // quite match. Must cast. Probably we should try and
830                 // examine the types and use a concrete llvm cast, but
831                 // right now we just use a temp memory location and
832                 // bitcast the pointer, which is the same thing the
833                 // old wrappers used to do.
834                 let lltemp = builder.alloca(llforeign_ret_ty, "");
835                 let lltemp_casted = builder.bitcast(lltemp, llrust_ret_ty.ptr_to());
836                 builder.store(llrust_ret_val, lltemp_casted);
837                 let llforeign_retval = builder.load(lltemp);
838                 builder.ret(llforeign_retval);
839             }
840
841             None => {
842                 // Neither ABI uses an outpointer, and the types
843                 // match. Easy peasy.
844                 builder.ret(llrust_ret_val);
845             }
846
847             Some(llforeign_outptr) if !rust_uses_outptr => {
848                 // Foreign ABI requires an out pointer, but Rust doesn't.
849                 // Store Rust return value.
850                 let llforeign_outptr_casted =
851                     builder.bitcast(llforeign_outptr, llrust_ret_ty.ptr_to());
852                 builder.store(llrust_ret_val, llforeign_outptr_casted);
853                 builder.ret_void();
854             }
855
856             Some(_) => {
857                 // Both ABIs use outpointers. Easy peasy.
858                 builder.ret_void();
859             }
860         }
861     }
862 }
863
864 ///////////////////////////////////////////////////////////////////////////
865 // General ABI Support
866 //
867 // This code is kind of a confused mess and needs to be reworked given
868 // the massive simplifications that have occurred.
869
870 pub fn link_name(i: &ast::ForeignItem) -> InternedString {
871     match attr::first_attr_value_str_by_name(&i.attrs[], "link_name") {
872         Some(ln) => ln.clone(),
873         None => match weak_lang_items::link_name(&i.attrs[]) {
874             Some(name) => name,
875             None => token::get_ident(i.ident),
876         }
877     }
878 }
879
880 /// The ForeignSignature is the LLVM types of the arguments/return type of a function. Note that
881 /// these LLVM types are not quite the same as the LLVM types would be for a native Rust function
882 /// because foreign functions just plain ignore modes. They also don't pass aggregate values by
883 /// pointer like we do.
884 fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
885                                fn_sig: &ty::FnSig<'tcx>,
886                                arg_tys: &[Ty<'tcx>])
887                                -> LlvmSignature {
888     let llarg_tys = arg_tys.iter().map(|&arg| foreign_arg_type_of(ccx, arg)).collect();
889     let (llret_ty, ret_def) = match fn_sig.output {
890         ty::FnConverging(ret_ty) =>
891             (type_of::foreign_arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
892         ty::FnDiverging =>
893             (Type::nil(ccx), false)
894     };
895     LlvmSignature {
896         llarg_tys: llarg_tys,
897         llret_ty: llret_ty,
898         ret_def: ret_def
899     }
900 }
901
902 fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
903                                   id: ast::NodeId) -> ForeignTypes<'tcx> {
904     foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx(), id))
905 }
906
907 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
908                                      ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
909     let fn_sig = match ty.sty {
910         ty::ty_bare_fn(_, ref fn_ty) => &fn_ty.sig,
911         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
912     };
913     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
914     let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
915     let fn_ty = cabi::compute_abi_info(ccx,
916                                        &llsig.llarg_tys[],
917                                        llsig.llret_ty,
918                                        llsig.ret_def);
919     debug!("foreign_types_for_fn_ty(\
920            ty={}, \
921            llsig={} -> {}, \
922            fn_ty={} -> {}, \
923            ret_def={}",
924            ty.repr(ccx.tcx()),
925            ccx.tn().types_to_str(&llsig.llarg_tys[]),
926            ccx.tn().type_to_string(llsig.llret_ty),
927            ccx.tn().types_to_str(&fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>()),
928            ccx.tn().type_to_string(fn_ty.ret_ty.ty),
929            llsig.ret_def);
930
931     ForeignTypes {
932         fn_sig: fn_sig,
933         llsig: llsig,
934         fn_ty: fn_ty
935     }
936 }
937
938 fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> Type {
939     let mut llargument_tys = Vec::new();
940
941     let ret_ty = tys.fn_ty.ret_ty;
942     let llreturn_ty = if ret_ty.is_indirect() {
943         llargument_tys.push(ret_ty.ty.ptr_to());
944         Type::void(ccx)
945     } else {
946         match ret_ty.cast {
947             Some(ty) => ty,
948             None => ret_ty.ty
949         }
950     };
951
952     for &arg_ty in &tys.fn_ty.arg_tys {
953         if arg_ty.is_ignore() {
954             continue;
955         }
956         // add padding
957         match arg_ty.pad {
958             Some(ty) => llargument_tys.push(ty),
959             None => ()
960         }
961
962         let llarg_ty = if arg_ty.is_indirect() {
963             arg_ty.ty.ptr_to()
964         } else {
965             match arg_ty.cast {
966                 Some(ty) => ty,
967                 None => arg_ty.ty
968             }
969         };
970
971         llargument_tys.push(llarg_ty);
972     }
973
974     if tys.fn_sig.variadic {
975         Type::variadic_func(&llargument_tys, &llreturn_ty)
976     } else {
977         Type::func(&llargument_tys[..], &llreturn_ty)
978     }
979 }
980
981 pub fn lltype_for_foreign_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
982                                        ty: Ty<'tcx>) -> Type {
983     lltype_for_fn_from_foreign_types(ccx, &foreign_types_for_fn_ty(ccx, ty))
984 }
985
986 fn add_argument_attributes(tys: &ForeignTypes,
987                            llfn: ValueRef) {
988     let mut i = if tys.fn_ty.ret_ty.is_indirect() {
989         1
990     } else {
991         0
992     };
993
994     match tys.fn_ty.ret_ty.attr {
995         Some(attr) => unsafe {
996             llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);
997         },
998         None => {}
999     }
1000
1001     i += 1;
1002
1003     for &arg_ty in &tys.fn_ty.arg_tys {
1004         if arg_ty.is_ignore() {
1005             continue;
1006         }
1007         // skip padding
1008         if arg_ty.pad.is_some() { i += 1; }
1009
1010         match arg_ty.attr {
1011             Some(attr) => unsafe {
1012                 llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);
1013             },
1014             None => ()
1015         }
1016
1017         i += 1;
1018     }
1019 }