From b8cca0971fc2dcd5f4bf4ac2ce82c1c635da0279 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Tue, 19 Oct 2010 14:54:10 -0700 Subject: Teach trans to allocate, initialize and load from local variables. --- src/comp/front/ast.rs | 2 +- src/comp/front/parser.rs | 4 +- src/comp/middle/fold.rs | 14 ++--- src/comp/middle/resolve.rs | 21 +++++--- src/comp/middle/trans.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++- src/comp/util/common.rs | 19 +++++++ 6 files changed, 174 insertions(+), 18 deletions(-) diff --git a/src/comp/front/ast.rs b/src/comp/front/ast.rs index e2dcf159..2135a97d 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 acf64c1b..68603e4a 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 81bbffeb..4dd10871 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 08b2e588..7951ec85 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 dd7ac62e..c0f718fb 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 a5b77c0e..20bff22d 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); } -- cgit v1.2.3