about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-07-15 11:38:16 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-07-15 11:38:46 -0700
commit9fadab64a2ef4ae0c1328e290642a9c6538a6022 (patch)
treebd523503562768faaad3316f6207fb0ea14d0c69 /src/comp
parent917afa4cc9d323a888bb174f46c17610aeebfb2b (diff)
downloadrust-9fadab64a2ef4ae0c1328e290642a9c6538a6022.tar.gz
rust-9fadab64a2ef4ae0c1328e290642a9c6538a6022.zip
rustc: Introduce a stub destination-passing-style translation engine, accessible via the --dps switch for now
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/driver/rustc.rs11
-rw-r--r--src/comp/driver/session.rs3
-rw-r--r--src/comp/middle/trans.rs30
-rw-r--r--src/comp/middle/trans_dps.rs156
-rw-r--r--src/comp/rustc.rc1
5 files changed, 186 insertions, 15 deletions
diff --git a/src/comp/driver/rustc.rs b/src/comp/driver/rustc.rs
index 83e775c847d..9d195c44ada 100644
--- a/src/comp/driver/rustc.rs
+++ b/src/comp/driver/rustc.rs
@@ -251,7 +251,10 @@ options:
     --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) {
diff --git a/src/comp/driver/session.rs b/src/comp/driver/session.rs
index f07fbc6f859..8c15b8bf0a1 100644
--- a/src/comp/driver/session.rs
+++ b/src/comp/driver/session.rs
@@ -40,7 +40,8 @@ type options =
         // 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);
 
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 4a1fd810174..02a85383e35 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -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.
diff --git a/src/comp/middle/trans_dps.rs b/src/comp/middle/trans_dps.rs
new file mode 100644
index 00000000000..f118c0ef057
--- /dev/null
+++ b/src/comp/middle/trans_dps.rs
@@ -0,0 +1,156 @@
+// 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;
+          }
+        }
+      }
+    }
+}
+
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 2115e872531..a64be9f1686 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -19,6 +19,7 @@ mod middle {
     mod trans;
     mod trans_alt;
     mod trans_comm;
+    mod trans_dps;
     mod ty;
     mod ast_map;
     mod resolve;