提交 9fadab64 编写于 作者: P Patrick Walton

rustc: Introduce a stub destination-passing-style translation engine,...

rustc: Introduce a stub destination-passing-style translation engine, accessible via the --dps switch for now
上级 917afa4c
......@@ -251,7 +251,10 @@ fn usage(str argv0) {
--time-llvm-passes time the individual phases of the LLVM backend
--sysroot <path> override the system root (default: rustc's directory)
--no-typestate don't run the typestate pass (unsafe!)
--test build test harness\n\n");
--test build test harness
--dps translate via destination-passing style (experimental)
");
}
fn get_os(str triple) -> session::os {
......@@ -352,6 +355,7 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
};
auto cfg = parse_cfgspecs(getopts::opt_strs(match, "cfg"));
auto test = opt_present(match, "test");
auto dps = opt_present(match, "dps");
let @session::options sopts =
@rec(library=library,
static=static,
......@@ -367,7 +371,8 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
library_search_paths=library_search_paths,
sysroot=sysroot,
cfg=cfg,
test=test);
test=test,
dps=dps);
ret sopts;
}
......@@ -398,7 +403,7 @@ fn opts() -> vec[getopts::opt] {
optopt("sysroot"), optflag("stats"), optflag("time-passes"),
optflag("time-llvm-passes"), optflag("no-typestate"),
optflag("noverify"), optmulti("cfg"), optflag("test"),
optflag("lib"), optflag("static")];
optflag("lib"), optflag("static"), optflag("dps")];
}
fn main(vec[str] args) {
......
......@@ -40,7 +40,8 @@
// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process
ast::crate_cfg cfg,
bool test);
bool test,
bool dps);
type crate_metadata = rec(str name, u8[] data);
......
......@@ -7083,19 +7083,27 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
auto lltop = bcx.llbb;
auto block_ty = node_id_type(cx.ccx, f.body.node.id);
// This call to trans_block is the place where we bridge between
// translation calls that don't have a return value (trans_crate,
// trans_mod, trans_item, trans_obj, et cetera) and those that do
// (trans_block, trans_expr, et cetera).
auto rslt =
if (!ty::type_is_nil(cx.ccx.tcx, block_ty) &&
!ty::type_is_bot(cx.ccx.tcx, block_ty)) {
trans_block(bcx, f.body, save_in(fcx.llretptr))
} else { trans_block(bcx, f.body, return) };
if (!is_terminated(rslt.bcx)) {
if (cx.ccx.sess.get_opts().dps) {
// Call into the new destination-passing-style translation engine.
auto dest = trans_dps::dest_move(cx.ccx.tcx, fcx.llretptr, block_ty);
bcx = trans_dps::trans_block(bcx, dest, f.body);
} else {
// This call to trans_block is the place where we bridge between
// translation calls that don't have a return value (trans_crate,
// trans_mod, trans_item, trans_obj, et cetera) and those that do
// (trans_block, trans_expr, et cetera).
auto rslt =
if (!ty::type_is_nil(cx.ccx.tcx, block_ty) &&
!ty::type_is_bot(cx.ccx.tcx, block_ty)) {
trans_block(bcx, f.body, save_in(fcx.llretptr))
} else { trans_block(bcx, f.body, return) };
bcx = rslt.bcx;
}
if (!is_terminated(bcx)) {
// FIXME: until LLVM has a unit type, we are moving around
// C_nil values rather than their void type.
rslt.bcx.build.RetVoid();
bcx.build.RetVoid();
}
// Insert the mandatory first few basic blocks before lltop.
......
// Translates individual functions in the completed AST to the LLVM IR, using
// destination-passing style.
import syntax::ast;
import middle::trans;
import middle::ty;
import trans::block_ctxt;
import trans::crate_ctxt;
import trans::fn_ctxt;
import trans::local_ctxt;
import lib::llvm::llvm::TypeRef;
import lib::llvm::llvm::ValueRef;
import std::option::none;
import std::option::some;
import type_of_node = trans::node_id_type;
// LLVM utilities
fn llelement_type(TypeRef llty) -> TypeRef {
lib::llvm::llvm::LLVMGetElementType(llty)
}
// Destination utilities
tag dest_slot {
dst_nil;
dst_val(ValueRef);
}
type dest = rec(dest_slot slot, bool move);
fn dest_slot_for_ptr(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest_slot {
if ty::type_is_nil(tcx, t) { dst_nil } else { dst_val(llptr) }
}
fn dest_copy(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest {
ret rec(slot=dest_slot_for_ptr(tcx, llptr, t), move=false);
}
fn dest_move(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest {
ret rec(slot=dest_slot_for_ptr(tcx, llptr, t), move=true);
}
fn dest_tmp(&@block_ctxt bcx, ty::t t) -> tup(@block_ctxt, dest) {
if ty::type_is_nil(bcx_tcx(bcx), t) {
ret tup(bcx, rec(slot=dst_nil, move=true));
}
auto r = trans::alloc_ty(bcx, t);
ret tup(r.bcx, dest_move(bcx_tcx(bcx), r.val, t));
}
// Accessors
// TODO: When we have overloading, simplify these names!
fn bcx_tcx(&@block_ctxt bcx) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
fn bcx_ccx(&@block_ctxt bcx) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
fn bcx_lcx(&@block_ctxt bcx) -> @local_ctxt { ret bcx.fcx.lcx; }
fn bcx_fcx(&@block_ctxt bcx) -> @fn_ctxt { ret bcx.fcx; }
// Common operations
fn store(&@block_ctxt bcx, &dest dest, ValueRef llsrc) -> @block_ctxt {
alt (dest.slot) {
dst_nil { /* no-op */ }
dst_val(?lldest) { bcx.build.Store(llsrc, lldest); }
}
ret bcx;
}
// AST substructure translation, with destinations
fn trans_expr(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
ret bcx; // TODO
}
fn trans_recv(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
ret bcx; // TODO
}
fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
-> @block_ctxt {
auto bcx = cx;
for each (@ast::local local in trans::block_locals(block)) {
bcx = trans::alloc_local(bcx, local).bcx;
}
for (@ast::stmt stmt in block.node.stmts) {
bcx = trans_stmt(bcx, stmt);
// If we hit a terminator, control won't go any further so
// we're in dead-code land. Stop here.
if trans::is_terminated(bcx) { ret bcx; }
}
alt (block.node.expr) {
some(?e) { ret trans_expr(bcx, dest, e); }
none { ret bcx; }
}
}
// AST substructure translation, without destinations
fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
auto llptr = bcx_fcx(bcx).lllocals.get(local.node.id);
auto t = type_of_node(bcx_ccx(bcx), local.node.id);
trans::add_clean(bcx, llptr, t);
alt (local.node.init) {
some(?init) {
alt (init.op) {
ast::init_assign {
ret trans_expr(bcx, dest_copy(bcx_tcx(bcx), llptr, t), init.expr);
}
ast::init_move {
ret trans_expr(bcx, dest_move(bcx_tcx(bcx), llptr, t), init.expr);
}
ast::init_recv {
ret trans_recv(bcx, dest_copy(bcx_tcx(bcx), llptr, t), init.expr);
}
}
}
none {
ret store(bcx, dest_copy(bcx_tcx(bcx), llptr, t),
trans_common::C_null(llelement_type(trans::val_ty(llptr))));
}
}
}
fn trans_stmt(&@block_ctxt cx, &@ast::stmt stmt) -> @block_ctxt {
auto bcx = cx;
alt (stmt.node) {
ast::stmt_expr(?e, _) {
auto tmp_r = dest_tmp(bcx, ty::expr_ty(bcx_tcx(bcx), e));
bcx = tmp_r._0; auto tmp = tmp_r._1;
ret trans_expr(bcx, tmp, e);
}
ast::stmt_decl(?d, _) {
alt (d.node) {
ast::decl_local(?local) { ret trans_init_local(bcx, local); }
ast::decl_item(?item) {
trans::trans_item(bcx_lcx(bcx), *item);
ret bcx;
}
}
}
}
}
......@@ -19,6 +19,7 @@ mod middle {
mod trans;
mod trans_alt;
mod trans_comm;
mod trans_dps;
mod ty;
mod ast_map;
mod resolve;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册