Skip to content

Commit 9fadab6

Browse files
committed
rustc: Introduce a stub destination-passing-style translation engine, accessible via the --dps switch for now
1 parent 917afa4 commit 9fadab6

File tree

5 files changed

+186
-15
lines changed

5 files changed

+186
-15
lines changed

src/comp/driver/rustc.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,10 @@ options:
251251
--time-llvm-passes time the individual phases of the LLVM backend
252252
--sysroot <path> override the system root (default: rustc's directory)
253253
--no-typestate don't run the typestate pass (unsafe!)
254-
--test build test harness\n\n");
254+
--test build test harness
255+
--dps translate via destination-passing style (experimental)
256+
257+
");
255258
}
256259

257260
fn get_os(str triple) -> session::os {
@@ -352,6 +355,7 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
352355
};
353356
auto cfg = parse_cfgspecs(getopts::opt_strs(match, "cfg"));
354357
auto test = opt_present(match, "test");
358+
auto dps = opt_present(match, "dps");
355359
let @session::options sopts =
356360
@rec(library=library,
357361
static=static,
@@ -367,7 +371,8 @@ fn build_session_options(str binary, getopts::match match, str binary_dir) ->
367371
library_search_paths=library_search_paths,
368372
sysroot=sysroot,
369373
cfg=cfg,
370-
test=test);
374+
test=test,
375+
dps=dps);
371376
ret sopts;
372377
}
373378

@@ -398,7 +403,7 @@ fn opts() -> vec[getopts::opt] {
398403
optopt("sysroot"), optflag("stats"), optflag("time-passes"),
399404
optflag("time-llvm-passes"), optflag("no-typestate"),
400405
optflag("noverify"), optmulti("cfg"), optflag("test"),
401-
optflag("lib"), optflag("static")];
406+
optflag("lib"), optflag("static"), optflag("dps")];
402407
}
403408

404409
fn main(vec[str] args) {

src/comp/driver/session.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ type options =
4040
// The crate config requested for the session, which may be combined
4141
// with additional crate configurations during the compile process
4242
ast::crate_cfg cfg,
43-
bool test);
43+
bool test,
44+
bool dps);
4445

4546
type crate_metadata = rec(str name, u8[] data);
4647

src/comp/middle/trans.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7083,19 +7083,27 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
70837083
auto lltop = bcx.llbb;
70847084
auto block_ty = node_id_type(cx.ccx, f.body.node.id);
70857085

