Translate exit-task glue such that rustc's output programs exit properly.

This commit is contained in:
Graydon Hoare 2010-09-27 15:38:34 -07:00
parent a2f4d9089a
commit f5787ed80c
2 changed files with 71 additions and 17 deletions

View File

@ -48,6 +48,10 @@ fn yield_glue_name() -> str {
ret "rust_yield_glue";
}
fn exit_task_glue_name() -> str {
ret "rust_exit_task_glue";
}
//
// Local Variables:
// mode: rust

View File

@ -25,6 +25,7 @@ import lib.llvm.True;
type glue_fns = rec(ValueRef activate_glue,
ValueRef yield_glue,
ValueRef exit_task_glue,
vec[ValueRef] upcall_glues);
type trans_ctxt = rec(session.session sess,
@ -240,32 +241,48 @@ fn new_builder(BasicBlockRef llbb) -> builder {
ret builder(llbuild);
}
fn trans_block(@fn_ctxt cx, &ast.block b, terminator term) {
fn new_block_ctxt(@fn_ctxt cx, terminator term) -> @block_ctxt {
let BasicBlockRef llbb =
llvm.LLVMAppendBasicBlock(cx.llfn, _str.buf(""));
auto bcx = @rec(llbb=llbb,
ret @rec(llbb=llbb,
build=new_builder(llbb),
term=term,
fcx=cx);
}
fn trans_block(@fn_ctxt cx, &ast.block b, terminator term) {
auto bcx = (new_block_ctxt(cx, term));
for (@ast.stmt s in b) {
trans_stmt(bcx, *s);
}
bcx.term(cx, bcx.build);
}
fn trans_fn(@trans_ctxt cx, &ast._fn f) {
let vec[TypeRef] args = vec(T_ptr(T_int()), // outptr.
fn new_fn_ctxt(@trans_ctxt cx,
str name,
TypeRef T_out,
vec[TypeRef] T_explicit_args) -> @fn_ctxt {
let vec[TypeRef] args = vec(T_ptr(T_out), // outptr.
T_taskptr() // taskptr
);
let ValueRef llfn = decl_cdecl_fn(cx.llmod, cx.path, args, T_nil());
args += T_explicit_args;
let ValueRef llfn = decl_cdecl_fn(cx.llmod, name, args, T_nil());
cx.fns.insert(cx.path, llfn);
let ValueRef lloutptr = llvm.LLVMGetParam(llfn, 0u);
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 1u);
auto fcx = @rec(llfn=llfn,
ret @rec(llfn=llfn,
lloutptr=lloutptr,
lltaskptr=lltaskptr,
tcx=cx);
}
fn trans_fn(@trans_ctxt cx, &ast._fn f) {
let TypeRef out = T_int();
let vec[TypeRef] args = vec();
auto fcx = new_fn_ctxt(cx, cx.path, out, args);
auto term = default_terminate;
trans_block(fcx, f.body, term);
}
@ -292,6 +309,24 @@ fn p2i(ValueRef v) -> ValueRef {
ret llvm.LLVMConstPtrToInt(v, T_int());
}
fn trans_exit_task_glue(@trans_ctxt cx) {
let vec[TypeRef] T_args = vec();
let vec[ValueRef] V_args = vec();
auto term = default_terminate;
auto llfn = cx.glues.exit_task_glue;
let ValueRef lloutptr = C_null(T_int());
let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 0u);
auto fcx = @rec(llfn=llfn,
lloutptr=lloutptr,
lltaskptr=lltaskptr,
tcx=cx);
auto bcx = new_block_ctxt(fcx, term);
trans_upcall(bcx, "upcall_exit", V_args);
bcx.term(fcx, bcx.build);
}
fn crate_constant(@trans_ctxt cx) -> ValueRef {
let ValueRef crate_ptr =
@ -306,9 +341,8 @@ fn crate_constant(@trans_ctxt cx) -> ValueRef {
let ValueRef yield_glue_off =
llvm.LLVMConstSub(p2i(cx.glues.yield_glue), crate_addr);
// FIXME: we aren't generating the exit-task glue yet.
// llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr);
let ValueRef exit_task_glue_off = C_null(T_int());
let ValueRef exit_task_glue_off =
llvm.LLVMConstSub(p2i(cx.glues.exit_task_glue), crate_addr);
let ValueRef crate_val =
C_struct(vec(C_null(T_int()), // ptrdiff_t image_base_off
@ -373,6 +407,22 @@ fn trans_crate(session.session sess, ast.crate crate) {
auto glues = @rec(activate_glue = decl_glue(llmod,
abi.activate_glue_name()),
yield_glue = decl_glue(llmod, abi.yield_glue_name()),
/*
* Note: the signature passed to decl_cdecl_fn here
* looks unusual because it is. It corresponds neither
* to an upcall signature nor a normal rust-ABI
* signature. In fact it is a fake signature, that
* exists solely to acquire the task pointer as an
* argument to the upcall. It so happens that the
* runtime sets up the task pointer as the sole incoming
* argument to the frame that we return into when
* returning to the exit task glue. So this is the
* signature required to retrieve it.
*/
exit_task_glue =
decl_cdecl_fn(llmod, abi.exit_task_glue_name(),
vec(T_taskptr()), T_nil()),
upcall_glues =
_vec.init_fn[ValueRef](bind decl_upcall(llmod, _),
abi.n_upcall_glues as uint));
@ -385,7 +435,7 @@ fn trans_crate(session.session sess, ast.crate crate) {
path = "_rust");
trans_mod(cx, crate.module);
trans_exit_task_glue(cx);
trans_main_fn(cx, crate_constant(cx));
llvm.LLVMWriteBitcodeToFile(llmod, _str.buf("rust_out.bc"));