Teach trans to allocate, initialize and load from local variables.
This commit is contained in:
parent
10d628dbd0
commit
b8cca0971f
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user