Skip to content

Commit d257382

Browse files
author
Elliott Slaughter
committed
Moved malloc and free upcalls into rust runtime.
1 parent de82a9b commit d257382

File tree

7 files changed

+123
-45
lines changed

7 files changed

+123
-45
lines changed

src/libcore/rt.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
11
//! Runtime calls emitted by the compiler.
22
33
import libc::c_char;
4+
import libc::c_void;
45
import libc::size_t;
6+
import libc::uintptr_t;
57

6-
type rust_task = libc::c_void;
8+
type rust_task = c_void;
79

810
extern mod rustrt {
911
#[rust_stack]
1012
fn rust_upcall_fail(expr: *c_char, file: *c_char, line: size_t);
13+
14+
#[rust_stack]
15+
fn rust_upcall_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char;
16+
17+
#[rust_stack]
18+
fn rust_upcall_exchange_free(ptr: *c_char);
19+
20+
#[rust_stack]
21+
fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
22+
23+
#[rust_stack]
24+
fn rust_upcall_free(ptr: *c_char);
1125
}
1226

1327
// FIXME (#2861): This needs both the attribute, and the name prefixed with
@@ -18,6 +32,26 @@ fn rt_fail(expr: *c_char, file: *c_char, line: size_t) {
1832
rustrt::rust_upcall_fail(expr, file, line);
1933
}
2034

35+
#[rt(exchange_malloc)]
36+
fn rt_exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
37+
ret rustrt::rust_upcall_exchange_malloc(td, size);
38+
}
39+
40+
#[rt(exchange_free)]
41+
fn rt_exchange_free(ptr: *c_char) {
42+
rustrt::rust_upcall_exchange_free(ptr);
43+
}
44+
45+
#[rt(malloc)]
46+
fn rt_malloc(td: *c_char, size: uintptr_t) -> *c_char {
47+
ret rustrt::rust_upcall_malloc(td, size);
48+
}
49+
50+
#[rt(free)]
51+
fn rt_free(ptr: *c_char) {
52+
rustrt::rust_upcall_free(ptr);
53+
}
54+
2155
// Local Variables:
2256
// mode: rust;
2357
// fill-column: 78;

src/rt/rust_upcall.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ upcall_exchange_malloc(type_desc *td, uintptr_t size) {
170170
return args.retval;
171171
}
172172

