Drop collect_items pass, create decls on demand
This solves a problem with inlined functions that have inner functions.
This commit is contained in:
parent
6f8fe78120
commit
fd465f91a8
15 changed files with 295 additions and 331 deletions
|
@ -131,7 +131,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
|
||||||
|
|
||||||
let ast_map =
|
let ast_map =
|
||||||
time(time_passes, "ast indexing",
|
time(time_passes, "ast indexing",
|
||||||
bind middle::ast_map::map_crate(*crate));
|
bind middle::ast_map::map_crate(sess, *crate));
|
||||||
time(time_passes, "external crate/lib resolution",
|
time(time_passes, "external crate/lib resolution",
|
||||||
bind creader::read_crates(sess, *crate));
|
bind creader::read_crates(sess, *crate));
|
||||||
let {def_map, exp_map, impl_map} =
|
let {def_map, exp_map, impl_map} =
|
||||||
|
|
|
@ -89,7 +89,7 @@ fn decode_inlined_item(cdata: cstore::crate_metadata,
|
||||||
to_id_range: to_id_range};
|
to_id_range: to_id_range};
|
||||||
let raw_ii = decode_ast(ast_doc);
|
let raw_ii = decode_ast(ast_doc);
|
||||||
let ii = renumber_ast(xcx, raw_ii);
|
let ii = renumber_ast(xcx, raw_ii);
|
||||||
ast_map::map_decoded_item(dcx.tcx.items, path, ii);
|
ast_map::map_decoded_item(tcx.sess, dcx.tcx.items, path, ii);
|
||||||
#debug["Fn named: %s", ii.ident()];
|
#debug["Fn named: %s", ii.ident()];
|
||||||
decode_side_tables(xcx, ast_doc);
|
decode_side_tables(xcx, ast_doc);
|
||||||
#debug["< Decoded inlined fn: %s::%s",
|
#debug["< Decoded inlined fn: %s::%s",
|
||||||
|
|
|
@ -328,7 +328,7 @@ fn purity_fn_family(p: purity) -> char {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||||
&index: [entry<int>], path: ast_map::path) {
|
&index: [entry<int>], path: ast_map::path) -> bool {
|
||||||
|
|
||||||
fn should_inline(attrs: [attribute]) -> bool {
|
fn should_inline(attrs: [attribute]) -> bool {
|
||||||
alt attr::find_inline_attr(attrs) {
|
alt attr::find_inline_attr(attrs) {
|
||||||
|
@ -342,7 +342,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||||
item_enum(_, _) | item_res(_, _, _, _, _) { true }
|
item_enum(_, _) | item_res(_, _, _, _, _) { true }
|
||||||
_ { false }
|
_ { false }
|
||||||
};
|
};
|
||||||
if !must_write && !ecx.reachable.contains_key(item.id) { ret; }
|
if !must_write && !ecx.reachable.contains_key(item.id) { ret false; }
|
||||||
|
|
||||||
alt item.node {
|
alt item.node {
|
||||||
item_const(_, _) {
|
item_const(_, _) {
|
||||||
|
@ -494,11 +494,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
nitem: @native_item, path: ast_map::path) {
|
nitem: @native_item, path: ast_map::path)
|
||||||
if !ecx.reachable.contains_key(nitem.id) { ret; }
|
-> bool {
|
||||||
|
if !ecx.reachable.contains_key(nitem.id) { ret false; }
|
||||||
ebml_w.start_tag(tag_items_data_item);
|
ebml_w.start_tag(tag_items_data_item);
|
||||||
alt nitem.node {
|
alt nitem.node {
|
||||||
native_item_fn(fn_decl, tps) {
|
native_item_fn(fn_decl, tps) {
|
||||||
|
@ -511,6 +513,7 @@ fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
|
ret true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
|
@ -520,17 +523,17 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: ebml::writer,
|
||||||
index += [{val: crate_node_id, pos: ebml_w.writer.tell()}];
|
index += [{val: crate_node_id, pos: ebml_w.writer.tell()}];
|
||||||
encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, [], "");
|
encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, [], "");
|
||||||
ecx.ccx.tcx.items.items {|key, val|
|
ecx.ccx.tcx.items.items {|key, val|
|
||||||
alt val {
|
let where = ebml_w.writer.tell();
|
||||||
|
let written = alt val {
|
||||||
middle::ast_map::node_item(i, path) {
|
middle::ast_map::node_item(i, path) {
|
||||||
index += [{val: key, pos: ebml_w.writer.tell()}];
|
encode_info_for_item(ecx, ebml_w, i, index, *path)
|
||||||
encode_info_for_item(ecx, ebml_w, i, index, *path);
|
|
||||||
}
|
}
|
||||||
middle::ast_map::node_native_item(i, path) {
|
middle::ast_map::node_native_item(i, _, path) {
|
||||||
index += [{val: key, pos: ebml_w.writer.tell()}];
|
encode_info_for_native_item(ecx, ebml_w, i, *path)
|
||||||
encode_info_for_native_item(ecx, ebml_w, i, *path);
|
|
||||||
}
|
}
|
||||||
_ { }
|
_ { false }
|
||||||
}
|
};
|
||||||
|
if written { index += [{val: key, pos: where}]; }
|
||||||
};
|
};
|
||||||
ebml_w.end_tag();
|
ebml_w.end_tag();
|
||||||
ret index;
|
ret index;
|
||||||
|
|
|
@ -58,7 +58,7 @@ fn traverse_def_id(cx: ctx, did: def_id) {
|
||||||
alt cx.ccx.tcx.items.get(did.node) {
|
alt cx.ccx.tcx.items.get(did.node) {
|
||||||
ast_map::node_item(item, _) { traverse_public_item(cx, item); }
|
ast_map::node_item(item, _) { traverse_public_item(cx, item); }
|
||||||
ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
|
ast_map::node_method(_, impl_id, _) { traverse_def_id(cx, impl_id); }
|
||||||
ast_map::node_native_item(item, _) { cx.rmap.insert(item.id, ()); }
|
ast_map::node_native_item(item, _, _) { cx.rmap.insert(item.id, ()); }
|
||||||
ast_map::node_variant(v, _, _) { cx.rmap.insert(v.node.id, ()); }
|
ast_map::node_variant(v, _, _) { cx.rmap.insert(v.node.id, ()); }
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,8 @@ import syntax::ast::*;
|
||||||
import syntax::ast_util;
|
import syntax::ast_util;
|
||||||
import syntax::ast_util::inlined_item_methods;
|
import syntax::ast_util::inlined_item_methods;
|
||||||
import syntax::{visit, codemap};
|
import syntax::{visit, codemap};
|
||||||
|
import driver::session::session;
|
||||||
|
import front::attr;
|
||||||
|
|
||||||
enum path_elt { path_mod(str), path_name(str) }
|
enum path_elt { path_mod(str), path_name(str) }
|
||||||
type path = [path_elt];
|
type path = [path_elt];
|
||||||
|
@ -24,20 +26,21 @@ fn path_to_str(p: path) -> str {
|
||||||
|
|
||||||
enum ast_node {
|
enum ast_node {
|
||||||
node_item(@item, @path),
|
node_item(@item, @path),
|
||||||
node_native_item(@native_item, @path),
|
node_native_item(@native_item, native_abi, @path),
|
||||||
node_method(@method, def_id /* impl did */, @path /* path to the impl */),
|
node_method(@method, def_id /* impl did */, @path /* path to the impl */),
|
||||||
node_variant(variant, def_id, @path),
|
node_variant(variant, @item, @path),
|
||||||
node_expr(@expr),
|
node_expr(@expr),
|
||||||
node_export(@view_path, @path),
|
node_export(@view_path, @path),
|
||||||
// Locals are numbered, because the alias analysis needs to know in which
|
// Locals are numbered, because the alias analysis needs to know in which
|
||||||
// order they are introduced.
|
// order they are introduced.
|
||||||
node_arg(arg, uint),
|
node_arg(arg, uint),
|
||||||
node_local(uint),
|
node_local(uint),
|
||||||
node_res_ctor(@item),
|
node_ctor(@item),
|
||||||
}
|
}
|
||||||
|
|
||||||
type map = std::map::hashmap<node_id, ast_node>;
|
type map = std::map::hashmap<node_id, ast_node>;
|
||||||
type ctx = {map: map, mutable path: path, mutable local_id: uint};
|
type ctx = {map: map, mutable path: path,
|
||||||
|
mutable local_id: uint, sess: session};
|
||||||
type vt = visit::vt<ctx>;
|
type vt = visit::vt<ctx>;
|
||||||
|
|
||||||
fn extend(cx: ctx, elt: str) -> @path {
|
fn extend(cx: ctx, elt: str) -> @path {
|
||||||
|
@ -47,7 +50,6 @@ fn extend(cx: ctx, elt: str) -> @path {
|
||||||
fn mk_ast_map_visitor() -> vt {
|
fn mk_ast_map_visitor() -> vt {
|
||||||
ret visit::mk_vt(@{
|
ret visit::mk_vt(@{
|
||||||
visit_item: map_item,
|
visit_item: map_item,
|
||||||
visit_native_item: map_native_item,
|
|
||||||
visit_expr: map_expr,
|
visit_expr: map_expr,
|
||||||
visit_fn: map_fn,
|
visit_fn: map_fn,
|
||||||
visit_local: map_local,
|
visit_local: map_local,
|
||||||
|
@ -57,10 +59,11 @@ fn mk_ast_map_visitor() -> vt {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_crate(c: crate) -> map {
|
fn map_crate(sess: session, c: crate) -> map {
|
||||||
let cx = {map: std::map::new_int_hash(),
|
let cx = {map: std::map::new_int_hash(),
|
||||||
mutable path: [],
|
mutable path: [],
|
||||||
mutable local_id: 0u};
|
mutable local_id: 0u,
|
||||||
|
sess: sess};
|
||||||
visit::visit_crate(c, cx, mk_ast_map_visitor());
|
visit::visit_crate(c, cx, mk_ast_map_visitor());
|
||||||
ret cx.map;
|
ret cx.map;
|
||||||
}
|
}
|
||||||
|
@ -68,7 +71,7 @@ fn map_crate(c: crate) -> map {
|
||||||
// Used for items loaded from external crate that are being inlined into this
|
// Used for items loaded from external crate that are being inlined into this
|
||||||
// crate. The `path` should be the path to the item but should not include
|
// crate. The `path` should be the path to the item but should not include
|
||||||
// the item itself.
|
// the item itself.
|
||||||
fn map_decoded_item(map: map, path: path, ii: inlined_item) {
|
fn map_decoded_item(sess: session, map: map, path: path, ii: inlined_item) {
|
||||||
// I believe it is ok for the local IDs of inlined items from other crates
|
// I believe it is ok for the local IDs of inlined items from other crates
|
||||||
// to overlap with the local ids from this crate, so just generate the ids
|
// to overlap with the local ids from this crate, so just generate the ids
|
||||||
// starting from 0. (In particular, I think these ids are only used in
|
// starting from 0. (In particular, I think these ids are only used in
|
||||||
|
@ -77,7 +80,8 @@ fn map_decoded_item(map: map, path: path, ii: inlined_item) {
|
||||||
// variables that are simultaneously in scope).
|
// variables that are simultaneously in scope).
|
||||||
let cx = {map: map,
|
let cx = {map: map,
|
||||||
mutable path: path,
|
mutable path: path,
|
||||||
mutable local_id: 0u};
|
mutable local_id: 0u,
|
||||||
|
sess: sess};
|
||||||
let v = mk_ast_map_visitor();
|
let v = mk_ast_map_visitor();
|
||||||
|
|
||||||
// methods get added to the AST map when their impl is visited. Since we
|
// methods get added to the AST map when their impl is visited. Since we
|
||||||
|
@ -86,7 +90,7 @@ fn map_decoded_item(map: map, path: path, ii: inlined_item) {
|
||||||
alt ii {
|
alt ii {
|
||||||
ii_item(i) { /* fallthrough */ }
|
ii_item(i) { /* fallthrough */ }
|
||||||
ii_method(impl_did, m) {
|
ii_method(impl_did, m) {
|
||||||
map_method(impl_did, @vec::init(path), m, cx);
|
map_method(impl_did, @path, m, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,19 +141,31 @@ fn map_item(i: @item, cx: ctx, v: vt) {
|
||||||
item_impl(_, _, _, ms) {
|
item_impl(_, _, _, ms) {
|
||||||
let impl_did = ast_util::local_def(i.id);
|
let impl_did = ast_util::local_def(i.id);
|
||||||
for m in ms {
|
for m in ms {
|
||||||
map_method(impl_did, item_path, m, cx);
|
map_method(impl_did, extend(cx, i.ident), m, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
item_res(_, _, _, dtor_id, ctor_id) {
|
item_res(_, _, _, dtor_id, ctor_id) {
|
||||||
cx.map.insert(ctor_id, node_res_ctor(i));
|
cx.map.insert(ctor_id, node_ctor(i));
|
||||||
cx.map.insert(dtor_id, node_item(i, item_path));
|
cx.map.insert(dtor_id, node_item(i, item_path));
|
||||||
}
|
}
|
||||||
item_enum(vs, _) {
|
item_enum(vs, _) {
|
||||||
for v in vs {
|
for v in vs {
|
||||||
cx.map.insert(v.node.id, node_variant(
|
cx.map.insert(v.node.id, node_variant(
|
||||||
v, ast_util::local_def(i.id), extend(cx, i.ident)));
|
v, i, extend(cx, i.ident)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
item_native_mod(nm) {
|
||||||
|
let abi = alt attr::native_abi(i.attrs) {
|
||||||
|
either::left(msg) { cx.sess.span_fatal(i.span, msg); }
|
||||||
|
either::right(abi) { abi }
|
||||||
|
};
|
||||||
|
for nitem in nm.items {
|
||||||
|
cx.map.insert(nitem.id, node_native_item(nitem, abi, @cx.path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item_class(_, _, ctor) {
|
||||||
|
cx.map.insert(ctor.node.id, node_ctor(i));
|
||||||
|
}
|
||||||
_ { }
|
_ { }
|
||||||
}
|
}
|
||||||
alt i.node {
|
alt i.node {
|
||||||
|
@ -179,11 +195,6 @@ fn map_view_item(vi: @view_item, cx: ctx, _v: vt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_native_item(i: @native_item, cx: ctx, v: vt) {
|
|
||||||
cx.map.insert(i.id, node_native_item(i, @cx.path));
|
|
||||||
visit::visit_native_item(i, cx, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn map_expr(ex: @expr, cx: ctx, v: vt) {
|
fn map_expr(ex: @expr, cx: ctx, v: vt) {
|
||||||
cx.map.insert(ex.id, node_expr(ex));
|
cx.map.insert(ex.id, node_expr(ex));
|
||||||
visit::visit_expr(ex, cx, v);
|
visit::visit_expr(ex, cx, v);
|
||||||
|
|
|
@ -2111,7 +2111,7 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||||
ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
|
ast_map::node_variant(v, _, pt) { (pt, v.node.name) }
|
||||||
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
ast_map::node_method(m, _, pt) { (pt, m.ident) }
|
||||||
// We can't monomorphize native functions
|
// We can't monomorphize native functions
|
||||||
ast_map::node_native_item(_, _) { ret none; }
|
ast_map::node_native_item(_, _, _) { ret none; }
|
||||||
_ { fail "unexpected node type"; }
|
_ { fail "unexpected node type"; }
|
||||||
};
|
};
|
||||||
let pt = *pt + [path_name(ccx.names(name))];
|
let pt = *pt + [path_name(ccx.names(name))];
|
||||||
|
@ -2128,11 +2128,11 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
|
||||||
ast_map::node_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
|
ast_map::node_item(@{node: ast::item_res(decl, _, _, _, _), _}, _) {
|
||||||
trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
|
trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl);
|
||||||
}
|
}
|
||||||
ast_map::node_variant(v, enum_id, _) {
|
ast_map::node_variant(v, enum_item, _) {
|
||||||
let tvs = ty::enum_variants(ccx.tcx, enum_id);
|
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
|
||||||
let this_tv = option::get(vec::find(*tvs, {|tv|
|
let this_tv = option::get(vec::find(*tvs, {|tv|
|
||||||
tv.id.node == fn_id.node}));
|
tv.id.node == fn_id.node}));
|
||||||
trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val,
|
trans_enum_variant(ccx, enum_item.id, v, this_tv.disr_val,
|
||||||
(*tvs).len() == 1u, [], psubsts, lldecl);
|
(*tvs).len() == 1u, [], psubsts, lldecl);
|
||||||
}
|
}
|
||||||
ast_map::node_method(mth, impl_def_id, _) {
|
ast_map::node_method(mth, impl_def_id, _) {
|
||||||
|
@ -2164,7 +2164,6 @@ fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id)
|
||||||
ty::item_path_str(ccx.tcx, fn_id),
|
ty::item_path_str(ccx.tcx, fn_id),
|
||||||
item.id];
|
item.id];
|
||||||
ccx.external.insert(fn_id, some(item.id));
|
ccx.external.insert(fn_id, some(item.id));
|
||||||
collect_item(ccx, @mutable none, item);
|
|
||||||
trans_item(ccx, *item);
|
trans_item(ccx, *item);
|
||||||
local_def(item.id)
|
local_def(item.id)
|
||||||
}
|
}
|
||||||
|
@ -2176,11 +2175,7 @@ fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id)
|
||||||
mth.id];
|
mth.id];
|
||||||
ccx.external.insert(fn_id, some(mth.id));
|
ccx.external.insert(fn_id, some(mth.id));
|
||||||
compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path|
|
compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path|
|
||||||
let mth_ty = ty::node_id_to_type(ccx.tcx, mth.id);
|
let llfn = get_item_val(ccx, mth.id);
|
||||||
let llfn = register_fn_full(ccx, mth.span, path,
|
|
||||||
"impl_method", bounds,
|
|
||||||
mth.id, mth_ty);
|
|
||||||
set_inline_hint_if_appr(mth.attrs, llfn);
|
|
||||||
trans_fn(ccx, path, mth.decl, mth.body,
|
trans_fn(ccx, path, mth.decl, mth.body,
|
||||||
llfn, impl_self(ty), bounds,
|
llfn, impl_self(ty), bounds,
|
||||||
none, mth.id, none);
|
none, mth.id, none);
|
||||||
|
@ -2243,8 +2238,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
|
||||||
|
|
||||||
let val = if fn_id.crate == ast::local_crate {
|
let val = if fn_id.crate == ast::local_crate {
|
||||||
// Internal reference.
|
// Internal reference.
|
||||||
assert (ccx.item_ids.contains_key(fn_id.node));
|
get_item_val(ccx, fn_id.node)
|
||||||
ccx.item_ids.get(fn_id.node)
|
|
||||||
} else {
|
} else {
|
||||||
// External reference.
|
// External reference.
|
||||||
trans_external_path(bcx, fn_id, tpt)
|
trans_external_path(bcx, fn_id, tpt)
|
||||||
|
@ -2375,8 +2369,7 @@ fn trans_var(cx: block, def: ast::def, id: ast::node_id, path: @ast::path)
|
||||||
}
|
}
|
||||||
ast::def_const(did) {
|
ast::def_const(did) {
|
||||||
if did.crate == ast::local_crate {
|
if did.crate == ast::local_crate {
|
||||||
assert (ccx.consts.contains_key(did.node));
|
ret lval_no_env(cx, get_item_val(ccx, did.node), owned);
|
||||||
ret lval_no_env(cx, ccx.consts.get(did.node), owned);
|
|
||||||
} else {
|
} else {
|
||||||
let tp = node_id_type(cx, id);
|
let tp = node_id_type(cx, id);
|
||||||
let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
|
let val = trans_external_path(cx, did, {bounds: @[], ty: tp});
|
||||||
|
@ -4323,19 +4316,14 @@ fn trans_const_expr(cx: crate_ctxt, e: @ast::expr) -> ValueRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_const(cx: crate_ctxt, e: @ast::expr, id: ast::node_id) {
|
fn trans_const(ccx: crate_ctxt, e: @ast::expr, id: ast::node_id) {
|
||||||
let v = trans_const_expr(cx, e);
|
let v = trans_const_expr(ccx, e);
|
||||||
|
|
||||||
// The scalars come back as 1st class LLVM vals
|
// The scalars come back as 1st class LLVM vals
|
||||||
// which we have to stick into global constants.
|
// which we have to stick into global constants.
|
||||||
|
let g = get_item_val(ccx, id);
|
||||||
alt cx.consts.find(id) {
|
llvm::LLVMSetInitializer(g, v);
|
||||||
some(g) {
|
llvm::LLVMSetGlobalConstant(g, True);
|
||||||
llvm::LLVMSetInitializer(g, v);
|
|
||||||
llvm::LLVMSetGlobalConstant(g, True);
|
|
||||||
}
|
|
||||||
_ { cx.sess.span_bug(e.span, "unbound const in trans_const"); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
||||||
|
@ -4344,15 +4332,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
||||||
};
|
};
|
||||||
alt item.node {
|
alt item.node {
|
||||||
ast::item_fn(decl, tps, body) {
|
ast::item_fn(decl, tps, body) {
|
||||||
let llfndecl = alt ccx.item_ids.find(item.id) {
|
let llfndecl = get_item_val(ccx, item.id);
|
||||||
some(llfndecl) { llfndecl }
|
|
||||||
_ {
|
|
||||||
ccx.sess.span_bug(
|
|
||||||
item.span,
|
|
||||||
#fmt["unbound function item %s in trans_item",
|
|
||||||
ast_map::path_to_str(*path)]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if decl.purity != ast::crust_fn {
|
if decl.purity != ast::crust_fn {
|
||||||
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
|
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
|
||||||
llfndecl, no_self, param_bounds(ccx, tps),
|
llfndecl, no_self, param_bounds(ccx, tps),
|
||||||
|
@ -4366,21 +4346,15 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
||||||
impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
|
impl::trans_impl(ccx, *path, item.ident, ms, item.id, tps);
|
||||||
}
|
}
|
||||||
ast::item_res(decl, tps, body, dtor_id, ctor_id) {
|
ast::item_res(decl, tps, body, dtor_id, ctor_id) {
|
||||||
let llctor_decl = ccx.item_ids.get(ctor_id);
|
let llctor_decl = get_item_val(ccx, ctor_id);
|
||||||
trans_res_ctor(ccx, *path, decl, ctor_id,
|
trans_res_ctor(ccx, *path, decl, ctor_id,
|
||||||
param_bounds(ccx, tps), none, llctor_decl);
|
param_bounds(ccx, tps), none, llctor_decl);
|
||||||
|
|
||||||
// Create a function for the destructor
|
// Create a function for the destructor
|
||||||
alt ccx.item_ids.find(item.id) {
|
let lldtor_decl = get_item_val(ccx, item.id);
|
||||||
some(lldtor_decl) {
|
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
|
||||||
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
|
lldtor_decl, no_self, param_bounds(ccx, tps),
|
||||||
lldtor_decl, no_self, param_bounds(ccx, tps),
|
none, dtor_id, none);
|
||||||
none, dtor_id, none);
|
|
||||||
}
|
|
||||||
_ {
|
|
||||||
ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast::item_mod(m) {
|
ast::item_mod(m) {
|
||||||
trans_mod(ccx, m);
|
trans_mod(ccx, m);
|
||||||
|
@ -4393,7 +4367,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
||||||
if variant.node.args.len() > 0u {
|
if variant.node.args.len() > 0u {
|
||||||
trans_enum_variant(ccx, item.id, variant,
|
trans_enum_variant(ccx, item.id, variant,
|
||||||
vi[i].disr_val, degen, tps,
|
vi[i].disr_val, degen, tps,
|
||||||
none, ccx.item_ids.get(variant.node.id));
|
none, get_item_val(ccx, variant.node.id));
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
@ -4407,81 +4381,74 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
|
||||||
native::trans_native_mod(ccx, native_mod, abi);
|
native::trans_native_mod(ccx, native_mod, abi);
|
||||||
}
|
}
|
||||||
ast::item_class(tps, items, ctor) {
|
ast::item_class(tps, items, ctor) {
|
||||||
alt ccx.item_ids.find(ctor.node.id) {
|
let llctor_decl = get_item_val(ccx, ctor.node.id);
|
||||||
some(llctor_decl) {
|
// Translate the ctor
|
||||||
// Translate the ctor
|
// First, add a preamble that
|
||||||
// First, add a preamble that
|
// generates a new name, obj:
|
||||||
// generates a new name, obj:
|
// let obj = { ... } (uninit record fields)
|
||||||
// let obj = { ... } (uninit record fields)
|
let rslt_path_ = {global: false,
|
||||||
let sess = ccx.sess;
|
idents: ["obj"],
|
||||||
let rslt_path_ = {global: false,
|
types: []}; // ??
|
||||||
idents: ["obj"],
|
let rslt_path = @{node: rslt_path_,
|
||||||
types: []}; // ??
|
span: ctor.node.body.span};
|
||||||
let rslt_path = @{node: rslt_path_,
|
let rslt_id : ast::node_id = ccx.sess.next_node_id();
|
||||||
span: ctor.node.body.span};
|
let rslt_pat : @ast::pat =
|
||||||
let rslt_id : ast::node_id = sess.next_node_id();
|
@{id: ccx.sess.next_node_id(),
|
||||||
let rslt_pat : @ast::pat =
|
node: ast::pat_ident(rslt_path, none),
|
||||||
@{id: sess.next_node_id(),
|
span: ctor.node.body.span};
|
||||||
node: ast::pat_ident(rslt_path, none),
|
// Set up obj's type
|
||||||
span: ctor.node.body.span};
|
let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer,
|
||||||
// Set up obj's type
|
span: ctor.node.body.span};
|
||||||
let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer,
|
// kludgy
|
||||||
span: ctor.node.body.span};
|
let ty_args = [], i = 0u;
|
||||||
// kludgy
|
for tp in tps {
|
||||||
let ty_args = [], i = 0u;
|
ty_args += [ty::mk_param(ccx.tcx, i,
|
||||||
for tp in tps {
|
local_def(tps[i].id))];
|
||||||
ty_args += [ty::mk_param(ccx.tcx, i,
|
}
|
||||||
local_def(tps[i].id))];
|
let rslt_ty = ty::mk_class(ccx.tcx,
|
||||||
}
|
local_def(item.id),
|
||||||
let rslt_ty = ty::mk_class(ccx.tcx,
|
ty_args);
|
||||||
local_def(item.id),
|
// Set up a local for obj
|
||||||
ty_args);
|
let rslt_loc_ : ast::local_ = {is_mutbl: true,
|
||||||
// Set up a local for obj
|
ty: rslt_ast_ty, // ???
|
||||||
let rslt_loc_ : ast::local_ = {is_mutbl: true,
|
pat: rslt_pat,
|
||||||
ty: rslt_ast_ty, // ???
|
init: none::<ast::initializer>,
|
||||||
pat: rslt_pat,
|
id: rslt_id};
|
||||||
init: none::<ast::initializer>,
|
// Register a type for obj
|
||||||
id: rslt_id};
|
smallintmap::insert(*ccx.tcx.node_types,
|
||||||
// Register a type for obj
|
rslt_loc_.id as uint, rslt_ty);
|
||||||
smallintmap::insert(*ccx.tcx.node_types,
|
// Create the decl statement that initializers obj
|
||||||
rslt_loc_.id as uint, rslt_ty);
|
let rslt_loc : @ast::local =
|
||||||
// Create the decl statement that initializers obj
|
@{node: rslt_loc_, span: ctor.node.body.span};
|
||||||
let rslt_loc : @ast::local =
|
let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]);
|
||||||
@{node: rslt_loc_, span: ctor.node.body.span};
|
let rslt_decl : @ast::decl
|
||||||
let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]);
|
= @{node: rslt_decl_, span: ctor.node.body.span};
|
||||||
let rslt_decl : @ast::decl
|
let prologue = @{node: ast::stmt_decl(rslt_decl,
|
||||||
= @{node: rslt_decl_, span: ctor.node.body.span};
|
ccx.sess.next_node_id()),
|
||||||
let prologue : @ast::stmt = @{node: ast::stmt_decl(rslt_decl,
|
span: ctor.node.body.span};
|
||||||
sess.next_node_id()),
|
let rslt_node_id = ccx.sess.next_node_id();
|
||||||
span: ctor.node.body.span};
|
ccx.tcx.def_map.insert(rslt_node_id,
|
||||||
let rslt_node_id = sess.next_node_id();
|
ast::def_local(rslt_loc_.id, true));
|
||||||
ccx.tcx.def_map.insert(rslt_node_id,
|
// And give the statement a type
|
||||||
ast::def_local(rslt_loc_.id, true));
|
smallintmap::insert(*ccx.tcx.node_types,
|
||||||
// And give the statement a type
|
rslt_node_id as uint, rslt_ty);
|
||||||
smallintmap::insert(*ccx.tcx.node_types,
|
// The result expression of the constructor is now a
|
||||||
rslt_node_id as uint, rslt_ty);
|
// reference to obj
|
||||||
// The result expression of the constructor is now a
|
let rslt_expr : @ast::expr =
|
||||||
// reference to obj
|
@{id: rslt_node_id,
|
||||||
let rslt_expr : @ast::expr =
|
node: ast::expr_path(rslt_path),
|
||||||
@{id: rslt_node_id,
|
span: ctor.node.body.span};
|
||||||
node: ast::expr_path(rslt_path),
|
let ctor_body_new : ast::blk_ = {stmts: [prologue]
|
||||||
span: ctor.node.body.span};
|
+ ctor.node.body.node.stmts,
|
||||||
let ctor_body_new : ast::blk_ = {stmts: [prologue]
|
expr: some(rslt_expr)
|
||||||
+ ctor.node.body.node.stmts,
|
with ctor.node.body.node};
|
||||||
expr: some(rslt_expr)
|
let ctor_body__ : ast::blk = {node: ctor_body_new
|
||||||
with ctor.node.body.node};
|
with ctor.node.body};
|
||||||
let ctor_body__ : ast::blk = {node: ctor_body_new
|
trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
|
||||||
with ctor.node.body};
|
ctor_body__, llctor_decl, no_self,
|
||||||
trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec,
|
param_bounds(ccx, tps), none, ctor.node.id,
|
||||||
ctor_body__, llctor_decl, no_self,
|
some(rslt_expr));
|
||||||
param_bounds(ccx, tps), none, ctor.node.id,
|
// TODO: translate methods!
|
||||||
some(rslt_expr));
|
|
||||||
// TODO: translate methods!
|
|
||||||
}
|
|
||||||
_ {
|
|
||||||
ccx.sess.span_bug(item.span, "unbound ctor in trans_item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
_ {/* fall through */ }
|
_ {/* fall through */ }
|
||||||
}
|
}
|
||||||
|
@ -4538,7 +4505,6 @@ fn register_fn_fuller(ccx: crate_ctxt, sp: span, path: path, _flav: str,
|
||||||
cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
|
cc: lib::llvm::CallConv, llfty: TypeRef) -> ValueRef {
|
||||||
let ps: str = mangle_exported_name(ccx, path, node_type);
|
let ps: str = mangle_exported_name(ccx, path, node_type);
|
||||||
let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
|
let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty);
|
||||||
ccx.item_ids.insert(node_id, llfn);
|
|
||||||
ccx.item_symbols.insert(node_id, ps);
|
ccx.item_symbols.insert(node_id, ps);
|
||||||
|
|
||||||
#debug["register_fn_fuller created fn %s for item %d with path %s",
|
#debug["register_fn_fuller created fn %s for item %d with path %s",
|
||||||
|
@ -4649,145 +4615,96 @@ fn fill_fn_pair(bcx: block, pair: ValueRef, llfn: ValueRef,
|
||||||
Store(bcx, llenvblobptr, env_cell);
|
Store(bcx, llenvblobptr, env_cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_native_item(ccx: crate_ctxt,
|
|
||||||
abi: @mutable option<ast::native_abi>,
|
|
||||||
i: @ast::native_item) {
|
|
||||||
alt i.node {
|
|
||||||
ast::native_item_fn(_, tps) {
|
|
||||||
let id = i.id;
|
|
||||||
let node_type = ty::node_id_to_type(ccx.tcx, id);
|
|
||||||
let fn_abi =
|
|
||||||
alt attr::get_meta_item_value_str_by_name(i.attrs, "abi") {
|
|
||||||
option::none {
|
|
||||||
// if abi isn't specified for this function, inherit from
|
|
||||||
// its enclosing native module
|
|
||||||
option::get(*abi)
|
|
||||||
}
|
|
||||||
_ {
|
|
||||||
alt attr::native_abi(i.attrs) {
|
|
||||||
either::right(abi_) { abi_ }
|
|
||||||
either::left(msg) { ccx.sess.span_fatal(i.span, msg) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
alt fn_abi {
|
|
||||||
ast::native_abi_rust_intrinsic {
|
|
||||||
// For intrinsics: link the function directly to the intrinsic
|
|
||||||
// function itself.
|
|
||||||
let fn_type = type_of_fn_from_ty(
|
|
||||||
ccx, node_type, param_bounds(ccx, tps));
|
|
||||||
let ri_name = "rust_intrinsic_" + native::link_name(i);
|
|
||||||
let llnativefn = get_extern_fn(
|
|
||||||
ccx.externs, ccx.llmod, ri_name,
|
|
||||||
lib::llvm::CCallConv, fn_type);
|
|
||||||
ccx.item_ids.insert(id, llnativefn);
|
|
||||||
ccx.item_symbols.insert(id, ri_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::native_abi_cdecl | ast::native_abi_stdcall {
|
|
||||||
// For true external functions: create a rust wrapper
|
|
||||||
// and link to that. The rust wrapper will handle
|
|
||||||
// switching to the C stack.
|
|
||||||
let path = *alt check ccx.tcx.items.get(i.id) {
|
|
||||||
ast_map::node_native_item(_, p) { p }
|
|
||||||
} + [path_name(i.ident)];
|
|
||||||
register_fn(ccx, i.span, path, "native fn", tps, i.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn item_path(ccx: crate_ctxt, i: @ast::item) -> path {
|
fn item_path(ccx: crate_ctxt, i: @ast::item) -> path {
|
||||||
*alt check ccx.tcx.items.get(i.id) {
|
*alt check ccx.tcx.items.get(i.id) {
|
||||||
ast_map::node_item(_, p) { p }
|
ast_map::node_item(_, p) { p }
|
||||||
} + [path_name(i.ident)]
|
} + [path_name(i.ident)]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
|
fn get_item_val(ccx: crate_ctxt, id: ast::node_id) -> ValueRef {
|
||||||
i: @ast::item) {
|
alt ccx.item_vals.find(id) {
|
||||||
let my_path = item_path(ccx, i);
|
some(v) { v }
|
||||||
alt i.node {
|
none {
|
||||||
ast::item_const(_, _) {
|
let val = alt check ccx.tcx.items.get(id) {
|
||||||
let typ = ty::node_id_to_type(ccx.tcx, i.id);
|
ast_map::node_item(i, pth) {
|
||||||
let s = mangle_exported_name(ccx, my_path, typ);
|
let my_path = *pth + [path_name(i.ident)];
|
||||||
let g = str::as_buf(s, {|buf|
|
alt check i.node {
|
||||||
llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
|
ast::item_const(_, _) {
|
||||||
});
|
let typ = ty::node_id_to_type(ccx.tcx, i.id);
|
||||||
ccx.item_symbols.insert(i.id, s);
|
let s = mangle_exported_name(ccx, my_path, typ);
|
||||||
ccx.consts.insert(i.id, g);
|
let g = str::as_buf(s, {|buf|
|
||||||
}
|
llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf)
|
||||||
ast::item_native_mod(native_mod) {
|
});
|
||||||
// Propagate the native ABI down to collect_native_item(),
|
ccx.item_symbols.insert(i.id, s);
|
||||||
alt attr::native_abi(i.attrs) {
|
g
|
||||||
either::left(msg) { ccx.sess.span_fatal(i.span, msg); }
|
}
|
||||||
either::right(abi_) { *abi = option::some(abi_); }
|
ast::item_fn(decl, tps, _) {
|
||||||
}
|
let llfn = if decl.purity != ast::crust_fn {
|
||||||
}
|
register_fn(ccx, i.span, my_path, "fn", tps, i.id)
|
||||||
ast::item_fn(decl, tps, _) {
|
} else {
|
||||||
let llfn = if decl.purity != ast::crust_fn {
|
native::register_crust_fn(ccx, i.span, my_path, i.id)
|
||||||
register_fn(ccx, i.span, my_path, "fn", tps, i.id)
|
};
|
||||||
} else {
|
set_inline_hint_if_appr(i.attrs, llfn);
|
||||||
native::register_crust_fn(ccx, i.span, my_path, i.id)
|
llfn
|
||||||
};
|
}
|
||||||
|
ast::item_res(_, tps, _, dtor_id, _) {
|
||||||
set_inline_hint_if_appr(i.attrs, llfn);
|
// Note that the destructor is associated with the item's id,
|
||||||
}
|
// not the dtor_id. This is a bit counter-intuitive, but
|
||||||
ast::item_impl(tps, _, _, methods) {
|
// simplifies ty_res, which would have to carry around two
|
||||||
let path = my_path + [path_name(int::str(i.id))];
|
// def_ids otherwise -- one to identify the type, and one to
|
||||||
for m in methods {
|
// find the dtor symbol.
|
||||||
let llm = register_fn(ccx, i.span,
|
let t = ty::node_id_to_type(ccx.tcx, dtor_id);
|
||||||
path + [path_name(m.ident)],
|
register_fn_full(ccx, i.span, my_path + [path_name("dtor")],
|
||||||
"impl_method", tps + m.tps, m.id);
|
"res_dtor", param_bounds(ccx, tps), i.id, t)
|
||||||
set_inline_hint_if_appr(m.attrs, llm);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
ast::item_res(_, tps, _, dtor_id, ctor_id) {
|
|
||||||
let llctor = register_fn(ccx, i.span, my_path, "res_ctor", tps,
|
|
||||||
ctor_id);
|
|
||||||
|
|
||||||
// Note that the destructor is associated with the item's id, not
|
|
||||||
// the dtor_id. This is a bit counter-intuitive, but simplifies
|
|
||||||
// ty_res, which would have to carry around two def_ids otherwise
|
|
||||||
// -- one to identify the type, and one to find the dtor symbol.
|
|
||||||
let t = ty::node_id_to_type(ccx.tcx, dtor_id);
|
|
||||||
let lldtor = register_fn_full(ccx, i.span, my_path +
|
|
||||||
[path_name("dtor")], "res_dtor",
|
|
||||||
param_bounds(ccx, tps), i.id, t);
|
|
||||||
|
|
||||||
// give hints that resource ctors/dtors ought to be inlined
|
|
||||||
set_inline_hint(llctor);
|
|
||||||
set_inline_hint(lldtor);
|
|
||||||
}
|
|
||||||
ast::item_enum(variants, tps) {
|
|
||||||
for variant in variants {
|
|
||||||
if variant.node.args.len() != 0u {
|
|
||||||
register_fn(ccx, i.span,
|
|
||||||
my_path + [path_name(variant.node.name)],
|
|
||||||
"enum", tps, variant.node.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast_map::node_method(m, impl_id, pth) {
|
||||||
|
let mty = ty::node_id_to_type(ccx.tcx, id);
|
||||||
|
let impl_tps = *ty::lookup_item_type(ccx.tcx, impl_id).bounds;
|
||||||
|
let pth = *pth + [path_name(int::str(impl_id.node)),
|
||||||
|
path_name(m.ident)];
|
||||||
|
let llfn = register_fn_full(ccx, m.span, pth, "impl_method",
|
||||||
|
impl_tps + param_bounds(ccx, m.tps),
|
||||||
|
id, mty);
|
||||||
|
set_inline_hint_if_appr(m.attrs, llfn);
|
||||||
|
llfn
|
||||||
|
}
|
||||||
|
ast_map::node_native_item(ni, _, pth) {
|
||||||
|
native::decl_native_fn(ccx, ni, *pth + [path_name(ni.ident)])
|
||||||
|
}
|
||||||
|
ast_map::node_ctor(i) {
|
||||||
|
alt check i.node {
|
||||||
|
ast::item_res(_, tps, _, _, _) {
|
||||||
|
let my_path = item_path(ccx, i);
|
||||||
|
let llctor = register_fn(ccx, i.span, my_path, "res_ctor",
|
||||||
|
tps, id);
|
||||||
|
set_inline_hint(llctor);
|
||||||
|
llctor
|
||||||
|
}
|
||||||
|
ast::item_class(tps, _, ctor) {
|
||||||
|
register_fn(ccx, i.span, item_path(ccx, i), "ctor", tps, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ast_map::node_variant(v, enm, pth) {
|
||||||
|
assert v.node.args.len() != 0u;
|
||||||
|
let pth = *pth + [path_name(enm.ident), path_name(v.node.name)];
|
||||||
|
let llfn = alt check enm.node {
|
||||||
|
ast::item_enum(_, tps) {
|
||||||
|
register_fn(ccx, v.span, pth, "enum", tps, id)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
set_inline_hint(llfn);
|
||||||
|
llfn
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ccx.item_vals.insert(id, val);
|
||||||
|
val
|
||||||
}
|
}
|
||||||
ast::item_class(tps,_,ctor) {
|
|
||||||
// Register the ctor
|
|
||||||
let t = ty::node_id_to_type(ccx.tcx, ctor.node.id);
|
|
||||||
register_fn_full(ccx, i.span, my_path, "ctor",
|
|
||||||
param_bounds(ccx, tps), ctor.node.id, t);
|
|
||||||
}
|
|
||||||
_ { }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
|
|
||||||
let abi = @mutable none;
|
|
||||||
visit::visit_crate(*crate, (), visit::mk_simple_visitor(@{
|
|
||||||
visit_native_item: bind collect_native_item(ccx, abi, _),
|
|
||||||
visit_item: bind collect_item(ccx, abi, _)
|
|
||||||
with *visit::default_simple_visitor()
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The constant translation pass.
|
// The constant translation pass.
|
||||||
fn trans_constant(ccx: crate_ctxt, it: @ast::item) {
|
fn trans_constant(ccx: crate_ctxt, it: @ast::item) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
|
@ -5043,7 +4960,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
||||||
tn: tn,
|
tn: tn,
|
||||||
externs: new_str_hash::<ValueRef>(),
|
externs: new_str_hash::<ValueRef>(),
|
||||||
intrinsics: intrinsics,
|
intrinsics: intrinsics,
|
||||||
item_ids: new_int_hash::<ValueRef>(),
|
item_vals: new_int_hash::<ValueRef>(),
|
||||||
exp_map: emap,
|
exp_map: emap,
|
||||||
item_symbols: new_int_hash::<str>(),
|
item_symbols: new_int_hash::<str>(),
|
||||||
mutable main_fn: none::<ValueRef>,
|
mutable main_fn: none::<ValueRef>,
|
||||||
|
@ -5051,7 +4968,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
||||||
enum_sizes: ty::new_ty_hash(),
|
enum_sizes: ty::new_ty_hash(),
|
||||||
discrims: ast_util::new_def_id_hash::<ValueRef>(),
|
discrims: ast_util::new_def_id_hash::<ValueRef>(),
|
||||||
discrim_symbols: new_int_hash::<str>(),
|
discrim_symbols: new_int_hash::<str>(),
|
||||||
consts: new_int_hash::<ValueRef>(),
|
|
||||||
tydescs: ty::new_ty_hash(),
|
tydescs: ty::new_ty_hash(),
|
||||||
dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
|
dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
|
||||||
external: util::common::new_def_hash(),
|
external: util::common::new_def_hash(),
|
||||||
|
@ -5084,7 +5000,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
|
||||||
crate_map: crate_map,
|
crate_map: crate_map,
|
||||||
dbg_cx: dbg_cx,
|
dbg_cx: dbg_cx,
|
||||||
mutable do_not_commit_warning_issued: false};
|
mutable do_not_commit_warning_issued: false};
|
||||||
collect_items(ccx, crate);
|
|
||||||
trans_constants(ccx, crate);
|
trans_constants(ccx, crate);
|
||||||
trans_mod(ccx, crate.node.module);
|
trans_mod(ccx, crate.node.module);
|
||||||
fill_crate_map(ccx, crate_map);
|
fill_crate_map(ccx, crate_map);
|
||||||
|
|
|
@ -81,7 +81,7 @@ type crate_ctxt = @{
|
||||||
tn: type_names,
|
tn: type_names,
|
||||||
externs: hashmap<str, ValueRef>,
|
externs: hashmap<str, ValueRef>,
|
||||||
intrinsics: hashmap<str, ValueRef>,
|
intrinsics: hashmap<str, ValueRef>,
|
||||||
item_ids: hashmap<ast::node_id, ValueRef>,
|
item_vals: hashmap<ast::node_id, ValueRef>,
|
||||||
exp_map: resolve::exp_map,
|
exp_map: resolve::exp_map,
|
||||||
item_symbols: hashmap<ast::node_id, str>,
|
item_symbols: hashmap<ast::node_id, str>,
|
||||||
mutable main_fn: option<ValueRef>,
|
mutable main_fn: option<ValueRef>,
|
||||||
|
@ -89,7 +89,6 @@ type crate_ctxt = @{
|
||||||
enum_sizes: hashmap<ty::t, uint>,
|
enum_sizes: hashmap<ty::t, uint>,
|
||||||
discrims: hashmap<ast::def_id, ValueRef>,
|
discrims: hashmap<ast::def_id, ValueRef>,
|
||||||
discrim_symbols: hashmap<ast::node_id, str>,
|
discrim_symbols: hashmap<ast::node_id, str>,
|
||||||
consts: hashmap<ast::node_id, ValueRef>,
|
|
||||||
tydescs: hashmap<ty::t, @tydesc_info>,
|
tydescs: hashmap<ty::t, @tydesc_info>,
|
||||||
dicts: hashmap<dict_id, ValueRef>,
|
dicts: hashmap<dict_id, ValueRef>,
|
||||||
// Track mapping of external ids to local items imported for inlining
|
// Track mapping of external ids to local items imported for inlining
|
||||||
|
@ -300,10 +299,7 @@ fn revoke_clean(cx: block, val: ValueRef) {
|
||||||
fn get_res_dtor(ccx: crate_ctxt, did: ast::def_id, inner_t: ty::t)
|
fn get_res_dtor(ccx: crate_ctxt, did: ast::def_id, inner_t: ty::t)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
if did.crate == ast::local_crate {
|
if did.crate == ast::local_crate {
|
||||||
alt ccx.item_ids.find(did.node) {
|
ret base::get_item_val(ccx, did.node);
|
||||||
some(x) { ret x; }
|
|
||||||
_ { ccx.sess.bug("get_res_dtor: can't find resource dtor!"); }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
|
let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds;
|
||||||
|
|
|
@ -793,7 +793,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
|
||||||
ast_map::node_method(method, _, _) {
|
ast_map::node_method(method, _, _) {
|
||||||
(method.ident, method.decl.output, method.id)
|
(method.ident, method.decl.output, method.id)
|
||||||
}
|
}
|
||||||
ast_map::node_res_ctor(item) {
|
ast_map::node_ctor(item) {
|
||||||
alt item.node {
|
alt item.node {
|
||||||
ast::item_res(decl, _, _, _, ctor_id) {
|
ast::item_res(decl, _, _, _, ctor_id) {
|
||||||
(item.ident, decl.output, ctor_id)
|
(item.ident, decl.output, ctor_id)
|
||||||
|
|
|
@ -48,17 +48,11 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident,
|
||||||
tps: [ast::ty_param]) {
|
tps: [ast::ty_param]) {
|
||||||
let sub_path = path + [path_name(name)];
|
let sub_path = path + [path_name(name)];
|
||||||
for m in methods {
|
for m in methods {
|
||||||
alt ccx.item_ids.find(m.id) {
|
let llfn = get_item_val(ccx, m.id);
|
||||||
some(llfn) {
|
let m_bounds = param_bounds(ccx, tps + m.tps);
|
||||||
let m_bounds = param_bounds(ccx, tps + m.tps);
|
trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
|
||||||
trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body,
|
llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
|
||||||
llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)),
|
m_bounds, none, m.id, none);
|
||||||
m_bounds, none, m.id, none);
|
|
||||||
}
|
|
||||||
_ {
|
|
||||||
ccx.sess.bug("unbound id in trans_impl");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +216,7 @@ fn trans_vtable(ccx: crate_ctxt, id: ast::node_id, name: str,
|
||||||
});
|
});
|
||||||
llvm::LLVMSetInitializer(vt_gvar, tbl);
|
llvm::LLVMSetInitializer(vt_gvar, tbl);
|
||||||
llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
|
llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
|
||||||
ccx.item_ids.insert(id, vt_gvar);
|
ccx.item_vals.insert(id, vt_gvar);
|
||||||
ccx.item_symbols.insert(id, name);
|
ccx.item_symbols.insert(id, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +337,12 @@ fn trans_impl_vtable(ccx: crate_ctxt, pt: path,
|
||||||
let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im|
|
let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im|
|
||||||
alt vec::find(ms, {|m| m.ident == im.ident}) {
|
alt vec::find(ms, {|m| m.ident == im.ident}) {
|
||||||
some(m) {
|
some(m) {
|
||||||
let target = ccx.item_ids.get(m.id);
|
|
||||||
trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)],
|
trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)],
|
||||||
extra_tps, target)
|
extra_tps, get_item_val(ccx, m.id))
|
||||||
}
|
}
|
||||||
_ {
|
_ {
|
||||||
ccx.sess.span_bug(it.span, "no matching method \
|
ccx.sess.span_bug(it.span, "no matching method \
|
||||||
in trans_impl_vtable");
|
in trans_impl_vtable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -491,7 +484,7 @@ fn get_dict_ptrs(bcx: block, origin: typeck::dict_origin)
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
fn get_vtable(ccx: crate_ctxt, did: ast::def_id) -> ValueRef {
|
fn get_vtable(ccx: crate_ctxt, did: ast::def_id) -> ValueRef {
|
||||||
if did.crate == ast::local_crate {
|
if did.crate == ast::local_crate {
|
||||||
ccx.item_ids.get(did.node)
|
get_item_val(ccx, did.node)
|
||||||
} else {
|
} else {
|
||||||
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
let name = csearch::get_symbol(ccx.sess.cstore, did);
|
||||||
get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
|
get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
|
||||||
|
|
|
@ -11,7 +11,8 @@ import base::*;
|
||||||
import type_of::*;
|
import type_of::*;
|
||||||
import std::map::hashmap;
|
import std::map::hashmap;
|
||||||
|
|
||||||
export link_name, trans_native_mod, register_crust_fn, trans_crust_fn;
|
export link_name, trans_native_mod, register_crust_fn, trans_crust_fn,
|
||||||
|
decl_native_fn;
|
||||||
|
|
||||||
fn link_name(i: @ast::native_item) -> str {
|
fn link_name(i: @ast::native_item) -> str {
|
||||||
alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") {
|
alt attr::get_meta_item_value_str_by_name(i.attrs, "link_name") {
|
||||||
|
@ -238,7 +239,10 @@ fn trans_native_mod(ccx: crate_ctxt,
|
||||||
|
|
||||||
let cc = lib::llvm::CCallConv;
|
let cc = lib::llvm::CCallConv;
|
||||||
alt abi {
|
alt abi {
|
||||||
ast::native_abi_rust_intrinsic { ret; }
|
ast::native_abi_rust_intrinsic {
|
||||||
|
for item in native_mod.items { get_item_val(ccx, item.id); }
|
||||||
|
ret;
|
||||||
|
}
|
||||||
ast::native_abi_cdecl { cc = lib::llvm::CCallConv; }
|
ast::native_abi_cdecl { cc = lib::llvm::CCallConv; }
|
||||||
ast::native_abi_stdcall { cc = lib::llvm::X86StdcallCallConv; }
|
ast::native_abi_stdcall { cc = lib::llvm::X86StdcallCallConv; }
|
||||||
}
|
}
|
||||||
|
@ -248,17 +252,9 @@ fn trans_native_mod(ccx: crate_ctxt,
|
||||||
ast::native_item_fn(fn_decl, tps) {
|
ast::native_item_fn(fn_decl, tps) {
|
||||||
let id = native_item.id;
|
let id = native_item.id;
|
||||||
let tys = c_stack_tys(ccx, id);
|
let tys = c_stack_tys(ccx, id);
|
||||||
alt ccx.item_ids.find(id) {
|
let llwrapfn = get_item_val(ccx, id);
|
||||||
some(llwrapfn) {
|
let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
|
||||||
let llshimfn = build_shim_fn(ccx, native_item, tys, cc);
|
build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
|
||||||
build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn);
|
|
||||||
}
|
|
||||||
none {
|
|
||||||
ccx.sess.span_bug(
|
|
||||||
native_item.span,
|
|
||||||
"unbound function item in trans_native_mod");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,3 +356,48 @@ fn register_crust_fn(ccx: crate_ctxt, sp: span,
|
||||||
register_fn_fuller(ccx, sp, path, "crust fn", node_id,
|
register_fn_fuller(ccx, sp, path, "crust fn", node_id,
|
||||||
t, lib::llvm::CCallConv, llfty)
|
t, lib::llvm::CCallConv, llfty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn abi_of_native_fn(ccx: crate_ctxt, i: @ast::native_item)
|
||||||
|
-> ast::native_abi {
|
||||||
|
alt attr::get_meta_item_value_str_by_name(i.attrs, "abi") {
|
||||||
|
none {
|
||||||
|
alt check ccx.tcx.items.get(i.id) {
|
||||||
|
ast_map::node_native_item(_, abi, _) { abi }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
some(_) {
|
||||||
|
alt attr::native_abi(i.attrs) {
|
||||||
|
either::right(abi) { abi }
|
||||||
|
either::left(msg) { ccx.sess.span_fatal(i.span, msg); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decl_native_fn(ccx: crate_ctxt, i: @ast::native_item,
|
||||||
|
pth: ast_map::path) -> ValueRef {
|
||||||
|
alt i.node {
|
||||||
|
ast::native_item_fn(_, tps) {
|
||||||
|
let node_type = ty::node_id_to_type(ccx.tcx, i.id);
|
||||||
|
alt abi_of_native_fn(ccx, i) {
|
||||||
|
ast::native_abi_rust_intrinsic {
|
||||||
|
// For intrinsics: link the function directly to the intrinsic
|
||||||
|
// function itself.
|
||||||
|
let fn_type = type_of_fn_from_ty(
|
||||||
|
ccx, node_type, param_bounds(ccx, tps));
|
||||||
|
let ri_name = "rust_intrinsic_" + native::link_name(i);
|
||||||
|
ccx.item_symbols.insert(i.id, ri_name);
|
||||||
|
get_extern_fn(ccx.externs, ccx.llmod, ri_name,
|
||||||
|
lib::llvm::CCallConv, fn_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
ast::native_abi_cdecl | ast::native_abi_stdcall {
|
||||||
|
// For true external functions: create a rust wrapper
|
||||||
|
// and link to that. The rust wrapper will handle
|
||||||
|
// switching to the C stack.
|
||||||
|
register_fn(ccx, i.span, pth, "native fn", tps, i.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2157,7 +2157,8 @@ fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] {
|
||||||
|
|
||||||
fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
|
fn impl_iface(cx: ctxt, id: ast::def_id) -> option<t> {
|
||||||
if id.crate == ast::local_crate {
|
if id.crate == ast::local_crate {
|
||||||
option::map(cx.tcache.find(id), {|it| it.ty})
|
let t = cx.tcache.get(id).ty;
|
||||||
|
if get(t).struct == ty_nil { none } else { some(t) }
|
||||||
} else {
|
} else {
|
||||||
csearch::get_impl_iface(cx, id)
|
csearch::get_impl_iface(cx, id)
|
||||||
}
|
}
|
||||||
|
@ -2203,7 +2204,7 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
|
||||||
*path + [item_elt]
|
*path + [item_elt]
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_map::node_native_item(nitem, path) {
|
ast_map::node_native_item(nitem, _, path) {
|
||||||
*path + [ast_map::path_name(nitem.ident)]
|
*path + [ast_map::path_name(nitem.ident)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2216,7 +2217,7 @@ fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_map::node_expr(_) | ast_map::node_arg(_, _) |
|
ast_map::node_expr(_) | ast_map::node_arg(_, _) |
|
||||||
ast_map::node_local(_) | ast_map::node_res_ctor(_) |
|
ast_map::node_local(_) | ast_map::node_ctor(_) |
|
||||||
ast_map::node_export(_, _) {
|
ast_map::node_export(_, _) {
|
||||||
cx.sess.bug(#fmt["cannot find item_path for node %?", node]);
|
cx.sess.bug(#fmt["cannot find item_path for node %?", node]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,7 +258,7 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t {
|
||||||
some(ast_map::node_item(item, _)) {
|
some(ast_map::node_item(item, _)) {
|
||||||
ty_of_item(tcx, mode, item)
|
ty_of_item(tcx, mode, item)
|
||||||
}
|
}
|
||||||
some(ast_map::node_native_item(native_item, _)) {
|
some(ast_map::node_native_item(native_item, _, _)) {
|
||||||
ty_of_native_item(tcx, mode, native_item)
|
ty_of_native_item(tcx, mode, native_item)
|
||||||
}
|
}
|
||||||
_ {
|
_ {
|
||||||
|
@ -906,7 +906,11 @@ mod collect {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ {}
|
_ {
|
||||||
|
// Store the bounds with a nil type.
|
||||||
|
tcx.tcache.insert(local_def(it.id), {bounds: i_bounds,
|
||||||
|
ty: ty::mk_nil(tcx)});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::item_res(decl, tps, _, dtor_id, ctor_id) {
|
ast::item_res(decl, tps, _, dtor_id, ctor_id) {
|
||||||
|
|
|
@ -109,7 +109,7 @@ fn build_ctxt(sess: session::session, ast: @ast::crate,
|
||||||
|
|
||||||
let ast = config::strip_unconfigured_items(ast);
|
let ast = config::strip_unconfigured_items(ast);
|
||||||
let ast = front::test::modify_for_testing(sess, ast);
|
let ast = front::test::modify_for_testing(sess, ast);
|
||||||
let ast_map = ast_map::map_crate(*ast);
|
let ast_map = ast_map::map_crate(sess, *ast);
|
||||||
*ignore_errors = true;
|
*ignore_errors = true;
|
||||||
let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast);
|
let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast);
|
||||||
*ignore_errors = false;
|
*ignore_errors = false;
|
||||||
|
|
|
@ -97,7 +97,7 @@ fn parse_item_attrs<T:send>(
|
||||||
astsrv::exec(srv) {|ctxt|
|
astsrv::exec(srv) {|ctxt|
|
||||||
let attrs = alt ctxt.ast_map.get(id) {
|
let attrs = alt ctxt.ast_map.get(id) {
|
||||||
ast_map::node_item(item, _) { item.attrs }
|
ast_map::node_item(item, _) { item.attrs }
|
||||||
ast_map::node_native_item(item, _) { item.attrs }
|
ast_map::node_native_item(item, _, _) { item.attrs }
|
||||||
_ {
|
_ {
|
||||||
fail "parse_item_attrs: not an item";
|
fail "parse_item_attrs: not an item";
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
|
||||||
ast_map::node_native_item(@{
|
ast_map::node_native_item(@{
|
||||||
ident: ident,
|
ident: ident,
|
||||||
node: ast::native_item_fn(decl, _), _
|
node: ast::native_item_fn(decl, _), _
|
||||||
}, _) {
|
}, _, _) {
|
||||||
some(pprust::fun_to_str(decl, ident, []))
|
some(pprust::fun_to_str(decl, ident, []))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ fn get_ret_ty(srv: astsrv::srv, fn_id: doc::ast_id) -> option<str> {
|
||||||
}, _) |
|
}, _) |
|
||||||
ast_map::node_native_item(@{
|
ast_map::node_native_item(@{
|
||||||
node: ast::native_item_fn(decl, _), _
|
node: ast::native_item_fn(decl, _), _
|
||||||
}, _) {
|
}, _, _) {
|
||||||
ret_ty_to_str(decl)
|
ret_ty_to_str(decl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ fn get_arg_tys(srv: astsrv::srv, fn_id: doc::ast_id) -> [(str, str)] {
|
||||||
}, _) |
|
}, _) |
|
||||||
ast_map::node_native_item(@{
|
ast_map::node_native_item(@{
|
||||||
node: ast::native_item_fn(decl, _), _
|
node: ast::native_item_fn(decl, _), _
|
||||||
}, _) {
|
}, _, _) {
|
||||||
decl_arg_tys(decl)
|
decl_arg_tys(decl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue