@@ -120,8 +120,7 @@ pub fn register_foreign_item_fn(ccx: @mut CrateContext,
120120 let cc = match llvm_calling_convention ( ccx, abis) {
121121 Some ( cc) => cc,
122122 None => {
123- // FIXME(#8357) We really ought to report a span here
124- ccx. sess . fatal (
123+ ccx. sess . span_fatal ( foreign_item. span ,
125124 format ! ( "ABI `{}` has no suitable ABI \
126125 for target architecture \
127126 in module {}",
@@ -135,6 +134,12 @@ pub fn register_foreign_item_fn(ccx: @mut CrateContext,
135134 let lname = link_name ( ccx, foreign_item) ;
136135 let tys = foreign_types_for_id ( ccx, foreign_item. id ) ;
137136
137+ // Make sure the calling convention is right for variadic functions
138+ // (should've been caught if not in typeck)
139+ if tys. fn_sig . variadic {
140+ assert ! ( cc == lib:: llvm:: CCallConv ) ;
141+ }
142+
138143 // Create the LLVM value for the C extern fn
139144 let llfn_ty = lltype_for_fn_from_foreign_types ( & tys) ;
140145 let llfn = base:: get_extern_fn ( & mut ccx. externs , ccx. llmod ,
@@ -148,7 +153,8 @@ pub fn trans_native_call(bcx: @mut Block,
148153 callee_ty : ty:: t ,
149154 llfn : ValueRef ,
150155 llretptr : ValueRef ,
151- llargs_rust : & [ ValueRef ] ) -> @mut Block {
156+ llargs_rust : & [ ValueRef ] ,
157+ passed_arg_tys : ~[ ty:: t ] ) -> @mut Block {
152158 /*!
153159 * Prepares a call to a native function. This requires adapting
154160 * from the Rust argument passing rules to the native rules.
@@ -160,6 +166,10 @@ pub fn trans_native_call(bcx: @mut Block,
160166 * - `llretptr`: where to store the return value of the function
161167 * - `llargs_rust`: a list of the argument values, prepared
162168 * as they would be if calling a Rust function
169+ * - `passed_arg_tys`: Rust type for the arguments. Normally we
170+ * can derive these from callee_ty but in the case of variadic
171+ * functions passed_arg_tys will include the Rust type of all
172+ * the arguments including the ones not specified in the fn's signature.
163173 */
164174
165175 let ccx = bcx. ccx ( ) ;
@@ -176,7 +186,7 @@ pub fn trans_native_call(bcx: @mut Block,
176186 ty:: ty_bare_fn( ref fn_ty) => ( fn_ty. abis , fn_ty. sig . clone ( ) ) ,
177187 _ => ccx. sess . bug ( "trans_native_call called on non-function type" )
178188 } ;
179- let llsig = foreign_signature ( ccx, & fn_sig) ;
189+ let llsig = foreign_signature ( ccx, & fn_sig, passed_arg_tys ) ;
180190 let ret_def = !ty:: type_is_voidish ( bcx. tcx ( ) , fn_sig. output ) ;
181191 let fn_type = cabi:: compute_abi_info ( ccx,
182192 llsig. llarg_tys ,
@@ -208,7 +218,7 @@ pub fn trans_native_call(bcx: @mut Block,
208218 let mut llarg_rust = llarg_rust;
209219
210220 // Does Rust pass this argument by pointer?
211- let rust_indirect = type_of:: arg_is_indirect ( ccx, fn_sig . inputs [ i] ) ;
221+ let rust_indirect = type_of:: arg_is_indirect ( ccx, passed_arg_tys [ i] ) ;
212222
213223 debug ! ( "argument {}, llarg_rust={}, rust_indirect={}, arg_ty={}" ,
214224 i,
@@ -219,7 +229,7 @@ pub fn trans_native_call(bcx: @mut Block,
219229 // Ensure that we always have the Rust value indirectly,
220230 // because it makes bitcasting easier.
221231 if !rust_indirect {
222- let scratch = base:: alloca ( bcx, type_of:: type_of ( ccx, fn_sig . inputs [ i] ) , "__arg" ) ;
232+ let scratch = base:: alloca ( bcx, type_of:: type_of ( ccx, passed_arg_tys [ i] ) , "__arg" ) ;
223233 Store ( bcx, llarg_rust, scratch) ;
224234 llarg_rust = scratch;
225235 }
@@ -331,6 +341,20 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
331341 foreign_mod : & ast:: foreign_mod ) {
332342 let _icx = push_ctxt ( "foreign::trans_foreign_mod" ) ;
333343 for & foreign_item in foreign_mod. items . iter ( ) {
344+ match foreign_item. node {
345+ ast:: foreign_item_fn( * ) => {
346+ let ( abis, mut path) = match ccx. tcx . items . get_copy ( & foreign_item. id ) {
347+ ast_map:: node_foreign_item( _, abis, _, path) => ( abis, ( * path) . clone ( ) ) ,
348+ _ => fail ! ( "Unable to find foreign item in tcx.items table." )
349+ } ;
350+ if !( abis. is_rust ( ) || abis. is_intrinsic ( ) ) {
351+ path. push ( ast_map:: path_name ( foreign_item. ident ) ) ;
352+ register_foreign_item_fn ( ccx, abis, & path, foreign_item) ;
353+ }
354+ }
355+ _ => ( )
356+ }
357+
334358 let lname = link_name ( ccx, foreign_item) ;
335359 ccx. item_symbols . insert ( foreign_item. id , lname. to_owned ( ) ) ;
336360 }
@@ -701,7 +725,7 @@ pub fn link_name(ccx: &CrateContext, i: @ast::foreign_item) -> @str {
701725 }
702726}
703727
704- fn foreign_signature ( ccx : & mut CrateContext , fn_sig : & ty:: FnSig )
728+ fn foreign_signature ( ccx : & mut CrateContext , fn_sig : & ty:: FnSig , arg_tys : & [ ty :: t ] )
705729 -> LlvmSignature {
706730 /*!
707731 * The ForeignSignature is the LLVM types of the arguments/return type
@@ -711,7 +735,7 @@ fn foreign_signature(ccx: &mut CrateContext, fn_sig: &ty::FnSig)
711735 * values by pointer like we do.
712736 */
713737
714- let llarg_tys = fn_sig . inputs . map ( |& arg| type_of ( ccx, arg) ) ;
738+ let llarg_tys = arg_tys . map ( |& arg| type_of ( ccx, arg) ) ;
715739 let llret_ty = type_of:: type_of ( ccx, fn_sig. output ) ;
716740 LlvmSignature {
717741 llarg_tys : llarg_tys,
@@ -731,7 +755,7 @@ fn foreign_types_for_fn_ty(ccx: &mut CrateContext,
731755 ty:: ty_bare_fn( ref fn_ty) => fn_ty. sig . clone ( ) ,
732756 _ => ccx. sess . bug ( "foreign_types_for_fn_ty called on non-function type" )
733757 } ;
734- let llsig = foreign_signature ( ccx, & fn_sig) ;
758+ let llsig = foreign_signature ( ccx, & fn_sig, fn_sig . inputs ) ;
735759 let ret_def = !ty:: type_is_voidish ( ccx. tcx , fn_sig. output ) ;
736760 let fn_ty = cabi:: compute_abi_info ( ccx,
737761 llsig. llarg_tys ,
@@ -790,7 +814,11 @@ fn lltype_for_fn_from_foreign_types(tys: &ForeignTypes) -> Type {
790814 llargument_tys. push ( llarg_ty) ;
791815 }
792816
793- Type :: func ( llargument_tys, & llreturn_ty)
817+ if tys. fn_sig . variadic {
818+ Type :: variadic_func ( llargument_tys, & llreturn_ty)
819+ } else {
820+ Type :: func ( llargument_tys, & llreturn_ty)
821+ }
794822}
795823
796824pub fn lltype_for_foreign_fn ( ccx : & mut CrateContext , ty : ty:: t ) -> Type {
0 commit comments