Skip to content

Commit

Permalink
Monomorphize resource and variant constructors
Browse files Browse the repository at this point in the history
Issue #1736
  • Loading branch information
marijnh committed Feb 8, 2012
1 parent 7c8d128 commit 0547d0c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 76 deletions.
8 changes: 8 additions & 0 deletions src/comp/middle/ast_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum ast_node {
node_item(@item, @path),
node_native_item(@native_item, @path),
node_method(@method, @path),
node_variant(variant, def_id, @path),
node_expr(@expr),
// Locals are numbered, because the alias analysis needs to know in which
// order they are introduced.
Expand Down Expand Up @@ -74,6 +75,13 @@ fn map_item(i: @item, cx: ctx, v: vt) {
cx.map.insert(ctor_id, node_res_ctor(i));
cx.map.insert(dtor_id, node_item(i, @cx.path));
}
item_enum(vs, _) {
for v in vs {
cx.map.insert(v.node.id, node_variant(
v, ast_util::local_def(i.id),
@(cx.path + [path_name(i.ident)])));
}
}
_ { }
}
alt i.node {
Expand Down
142 changes: 75 additions & 67 deletions src/comp/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2429,7 +2429,7 @@ fn trans_external_path(cx: @block_ctxt, did: ast::def_id,

fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
dicts: option<typeck::dict_res>)
-> {llfn: ValueRef, fty: ty::t} {
-> option<{llfn: ValueRef, fty: ty::t}> {
let substs = vec::map(substs, {|t|
alt ty::get(t).struct {
ty::ty_box(mt) {
Expand All @@ -2447,29 +2447,47 @@ fn monomorphic_fn(ccx: @crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
none { [] }
}};
alt ccx.monomorphized.find(hash_id) {
some(val) { ret val; }
some(val) { ret some(val); }
none {}
}
let tpt = ty::lookup_item_type(ccx.tcx, fn_id);
let mono_ty = ty::substitute_type_params(ccx.tcx, substs, tpt.ty);
let (item, pt) = alt ccx.tcx.items.get(fn_id.node) {
ast_map::node_item(i, p) { (i, p) } _ { fail; }
};
let pt = *pt + [path_name(item.ident)];
let result = alt item.node {
ast::item_fn(decl, _, body) {
let llfty = type_of_fn_from_ty(ccx, mono_ty, []);
let llfty = type_of_fn_from_ty(ccx, mono_ty, []);
let lldecl;
alt ccx.tcx.items.get(fn_id.node) {
ast_map::node_item(item, pt) {
let pt = *pt + [path_name(item.ident)];
let s = mangle_exported_name(ccx, pt, mono_ty);
lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
alt item.node {
ast::item_fn(decl, _, body) {
trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
some(substs), fn_id.node);
}
ast::item_res(decl, _, _, _, ctor_id) {
trans_res_ctor(ccx, pt, decl, ctor_id, [], some(substs), lldecl);
}
_ { fail "Unexpected item type"; }
}
}
ast_map::node_variant(v, enum_id, pt) {
let pt = *pt + [path_name(v.node.name)];
let s = mangle_exported_name(ccx, pt, mono_ty);
let lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
trans_fn(ccx, pt, decl, body, lldecl, no_self, [],
some(substs), fn_id.node);
lldecl
lldecl = decl_cdecl_fn(ccx.llmod, s, llfty);
let tvs = ty::enum_variants(ccx.tcx, enum_id);
let this_tv = option::get(vec::find(*tvs, {|tv|
tv.id.node == fn_id.node}));
trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val,
vec::len(*tvs) == 1u, [], some(substs), lldecl);
}
_ { fail "FIXME[mono] handle other constructs"; }
};
let val = {llfn: result, fty: mono_ty};
ast_map::node_native_item(_, _) {
ret none;
}
_ { fail "Unexpected node type"; }
}
let val = {llfn: lldecl, fty: mono_ty};
ccx.monomorphized.insert(hash_id, val);
val
some(val)
}

fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
Expand All @@ -2484,10 +2502,14 @@ fn lval_static_fn(bcx: @block_ctxt, fn_id: ast::def_id, id: ast::node_id)
alt b { ty::bound_iface(_) { false } _ { true } }
})}) {
let dicts = ccx.dict_map.find(id);
let {llfn, fty} = monomorphic_fn(ccx, fn_id, tys, dicts);
ret {bcx: bcx, val: llfn,
kind: owned, env: null_env,
generic: generic_mono(fty)};
alt monomorphic_fn(ccx, fn_id, tys, dicts) {
some({llfn, fty}) {
ret {bcx: bcx, val: llfn,
kind: owned, env: null_env,
generic: generic_mono(fty)};
}
none {}
}
}
let val = if fn_id.crate == ast::local_crate {
// Internal reference.
Expand Down Expand Up @@ -4362,15 +4384,6 @@ fn copy_args_to_allocas(fcx: @fn_ctxt, bcx: @block_ctxt, args: [ast::arg],
ret bcx;
}

fn arg_tys_of_fn(ccx: @crate_ctxt, id: ast::node_id) -> [ty::arg] {
let tt = ty::node_id_to_type(ccx.tcx, id);
alt ty::get(tt).struct {
ty::ty_fn({inputs, _}) { inputs }
_ { ccx.sess.bug(#fmt("arg_tys_of_fn called on non-function\
type %s", ty_to_str(ccx.tcx, tt)));}
}
}

// Ties up the llstaticallocas -> llloadenv -> llderivedtydescs ->
// lldynamicallocas -> lltop edges, and builds the return block.
fn finish_fn(fcx: @fn_ctxt, lltop: BasicBlockRef) {
Expand Down Expand Up @@ -4407,7 +4420,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
let lltop = bcx.llbb;
let block_ty = node_id_type(bcx, body.node.id);

let arg_tys = arg_tys_of_fn(fcx.ccx, id);
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
alt param_substs {
some(ts) {
arg_tys = vec::map(arg_tys, {|a|
Expand Down Expand Up @@ -4459,23 +4472,23 @@ fn trans_fn(ccx: @crate_ctxt, path: path, decl: ast::fn_decl,
}

fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
ctor_id: ast::node_id, ty_params: [ast::ty_param]) {
ctor_id: ast::node_id, ty_params: [ast::ty_param],
param_substs: option<[ty::t]>, llfndecl: ValueRef) {
// Create a function for the constructor
let llctor_decl = ccx.item_ids.get(ctor_id);
let fcx = new_fn_ctxt_w_id(ccx, path, llctor_decl, ctor_id, none, none);
let ret_t = ty::ret_ty_of_fn(ccx.tcx, ctor_id);
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, ctor_id,
param_substs, none);
create_llargs_for_fn_args(fcx, no_self, dtor.inputs, ty_params);
let bcx = new_top_block_ctxt(fcx, none);
let lltop = bcx.llbb;
let arg_t = arg_tys_of_fn(ccx, ctor_id)[0].ty;
let bcx = new_top_block_ctxt(fcx, none), lltop = bcx.llbb;
let fty = node_id_type(bcx, ctor_id);
let arg_t = ty::ty_fn_args(fty)[0].ty;
let tup_t = ty::mk_tup(ccx.tcx, [ty::mk_int(ccx.tcx), arg_t]);
let arg = alt fcx.llargs.find(dtor.inputs[0].id) {
some(local_mem(x)) { x }
_ { ccx.sess.bug("Someone forgot to document an invariant \
in trans_res_ctor"); }
};
let llretptr = fcx.llretptr;
if ty::type_has_dynamic_size(ccx.tcx, ret_t) {
if ty::type_has_dynamic_size(ccx.tcx, ty::ty_fn_ret(fty)) {
let llret_t = T_ptr(T_struct([ccx.int_type, llvm::LLVMTypeOf(arg)]));
llretptr = BitCast(bcx, llretptr, llret_t);
}
Expand All @@ -4495,11 +4508,8 @@ fn trans_res_ctor(ccx: @crate_ctxt, path: path, dtor: ast::fn_decl,
fn trans_enum_variant(ccx: @crate_ctxt,
enum_id: ast::node_id,
variant: ast::variant, disr: int, is_degen: bool,
ty_params: [ast::ty_param]) {
if vec::len(variant.node.args) == 0u {
ret; // nullary constructors are just constants
}

ty_params: [ast::ty_param],
param_substs: option<[ty::t]>, llfndecl: ValueRef) {
// Translate variant arguments to function arguments.
let fn_args = [], i = 0u;
for varg in variant.node.args {
Expand All @@ -4508,27 +4518,21 @@ fn trans_enum_variant(ccx: @crate_ctxt,
ident: "arg" + uint::to_str(i, 10u),
id: varg.id}];
}
assert (ccx.item_ids.contains_key(variant.node.id));
let llfndecl: ValueRef;
alt ccx.item_ids.find(variant.node.id) {
some(x) { llfndecl = x; }
_ {
ccx.sess.span_fatal(variant.span,
"unbound variant id in trans_enum_variant");
}
}
let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id, none,
none);
let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id,
param_substs, none);
create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
let ty_param_substs = [], i = 0u;
for tp: ast::ty_param in ty_params {
ty_param_substs += [ty::mk_param(ccx.tcx, i,
local_def(tp.id))];
i += 1u;
}
let arg_tys = arg_tys_of_fn(ccx, variant.node.id);
let bcx = new_top_block_ctxt(fcx, none);
let lltop = bcx.llbb;
let ty_param_substs = alt param_substs {
some(ts) { ts }
none {
let i = 0u;
vec::map(ty_params, {|tp|
i += 1u;
ty::mk_param(ccx.tcx, i - 1u, local_def(tp.id))
})
}
};
let bcx = new_top_block_ctxt(fcx, none), lltop = bcx.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id));
bcx = copy_args_to_allocas(fcx, bcx, fn_args, arg_tys);

// Cast the enum to a type we can GEP into.
Expand Down Expand Up @@ -4852,7 +4856,8 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
}
ast::item_res(decl, tps, body, dtor_id, ctor_id) {
trans_res_ctor(ccx, *path, decl, ctor_id, tps);
let llctor_decl = ccx.item_ids.get(ctor_id);
trans_res_ctor(ccx, *path, decl, ctor_id, tps, none, llctor_decl);

// Create a function for the destructor
alt ccx.item_ids.find(item.id) {
Expand All @@ -4873,8 +4878,11 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) {
let vi = ty::enum_variants(ccx.tcx, local_def(item.id));
let i = 0;
for variant: ast::variant in variants {
trans_enum_variant(ccx, item.id, variant,
vi[i].disr_val, degen, tps);
if vec::len(variant.node.args) > 0u {
trans_enum_variant(ccx, item.id, variant,
vi[i].disr_val, degen, tps,
none, ccx.item_ids.get(variant.node.id));
}
i += 1;
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/comp/middle/tstate/ck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import syntax::ast;
import ast::{stmt, fn_ident, node_id, crate, return_val, noreturn, expr};
import syntax::{visit, print};
import syntax::codemap::span;
import middle::ty::{type_is_nil, ret_ty_of_fn};
import tstate::ann::{
precond, prestate,
import middle::ty;
import tstate::ann::{precond, prestate,
implies, ann_precond, ann_prestate};
import option;
import aux::*;
Expand Down Expand Up @@ -113,7 +112,8 @@ fn check_states_against_conditions(fcx: fn_ctxt,
/* Check that the return value is initialized */
let post = aux::block_poststate(fcx.ccx, f_body);
if !promises(fcx, post, fcx.enclosing.i_return) &&
!type_is_nil(ret_ty_of_fn(fcx.ccx.tcx, id)) &&
!ty::type_is_nil(ty::ty_fn_ret(ty::node_id_to_type(
fcx.ccx.tcx, id))) &&
f_decl.cf == return_val {
fcx.ccx.tcx.sess.span_err(f_body.span,
"In function " + fcx.name +
Expand Down
5 changes: 0 additions & 5 deletions src/comp/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export mk_named, type_name;
export mt;
export node_type_table;
export pat_ty;
export ret_ty_of_fn;
export sequence_element_type;
export sort_methods;
export stmt_node_id;
Expand Down Expand Up @@ -2429,10 +2428,6 @@ fn lookup_item_type(cx: ctxt, did: ast::def_id) -> ty_param_bounds_and_ty {
}
}

fn ret_ty_of_fn(cx: ctxt, id: ast::node_id) -> t {
ty_fn_ret(node_id_to_type(cx, id))
}

fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
const tycat_other: int = 0;
const tycat_bool: int = 1;
Expand Down

0 comments on commit 0547d0c

Please sign in to comment.