From fd465f91a89450b7daebecdde9c280a923bbe394 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 7 Mar 2012 12:21:08 +0100 Subject: [PATCH] Drop collect_items pass, create decls on demand This solves a problem with inlined functions that have inner functions. --- src/rustc/driver/driver.rs | 2 +- src/rustc/metadata/astencode.rs | 2 +- src/rustc/metadata/encoder.rs | 27 +- src/rustc/metadata/reachable.rs | 2 +- src/rustc/middle/ast_map.rs | 47 ++-- src/rustc/middle/trans/base.rs | 419 +++++++++++----------------- src/rustc/middle/trans/common.rs | 8 +- src/rustc/middle/trans/debuginfo.rs | 2 +- src/rustc/middle/trans/impl.rs | 25 +- src/rustc/middle/trans/native.rs | 67 ++++- src/rustc/middle/ty.rs | 7 +- src/rustc/middle/typeck.rs | 8 +- src/rustdoc/astsrv.rs | 2 +- src/rustdoc/attr_pass.rs | 2 +- src/rustdoc/tystr_pass.rs | 6 +- 15 files changed, 295 insertions(+), 331 deletions(-) diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs index fe05a4422ed7..4f037511418f 100644 --- a/src/rustc/driver/driver.rs +++ b/src/rustc/driver/driver.rs @@ -131,7 +131,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg, let ast_map = 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", bind creader::read_crates(sess, *crate)); let {def_map, exp_map, impl_map} = diff --git a/src/rustc/metadata/astencode.rs b/src/rustc/metadata/astencode.rs index d7215fbfcab3..8e6d7a0a5262 100644 --- a/src/rustc/metadata/astencode.rs +++ b/src/rustc/metadata/astencode.rs @@ -89,7 +89,7 @@ fn decode_inlined_item(cdata: cstore::crate_metadata, to_id_range: to_id_range}; let raw_ii = decode_ast(ast_doc); 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()]; decode_side_tables(xcx, ast_doc); #debug["< Decoded inlined fn: %s::%s", diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index c2c0cbc91503..0b24b3325d99 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -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, - &index: [entry], path: ast_map::path) { + &index: [entry], path: ast_map::path) -> bool { fn should_inline(attrs: [attribute]) -> bool { 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 } _ { 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 { item_const(_, _) { @@ -494,11 +494,13 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item, ebml_w.end_tag(); } } + ret true; } fn encode_info_for_native_item(ecx: @encode_ctxt, ebml_w: ebml::writer, - nitem: @native_item, path: ast_map::path) { - if !ecx.reachable.contains_key(nitem.id) { ret; } + nitem: @native_item, path: ast_map::path) + -> bool { + if !ecx.reachable.contains_key(nitem.id) { ret false; } ebml_w.start_tag(tag_items_data_item); alt nitem.node { 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(); + ret true; } 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()}]; encode_info_for_mod(ecx, ebml_w, crate_mod, crate_node_id, [], ""); 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) { - 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) { - index += [{val: key, pos: ebml_w.writer.tell()}]; - encode_info_for_native_item(ecx, ebml_w, i, *path); + middle::ast_map::node_native_item(i, _, path) { + encode_info_for_native_item(ecx, ebml_w, i, *path) } - _ { } - } + _ { false } + }; + if written { index += [{val: key, pos: where}]; } }; ebml_w.end_tag(); ret index; diff --git a/src/rustc/metadata/reachable.rs b/src/rustc/metadata/reachable.rs index dad1f9b70391..b66ac037bdea 100644 --- a/src/rustc/metadata/reachable.rs +++ b/src/rustc/metadata/reachable.rs @@ -58,7 +58,7 @@ fn traverse_def_id(cx: ctx, did: def_id) { alt cx.ccx.tcx.items.get(did.node) { 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_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, ()); } _ {} } diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs index c39686b0d309..4240c0e50925 100644 --- a/src/rustc/middle/ast_map.rs +++ b/src/rustc/middle/ast_map.rs @@ -4,6 +4,8 @@ import syntax::ast::*; import syntax::ast_util; import syntax::ast_util::inlined_item_methods; import syntax::{visit, codemap}; +import driver::session::session; +import front::attr; enum path_elt { path_mod(str), path_name(str) } type path = [path_elt]; @@ -24,20 +26,21 @@ fn path_to_str(p: path) -> str { enum ast_node { 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_variant(variant, def_id, @path), + node_variant(variant, @item, @path), node_expr(@expr), node_export(@view_path, @path), // Locals are numbered, because the alias analysis needs to know in which // order they are introduced. node_arg(arg, uint), node_local(uint), - node_res_ctor(@item), + node_ctor(@item), } type map = std::map::hashmap; -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; fn extend(cx: ctx, elt: str) -> @path { @@ -47,7 +50,6 @@ fn extend(cx: ctx, elt: str) -> @path { fn mk_ast_map_visitor() -> vt { ret visit::mk_vt(@{ visit_item: map_item, - visit_native_item: map_native_item, visit_expr: map_expr, visit_fn: map_fn, 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(), mutable path: [], - mutable local_id: 0u}; + mutable local_id: 0u, + sess: sess}; visit::visit_crate(c, cx, mk_ast_map_visitor()); 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 // crate. The `path` should be the path to the item but should not include // 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 // 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 @@ -77,7 +80,8 @@ fn map_decoded_item(map: map, path: path, ii: inlined_item) { // variables that are simultaneously in scope). let cx = {map: map, mutable path: path, - mutable local_id: 0u}; + mutable local_id: 0u, + sess: sess}; let v = mk_ast_map_visitor(); // 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 { ii_item(i) { /* fallthrough */ } 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) { let impl_did = ast_util::local_def(i.id); 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) { - 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)); } item_enum(vs, _) { for v in vs { 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 { @@ -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) { cx.map.insert(ex.id, node_expr(ex)); visit::visit_expr(ex, cx, v); diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 74a9c6111fa8..6f53c56e32cb 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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_method(m, _, pt) { (pt, m.ident) } // We can't monomorphize native functions - ast_map::node_native_item(_, _) { ret none; } + ast_map::node_native_item(_, _, _) { ret none; } _ { fail "unexpected node type"; } }; 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, _, _, _, _), _}, _) { trans_res_ctor(ccx, pt, decl, fn_id.node, [], psubsts, lldecl); } - ast_map::node_variant(v, enum_id, _) { - let tvs = ty::enum_variants(ccx.tcx, enum_id); + ast_map::node_variant(v, enum_item, _) { + let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.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, + trans_enum_variant(ccx, enum_item.id, v, this_tv.disr_val, (*tvs).len() == 1u, [], psubsts, lldecl); } 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), item.id]; ccx.external.insert(fn_id, some(item.id)); - collect_item(ccx, @mutable none, item); trans_item(ccx, *item); local_def(item.id) } @@ -2176,11 +2175,7 @@ fn maybe_instantiate_inline(ccx: crate_ctxt, fn_id: ast::def_id) mth.id]; ccx.external.insert(fn_id, some(mth.id)); 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 = register_fn_full(ccx, mth.span, path, - "impl_method", bounds, - mth.id, mth_ty); - set_inline_hint_if_appr(mth.attrs, llfn); + let llfn = get_item_val(ccx, mth.id); trans_fn(ccx, path, mth.decl, mth.body, llfn, impl_self(ty), bounds, 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 { // Internal reference. - assert (ccx.item_ids.contains_key(fn_id.node)); - ccx.item_ids.get(fn_id.node) + get_item_val(ccx, fn_id.node) } else { // External reference. 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) { if did.crate == ast::local_crate { - assert (ccx.consts.contains_key(did.node)); - ret lval_no_env(cx, ccx.consts.get(did.node), owned); + ret lval_no_env(cx, get_item_val(ccx, did.node), owned); } else { let tp = node_id_type(cx, id); 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) { - let v = trans_const_expr(cx, e); +fn trans_const(ccx: crate_ctxt, e: @ast::expr, id: ast::node_id) { + let v = trans_const_expr(ccx, e); // The scalars come back as 1st class LLVM vals // which we have to stick into global constants. - - alt cx.consts.find(id) { - some(g) { - llvm::LLVMSetInitializer(g, v); - llvm::LLVMSetGlobalConstant(g, True); - } - _ { cx.sess.span_bug(e.span, "unbound const in trans_const"); } - } + let g = get_item_val(ccx, id); + llvm::LLVMSetInitializer(g, v); + llvm::LLVMSetGlobalConstant(g, True); } 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 { ast::item_fn(decl, tps, body) { - let llfndecl = alt ccx.item_ids.find(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)]); - } - }; + let llfndecl = get_item_val(ccx, item.id); if decl.purity != ast::crust_fn { trans_fn(ccx, *path + [path_name(item.ident)], decl, body, 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); } 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, param_bounds(ccx, tps), none, llctor_decl); // Create a function for the destructor - alt ccx.item_ids.find(item.id) { - some(lldtor_decl) { - trans_fn(ccx, *path + [path_name(item.ident)], decl, body, - lldtor_decl, no_self, param_bounds(ccx, tps), - none, dtor_id, none); - } - _ { - ccx.sess.span_fatal(item.span, "unbound dtor in trans_item"); - } - } + let lldtor_decl = get_item_val(ccx, item.id); + trans_fn(ccx, *path + [path_name(item.ident)], decl, body, + lldtor_decl, no_self, param_bounds(ccx, tps), + none, dtor_id, none); } ast::item_mod(m) { trans_mod(ccx, m); @@ -4393,7 +4367,7 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) { if variant.node.args.len() > 0u { trans_enum_variant(ccx, item.id, variant, vi[i].disr_val, degen, tps, - none, ccx.item_ids.get(variant.node.id)); + none, get_item_val(ccx, variant.node.id)); } i += 1; } @@ -4407,81 +4381,74 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) { native::trans_native_mod(ccx, native_mod, abi); } ast::item_class(tps, items, ctor) { - alt ccx.item_ids.find(ctor.node.id) { - some(llctor_decl) { - // Translate the ctor - // First, add a preamble that - // generates a new name, obj: - // let obj = { ... } (uninit record fields) - let sess = ccx.sess; - let rslt_path_ = {global: false, - idents: ["obj"], - types: []}; // ?? - let rslt_path = @{node: rslt_path_, - span: ctor.node.body.span}; - let rslt_id : ast::node_id = sess.next_node_id(); - let rslt_pat : @ast::pat = - @{id: sess.next_node_id(), - node: ast::pat_ident(rslt_path, none), - span: ctor.node.body.span}; - // Set up obj's type - let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer, - span: ctor.node.body.span}; - // kludgy - let ty_args = [], i = 0u; - for tp in tps { - 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), - ty_args); - // Set up a local for obj - let rslt_loc_ : ast::local_ = {is_mutbl: true, - ty: rslt_ast_ty, // ??? - pat: rslt_pat, - init: none::, - id: rslt_id}; - // Register a type for obj - smallintmap::insert(*ccx.tcx.node_types, - rslt_loc_.id as uint, rslt_ty); - // Create the decl statement that initializers obj - let rslt_loc : @ast::local = - @{node: rslt_loc_, span: ctor.node.body.span}; - let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]); - let rslt_decl : @ast::decl - = @{node: rslt_decl_, span: ctor.node.body.span}; - let prologue : @ast::stmt = @{node: ast::stmt_decl(rslt_decl, - sess.next_node_id()), - span: ctor.node.body.span}; - let rslt_node_id = sess.next_node_id(); - ccx.tcx.def_map.insert(rslt_node_id, - ast::def_local(rslt_loc_.id, true)); - // And give the statement a type - smallintmap::insert(*ccx.tcx.node_types, - rslt_node_id as uint, rslt_ty); - // The result expression of the constructor is now a - // reference to obj - let rslt_expr : @ast::expr = - @{id: rslt_node_id, - node: ast::expr_path(rslt_path), - span: ctor.node.body.span}; - let ctor_body_new : ast::blk_ = {stmts: [prologue] - + ctor.node.body.node.stmts, - expr: some(rslt_expr) - with ctor.node.body.node}; - let ctor_body__ : ast::blk = {node: ctor_body_new - with ctor.node.body}; - trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec, - ctor_body__, llctor_decl, no_self, - param_bounds(ccx, tps), none, ctor.node.id, - some(rslt_expr)); - // TODO: translate methods! - } - _ { - ccx.sess.span_bug(item.span, "unbound ctor in trans_item"); - } - } + let llctor_decl = get_item_val(ccx, ctor.node.id); + // Translate the ctor + // First, add a preamble that + // generates a new name, obj: + // let obj = { ... } (uninit record fields) + let rslt_path_ = {global: false, + idents: ["obj"], + types: []}; // ?? + let rslt_path = @{node: rslt_path_, + span: ctor.node.body.span}; + let rslt_id : ast::node_id = ccx.sess.next_node_id(); + let rslt_pat : @ast::pat = + @{id: ccx.sess.next_node_id(), + node: ast::pat_ident(rslt_path, none), + span: ctor.node.body.span}; + // Set up obj's type + let rslt_ast_ty : @ast::ty = @{node: ast::ty_infer, + span: ctor.node.body.span}; + // kludgy + let ty_args = [], i = 0u; + for tp in tps { + 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), + ty_args); + // Set up a local for obj + let rslt_loc_ : ast::local_ = {is_mutbl: true, + ty: rslt_ast_ty, // ??? + pat: rslt_pat, + init: none::, + id: rslt_id}; + // Register a type for obj + smallintmap::insert(*ccx.tcx.node_types, + rslt_loc_.id as uint, rslt_ty); + // Create the decl statement that initializers obj + let rslt_loc : @ast::local = + @{node: rslt_loc_, span: ctor.node.body.span}; + let rslt_decl_ : ast::decl_ = ast::decl_local([rslt_loc]); + let rslt_decl : @ast::decl + = @{node: rslt_decl_, span: ctor.node.body.span}; + let prologue = @{node: ast::stmt_decl(rslt_decl, + ccx.sess.next_node_id()), + span: ctor.node.body.span}; + let rslt_node_id = ccx.sess.next_node_id(); + ccx.tcx.def_map.insert(rslt_node_id, + ast::def_local(rslt_loc_.id, true)); + // And give the statement a type + smallintmap::insert(*ccx.tcx.node_types, + rslt_node_id as uint, rslt_ty); + // The result expression of the constructor is now a + // reference to obj + let rslt_expr : @ast::expr = + @{id: rslt_node_id, + node: ast::expr_path(rslt_path), + span: ctor.node.body.span}; + let ctor_body_new : ast::blk_ = {stmts: [prologue] + + ctor.node.body.node.stmts, + expr: some(rslt_expr) + with ctor.node.body.node}; + let ctor_body__ : ast::blk = {node: ctor_body_new + with ctor.node.body}; + trans_fn(ccx, *path + [path_name(item.ident)], ctor.node.dec, + ctor_body__, llctor_decl, no_self, + param_bounds(ccx, tps), none, ctor.node.id, + some(rslt_expr)); + // TODO: translate methods! } _ {/* 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 { let ps: str = mangle_exported_name(ccx, path, node_type); let llfn: ValueRef = decl_fn(ccx.llmod, ps, cc, llfty); - ccx.item_ids.insert(node_id, llfn); ccx.item_symbols.insert(node_id, ps); #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); } -fn collect_native_item(ccx: crate_ctxt, - abi: @mutable option, - 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 { *alt check ccx.tcx.items.get(i.id) { ast_map::node_item(_, p) { p } } + [path_name(i.ident)] } -fn collect_item(ccx: crate_ctxt, abi: @mutable option, - i: @ast::item) { - let my_path = item_path(ccx, i); - alt i.node { - ast::item_const(_, _) { - let typ = ty::node_id_to_type(ccx.tcx, i.id); - let s = mangle_exported_name(ccx, my_path, typ); - let g = str::as_buf(s, {|buf| - llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf) - }); - ccx.item_symbols.insert(i.id, s); - ccx.consts.insert(i.id, g); - } - ast::item_native_mod(native_mod) { - // Propagate the native ABI down to collect_native_item(), - alt attr::native_abi(i.attrs) { - 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) - } else { - native::register_crust_fn(ccx, i.span, my_path, i.id) - }; - - set_inline_hint_if_appr(i.attrs, llfn); - } - ast::item_impl(tps, _, _, methods) { - let path = my_path + [path_name(int::str(i.id))]; - for m in methods { - let llm = register_fn(ccx, i.span, - path + [path_name(m.ident)], - "impl_method", tps + m.tps, m.id); - 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); +fn get_item_val(ccx: crate_ctxt, id: ast::node_id) -> ValueRef { + alt ccx.item_vals.find(id) { + some(v) { v } + none { + let val = alt check ccx.tcx.items.get(id) { + ast_map::node_item(i, pth) { + let my_path = *pth + [path_name(i.ident)]; + alt check i.node { + ast::item_const(_, _) { + let typ = ty::node_id_to_type(ccx.tcx, i.id); + let s = mangle_exported_name(ccx, my_path, typ); + let g = str::as_buf(s, {|buf| + llvm::LLVMAddGlobal(ccx.llmod, type_of(ccx, typ), buf) + }); + ccx.item_symbols.insert(i.id, s); + g + } + ast::item_fn(decl, tps, _) { + let llfn = if decl.purity != ast::crust_fn { + register_fn(ccx, i.span, my_path, "fn", tps, i.id) + } else { + native::register_crust_fn(ccx, i.span, my_path, i.id) + }; + set_inline_hint_if_appr(i.attrs, llfn); + llfn + } + ast::item_res(_, tps, _, dtor_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); + register_fn_full(ccx, i.span, my_path + [path_name("dtor")], + "res_dtor", param_bounds(ccx, tps), i.id, t) + } } - } + } + 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. fn trans_constant(ccx: crate_ctxt, it: @ast::item) { alt it.node { @@ -5043,7 +4960,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, tn: tn, externs: new_str_hash::(), intrinsics: intrinsics, - item_ids: new_int_hash::(), + item_vals: new_int_hash::(), exp_map: emap, item_symbols: new_int_hash::(), mutable main_fn: none::, @@ -5051,7 +4968,6 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt, enum_sizes: ty::new_ty_hash(), discrims: ast_util::new_def_id_hash::(), discrim_symbols: new_int_hash::(), - consts: new_int_hash::(), tydescs: ty::new_ty_hash(), dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}), 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, dbg_cx: dbg_cx, mutable do_not_commit_warning_issued: false}; - collect_items(ccx, crate); trans_constants(ccx, crate); trans_mod(ccx, crate.node.module); fill_crate_map(ccx, crate_map); diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 5bb2dfb885fe..82f826d9ee8d 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -81,7 +81,7 @@ type crate_ctxt = @{ tn: type_names, externs: hashmap, intrinsics: hashmap, - item_ids: hashmap, + item_vals: hashmap, exp_map: resolve::exp_map, item_symbols: hashmap, mutable main_fn: option, @@ -89,7 +89,6 @@ type crate_ctxt = @{ enum_sizes: hashmap, discrims: hashmap, discrim_symbols: hashmap, - consts: hashmap, tydescs: hashmap, dicts: hashmap, // 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) -> ValueRef { if did.crate == ast::local_crate { - alt ccx.item_ids.find(did.node) { - some(x) { ret x; } - _ { ccx.sess.bug("get_res_dtor: can't find resource dtor!"); } - } + ret base::get_item_val(ccx, did.node); } let param_bounds = ty::lookup_item_type(ccx.tcx, did).bounds; diff --git a/src/rustc/middle/trans/debuginfo.rs b/src/rustc/middle/trans/debuginfo.rs index 47a3d2e57166..fd3f94625d1f 100644 --- a/src/rustc/middle/trans/debuginfo.rs +++ b/src/rustc/middle/trans/debuginfo.rs @@ -793,7 +793,7 @@ fn create_function(fcx: fn_ctxt) -> @metadata { ast_map::node_method(method, _, _) { (method.ident, method.decl.output, method.id) } - ast_map::node_res_ctor(item) { + ast_map::node_ctor(item) { alt item.node { ast::item_res(decl, _, _, _, ctor_id) { (item.ident, decl.output, ctor_id) diff --git a/src/rustc/middle/trans/impl.rs b/src/rustc/middle/trans/impl.rs index 86522ba9934d..16cc55a6f944 100644 --- a/src/rustc/middle/trans/impl.rs +++ b/src/rustc/middle/trans/impl.rs @@ -48,17 +48,11 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident, tps: [ast::ty_param]) { let sub_path = path + [path_name(name)]; for m in methods { - alt ccx.item_ids.find(m.id) { - some(llfn) { - let m_bounds = param_bounds(ccx, tps + m.tps); - trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body, - llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)), - m_bounds, none, m.id, none); - } - _ { - ccx.sess.bug("unbound id in trans_impl"); - } - } + let llfn = get_item_val(ccx, m.id); + let m_bounds = param_bounds(ccx, tps + m.tps); + trans_fn(ccx, sub_path + [path_name(m.ident)], m.decl, m.body, + llfn, impl_self(ty::node_id_to_type(ccx.tcx, id)), + m_bounds, none, m.id, none); } } @@ -222,7 +216,7 @@ fn trans_vtable(ccx: crate_ctxt, id: ast::node_id, name: str, }); llvm::LLVMSetInitializer(vt_gvar, tbl); 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); } @@ -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| alt vec::find(ms, {|m| m.ident == im.ident}) { some(m) { - let target = ccx.item_ids.get(m.id); 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 \ - 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(); fn get_vtable(ccx: crate_ctxt, did: ast::def_id) -> ValueRef { if did.crate == ast::local_crate { - ccx.item_ids.get(did.node) + get_item_val(ccx, did.node) } else { let name = csearch::get_symbol(ccx.sess.cstore, did); get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8())) diff --git a/src/rustc/middle/trans/native.rs b/src/rustc/middle/trans/native.rs index dff2a207cd03..ba2c60a6bc9b 100644 --- a/src/rustc/middle/trans/native.rs +++ b/src/rustc/middle/trans/native.rs @@ -11,7 +11,8 @@ import base::*; import type_of::*; 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 { 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; 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_stdcall { cc = lib::llvm::X86StdcallCallConv; } } @@ -248,17 +252,9 @@ fn trans_native_mod(ccx: crate_ctxt, ast::native_item_fn(fn_decl, tps) { let id = native_item.id; let tys = c_stack_tys(ccx, id); - alt ccx.item_ids.find(id) { - some(llwrapfn) { - let llshimfn = build_shim_fn(ccx, native_item, tys, cc); - 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"); - } - } + let llwrapfn = get_item_val(ccx, id); + let llshimfn = build_shim_fn(ccx, native_item, tys, cc); + build_wrap_fn(ccx, tys, vec::len(tps), llshimfn, llwrapfn); } } } @@ -360,3 +356,48 @@ fn register_crust_fn(ccx: crate_ctxt, sp: span, register_fn_fuller(ccx, sp, path, "crust fn", node_id, 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) + } + } + } + } +} diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index b940b55d6421..fa4e254d9341 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2157,7 +2157,8 @@ fn iface_methods(cx: ctxt, id: ast::def_id) -> @[method] { fn impl_iface(cx: ctxt, id: ast::def_id) -> option { 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 { 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] } - ast_map::node_native_item(nitem, path) { + ast_map::node_native_item(nitem, _, path) { *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_local(_) | ast_map::node_res_ctor(_) | + ast_map::node_local(_) | ast_map::node_ctor(_) | ast_map::node_export(_, _) { cx.sess.bug(#fmt["cannot find item_path for node %?", node]); } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 78796d1ecc24..998ffa654d47 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -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, _)) { 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) } _ { @@ -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) { diff --git a/src/rustdoc/astsrv.rs b/src/rustdoc/astsrv.rs index 718e8af35b9b..7bbc8fc3b436 100644 --- a/src/rustdoc/astsrv.rs +++ b/src/rustdoc/astsrv.rs @@ -109,7 +109,7 @@ fn build_ctxt(sess: session::session, ast: @ast::crate, let ast = config::strip_unconfigured_items(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; let exp_map = resolve::resolve_crate_reexports(sess, ast_map, ast); *ignore_errors = false; diff --git a/src/rustdoc/attr_pass.rs b/src/rustdoc/attr_pass.rs index 70572fad825d..20c7591417e8 100644 --- a/src/rustdoc/attr_pass.rs +++ b/src/rustdoc/attr_pass.rs @@ -97,7 +97,7 @@ fn parse_item_attrs( astsrv::exec(srv) {|ctxt| let attrs = alt ctxt.ast_map.get(id) { 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"; } diff --git a/src/rustdoc/tystr_pass.rs b/src/rustdoc/tystr_pass.rs index 5e630ac2ade8..5ad366115ea2 100644 --- a/src/rustdoc/tystr_pass.rs +++ b/src/rustdoc/tystr_pass.rs @@ -57,7 +57,7 @@ fn get_fn_sig(srv: astsrv::srv, fn_id: doc::ast_id) -> option { ast_map::node_native_item(@{ ident: ident, node: ast::native_item_fn(decl, _), _ - }, _) { + }, _, _) { some(pprust::fun_to_str(decl, ident, [])) } } @@ -100,7 +100,7 @@ fn get_ret_ty(srv: astsrv::srv, fn_id: doc::ast_id) -> option { }, _) | ast_map::node_native_item(@{ node: ast::native_item_fn(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(@{ node: ast::native_item_fn(decl, _), _ - }, _) { + }, _, _) { decl_arg_tys(decl) } }