@@ -169,56 +169,35 @@ pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) ->
169
169
170
170
pub fn get_extern_fn ( externs : ExternMap ,
171
171
llmod : ModuleRef ,
172
- name : @ str ,
172
+ name : & str ,
173
173
cc : lib:: llvm:: CallConv ,
174
174
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
+ }
177
179
None => ( )
178
180
}
179
181
let f = decl_fn ( llmod, name, cc, ty) ;
180
- externs. insert ( name, f) ;
182
+ externs. insert ( name. to_owned ( ) , f) ;
181
183
return f;
182
184
}
183
185
184
186
pub 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) {
187
189
Some ( n) => return copy * n,
188
190
None => ( )
189
191
}
190
192
unsafe {
191
193
let c = str:: as_c_str ( name, |buf| {
192
194
llvm:: LLVMAddGlobal ( llmod, ty, buf)
193
195
} ) ;
194
- externs. insert ( name, c) ;
196
+ externs. insert ( name. to_owned ( ) , c) ;
195
197
return c;
196
198
}
197
199
}
198
200
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
-
222
201
pub fn umax ( cx : block , a : ValueRef , b : ValueRef ) -> ValueRef {
223
202
let _icx = cx. insn_ctxt ( "umax" ) ;
224
203
let cond = ICmp ( cx, lib:: llvm:: IntULT , a, b) ;
@@ -517,7 +496,6 @@ pub fn get_res_dtor(ccx: @CrateContext,
517
496
None ,
518
497
ty:: lookup_item_type ( tcx, parent_id) . ty ) ;
519
498
let llty = type_of_dtor ( ccx, class_ty) ;
520
- let name = name. to_managed ( ) ; // :-(
521
499
get_extern_fn ( ccx. externs ,
522
500
ccx. llmod ,
523
501
name,
@@ -805,13 +783,13 @@ pub fn fail_if_zero(cx: block, span: span, divrem: ast::binop,
805
783
}
806
784
}
807
785
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))
810
788
}
811
789
812
790
pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t)
813
791
-> ValueRef {
814
- let name = csearch::get_symbol(ccx.sess.cstore, did).to_managed(); // Sad
792
+ let name = csearch::get_symbol(ccx.sess.cstore, did);
815
793
match ty::get(t).sty {
816
794
ty::ty_bare_fn(_) | ty::ty_closure(_) => {
817
795
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)
825
803
};
826
804
}
827
805
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
+
828
865
pub fn invoke( bcx: block, llfn: ValueRef , llargs: ~[ ValueRef ] )
829
866
-> ( ValueRef , block) {
830
867
let _icx = bcx. insn_ctxt ( "invoke_" ) ;
@@ -1570,7 +1607,7 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
1570
1607
// slot where the return value of the function must go.
1571
1608
pub fn make_return_pointer ( fcx : fn_ctxt , output_type : ty:: t ) -> ValueRef {
1572
1609
unsafe {
1573
- if !ty :: type_is_immediate ( output_type) {
1610
+ if type_of :: return_uses_outptr ( output_type) {
1574
1611
llvm:: LLVMGetParam ( fcx. llfn , 0 )
1575
1612
} else {
1576
1613
let lloutputtype = type_of:: type_of ( * fcx. ccx , output_type) ;
@@ -1611,7 +1648,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
1611
1648
ty:: subst_tps ( ccx. tcx , substs. tys , substs. self_ty , output_type)
1612
1649
}
1613
1650
} ;
1614
- let is_immediate = ty :: type_is_immediate ( substd_output_type) ;
1651
+ let uses_outptr = type_of :: return_uses_outptr ( substd_output_type) ;
1615
1652
1616
1653
let fcx = @mut fn_ctxt_ {
1617
1654
llfn : llfndecl,
@@ -1623,7 +1660,7 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
1623
1660
llself : None ,
1624
1661
personality : None ,
1625
1662
loop_ret : None ,
1626
- has_immediate_return_value : is_immediate ,
1663
+ caller_expects_out_pointer : uses_outptr ,
1627
1664
llargs : @mut HashMap :: new ( ) ,
1628
1665
lllocals : @mut HashMap :: new ( ) ,
1629
1666
llupvars : @mut HashMap :: new ( ) ,
@@ -1783,7 +1820,7 @@ pub fn build_return_block(fcx: fn_ctxt) {
1783
1820
let ret_cx = raw_block ( fcx, false , fcx. llreturn ) ;
1784
1821
1785
1822
// Return the value if this function immediate; otherwise, return void.
1786
- if fcx. has_immediate_return_value {
1823
+ if ! fcx. caller_expects_out_pointer {
1787
1824
Ret ( ret_cx, Load ( ret_cx, fcx. llretptr . get ( ) ) )
1788
1825
} else {
1789
1826
RetVoid ( ret_cx)
@@ -1871,9 +1908,7 @@ pub fn trans_closure(ccx: @CrateContext,
1871
1908
// translation calls that don't have a return value (trans_crate,
1872
1909
// trans_mod, trans_item, et cetera) and those that do
1873
1910
// (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) {
1877
1912
bcx = controlflow:: trans_block ( bcx, body, expr:: Ignore ) ;
1878
1913
} else {
1879
1914
let dest = expr:: SaveIn ( fcx. llretptr . get ( ) ) ;
@@ -2114,13 +2149,14 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
2114
2149
ast::item_fn(ref decl, purity, _abis, ref generics, ref body) => {
2115
2150
if purity == ast::extern_fn {
2116
2151
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);
2124
2160
} else if !generics.is_type_parameterized() {
2125
2161
let llfndecl = get_item_val(ccx, item.id);
2126
2162
trans_fn(ccx,
@@ -2180,7 +2216,7 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::item) {
2180
2216
}
2181
2217
},
2182
2218
ast::item_foreign_mod(ref foreign_mod) => {
2183
- foreign::trans_foreign_mod(ccx, path, foreign_mod);
2219
+ foreign::trans_foreign_mod(ccx, foreign_mod);
2184
2220
}
2185
2221
ast::item_struct(struct_def, ref generics) => {
2186
2222
if !generics.is_type_parameterized() {
@@ -2293,7 +2329,7 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
2293
2329
2294
2330
fn create_main(ccx: @CrateContext, main_llfn: ValueRef) -> ValueRef {
2295
2331
let nt = ty::mk_nil();
2296
- let llfty = type_of_fn (ccx, [], nt);
2332
+ let llfty = type_of_rust_fn (ccx, [], nt);
2297
2333
let llfdecl = decl_fn(ccx.llmod, " _rust_main",
2298
2334
lib::llvm::CCallConv, llfty);
2299
2335
@@ -2456,11 +2492,11 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
2456
2492
let llfn = if purity != ast::extern_fn {
2457
2493
register_fn(ccx, i.span, my_path, i.id, i.attrs)
2458
2494
} 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)
2464
2500
};
2465
2501
set_inline_hint_if_appr(i.attrs, llfn);
2466
2502
llfn
@@ -2485,15 +2521,13 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
2485
2521
exprt = true;
2486
2522
register_method(ccx, id, pth, m)
2487
2523
}
2488
- ast_map::node_foreign_item(ni, _ , _, pth) => {
2524
+ ast_map::node_foreign_item(ni, abis , _, pth) => {
2489
2525
exprt = true;
2490
2526
match ni.node {
2491
2527
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)
2497
2531
}
2498
2532
ast::foreign_item_const(*) => {
2499
2533
let typ = ty::node_id_to_type(tcx, ni.id);
0 commit comments