about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-10-19 14:54:10 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-10-19 14:54:10 -0700
commitb8cca0971fc2dcd5f4bf4ac2ce82c1c635da0279 (patch)
tree9744ef42235ff93c1534461210c80b0f9ecb35b0 /src/comp
parent10d628dbd06ec71956c7849c24822dde8710c2bd (diff)
downloadrust-b8cca0971fc2dcd5f4bf4ac2ce82c1c635da0279.tar.gz
rust-b8cca0971fc2dcd5f4bf4ac2ce82c1c635da0279.zip
Teach trans to allocate, initialize and load from local variables.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/front/ast.rs2
-rw-r--r--src/comp/front/parser.rs4
-rw-r--r--src/comp/middle/fold.rs14
-rw-r--r--src/comp/middle/resolve.rs21
-rw-r--r--src/comp/middle/trans.rs132
-rw-r--r--src/comp/util/common.rs19
6 files changed, 174 insertions, 18 deletions
diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs
index e2dcf15963f..2135a97dac9 100644
--- a/src/comp/front/ast.rs
+++ b/src/comp/front/ast.rs
@@ -78,7 +78,7 @@ type local = rec(option[@ty] ty,
 
 type decl = spanned[decl_];
 tag decl_ {
-    decl_local(local);
+    decl_local(@local);
     decl_item(@item);
 }
 
diff --git a/src/comp/front/parser.rs b/src/comp/front/parser.rs
index acf64c1b183..68603e4a04e 100644
--- a/src/comp/front/parser.rs
+++ b/src/comp/front/parser.rs
@@ -629,7 +629,7 @@ io fn parse_let(parser p) -> @ast.decl {
                               init = init,
                               id = p.next_def_id());
 
-    ret @spanned(lo, hi, ast.decl_local(local));
+    ret @spanned(lo, hi, ast.decl_local(@local));
 }
 
 io fn parse_auto(parser p) -> @ast.decl {
@@ -648,7 +648,7 @@ io fn parse_auto(parser p) -> @ast.decl {
                               init = init,
                               id = p.next_def_id());
 
-    ret @spanned(lo, hi, ast.decl_local(local));
+    ret @spanned(lo, hi, ast.decl_local(@local));
 }
 
 io fn parse_stmt(parser p) -> @ast.stmt {
diff --git a/src/comp/middle/fold.rs b/src/comp/middle/fold.rs
index 81bbffeb3ee..4dd10871a8c 100644
--- a/src/comp/middle/fold.rs
+++ b/src/comp/middle/fold.rs
@@ -103,7 +103,7 @@ type ast_fold[ENV] =
 
      // Decl folds.
      (fn(&ENV e, &span sp,
-         &ast.local local) -> @decl)              fold_decl_local,
+         @ast.local local) -> @decl)              fold_decl_local,
 
      (fn(&ENV e, &span sp,
          @item item) -> @decl)                    fold_decl_item,
@@ -238,7 +238,7 @@ fn fold_decl[ENV](&ENV env, ast_fold[ENV] fld, @decl d) -> @decl {
                     init_ = some[@ast.expr](fold_expr(env, fld, e));
                 }
             }
-            let ast.local local_ = rec(ty=ty_, init=init_ with local);
+            let @ast.local local_ = @rec(ty=ty_, init=init_ with *local);
             ret fld.fold_decl_local(env_, d.span, local_);
         }
 
@@ -356,7 +356,7 @@ fn fold_expr[ENV](&ENV env, ast_fold[ENV] fld, &@expr e) -> @expr {
 
         case (ast.expr_name(?n, ?r, ?t)) {
             auto n_ = fold_name(env_, fld, n);
-            ret fld.fold_expr_name(env_, e.span, n, r, t);
+            ret fld.fold_expr_name(env_, e.span, n_, r, t);
         }
     }
 