173+
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
174+
// autogenerated wrappers for upcall_exchange_malloc. Remove this when we
175+
// fully move away away from the C upcall path.
176+
extern "C" CDECL uintptr_t
177+
rust_upcall_exchange_malloc(type_desc *td, uintptr_t size) {
178+
return upcall_exchange_malloc(td, size);
179+
}
180+
173181
struct s_exchange_free_args {
174182
rust_task *task;
175183
void *ptr;
@@ -189,6 +197,14 @@ upcall_exchange_free(void *ptr) {
189197
UPCALL_SWITCH_STACK(task, &args, upcall_s_exchange_free);
190198
}
191199

200+
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
201+
// autogenerated wrappers for upcall_exchange_free. Remove this when we fully
202+
// move away away from the C upcall path.
203+
extern "C" CDECL void
204+
rust_upcall_exchange_free(void *ptr) {
205+
return upcall_exchange_free(ptr);
206+
}
207+
192208
/**********************************************************************
193209
* Allocate an object in the task-local heap.
194210
*/
@@ -230,6 +246,14 @@ upcall_malloc(type_desc *td, uintptr_t size) {
230246
return args.retval;
231247
}
232248

249+
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
250+
// autogenerated wrappers for upcall_malloc. Remove this when we fully move
251+
// away away from the C upcall path.
252+
extern "C" CDECL uintptr_t
253+
rust_upcall_malloc(type_desc *td, uintptr_t size) {
254+
return upcall_malloc(td, size);
255+
}
256+
233257
/**********************************************************************
234258
* Called whenever an object in the task-local heap is freed.
235259
*/
@@ -262,6 +286,14 @@ upcall_free(void* ptr) {
262286
UPCALL_SWITCH_STACK(task, &args, upcall_s_free);
263287
}
264288

289+
// FIXME (#2861): Alias used by libcore/rt.rs to avoid naming conflicts with
290+
// autogenerated wrappers for upcall_free. Remove this when we fully move away
291+
// away from the C upcall path.
292+
extern "C" CDECL void
293+
rust_upcall_free(void* ptr) {
294+
upcall_free(ptr);
295+
}
296+
265297
/**********************************************************************
266298
* Sanity checks on boxes, insert when debugging possible
267299
* use-after-free bugs. See maybe_validate_box() in trans.rs.

src/rustc/middle/trans/base.rs

+34-28
Original file line numberDiff line numberDiff line change
@@ -244,15 +244,13 @@ fn trans_foreign_call(cx: block, externs: hashmap<~str, ValueRef>,
244244

245245
fn trans_free(cx: block, v: ValueRef) -> block {
246246
let _icx = cx.insn_ctxt(~"trans_free");
247-
Call(cx, cx.ccx().upcalls.free, ~[PointerCast(cx, v, T_ptr(T_i8()))]);
248-
cx
247+
trans_rtcall(cx, ~"free", ~[PointerCast(cx, v, T_ptr(T_i8()))], ignore)
249248
}
250249

251250
fn trans_unique_free(cx: block, v: ValueRef) -> block {
252251
let _icx = cx.insn_ctxt(~"trans_unique_free");
253-
Call(cx, cx.ccx().upcalls.exchange_free,
254-
~[PointerCast(cx, v, T_ptr(T_i8()))]);
255-
ret cx;
252+
trans_rtcall(cx, ~"exchange_free", ~[PointerCast(cx, v, T_ptr(T_i8()))],
253+
ignore)
256254
}
257255

258256
fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
@@ -356,15 +354,13 @@ fn opaque_box_body(bcx: block,
356354
// malloc_raw_dyn: allocates a box to contain a given type, but with a
357355
// potentially dynamic size.
358356
fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
359-
size: ValueRef) -> ValueRef {
357+
size: ValueRef) -> result {
360358
let _icx = bcx.insn_ctxt(~"malloc_raw");
361359
let ccx = bcx.ccx();
362360

363-
let (mk_fn, upcall) = alt heap {
364-
heap_shared { (ty::mk_imm_box, ccx.upcalls.malloc) }
365-
heap_exchange {
366-
(ty::mk_imm_uniq, ccx.upcalls.exchange_malloc )
367-
}
361+
let (mk_fn, rtcall) = alt heap {
362+
heap_shared { (ty::mk_imm_box, ~"malloc") }
363+
heap_exchange { (ty::mk_imm_uniq, ~"exchange_malloc") }
368364
};
369365

370366
// Grab the TypeRef type of box_ptr_ty.
@@ -376,37 +372,42 @@ fn malloc_raw_dyn(bcx: block, t: ty::t, heap: heap,
376372
lazily_emit_all_tydesc_glue(ccx, static_ti);
377373

378374
// Allocate space:
379-
let rval = Call(bcx, upcall, ~[static_ti.tydesc, size]);
380-
ret PointerCast(bcx, rval, llty);
375+
let tydesc = PointerCast(bcx, static_ti.tydesc, T_ptr(T_i8()));
376+
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
377+
let bcx = trans_rtcall(bcx, rtcall, ~[tydesc, size], save_in(rval));
378+
let retval = {bcx: bcx, val: PointerCast(bcx, Load(bcx, rval), llty)};
379+
ret retval;
381380
}
382381

383382
// malloc_raw: expects an unboxed type and returns a pointer to
384383
// enough space for a box of that type. This includes a rust_opaque_box
385384
// header.
386-
fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> ValueRef {
385+
fn malloc_raw(bcx: block, t: ty::t, heap: heap) -> result {
387386
malloc_raw_dyn(bcx, t, heap, llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
388387
}
389388

390389
// malloc_general_dyn: usefully wraps malloc_raw_dyn; allocates a box,
391390
// and pulls out the body
392-
fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef) ->
393-
{box: ValueRef, body: ValueRef} {
391+
fn malloc_general_dyn(bcx: block, t: ty::t, heap: heap, size: ValueRef)
392+
-> {bcx: block, box: ValueRef, body: ValueRef} {
394393
let _icx = bcx.insn_ctxt(~"malloc_general");
395-
let llbox = malloc_raw_dyn(bcx, t, heap, size);
394+
let {bcx: bcx, val: llbox} = malloc_raw_dyn(bcx, t, heap, size);
396395
let non_gc_box = non_gc_box_cast(bcx, llbox);
397396
let body = GEPi(bcx, non_gc_box, ~[0u, abi::box_field_body]);
398-
ret {box: llbox, body: body};
397+
ret {bcx: bcx, box: llbox, body: body};
399398
}
400399

401-
fn malloc_general(bcx: block, t: ty::t, heap: heap) ->
402-
{box: ValueRef, body: ValueRef} {
400+
fn malloc_general(bcx: block, t: ty::t, heap: heap)
401+
-> {bcx: block, box: ValueRef, body: ValueRef} {
403402
malloc_general_dyn(bcx, t, heap,
404403
llsize_of(bcx.ccx(), type_of(bcx.ccx(), t)))
405404
}
406-
fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
405+
fn malloc_boxed(bcx: block, t: ty::t)
406+
-> {bcx: block, box: ValueRef, body: ValueRef} {
407407
malloc_general(bcx, t, heap_shared)
408408
}
409-
fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} {
409+
fn malloc_unique(bcx: block, t: ty::t)
410+
-> {bcx: block, box: ValueRef, body: ValueRef} {
410411
malloc_general(bcx, t, heap_exchange)
411412
}
412413

@@ -1464,7 +1465,7 @@ fn trans_boxed_expr(bcx: block, contents: @ast::expr,
14641465
t: ty::t, heap: heap,
14651466
dest: dest) -> block {
14661467
let _icx = bcx.insn_ctxt(~"trans_boxed_expr");
1467-
let {box, body} = malloc_general(bcx, t, heap);
1468+
let {bcx, box, body} = malloc_general(bcx, t, heap);
14681469
add_clean_free(bcx, box, heap);
14691470
let bcx = trans_expr_save_in(bcx, contents, body);
14701471
revoke_clean(bcx, box);
@@ -3942,12 +3943,13 @@ fn trans_fail_value(bcx: block, sp_opt: option<span>,
39423943
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
39433944
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
39443945
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
3945-
let bcx = trans_rtcall(bcx, ~"fail", args);
3946+
let bcx = trans_rtcall(bcx, ~"fail", args, ignore);
39463947
Unreachable(bcx);
39473948
ret bcx;
39483949
}
39493950

3950-
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block {
3951+
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: dest)
3952+
-> block {
39513953
let did = bcx.ccx().rtcalls[name];
39523954
let fty = if did.crate == ast::local_crate {
39533955
ty::node_id_to_type(bcx.ccx().tcx, did.node)
@@ -3958,7 +3960,7 @@ fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef]) -> block {
39583960
ret trans_call_inner(
39593961
bcx, none, fty, rty,
39603962
|bcx| lval_static_fn_inner(bcx, did, 0, ~[], none),
3961-
arg_vals(args), ignore);
3963+
arg_vals(args), dest);
39623964
}
39633965

39643966
fn trans_break_cont(bcx: block, to_end: bool)
@@ -5396,8 +5398,12 @@ fn gather_rtcalls(ccx: @crate_ctxt, crate: @ast::crate) {
53965398
// supported. Also probably want to check type signature so we don't crash
53975399
// in some obscure place in LLVM if the user provides the wrong signature
53985400
// for an rtcall.
5399-
if !ccx.rtcalls.contains_key(~"fail") {
5400-
fail ~"no definition for runtime call fail";
5401+
let expected_rtcalls =
5402+
~[~"exchange_free", ~"exchange_malloc", ~"fail", ~"free", ~"malloc"];
5403+
for vec::each(expected_rtcalls) |name| {
5404+
if !ccx.rtcalls.contains_key(name) {
5405+
fail #fmt("no definition for runtime call %s", name);
5406+
}
54015407
}
54025408
}
54035409

src/rustc/middle/trans/closure.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ fn mk_closure_tys(tcx: ty::ctxt,
138138
fn allocate_cbox(bcx: block,
139139
ck: ty::closure_kind,
140140
cdata_ty: ty::t)
141-
-> ValueRef {
141+
-> result {
142142
let _icx = bcx.insn_ctxt(~"closure::allocate_cbox");
143143
let ccx = bcx.ccx(), tcx = ccx.tcx;
144144

@@ -153,7 +153,7 @@ fn allocate_cbox(bcx: block,
153153
}
154154

155155
// Allocate and initialize the box:
156-
let llbox = alt ck {
156+
let {bcx, val} = alt ck {
157157
ty::ck_box {
158158
malloc_raw(bcx, cdata_ty, heap_shared)
159159
}
@@ -164,11 +164,11 @@ fn allocate_cbox(bcx: block,
164164
let cbox_ty = tuplify_box_ty(tcx, cdata_ty);
165165
let llbox = base::alloc_ty(bcx, cbox_ty);
166166
nuke_ref_count(bcx, llbox);
167-
llbox
167+
{bcx: bcx, val: llbox}
168168
}
169169
};
170170

171-
ret llbox;
171+
ret {bcx: bcx, val: val};
172172
}
173173

174174
type closure_result = {
@@ -191,7 +191,7 @@ fn store_environment(bcx: block,
191191
let cdata_ty = mk_closure_tys(tcx, bound_values);
192192

193193
// allocate closure in the heap
194-
let llbox = allocate_cbox(bcx, ck, cdata_ty);
194+
let {bcx: bcx, val: llbox} = allocate_cbox(bcx, ck, cdata_ty);
195195
let mut temp_cleanups = ~[];
196196

197197
// cbox_ty has the form of a tuple: (a, b, c) we want a ptr to a
@@ -362,14 +362,14 @@ fn trans_expr_fn(bcx: block,
362362
dest: dest) -> block {
363363
let _icx = bcx.insn_ctxt(~"closure::trans_expr_fn");
364364
if dest == ignore { ret bcx; }
365-
let ccx = bcx.ccx(), bcx = bcx;
365+
let ccx = bcx.ccx();
366366
let fty = node_id_type(bcx, id);
367367
let llfnty = type_of_fn_from_ty(ccx, fty);
368368
let sub_path = vec::append_one(bcx.fcx.path, path_name(@~"anon"));
369369
let s = mangle_internal_name_by_path(ccx, sub_path);
370370
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
371371

372-
let trans_closure_env = fn@(ck: ty::closure_kind) -> ValueRef {
372+
let trans_closure_env = fn@(ck: ty::closure_kind) -> result {
373373
let cap_vars = capture::compute_capture_vars(
374374
ccx.tcx, id, proto, cap_clause);
375375
let ret_handle = alt is_loop_body { some(x) { x } none { none } };
@@ -384,20 +384,21 @@ fn trans_expr_fn(bcx: block,
384384
Store(bcx, C_bool(true), bcx.fcx.llretptr);
385385
}
386386
});
387-
llbox
387+
{bcx: bcx, val: llbox}
388388
};
389389

390-
let closure = alt proto {
390+
let {bcx: bcx, val: closure} = alt proto {
391391
ast::proto_any | ast::proto_block { trans_closure_env(ty::ck_block) }
392392
ast::proto_box { trans_closure_env(ty::ck_box) }
393393
ast::proto_uniq { trans_closure_env(ty::ck_uniq) }
394394
ast::proto_bare {
395395
trans_closure(ccx, sub_path, decl, body, llfn, no_self, none,
396396
id, |_fcx| { }, |_bcx| { });
397-
C_null(T_opaque_box_ptr(ccx))
397+
{bcx: bcx, val: C_null(T_opaque_box_ptr(ccx))}
398398
}
399399
};
400400
fill_fn_pair(bcx, get_dest_addr(dest), llfn, closure);
401+
401402
ret bcx;
402403
}
403404

@@ -459,9 +460,12 @@ fn make_opaque_cbox_take_glue(
459460
let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx)));
460461

461462
// Allocate memory, update original ptr, and copy existing data
462-
let malloc = ccx.upcalls.exchange_malloc;
463-
let cbox_out = Call(bcx, malloc, ~[tydesc, sz]);
464-
let cbox_out = PointerCast(bcx, cbox_out, llopaquecboxty);
463+
let malloc = ~"exchange_malloc";
464+
let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
465+
let rval = alloca_zeroed(bcx, T_ptr(T_i8()));
466+
let bcx = trans_rtcall(bcx, malloc, ~[opaque_tydesc, sz],
467+
save_in(rval));
468+
let cbox_out = PointerCast(bcx, Load(bcx, rval), llopaquecboxty);
465469
call_memmove(bcx, cbox_out, cbox_in, sz);
466470
Store(bcx, cbox_out, cboxptr);
467471

src/rustc/middle/trans/impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ fn trans_cast(bcx: block, val: @ast::expr, id: ast::node_id, dest: dest)
288288
if dest == ignore { ret trans_expr(bcx, val, ignore); }
289289
let ccx = bcx.ccx();
290290
let v_ty = expr_ty(bcx, val);
291-
let {box: llbox, body: body} = malloc_boxed(bcx, v_ty);
291+
let {bcx: bcx, box: llbox, body: body} = malloc_boxed(bcx, v_ty);
292292
add_clean_free(bcx, llbox, heap_shared);
293293
let bcx = trans_expr_save_in(bcx, val, body);
294294
revoke_clean(bcx, llbox);

src/rustc/middle/trans/tvec.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ fn alloc_raw(bcx: block, unit_ty: ty::t,
6868
let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
6969
let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));
7070

71-
let {box, body} = base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
71+
let {bcx, box, body} =
72+
base::malloc_general_dyn(bcx, vecbodyty, heap, vecsize);
7273
Store(bcx, fill, GEPi(bcx, body, ~[0u, abi::vec_elt_fill]));
7374
Store(bcx, alloc, GEPi(bcx, body, ~[0u, abi::vec_elt_alloc]));
7475
ret {bcx: bcx, val: box};

src/rustc/middle/trans/uniq.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ fn autoderef(bcx: block, v: ValueRef, t: ty::t) -> {v: ValueRef, t: ty::t} {
3434
fn duplicate(bcx: block, v: ValueRef, t: ty::t) -> result {
3535
let _icx = bcx.insn_ctxt(~"uniq::duplicate");
3636
let content_ty = content_ty(t);
37-
let {box: dst_box, body: dst_body} = malloc_unique(bcx, content_ty);
37+
let {bcx: bcx, box: dst_box, body: dst_body} =
38+
malloc_unique(bcx, content_ty);
3839

3940
let src_box = v;
4041
let src_body = opaque_box_body(bcx, content_ty, src_box);

0 commit comments

Comments
 (0)