@@ -169,56 +169,35 @@ pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) ->
169169
170170pub fn get_extern_fn ( externs : ExternMap ,
171171 llmod : ModuleRef ,
172- name : @ str ,
172+ name : & str ,
173173 cc : lib:: llvm:: CallConv ,
174174 ty : TypeRef ) -> ValueRef {
175- match externs. find ( & name) {
176- Some ( n) => return copy * n,
175+ match externs. find_equiv ( & name) {
176+ Some ( & n) => {
177+ return n;
178+ }
177179 None => ( )
178180 }
179181 let f = decl_fn ( llmod, name, cc, ty) ;
180- externs. insert ( name, f) ;
182+ externs. insert ( name. to_owned ( ) , f) ;
181183 return f;
182184}
183185
184186pub fn get_extern_const ( externs : ExternMap , llmod : ModuleRef ,
185- name : @ str , ty : TypeRef ) -> ValueRef {
186- match externs. find ( & name) {
187+ name : & str , ty : TypeRef ) -> ValueRef {
188+ match externs. find_equiv ( & name) {
187189 Some ( n) => return copy * n,
188190 None => ( )
189191 }
190192 unsafe {
191193 let c = str:: as_c_str ( name, |buf| {
192194 llvm:: LLVMAddGlobal ( llmod, ty, buf)
193195 } ) ;
194- externs. insert ( name, c) ;
196+ externs. insert ( name. to_owned ( ) , c) ;
195197 return c;
196198 }
197199}
198200
199- fn get_simple_extern_fn ( cx : block ,
200- externs : ExternMap ,
201- llmod : ModuleRef ,
202- name : @str ,
203- n_args : int ) -> ValueRef {
204- let _icx = cx. insn_ctxt ( "get_simple_extern_fn" ) ;
205- let ccx = cx. fcx . ccx ;
206- let inputs = vec:: from_elem ( n_args as uint , ccx. int_type ) ;
207- let output = ccx. int_type ;
208- let t = T_fn ( inputs, output) ;
209- return get_extern_fn ( externs, llmod, name, lib:: llvm:: CCallConv , t) ;
210- }
211-
212- pub fn trans_foreign_call ( cx : block , externs : ExternMap ,
213- llmod : ModuleRef , name : @str , args : & [ ValueRef ] ) ->
214- ValueRef {
215- let _icx = cx. insn_ctxt ( "trans_foreign_call" ) ;
216- let n = args. len ( ) as int ;
217- let llforeign: ValueRef =
218- get_simple_extern_fn ( cx, externs, llmod, name, n) ;
219- return Call ( cx, llforeign, args) ;
220- }
221-
222201pub fn umax ( cx : block , a : ValueRef , b : ValueRef ) -> ValueRef {
223202 let _icx = cx. insn_ctxt ( "umax" ) ;
224203 let cond = ICmp ( cx, lib:: llvm:: IntULT , a, b) ;
@@ -517,7 +496,6 @@ pub fn get_res_dtor(ccx: @CrateContext,
517496 None ,
518497 ty:: lookup_item_type ( tcx, parent_id) . ty ) ;
519498 let llty = type_of_dtor ( ccx, class_ty) ;
520- let name = name. to_managed ( ) ; // :-(
521499 get_extern_fn ( ccx. externs ,
522500 ccx. llmod ,
523501 name,
@@ -805,13 +783,13 @@ pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
805783 }
806784}
807785
808- pub fn null_env_ptr(bcx: block ) -> ValueRef {
809- C_null(T_opaque_box_ptr(bcx. ccx() ))
786+ pub fn null_env_ptr(ccx: @CrateContext ) -> ValueRef {
787+ C_null(T_opaque_box_ptr(ccx))
810788}
811789
812790pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t)
813791 -> ValueRef {
814- let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad
792+ let name = csearch::get_symbol(ccx.sess.cstore, did);
815793 match ty::get(t).sty {
816794 ty::ty_bare_fn(_) | ty::ty_closure(_) => {
817795 let llty = type_of_fn_from_ty(ccx, t);
@@ -825,6 +803,65 @@ pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t)
825803 };
826804}
827805
806+ pub fn trans_external_path_casted(
807+ ccx: @CrateContext,
808+ did: ast::def_id,
809+ t: ty::t,
810+ cast_build: &fn(ValueRef, TypeRef) -> ValueRef)
811+ -> ValueRef
812+ {
813+ /*!
814+ * Translates a reference to an external path,
815+ * adding a new entry to the externs table if
816+ * necessary.
817+ *
818+ * If this is a reference to an non-Rust function, and an entry in
819+ * the externs table already exists but with an incompatible type,
820+ * use the `cast_build` argument to construct a cast to the type
821+ * `t`. This is kind of a hack, but I don't know of a better
822+ * solution. The problem is that if different crates may link to
823+ * the same external function but declare it with distinct types.
824+ * However, LLVM only permits us to declare a single prototype for any
825+ * given function.
826+ *
827+ * Maybe this should just be an error, but it isn't *necessarily*
828+ * invalid. First off, some functions accept multiple types of
829+ * arguments, but worse we seem to get into this situation when
830+ * testing libcore because the structs in the --test build are
831+ * distinct from the structs in the normal build. So instead we
832+ * just bitcast as needed for now.
833+ *
834+ * The same situation can arise with external structs but I'm choosing
835+ * to ignore that for now.
836+ */
837+
838+ let name = csearch::get_symbol(ccx.sess.cstore, did);
839+ debug!(" trans_external_path_casted: did=%?, t=%s, name=%?",
840+ did, t. repr ( ccx. tcx ) , name) ;
841+ match ty:: get ( t) . sty {
842+ ty:: ty_bare_fn( ref f) if f. abis . is_rust ( ) => {
843+ let llty = type_of_fn_from_ty ( ccx, t) ;
844+ get_extern_fn ( ccx. externs , ccx. llmod , name,
845+ lib:: llvm:: CCallConv , llty)
846+ }
847+ ty:: ty_bare_fn( _) => {
848+ let llty = type_of_fn_from_ty ( ccx, t) ;
849+ let llval = get_extern_fn ( ccx. externs , ccx. llmod , name,
850+ lib:: llvm:: CCallConv , llty) ;
851+ let llptr_ty = T_ptr ( llty) ;
852+ if val_ty ( llval) != llptr_ty {
853+ cast_build ( llval, llptr_ty)
854+ } else {
855+ llval
856+ }
857+ }
858+ _ => {
859+ let llty = type_of ( ccx, t) ;
860+ get_extern_const ( ccx. externs , ccx. llmod , name, llty)
861+ }
862+ }
863+ }
864+
828865pub fn invoke( bcx: block, llfn: ValueRef , llargs: ~[ ValueRef ] )
829866 -> ( ValueRef , block) {
830867 let _icx = bcx. insn_ctxt ( "invoke_" ) ;
@@ -1570,7 +1607,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
15701607// slot where the return value of the function must go.
15711608pub fn make_return_pointer ( fcx : fn_ctxt , output_type : ty:: t ) -> ValueRef {
15721609 unsafe {
1573- if !ty :: type_is_immediate ( output_type) {
1610+ if type_of :: return_uses_outptr ( output_type) {
15741611 llvm:: LLVMGetParam ( fcx. llfn , 0 )
15751612 } else {
15761613 let lloutputtype = type_of:: type_of ( * fcx. ccx , output_type) ;
@@ -1611,7 +1648,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
16111648 ty:: subst_tps ( ccx. tcx , substs. tys , substs. self_ty , output_type)
16121649 }
16131650 } ;
1614- let is_immediate = ty :: type_is_immediate ( substd_output_type) ;
1651+ let uses_outptr = type_of :: return_uses_outptr ( substd_output_type) ;
16151652
16161653 let fcx = @mut fn_ctxt_ {
16171654 llfn : llfndecl,
@@ -1623,7 +1660,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
16231660 llself : None ,
16241661 personality : None ,
16251662 loop_ret : None ,
1626- has_immediate_return_value : is_immediate ,
1663+ caller_expects_out_pointer : uses_outptr ,
16271664 llargs : @mut HashMap :: new ( ) ,
16281665 lllocals : @mut HashMap :: new ( ) ,
16291666 llupvars : @mut HashMap :: new ( ) ,
@@ -1783,7 +1820,7 @@ pub fn build_return_block(fcx: fn_ctxt) {
17831820 let ret_cx = raw_block ( fcx, false , fcx. llreturn ) ;
17841821
17851822 // Return the value if this function immediate; otherwise, return void.
1786- if fcx. has_immediate_return_value {
1823+ if ! fcx. caller_expects_out_pointer {
17871824 Ret ( ret_cx, Load ( ret_cx, fcx. llretptr . get ( ) ) )
17881825 } else {
17891826 RetVoid ( ret_cx)
@@ -1871,9 +1908,7 @@ pub fn trans_closure(ccx: @CrateContext,
18711908 // translation calls that don't have a return value (trans_crate,
18721909 // trans_mod, trans_item, et cetera) and those that do
18731910 // (trans_block, trans_expr, et cetera).
1874- if body. node . expr . is_none ( ) || ty:: type_is_bot ( block_ty) ||
1875- ty:: type_is_nil ( block_ty)
1876- {
1911+ if body. node . expr . is_none ( ) || ty:: type_is_voidish ( block_ty) {
18771912 bcx = controlflow:: trans_block ( bcx, body, expr:: Ignore ) ;
18781913 } else {
18791914 let dest = expr:: SaveIn ( fcx. llretptr . get ( ) ) ;
@@ -2114,13 +2149,14 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
21142149 ast::item_fn(ref decl, purity, _abis, ref generics, ref body) => {
21152150 if purity == ast::extern_fn {
21162151 let llfndecl = get_item_val(ccx, item.id);
2117- foreign::trans_foreign_fn(ccx,
2118- vec::append(/*bad*/copy *path,
2119- [path_name(item.ident)]),
2120- decl,
2121- body,
2122- llfndecl,
2123- item.id);
2152+ foreign::trans_rust_fn_with_foreign_abi(
2153+ ccx,
2154+ &vec::append(/*bad*/copy *path,
2155+ [path_name(item.ident)]),
2156+ decl,
2157+ body,
2158+ llfndecl,
2159+ item.id);
21242160 } else if !generics.is_type_parameterized() {
21252161 let llfndecl = get_item_val(ccx, item.id);
21262162 trans_fn(ccx,
@@ -2180,7 +2216,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
21802216 }
21812217 },
21822218 ast::item_foreign_mod(ref foreign_mod) => {
2183- foreign::trans_foreign_mod(ccx, path, foreign_mod);
2219+ foreign::trans_foreign_mod(ccx, foreign_mod);
21842220 }
21852221 ast::item_struct(struct_def, ref generics) => {
21862222 if !generics.is_type_parameterized() {
@@ -2293,7 +2329,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
22932329
22942330 fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef {
22952331 let nt = ty::mk_nil();
2296- let llfty = type_of_fn (ccx, [], nt);
2332+ let llfty = type_of_rust_fn (ccx, [], nt);
22972333 let llfdecl = decl_fn(ccx.llmod, " _rust_main",
22982334 lib::llvm::CCallConv, llfty);
22992335
@@ -2456,11 +2492,11 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
24562492 let llfn = if purity != ast::extern_fn {
24572493 register_fn(ccx, i.span, my_path, i.id, i.attrs)
24582494 } else {
2459- foreign::register_foreign_fn (ccx,
2460- i.span,
2461- my_path,
2462- i.id,
2463- i.attrs)
2495+ foreign::register_rust_fn_with_foreign_abi (ccx,
2496+ i.span,
2497+ my_path,
2498+ i.id,
2499+ i.attrs)
24642500 };
24652501 set_inline_hint_if_appr(i.attrs, llfn);
24662502 llfn
@@ -2485,15 +2521,13 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
24852521 exprt = true;
24862522 register_method(ccx, id, pth, m)
24872523 }
2488- ast_map::node_foreign_item(ni, _ , _, pth) => {
2524+ ast_map::node_foreign_item(ni, abis , _, pth) => {
24892525 exprt = true;
24902526 match ni.node {
24912527 ast::foreign_item_fn(*) => {
2492- register_fn(ccx, ni.span,
2493- vec::append(/*bad*/copy *pth,
2494- [path_name(ni.ident)]),
2495- ni.id,
2496- ni.attrs)
2528+ let path = vec::append(/*bad*/copy *pth,
2529+ [path_name(ni.ident)]);
2530+ foreign::register_foreign_item_fn(ccx, abis, &path, ni)
24972531 }
24982532 ast::foreign_item_const(*) => {
24992533 let typ = ty::node_id_to_type(tcx, ni.id);
0 commit comments