@@ -375,7 +375,7 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
     alt (s.node) {
         case (ast.stmt_decl(?d)) {
             auto dd = fold_decl(env_, fld, d);
-            ret fld.fold_stmt_decl(env_, s.span, d);
+            ret fld.fold_stmt_decl(env_, s.span, dd);
         }
 
         case (ast.stmt_ret(?oe)) {
@@ -390,12 +390,12 @@ fn fold_stmt[ENV](&ENV env, ast_fold[ENV] fld, &@stmt s) -> @stmt {
 
         case (ast.stmt_log(?e)) {
             auto ee = fold_expr(env_, fld, e);
-            ret fld.fold_stmt_log(env_, s.span, e);
+            ret fld.fold_stmt_log(env_, s.span, ee);
         }
 
         case (ast.stmt_expr(?e)) {
             auto ee = fold_expr(env_, fld, e);
-            ret fld.fold_stmt_expr(env_, s.span, e);
+            ret fld.fold_stmt_expr(env_, s.span, ee);
         }
     }
     ret s;
@@ -621,7 +621,7 @@ fn identity_fold_expr_name[ENV](&ENV env, &span sp,
 // Decl identities.
 
 fn identity_fold_decl_local[ENV](&ENV e, &span sp,
-                                 &ast.local local) -> @decl {
+                                 @ast.local local) -> @decl {
     ret @respan(sp, ast.decl_local(local));
 }
 
diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs
index 08b2e588596..7951ec85a03 100644
--- a/src/comp/middle/resolve.rs
+++ b/src/comp/middle/resolve.rs
@@ -18,7 +18,8 @@ tag scope {
     scope_block(ast.block);
 }
 
-type env = list[scope];
+type env = rec(list[scope] scopes,
+               session.session sess);
 
 fn lookup_name(&env e, ast.ident i) -> option[def] {
 
@@ -97,7 +98,7 @@ fn lookup_name(&env e, ast.ident i) -> option[def] {
         ret none[def];
     }
 
-    ret std.list.find[scope,def](e, bind in_scope(i, _));
+    ret std.list.find[scope,def](e.scopes, bind in_scope(i, _));
 }
 
 fn fold_expr_name(&env e, &span sp, &ast.name n,
@@ -110,7 +111,7 @@ fn fold_expr_name(&env e, &span sp, &ast.name n,
             log "resolved name " + n.node.ident;
         }
         case (none[def]) {
-            log "unresolved name " + n.node.ident;
+            e.sess.err("unresolved name: " + n.node.ident);
         }
     }
 
@@ -118,25 +119,31 @@ fn fold_expr_name(&env e, &span sp, &ast.name n,
 }
 
 fn update_env_for_crate(&env e, @ast.crate c) -> env {
-    ret cons[scope](scope_crate(c), @e);
+    ret rec(scopes = cons[scope](scope_crate(c), @e.scopes) with e);
 }
 
 fn update_env_for_item(&env e, @ast.item i) -> env {
-    ret cons[scope](scope_item(i), @e);
+    ret rec(scopes = cons[scope](scope_item(i), @e.scopes) with e);
 }
 
 fn update_env_for_block(&env e, &ast.block b) -> env {
-    ret cons[scope](scope_block(b), @e);
+    ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e);
 }
 
 fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {
+
     let fold.ast_fold[env] fld = fold.new_identity_fold[env]();
+
     fld = @rec( fold_expr_name = bind fold_expr_name(_,_,_,_,_),
                 update_env_for_crate = bind update_env_for_crate(_,_),
                 update_env_for_item = bind update_env_for_item(_,_),
                 update_env_for_block = bind update_env_for_block(_,_)
                 with *fld );
-    ret fold.fold_crate[env](nil[scope], fld, crate);
+
+    auto e = rec(scopes = nil[scope],
+                 sess = sess);
+
+    ret fold.fold_crate[env](e, fld, crate);
 }
 
 // Local Variables:
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index dd7ac62e968..c0f718fbecb 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -12,7 +12,9 @@ import driver.session;
 import back.x86;
 import back.abi;
 
+import util.common;
 import util.common.istr;
+import util.common.new_def_hash;
 import util.common.new_str_hash;
 
 import lib.llvm.llvm;
@@ -49,6 +51,7 @@ state type trans_ctxt = rec(session.session sess,
 state type fn_ctxt = rec(ValueRef llfn,
                          ValueRef lloutptr,
                          ValueRef lltaskptr,
+                         hashmap[ast.def_id, ValueRef] lllocals,
                          @trans_ctxt tcx);
 
 type terminator = fn(@fn_ctxt cx, builder build);
@@ -126,11 +129,23 @@ fn T_i64() -> TypeRef {
     ret llvm.LLVMInt64Type();
 }
 
+fn T_f32() -> TypeRef {
+    ret llvm.LLVMFloatType();
+}
+
+fn T_f64() -> TypeRef {
+    ret llvm.LLVMDoubleType();
+}
+
 fn T_int() -> TypeRef {
     // FIXME: switch on target type.
     ret T_i32();
 }
 
+fn T_char() -> TypeRef {
+    ret T_i32();
+}
+
 fn T_fn(vec[TypeRef] inputs, TypeRef output) -> TypeRef {
     ret llvm.LLVMFunctionType(output,
                               _vec.buf[TypeRef](inputs),
@@ -180,6 +195,10 @@ fn T_str(uint n) -> TypeRef {
     ret T_vec(T_i8(), n);
 }
 
+fn T_box(TypeRef t) -> TypeRef {
+    ret T_struct(vec(T_int(), t));
+}
+
 fn T_crate() -> TypeRef {
     ret T_struct(vec(T_int(),      // ptrdiff_t image_base_off
                      T_int(),      // uintptr_t self_addr
@@ -206,6 +225,49 @@ fn T_taskptr() -> TypeRef {
     ret T_ptr(T_task());
 }
 
+fn type_of(@trans_ctxt cx, @ast.ty t) -> TypeRef {
+    alt (t.node) {
+        case (ast.ty_nil) { ret T_nil(); }
+        case (ast.ty_bool) { ret T_i1(); }
+        case (ast.ty_int) { ret T_int(); }
+        case (ast.ty_uint) { ret T_int(); }
+        case (ast.ty_machine(?tm)) {
+            alt (tm) {
+                case (common.ty_i8) { ret T_i8(); }
+                case (common.ty_u8) { ret T_i8(); }
+                case (common.ty_i16) { ret T_i16(); }
+                case (common.ty_u16) { ret T_i16(); }
+                case (common.ty_i32) { ret T_i32(); }
+                case (common.ty_u32) { ret T_i32(); }
+                case (common.ty_i64) { ret T_i64(); }
+                case (common.ty_u64) { ret T_i64(); }
+                case (common.ty_f32) { ret T_f32(); }
+                case (common.ty_f64) { ret T_f64(); }
+            }
+        }
+        case (ast.ty_char) { ret T_char(); }
+        case (ast.ty_str) { ret T_str(0u); }
+        case (ast.ty_box(?t)) {
+            ret T_ptr(T_box(type_of(cx, t)));
+        }
+        case (ast.ty_vec(?t)) {
+            ret T_ptr(T_vec(type_of(cx, t), 0u));
+        }
+        case (ast.ty_tup(?elts)) {
+            let vec[TypeRef] tys = vec();
+            for (tup(bool, @ast.ty) elt in elts) {
+                tys += type_of(cx, elt._1);
+            }
+            ret T_struct(tys);
+        }
+        case (ast.ty_path(?pth,  ?def)) {
+            // FIXME: implement.
+            cx.sess.unimpl("ty_path in trans.type_of");
+        }
+    }
+    fail;
+}
+
 // LLVM constant constructors.
 
 fn C_null(TypeRef t) -> ValueRef {
@@ -356,7 +418,7 @@ fn trans_lit(@block_ctxt cx, &ast.lit lit) -> result {
             ret res(cx, C_int(u as int));
         }
         case (ast.lit_char(?c)) {
-            ret res(cx, C_integral(c as int, T_i32()));
+            ret res(cx, C_integral(c as int, T_char()));
         }
         case (ast.lit_bool(?b)) {
             ret res(cx, C_bool(b));
@@ -572,6 +634,25 @@ fn trans_expr(@block_ctxt cx, &ast.expr e) -> result {
 
             ret res(next_cx, sub.val);
         }
+
+        case (ast.expr_name(?n, ?dopt, _)) {
+            alt (dopt) {
+                case (some[ast.def](?def)) {
+                    alt (def) {
+                        case (ast.def_local(?did)) {
+                            auto llptr = cx.fcx.lllocals.get(did);
+                            ret res(cx, cx.build.Load(llptr));
+                        }
+                        case (_) {
+                            cx.fcx.tcx.sess.unimpl("def variant in trans");
+                        }
+                    }
+                }
+                case (none[ast.def]) {
+                    cx.fcx.tcx.sess.err("unresolved expr_name in trans");
+                }
+            }
+        }
     }
     cx.fcx.tcx.sess.unimpl("expr variant in trans_expr");
     fail;
@@ -616,6 +697,20 @@ fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
             sub.bcx = trans_expr(cx, *e).bcx;
         }
 
+        case (ast.stmt_decl(?d)) {
+            alt (d.node) {
+                case (ast.decl_local(?local)) {
+                    alt (local.init) {
+                        case (some[@ast.expr](?e)) {
+                            log "storing init of local " + local.ident;
+                            auto llptr = cx.fcx.lllocals.get(local.id);
+                            sub = trans_expr(cx, *e);
+                            sub.val = sub.bcx.build.Store(sub.val, llptr);
+                        }
+                    }
+                }
+            }
+        }
         case (_) {
             cx.fcx.tcx.sess.unimpl("stmt variant");
         }
@@ -685,9 +780,41 @@ fn trans_block_cleanups(@block_ctxt cx) -> @block_ctxt {
     ret bcx;
 }
 
+iter block_locals(&ast.block b) -> @ast.local {
+    // FIXME: putting from inside an iter block doesn't work, so we can't
+    // use the index here.
+    for (@ast.stmt s in b.node.stmts) {
+        alt (s.node) {
+            case (ast.stmt_decl(?d)) {
+                alt (d.node) {
+                    case (ast.decl_local(?local)) {
+                        put local;
+                    }
+                }
+            }
+        }
+    }
+}
+
 fn trans_block(@block_ctxt cx, &ast.block b) -> result {
     auto bcx = cx;
 
+    for each (@ast.local local in block_locals(b)) {
+        log "declaring local " + local.ident;
+        auto ty = T_nil();
+        alt (local.ty) {
+            case (some[@ast.ty](?t)) {
+                ty = type_of(cx.fcx.tcx, t);
+            }
+            case (none[@ast.ty]) {
+                cx.fcx.tcx.sess.err("missing type for local " + local.ident);
+            }
+        }
+        auto val = bcx.build.Alloca(ty);
+        log "built alloca: " + val_str(val);
+        cx.fcx.lllocals.insert(local.id, val);
+    }
+
     for (@ast.stmt s in b.node.stmts) {
         bcx = trans_stmt(bcx, *s).bcx;
     }
@@ -709,9 +836,11 @@ fn new_fn_ctxt(@trans_ctxt cx,
     cx.fns.insert(cx.path, llfn);
     let ValueRef lloutptr = llvm.LLVMGetParam(llfn, 0u);
     let ValueRef lltaskptr = llvm.LLVMGetParam(llfn, 1u);
+    let hashmap[ast.def_id, ValueRef] lllocals = new_def_hash[ValueRef]();
     ret @rec(llfn=llfn,
              lloutptr=lloutptr,
              lltaskptr=lltaskptr,
+             lllocals=lllocals,
              tcx=cx);
 }
 
@@ -758,6 +887,7 @@ fn trans_exit_task_glue(@trans_ctxt cx) {
     auto fcx = @rec(llfn=llfn,
                     lloutptr=lloutptr,
                     lltaskptr=lltaskptr,
+                    lllocals=new_def_hash[ValueRef](),
                     tcx=cx);
 
     auto bcx = new_top_block_ctxt(fcx);
diff --git a/src/comp/util/common.rs b/src/comp/util/common.rs
index a5b77c0e793..20bff22dda5 100644
--- a/src/comp/util/common.rs
+++ b/src/comp/util/common.rs
@@ -1,5 +1,6 @@
 import std._uint;
 import std._int;
+import front.ast;
 
 type pos = rec(uint line, uint col);
 type span = rec(str filename, pos lo, pos hi);
@@ -43,6 +44,24 @@ fn new_str_hash[V]() -> std.map.hashmap[str,V] {
     ret std.map.mk_hashmap[str,V](hasher, eqer);
 }
 
+fn new_def_hash[V]() -> std.map.hashmap[ast.def_id,V] {
+
+    fn hash(&ast.def_id d) -> uint {
+        let uint u = d._0 as uint;
+        u <<= 16u;
+        u |= d._1 as uint;
+        ret u;
+    }
+
+    fn eq(&ast.def_id a, &ast.def_id b) -> bool {
+        ret a._0 == b._0 && a._1 == b._1;
+    }
+
+    let std.map.hashfn[ast.def_id] hasher = hash;
+    let std.map.eqfn[ast.def_id] eqer = eq;
+    ret std.map.mk_hashmap[ast.def_id,V](hasher, eqer);
+}
+
 fn istr(int i) -> str {
     ret _int.to_str(i, 10u);
 }