Skip to content

Commit e6a5165

Browse files
committed
Issue #3678: Remove wrappers and call foreign functions directly
1 parent e6a838d commit e6a5165

21 files changed

+1636
-1681
lines changed

src/librustc/back/upcall.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use lib::llvm::{ModuleRef, ValueRef, TypeRef};
1616

1717
pub struct Upcalls {
1818
trace: ValueRef,
19-
call_shim_on_c_stack: ValueRef,
20-
call_shim_on_rust_stack: ValueRef,
2119
rust_personality: ValueRef,
2220
reset_stack_limit: ValueRef
2321
}
@@ -45,14 +43,6 @@ pub fn declare_upcalls(targ_cfg: @session::config,
4543
trace: dv(~"trace", ~[T_ptr(T_i8()),
4644
T_ptr(T_i8()),
4745
int_t]),
48-
call_shim_on_c_stack:
49-
d(~"call_shim_on_c_stack",
50-
// arguments: void *args, void *fn_ptr
51-
~[T_ptr(T_i8()), T_ptr(T_i8())],
52-
int_t),
53-
call_shim_on_rust_stack:
54-
d(~"call_shim_on_rust_stack",
55-
~[T_ptr(T_i8()), T_ptr(T_i8())], int_t),
5646
rust_personality:
5747
nothrow(d(~"rust_personality", ~[], T_i32())),
5848
reset_stack_limit:

src/librustc/middle/trans/base.rs

Lines changed: 95 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -169,56 +169,35 @@ pub fn decl_internal_cdecl_fn(llmod: ModuleRef, name: ~str, llty: TypeRef) ->
169169

170170
pub 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

184186
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) {
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-
222201
pub 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
812790
pub 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+
828865
pub 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.
15711608
pub 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

Comments
 (0)