7086-
// This call to trans_block is the place where we bridge between
7087-
// translation calls that don't have a return value (trans_crate,
7088-
// trans_mod, trans_item, trans_obj, et cetera) and those that do
7089-
// (trans_block, trans_expr, et cetera).
7090-
auto rslt =
7091-
if (!ty::type_is_nil(cx.ccx.tcx, block_ty) &&
7092-
!ty::type_is_bot(cx.ccx.tcx, block_ty)) {
7093-
trans_block(bcx, f.body, save_in(fcx.llretptr))
7094-
} else { trans_block(bcx, f.body, return) };
7095-
if (!is_terminated(rslt.bcx)) {
7086+
if (cx.ccx.sess.get_opts().dps) {
7087+
// Call into the new destination-passing-style translation engine.
7088+
auto dest = trans_dps::dest_move(cx.ccx.tcx, fcx.llretptr, block_ty);
7089+
bcx = trans_dps::trans_block(bcx, dest, f.body);
7090+
} else {
7091+
// This call to trans_block is the place where we bridge between
7092+
// translation calls that don't have a return value (trans_crate,
7093+
// trans_mod, trans_item, trans_obj, et cetera) and those that do
7094+
// (trans_block, trans_expr, et cetera).
7095+
auto rslt =
7096+
if (!ty::type_is_nil(cx.ccx.tcx, block_ty) &&
7097+
!ty::type_is_bot(cx.ccx.tcx, block_ty)) {
7098+
trans_block(bcx, f.body, save_in(fcx.llretptr))
7099+
} else { trans_block(bcx, f.body, return) };
7100+
bcx = rslt.bcx;
7101+
}
7102+
7103+
if (!is_terminated(bcx)) {
70967104
// FIXME: until LLVM has a unit type, we are moving around
70977105
// C_nil values rather than their void type.
7098-
rslt.bcx.build.RetVoid();
7106+
bcx.build.RetVoid();
70997107
}
71007108

71017109
// Insert the mandatory first few basic blocks before lltop.

src/comp/middle/trans_dps.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
// Translates individual functions in the completed AST to the LLVM IR, using
2+
// destination-passing style.
3+
4+
import syntax::ast;
5+
import middle::trans;
6+
import middle::ty;
7+
import trans::block_ctxt;
8+
import trans::crate_ctxt;
9+
import trans::fn_ctxt;
10+
import trans::local_ctxt;
11+
import lib::llvm::llvm::TypeRef;
12+
import lib::llvm::llvm::ValueRef;
13+
import std::option::none;
14+
import std::option::some;
15+
16+
import type_of_node = trans::node_id_type;
17+
18+
19+
// LLVM utilities
20+
21+
fn llelement_type(TypeRef llty) -> TypeRef {
22+
lib::llvm::llvm::LLVMGetElementType(llty)
23+
}
24+
25+
26+
// Destination utilities
27+
28+
tag dest_slot {
29+
dst_nil;
30+
dst_val(ValueRef);
31+
}
32+
33+
type dest = rec(dest_slot slot, bool move);
34+
35+
fn dest_slot_for_ptr(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest_slot {
36+
if ty::type_is_nil(tcx, t) { dst_nil } else { dst_val(llptr) }
37+
}
38+
39+
fn dest_copy(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest {
40+
ret rec(slot=dest_slot_for_ptr(tcx, llptr, t), move=false);
41+
}
42+
43+
fn dest_move(&ty::ctxt tcx, ValueRef llptr, ty::t t) -> dest {
44+
ret rec(slot=dest_slot_for_ptr(tcx, llptr, t), move=true);
45+
}
46+
47+
fn dest_tmp(&@block_ctxt bcx, ty::t t) -> tup(@block_ctxt, dest) {
48+
if ty::type_is_nil(bcx_tcx(bcx), t) {
49+
ret tup(bcx, rec(slot=dst_nil, move=true));
50+
}
51+
auto r = trans::alloc_ty(bcx, t);
52+
ret tup(r.bcx, dest_move(bcx_tcx(bcx), r.val, t));
53+
}
54+
55+
56+
// Accessors
57+
// TODO: When we have overloading, simplify these names!
58+
59+
fn bcx_tcx(&@block_ctxt bcx) -> ty::ctxt { ret bcx.fcx.lcx.ccx.tcx; }
60+
fn bcx_ccx(&@block_ctxt bcx) -> @crate_ctxt { ret bcx.fcx.lcx.ccx; }
61+
fn bcx_lcx(&@block_ctxt bcx) -> @local_ctxt { ret bcx.fcx.lcx; }
62+
fn bcx_fcx(&@block_ctxt bcx) -> @fn_ctxt { ret bcx.fcx; }
63+
64+
65+
// Common operations
66+
67+
fn store(&@block_ctxt bcx, &dest dest, ValueRef llsrc) -> @block_ctxt {
68+
alt (dest.slot) {
69+
dst_nil { /* no-op */ }
70+
dst_val(?lldest) { bcx.build.Store(llsrc, lldest); }
71+
}
72+
ret bcx;
73+
}
74+
75+
76+
// AST substructure translation, with destinations
77+
78+
fn trans_expr(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
79+
ret bcx; // TODO
80+
}
81+
82+
fn trans_recv(&@block_ctxt bcx, &dest dest, &@ast::expr expr) -> @block_ctxt {
83+
ret bcx; // TODO
84+
}
85+
86+
fn trans_block(&@block_ctxt cx, &dest dest, &ast::block block)
87+
-> @block_ctxt {
88+
auto bcx = cx;
89+
for each (@ast::local local in trans::block_locals(block)) {
90+
bcx = trans::alloc_local(bcx, local).bcx;
91+
}
92+
93+
for (@ast::stmt stmt in block.node.stmts) {
94+
bcx = trans_stmt(bcx, stmt);
95+
96+
// If we hit a terminator, control won't go any further so
97+
// we're in dead-code land. Stop here.
98+
if trans::is_terminated(bcx) { ret bcx; }
99+
}
100+
101+
alt (block.node.expr) {
102+
some(?e) { ret trans_expr(bcx, dest, e); }
103+
none { ret bcx; }
104+
}
105+
}
106+
107+
108+
// AST substructure translation, without destinations
109+
110+
fn trans_init_local(&@block_ctxt bcx, &@ast::local local) -> @block_ctxt {
111+
auto llptr = bcx_fcx(bcx).lllocals.get(local.node.id);
112+
113+
auto t = type_of_node(bcx_ccx(bcx), local.node.id);
114+
trans::add_clean(bcx, llptr, t);
115+
116+
alt (local.node.init) {
117+
some(?init) {
118+
alt (init.op) {
119+
ast::init_assign {
120+
ret trans_expr(bcx, dest_copy(bcx_tcx(bcx), llptr, t), init.expr);
121+
}
122+
ast::init_move {
123+
ret trans_expr(bcx, dest_move(bcx_tcx(bcx), llptr, t), init.expr);
124+
}
125+
ast::init_recv {
126+
ret trans_recv(bcx, dest_copy(bcx_tcx(bcx), llptr, t), init.expr);
127+
}
128+
}
129+
}
130+
none {
131+
ret store(bcx, dest_copy(bcx_tcx(bcx), llptr, t),
132+
trans_common::C_null(llelement_type(trans::val_ty(llptr))));
133+
}
134+
}
135+
}
136+
137+
fn trans_stmt(&@block_ctxt cx, &@ast::stmt stmt) -> @block_ctxt {
138+
auto bcx = cx;
139+
alt (stmt.node) {
140+
ast::stmt_expr(?e, _) {
141+
auto tmp_r = dest_tmp(bcx, ty::expr_ty(bcx_tcx(bcx), e));
142+
bcx = tmp_r._0; auto tmp = tmp_r._1;
143+
ret trans_expr(bcx, tmp, e);
144+
}
145+
ast::stmt_decl(?d, _) {
146+
alt (d.node) {
147+
ast::decl_local(?local) { ret trans_init_local(bcx, local); }
148+
ast::decl_item(?item) {
149+
trans::trans_item(bcx_lcx(bcx), *item);
150+
ret bcx;
151+
}
152+
}
153+
}
154+
}
155+
}
156+

src/comp/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod middle {
1919
mod trans;
2020
mod trans_alt;
2121
mod trans_comm;
22+
mod trans_dps;
2223
mod ty;
2324
mod ast_map;
2425
mod resolve;

0 commit comments

Comments
 (0)