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.
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.
13 use llvm::{ValueRef, CallConv, get_param};
15 use middle::weak_lang_items;
16 use trans::base::{llvm_linkage_by_name, push_ctxt};
22 use trans::type_::Type;
23 use trans::type_of::*;
25 use middle::ty::FnSig;
26 use middle::ty::{mod, Ty};
27 use middle::subst::{Subst, Substs};
30 use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
31 use syntax::abi::{RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
32 use syntax::codemap::Span;
33 use syntax::parse::token::{InternedString, special_idents};
34 use syntax::parse::token;
36 use syntax::{attr, ast_map};
37 use util::ppaux::Repr;
39 ///////////////////////////////////////////////////////////////////////////
42 struct ForeignTypes<'tcx> {
43 /// Rust signature of the function
44 fn_sig: ty::FnSig<'tcx>,
46 /// Adapter object for handling native ABI rules (trust me, you
47 /// don't want to know)
50 /// LLVM types that will appear on the foreign function
54 struct LlvmSignature {
55 // LLVM versions of the types of this function's arguments.
56 llarg_tys: Vec<Type> ,
58 // LLVM version of the type that this function returns. Note that
59 // this *may not be* the declared return type of the foreign
60 // function, because the foreign function may opt to return via an
64 /// True if there is a return value (not bottom, not unit)
69 ///////////////////////////////////////////////////////////////////////////
70 // Calls to external functions
72 pub fn llvm_calling_convention(ccx: &CrateContext,
73 abi: Abi) -> CallConv {
74 match ccx.sess().target.target.adjust_abi(abi) {
76 // Intrinsics are emitted at the call site
77 ccx.sess().bug("asked to register intrinsic fn");
81 // FIXME(#3678) Implement linking to foreign fns with Rust ABI
82 ccx.sess().unimpl("foreign functions with Rust ABI");
86 // FIXME(#3678) Implement linking to foreign fns with Rust ABI
87 ccx.sess().unimpl("foreign functions with RustCall ABI");
90 // It's the ABI's job to select this, not us.
91 System => ccx.sess().bug("system abi should be selected elsewhere"),
93 Stdcall => llvm::X86StdcallCallConv,
94 Fastcall => llvm::X86FastcallCallConv,
96 Win64 => llvm::X86_64_Win64,
98 // These API constants ought to be more specific...
99 Cdecl => llvm::CCallConv,
100 Aapcs => llvm::CCallConv,
104 pub fn register_static(ccx: &CrateContext,
105 foreign_item: &ast::ForeignItem) -> ValueRef {
106 let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
107 let llty = type_of::type_of(ccx, ty);
109 let ident = link_name(foreign_item);
110 match attr::first_attr_value_str_by_name(foreign_item.attrs.as_slice(),
112 // If this is a static with a linkage specified, then we need to handle
113 // it a little specially. The typesystem prevents things like &T and
114 // extern "C" fn() from being non-null, so we can't just declare a
115 // static and call it a day. Some linkages (like weak) will make it such
116 // that the static actually has a null value.
118 let linkage = match llvm_linkage_by_name(name.get()) {
119 Some(linkage) => linkage,
121 ccx.sess().span_fatal(foreign_item.span,
122 "invalid linkage specified");
125 let llty2 = match ty.sty {
126 ty::ty_ptr(ref mt) => type_of::type_of(ccx, mt.ty),
128 ccx.sess().span_fatal(foreign_item.span,
129 "must have type `*T` or `*mut T`");
133 // Declare a symbol `foo` with the desired linkage.
134 let g1 = ident.get().with_c_str(|buf| {
135 llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), buf)
137 llvm::SetLinkage(g1, linkage);
139 // Declare an internal global `extern_with_linkage_foo` which
140 // is initialized with the address of `foo`. If `foo` is
141 // discarded during linking (for example, if `foo` has weak
142 // linkage and there are no definitions), then
143 // `extern_with_linkage_foo` will instead be initialized to
145 let mut real_name = "_rust_extern_with_linkage_".to_string();
146 real_name.push_str(ident.get());
147 let g2 = real_name.with_c_str(|buf| {
148 llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
150 llvm::SetLinkage(g2, llvm::InternalLinkage);
151 llvm::LLVMSetInitializer(g2, g1);
156 // Generate an external declaration.
157 ident.get().with_c_str(|buf| {
158 llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf)
164 pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
165 abi: Abi, fty: Ty<'tcx>,
166 name: &str) -> ValueRef {
168 * Registers a foreign function found in a library.
169 * Just adds a LLVM global.
172 debug!("register_foreign_item_fn(abi={}, \
179 let cc = llvm_calling_convention(ccx, abi);
181 // Register the function as a C extern fn
182 let tys = foreign_types_for_fn_ty(ccx, fty);
184 // Make sure the calling convention is right for variadic functions
185 // (should've been caught if not in typeck)
186 if tys.fn_sig.variadic {
187 assert!(cc == llvm::CCallConv);
190 // Create the LLVM value for the C extern fn
191 let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
193 let llfn = base::get_extern_fn(ccx,
194 &mut *ccx.externs().borrow_mut(),
199 add_argument_attributes(&tys, llfn);
204 pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
208 llargs_rust: &[ValueRef],
209 passed_arg_tys: Vec<Ty<'tcx>>)
210 -> Block<'blk, 'tcx> {
212 * Prepares a call to a native function. This requires adapting
213 * from the Rust argument passing rules to the native rules.
217 * - `callee_ty`: Rust type for the function we are calling
218 * - `llfn`: the function pointer we are calling
219 * - `llretptr`: where to store the return value of the function
220 * - `llargs_rust`: a list of the argument values, prepared
221 * as they would be if calling a Rust function
222 * - `passed_arg_tys`: Rust type for the arguments. Normally we
223 * can derive these from callee_ty but in the case of variadic
224 * functions passed_arg_tys will include the Rust type of all
225 * the arguments including the ones not specified in the fn's signature.
231 debug!("trans_native_call(callee_ty={}, \
235 ccx.tn().val_to_string(llfn),
236 ccx.tn().val_to_string(llretptr));
238 let (fn_abi, fn_sig) = match callee_ty.sty {
239 ty::ty_bare_fn(ref fn_ty) => (fn_ty.abi, fn_ty.sig.clone()),
240 _ => ccx.sess().bug("trans_native_call called on non-function type")
242 let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice());
243 let fn_type = cabi::compute_abi_info(ccx,
244 llsig.llarg_tys.as_slice(),
248 let arg_tys: &[cabi::ArgType] = fn_type.arg_tys.as_slice();
250 let mut llargs_foreign = Vec::new();
252 // If the foreign ABI expects return value by pointer, supply the
253 // pointer that Rust gave us. Sometimes we have to bitcast
254 // because foreign fns return slightly different (but equivalent)
255 // views on the same type (e.g., i64 in place of {i32,i32}).
256 if fn_type.ret_ty.is_indirect() {
257 match fn_type.ret_ty.cast {
260 BitCast(bcx, llretptr, ty.ptr_to());
261 llargs_foreign.push(llcastedretptr);
264 llargs_foreign.push(llretptr);
269 for (i, &llarg_rust) in llargs_rust.iter().enumerate() {
270 let mut llarg_rust = llarg_rust;
272 if arg_tys[i].is_ignore() {
276 // Does Rust pass this argument by pointer?
277 let rust_indirect = type_of::arg_is_indirect(ccx, passed_arg_tys[i]);
279 debug!("argument {}, llarg_rust={}, rust_indirect={}, arg_ty={}",
281 ccx.tn().val_to_string(llarg_rust),
283 ccx.tn().type_to_string(arg_tys[i].ty));
285 // Ensure that we always have the Rust value indirectly,
286 // because it makes bitcasting easier.
290 type_of::type_of(ccx, passed_arg_tys[i]),
292 base::store_ty(bcx, llarg_rust, scratch, passed_arg_tys[i]);
293 llarg_rust = scratch;
296 debug!("llarg_rust={} (after indirection)",
297 ccx.tn().val_to_string(llarg_rust));
299 // Check whether we need to do any casting
300 match arg_tys[i].cast {
301 Some(ty) => llarg_rust = BitCast(bcx, llarg_rust, ty.ptr_to()),
305 debug!("llarg_rust={} (after casting)",
306 ccx.tn().val_to_string(llarg_rust));
308 // Finally, load the value if needed for the foreign ABI
309 let foreign_indirect = arg_tys[i].is_indirect();
310 let llarg_foreign = if foreign_indirect {
313 if ty::type_is_bool(passed_arg_tys[i]) {
314 let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, llvm::False);
315 Trunc(bcx, val, Type::i1(bcx.ccx()))
317 Load(bcx, llarg_rust)
321 debug!("argument {}, llarg_foreign={}",
322 i, ccx.tn().val_to_string(llarg_foreign));
324 // fill padding with undef value
325 match arg_tys[i].pad {
326 Some(ty) => llargs_foreign.push(C_undef(ty)),
329 llargs_foreign.push(llarg_foreign);
332 let cc = llvm_calling_convention(ccx, fn_abi);
334 // A function pointer is called without the declaration available, so we have to apply
335 // any attributes with ABI implications directly to the call instruction.
336 let mut attrs = llvm::AttrBuilder::new();
338 // Add attributes that are always applicable, independent of the concrete foreign ABI
339 if fn_type.ret_ty.is_indirect() {
340 let llret_sz = machine::llsize_of_real(ccx, fn_type.ret_ty.ty);
342 // The outptr can be noalias and nocapture because it's entirely
343 // invisible to the program. We also know it's nonnull as well
344 // as how many bytes we can dereference
345 attrs.arg(1, llvm::NoAliasAttribute)
346 .arg(1, llvm::NoCaptureAttribute)
347 .arg(1, llvm::DereferenceableAttribute(llret_sz));
350 // Add attributes that depend on the concrete foreign ABI
351 let mut arg_idx = if fn_type.ret_ty.is_indirect() { 1 } else { 0 };
352 match fn_type.ret_ty.attr {
353 Some(attr) => { attrs.arg(arg_idx, attr); },
358 for arg_ty in fn_type.arg_tys.iter() {
359 if arg_ty.is_ignore() {
363 if arg_ty.pad.is_some() { arg_idx += 1; }
366 Some(attr) => { attrs.arg(arg_idx, attr); },
373 let llforeign_retval = CallWithConv(bcx,
375 llargs_foreign.as_slice(),
379 // If the function we just called does not use an outpointer,
380 // store the result into the rust outpointer. Cast the outpointer
381 // type to match because some ABIs will use a different type than
382 // the Rust type. e.g., a {u32,u32} struct could be returned as
384 if llsig.ret_def && !fn_type.ret_ty.is_indirect() {
385 let llrust_ret_ty = llsig.llret_ty;
386 let llforeign_ret_ty = match fn_type.ret_ty.cast {
388 None => fn_type.ret_ty.ty
391 debug!("llretptr={}", ccx.tn().val_to_string(llretptr));
392 debug!("llforeign_retval={}", ccx.tn().val_to_string(llforeign_retval));
393 debug!("llrust_ret_ty={}", ccx.tn().type_to_string(llrust_ret_ty));
394 debug!("llforeign_ret_ty={}", ccx.tn().type_to_string(llforeign_ret_ty));
396 if llrust_ret_ty == llforeign_ret_ty {
397 match fn_sig.output {
398 ty::FnConverging(result_ty) => {
399 base::store_ty(bcx, llforeign_retval, llretptr, result_ty)
401 ty::FnDiverging => {}
404 // The actual return type is a struct, but the ABI
405 // adaptation code has cast it into some scalar type. The
406 // code that follows is the only reliable way I have
407 // found to do a transform like i64 -> {i32,i32}.
408 // Basically we dump the data onto the stack then memcpy it.
410 // Other approaches I tried:
411 // - Casting rust ret pointer to the foreign type and using Store
412 // is (a) unsafe if size of foreign type > size of rust type and
413 // (b) runs afoul of strict aliasing rules, yielding invalid
414 // assembly under -O (specifically, the store gets removed).
415 // - Truncating foreign type to correct integral type and then
416 // bitcasting to the struct type yields invalid cast errors.
417 let llscratch = base::alloca(bcx, llforeign_ret_ty, "__cast");
418 Store(bcx, llforeign_retval, llscratch);
419 let llscratch_i8 = BitCast(bcx, llscratch, Type::i8(ccx).ptr_to());
420 let llretptr_i8 = BitCast(bcx, llretptr, Type::i8(ccx).ptr_to());
421 let llrust_size = machine::llsize_of_store(ccx, llrust_ret_ty);
422 let llforeign_align = machine::llalign_of_min(ccx, llforeign_ret_ty);
423 let llrust_align = machine::llalign_of_min(ccx, llrust_ret_ty);
424 let llalign = cmp::min(llforeign_align, llrust_align);
425 debug!("llrust_size={}", llrust_size);
426 base::call_memcpy(bcx, llretptr_i8, llscratch_i8,
427 C_uint(ccx, llrust_size), llalign as u32);
434 pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
435 let _icx = push_ctxt("foreign::trans_foreign_mod");
436 for foreign_item in foreign_mod.items.iter() {
437 let lname = link_name(&**foreign_item);
439 match foreign_item.node {
440 ast::ForeignItemFn(..) => {
441 match foreign_mod.abi {
442 Rust | RustIntrinsic => {}
444 let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
445 register_foreign_item_fn(ccx, abi, ty,
446 lname.get().as_slice());
447 // Unlike for other items, we shouldn't call
448 // `base::update_linkage` here. Foreign items have
449 // special linkage requirements, which are handled
450 // inside `foreign::register_*`.
457 ccx.item_symbols().borrow_mut().insert(foreign_item.id,
458 lname.get().to_string());
462 ///////////////////////////////////////////////////////////////////////////
463 // Rust functions with foreign ABIs
465 // These are normal Rust functions defined with foreign ABIs. For
466 // now, and perhaps forever, we translate these using a "layer of
467 // indirection". That is, given a Rust declaration like:
469 // extern "C" fn foo(i: u32) -> u32 { ... }
471 // we will generate a function like:
475 // foo0(&r, NULL, i);
480 // void foo0(uint32_t *r, void *env, uint32_t i) { ... }
482 // Here the (internal) `foo0` function follows the Rust ABI as normal,
483 // where the `foo` function follows the C ABI. We rely on LLVM to
484 // inline the one into the other. Of course we could just generate the
485 // correct code in the first place, but this is much simpler.
487 pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
491 let tys = foreign_types_for_fn_ty(ccx, t);
492 let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
493 let cconv = match t.sty {
494 ty::ty_bare_fn(ref fn_ty) => {
495 llvm_calling_convention(ccx, fn_ty.abi)
497 _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
499 let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil(ccx.tcx())));
500 add_argument_attributes(&tys, llfn);
501 debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
502 ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
506 pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
509 node_id: ast::NodeId)
511 let _icx = push_ctxt("foreign::register_foreign_fn");
513 let tys = foreign_types_for_id(ccx, node_id);
514 let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
515 let t = ty::node_id_to_type(ccx.tcx(), node_id);
516 let cconv = match t.sty {
517 ty::ty_bare_fn(ref fn_ty) => {
518 llvm_calling_convention(ccx, fn_ty.abi)
520 _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
522 let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
523 add_argument_attributes(&tys, llfn);
524 debug!("register_rust_fn_with_foreign_abi(node_id={}, llfn_ty={}, llfn={})",
525 node_id, ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
529 pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
532 attrs: &[ast::Attribute],
534 param_substs: &Substs<'tcx>,
536 hash: Option<&str>) {
537 let _icx = push_ctxt("foreign::build_foreign_fn");
539 let fnty = ty::node_id_to_type(ccx.tcx(), id);
540 let mty = fnty.subst(ccx.tcx(), param_substs);
541 let tys = foreign_types_for_fn_ty(ccx, mty);
543 unsafe { // unsafe because we call LLVM operations
544 // Build up the Rust function (`foo0` above).
545 let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
547 // Build up the foreign wrapper (`foo` above).
548 return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
551 fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
554 param_substs: &Substs<'tcx>,
555 attrs: &[ast::Attribute],
559 let _icx = push_ctxt("foreign::foreign::build_rust_fn");
561 let t = ty::node_id_to_type(tcx, id).subst(ccx.tcx(), param_substs);
563 let ps = ccx.tcx().map.with_path(id, |path| {
564 let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
565 link::mangle(path.chain(abi.into_iter()), hash)
568 // Compute the type that the function would have if it were just a
569 // normal Rust function. This will be the type of the wrappee fn.
571 ty::ty_bare_fn(ref f) => {
572 assert!(f.abi != Rust && f.abi != RustIntrinsic);
575 ccx.sess().bug(format!("build_rust_fn: extern fn {} has ty {}, \
576 expected a bare fn ty",
577 ccx.tcx().map.path_to_string(id),
578 t.repr(tcx)).as_slice());
582 debug!("build_rust_fn: path={} id={} t={}",
583 ccx.tcx().map.path_to_string(id),
586 let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
587 base::set_llvm_fn_attrs(ccx, attrs, llfn);
588 base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]);
592 unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
595 tys: &ForeignTypes<'tcx>,
597 let _icx = push_ctxt(
598 "foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
601 debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
602 ccx.tn().val_to_string(llrustfn),
603 ccx.tn().val_to_string(llwrapfn),
606 // Avoid all the Rust generation stuff and just generate raw
609 // We want to generate code like this:
613 // foo0(&r, NULL, i);
618 "the block".with_c_str(
619 |s| llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llwrapfn, s));
621 let builder = ccx.builder();
622 builder.position_at_end(the_block);
624 // Array for the arguments we will pass to the rust function.
625 let mut llrust_args = Vec::new();
626 let mut next_foreign_arg_counter: c_uint = 0;
627 let next_foreign_arg: |pad: bool| -> c_uint = |pad: bool| {
628 next_foreign_arg_counter += if pad {
633 next_foreign_arg_counter - 1
636 // If there is an out pointer on the foreign function
637 let foreign_outptr = {
638 if tys.fn_ty.ret_ty.is_indirect() {
639 Some(get_param(llwrapfn, next_foreign_arg(false)))
645 // Push Rust return pointer, using null if it will be unused.
646 let rust_uses_outptr = match tys.fn_sig.output {
647 ty::FnConverging(ret_ty) => type_of::return_uses_outptr(ccx, ret_ty),
648 ty::FnDiverging => false
650 let return_alloca: Option<ValueRef>;
651 let llrust_ret_ty = tys.llsig.llret_ty;
652 let llrust_retptr_ty = llrust_ret_ty.ptr_to();
653 if rust_uses_outptr {
654 // Rust expects to use an outpointer. If the foreign fn
655 // also uses an outpointer, we can reuse it, but the types
656 // may vary, so cast first to the Rust type. If the
657 // foreign fn does NOT use an outpointer, we will have to
658 // alloca some scratch space on the stack.
659 match foreign_outptr {
660 Some(llforeign_outptr) => {
661 debug!("out pointer, foreign={}",
662 ccx.tn().val_to_string(llforeign_outptr));
664 builder.bitcast(llforeign_outptr, llrust_retptr_ty);
665 debug!("out pointer, foreign={} (casted)",
666 ccx.tn().val_to_string(llrust_retptr));
667 llrust_args.push(llrust_retptr);
668 return_alloca = None;
672 let slot = builder.alloca(llrust_ret_ty, "return_alloca");
673 debug!("out pointer, \
677 ccx.tn().val_to_string(slot),
678 ccx.tn().type_to_string(llrust_ret_ty),
679 tys.fn_sig.output.repr(tcx));
680 llrust_args.push(slot);
681 return_alloca = Some(slot);
685 // Rust does not expect an outpointer. If the foreign fn
686 // does use an outpointer, then we will do a store of the
687 // value that the Rust fn returns.
688 return_alloca = None;
691 // Build up the arguments to the call to the rust function.
692 // Careful to adapt for cases where the native convention uses
693 // a pointer and Rust does not or vice versa.
694 for i in range(0, tys.fn_sig.inputs.len()) {
695 let rust_ty = tys.fn_sig.inputs[i];
696 let llrust_ty = tys.llsig.llarg_tys[i];
697 let rust_indirect = type_of::arg_is_indirect(ccx, rust_ty);
698 let llforeign_arg_ty = tys.fn_ty.arg_tys[i];
699 let foreign_indirect = llforeign_arg_ty.is_indirect();
701 if llforeign_arg_ty.is_ignore() {
702 debug!("skipping ignored arg #{}", i);
703 llrust_args.push(C_undef(llrust_ty));
708 let foreign_index = next_foreign_arg(llforeign_arg_ty.pad.is_some());
709 let mut llforeign_arg = get_param(llwrapfn, foreign_index);
711 debug!("llforeign_arg {}{}: {}", "#",
712 i, ccx.tn().val_to_string(llforeign_arg));
713 debug!("rust_indirect = {}, foreign_indirect = {}",
714 rust_indirect, foreign_indirect);
716 // Ensure that the foreign argument is indirect (by
717 // pointer). It makes adapting types easier, since we can
718 // always just bitcast pointers.
719 if !foreign_indirect {
720 llforeign_arg = if ty::type_is_bool(rust_ty) {
721 let lltemp = builder.alloca(Type::bool(ccx), "");
722 builder.store(builder.zext(llforeign_arg, Type::bool(ccx)), lltemp);
725 let lltemp = builder.alloca(val_ty(llforeign_arg), "");
726 builder.store(llforeign_arg, lltemp);
731 // If the types in the ABI and the Rust types don't match,
732 // bitcast the llforeign_arg pointer so it matches the types
734 if llforeign_arg_ty.cast.is_some() {
735 assert!(!foreign_indirect);
736 llforeign_arg = builder.bitcast(llforeign_arg, llrust_ty.ptr_to());
739 let llrust_arg = if rust_indirect {
742 if ty::type_is_bool(rust_ty) {
743 let tmp = builder.load_range_assert(llforeign_arg, 0, 2, llvm::False);
744 builder.trunc(tmp, Type::i1(ccx))
746 builder.load(llforeign_arg)
750 debug!("llrust_arg {}{}: {}", "#",
751 i, ccx.tn().val_to_string(llrust_arg));
752 llrust_args.push(llrust_arg);
755 // Perform the call itself
756 debug!("calling llrustfn = {}, t = {}",
757 ccx.tn().val_to_string(llrustfn), t.repr(ccx.tcx()));
758 let attributes = base::get_fn_llvm_attributes(ccx, t);
759 let llrust_ret_val = builder.call(llrustfn, llrust_args.as_slice(), Some(attributes));
761 // Get the return value where the foreign fn expects it.
762 let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast {
764 None => tys.fn_ty.ret_ty.ty
766 match foreign_outptr {
767 None if !tys.llsig.ret_def => {
768 // Function returns `()` or `bot`, which in Rust is the LLVM
769 // type "{}" but in foreign ABIs is "Void".
773 None if rust_uses_outptr => {
774 // Rust uses an outpointer, but the foreign ABI does not. Load.
775 let llrust_outptr = return_alloca.unwrap();
776 let llforeign_outptr_casted =
777 builder.bitcast(llrust_outptr, llforeign_ret_ty.ptr_to());
778 let llforeign_retval = builder.load(llforeign_outptr_casted);
779 builder.ret(llforeign_retval);
782 None if llforeign_ret_ty != llrust_ret_ty => {
783 // Neither ABI uses an outpointer, but the types don't
784 // quite match. Must cast. Probably we should try and
785 // examine the types and use a concrete llvm cast, but
786 // right now we just use a temp memory location and
787 // bitcast the pointer, which is the same thing the
788 // old wrappers used to do.
789 let lltemp = builder.alloca(llforeign_ret_ty, "");
790 let lltemp_casted = builder.bitcast(lltemp, llrust_ret_ty.ptr_to());
791 builder.store(llrust_ret_val, lltemp_casted);
792 let llforeign_retval = builder.load(lltemp);
793 builder.ret(llforeign_retval);
797 // Neither ABI uses an outpointer, and the types
798 // match. Easy peasy.
799 builder.ret(llrust_ret_val);
802 Some(llforeign_outptr) if !rust_uses_outptr => {
803 // Foreign ABI requires an out pointer, but Rust doesn't.
804 // Store Rust return value.
805 let llforeign_outptr_casted =
806 builder.bitcast(llforeign_outptr, llrust_retptr_ty);
807 builder.store(llrust_ret_val, llforeign_outptr_casted);
812 // Both ABIs use outpointers. Easy peasy.
819 ///////////////////////////////////////////////////////////////////////////
820 // General ABI Support
822 // This code is kind of a confused mess and needs to be reworked given
823 // the massive simplifications that have occurred.
825 pub fn link_name(i: &ast::ForeignItem) -> InternedString {
826 match attr::first_attr_value_str_by_name(i.attrs.as_slice(), "link_name") {
827 Some(ln) => ln.clone(),
828 None => match weak_lang_items::link_name(i.attrs.as_slice()) {
830 None => token::get_ident(i.ident),
835 fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
836 fn_sig: &ty::FnSig<'tcx>, arg_tys: &[Ty<'tcx>])
839 * The ForeignSignature is the LLVM types of the arguments/return type
840 * of a function. Note that these LLVM types are not quite the same
841 * as the LLVM types would be for a native Rust function because foreign
842 * functions just plain ignore modes. They also don't pass aggregate
843 * values by pointer like we do.
846 let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect();
847 let (llret_ty, ret_def) = match fn_sig.output {
848 ty::FnConverging(ret_ty) =>
849 (type_of::arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
851 (Type::nil(ccx), false)
854 llarg_tys: llarg_tys,
860 fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
861 id: ast::NodeId) -> ForeignTypes<'tcx> {
862 foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx(), id))
865 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
866 ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
867 let fn_sig = match ty.sty {
868 ty::ty_bare_fn(ref fn_ty) => fn_ty.sig.clone(),
869 _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
871 let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs.as_slice());
872 let fn_ty = cabi::compute_abi_info(ccx,
873 llsig.llarg_tys.as_slice(),
876 debug!("foreign_types_for_fn_ty(\
882 ccx.tn().types_to_str(llsig.llarg_tys.as_slice()),
883 ccx.tn().type_to_string(llsig.llret_ty),
884 ccx.tn().types_to_str(fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>().as_slice()),
885 ccx.tn().type_to_string(fn_ty.ret_ty.ty),
895 fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> Type {
896 let mut llargument_tys = Vec::new();
898 let ret_ty = tys.fn_ty.ret_ty;
899 let llreturn_ty = if ret_ty.is_indirect() {
900 llargument_tys.push(ret_ty.ty.ptr_to());
909 for &arg_ty in tys.fn_ty.arg_tys.iter() {
910 if arg_ty.is_ignore() {
915 Some(ty) => llargument_tys.push(ty),
919 let llarg_ty = if arg_ty.is_indirect() {
928 llargument_tys.push(llarg_ty);
931 if tys.fn_sig.variadic {
932 Type::variadic_func(llargument_tys.as_slice(), &llreturn_ty)
934 Type::func(llargument_tys.as_slice(), &llreturn_ty)
938 pub fn lltype_for_foreign_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
939 ty: Ty<'tcx>) -> Type {
940 lltype_for_fn_from_foreign_types(ccx, &foreign_types_for_fn_ty(ccx, ty))
943 fn add_argument_attributes(tys: &ForeignTypes,
945 let mut i = if tys.fn_ty.ret_ty.is_indirect() {
951 match tys.fn_ty.ret_ty.attr {
952 Some(attr) => unsafe {
953 llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);
960 for &arg_ty in tys.fn_ty.arg_tys.iter() {
961 if arg_ty.is_ignore() {
965 if arg_ty.pad.is_some() { i += 1; }
968 Some(attr) => unsafe {
969 llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);