Teach trans to allocate, initialize and load from local variables.

This commit is contained in:
Graydon Hoare 2010-10-19 14:54:10 -07:00
parent 10d628dbd0
commit b8cca0971f
6 changed files with 174 additions and 18 deletions

View file

@ -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);
}

View file

@ -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 {

View file

@ -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));
}

View file

@ -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:

View file

@ -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);

View file

@ -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);
}