提交 2c8c50d6 编写于 作者: M Marijn Haverbeke

Make sure enum and resource constructors are inlined properly

上级 4650e8bc
......@@ -137,6 +137,7 @@ fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
vfn(i.id);
alt i.node {
ast::item_res(_, _, _, d_id, c_id) { vfn(d_id); vfn(c_id); }
ast::item_enum(vs, _) { for v in vs { vfn(v.node.id); } }
_ {}
}
},
......
......@@ -28,7 +28,7 @@
const tag_items_data_item_variant: uint = 0x0eu;
const tag_items_data_item_enum_id: uint = 0x0fu;
const tag_items_data_parent_item: uint = 0x0fu;
const tag_index: uint = 0x11u;
......@@ -62,6 +62,8 @@
const tag_crate_hash: uint = 0x28u;
const tag_parent_item: uint = 0x29u;
const tag_mod_impl: uint = 0x30u;
const tag_item_method: uint = 0x31u;
......
......@@ -19,7 +19,7 @@
export get_impl_iface;
export get_impl_method;
export get_item_path;
export maybe_get_item_ast;
export maybe_get_item_ast, found_ast, found, found_parent, not_found;
fn get_symbol(cstore: cstore::cstore, def: ast::def_id) -> str {
let cdata = cstore::get_crate_data(cstore, def.crate).data;
......@@ -80,11 +80,17 @@ fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path {
[ast_map::path_mod(cdata.name)] + path
}
enum found_ast {
found(ast::inlined_item),
found_parent(ast::def_id, ast::inlined_item),
not_found,
}
// Finds the AST for this item in the crate metadata, if any. If the item was
// not marked for inlining, then the AST will not be present and hence none
// will be returned.
fn maybe_get_item_ast(tcx: ty::ctxt, maps: maps, def: ast::def_id)
-> option<ast::inlined_item> {
-> found_ast {
let cstore = tcx.sess.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::maybe_get_item_ast(cdata, tcx, maps, def.node)
......
......@@ -96,9 +96,12 @@ fn item_symbol(item: ebml::doc) -> str {
ret str::from_bytes(ebml::doc_data(sym));
}
fn variant_enum_id(d: ebml::doc) -> ast::def_id {
let tagdoc = ebml::get_doc(d, tag_items_data_item_enum_id);
ret parse_def_id(ebml::doc_data(tagdoc));
fn item_parent_item(d: ebml::doc) -> option<ast::def_id> {
let found = none;
ebml::tagged_docs(d, tag_items_data_parent_item) {|did|
found = some(parse_def_id(ebml::doc_data(did)));
}
found
}
fn variant_disr_val(d: ebml::doc) -> option<int> {
......@@ -230,7 +233,7 @@ fn lookup_def(cnum: ast::crate_num, data: @[u8], did_: ast::def_id) ->
'm' { ast::def_mod(did) }
'n' { ast::def_native_mod(did) }
'v' {
let tid = variant_enum_id(item);
let tid = option::get(item_parent_item(item));
tid = {crate: cnum, node: tid.node};
ast::def_variant(tid, did)
}
......@@ -278,10 +281,26 @@ fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path {
}
fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt, maps: maps,
id: ast::node_id) -> option<ast::inlined_item> {
id: ast::node_id) -> csearch::found_ast {
let item_doc = lookup_item(id, cdata.data);
let path = vec::init(item_path(item_doc));
astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc)
alt astencode::decode_inlined_item(cdata, tcx, maps, path, item_doc) {
some(ii) { csearch::found(ii) }
none {
alt item_parent_item(item_doc) {
some(did) {
let did = translate_def_id(cdata, did);
let parent_item = lookup_item(did.node, cdata.data);
alt astencode::decode_inlined_item(cdata, tcx, maps, path,
parent_item) {
some(ii) { csearch::found_parent(did, ii) }
none { csearch::not_found }
}
}
none { csearch::not_found }
}
}
}
}
fn get_enum_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
......
......@@ -241,8 +241,8 @@ fn encode_disr_val(_ecx: @encode_ctxt, ebml_w: ebml::writer, disr_val: int) {
ebml_w.end_tag();
}
fn encode_enum_id(ebml_w: ebml::writer, id: def_id) {
ebml_w.start_tag(tag_items_data_item_enum_id);
fn encode_parent_item(ebml_w: ebml::writer, id: def_id) {
ebml_w.start_tag(tag_items_data_parent_item);
ebml_w.writer.write(str::bytes(def_to_str(id)));
ebml_w.end_tag();
}
......@@ -260,7 +260,7 @@ fn encode_enum_variant_info(ecx: @encode_ctxt, ebml_w: ebml::writer,
encode_def_id(ebml_w, local_def(variant.node.id));
encode_family(ebml_w, 'v');
encode_name(ebml_w, variant.node.name);
encode_enum_id(ebml_w, local_def(id));
encode_parent_item(ebml_w, local_def(id));
encode_type(ecx, ebml_w,
node_id_to_type(ecx.ccx.tcx, variant.node.id));
if vec::len(variant.node.args) > 0u && ty_params.len() == 0u {
......@@ -397,6 +397,7 @@ fn should_inline(attrs: [attribute]) -> bool {
for v: variant in variants {
encode_variant_id(ebml_w, local_def(v.node.id));
}
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
encode_enum_variant_info(ecx, ebml_w, item.id, variants,
......@@ -414,11 +415,7 @@ fn should_inline(attrs: [attribute]) -> bool {
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, ty::ty_fn_ret(fn_ty));
encode_name(ebml_w, item.ident);
if tps.len() == 0u {
encode_symbol(ecx, ebml_w, item.id);
} else {
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
}
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
......@@ -428,9 +425,7 @@ fn should_inline(attrs: [attribute]) -> bool {
encode_family(ebml_w, 'f');
encode_type_param_bounds(ebml_w, ecx, tps);
encode_type(ecx, ebml_w, fn_ty);
if tps.len() == 0u {
encode_symbol(ecx, ebml_w, ctor_id);
}
encode_parent_item(ebml_w, local_def(item.id));
encode_path(ebml_w, path, ast_map::path_name(item.ident));
ebml_w.end_tag();
}
......
......@@ -864,17 +864,8 @@ fn get_res_dtor(ccx: @crate_ctxt, did: ast::def_id, substs: [ty::t])
let did = if did.crate != ast::local_crate && substs.len() > 0u {
maybe_instantiate_inline(ccx, did)
} else { did };
if did.crate == ast::local_crate {
option::get(monomorphic_fn(ccx, did, substs, none))
} else {
assert substs.len() == 0u;
let nil = ty::mk_nil(ccx.tcx);
let arg = {mode: ast::expl(ast::by_ref),
ty: ty::mk_mut_ptr(ccx.tcx, nil)};
let f_t = type_of::type_of_fn(ccx, [arg], nil, 0u);
get_extern_const(ccx.externs, ccx.llmod,
csearch::get_symbol(ccx.sess.cstore, did), f_t)
}
assert did.crate == ast::local_crate;
option::get(monomorphic_fn(ccx, did, substs, none))
}
fn trans_res_drop(bcx: block, rs: ValueRef, did: ast::def_id,
......@@ -2094,22 +2085,34 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id)
}
some(none) { fn_id } // Not inlinable
none { // Not seen yet
alt csearch::maybe_get_item_ast(ccx.tcx, ccx.maps, fn_id) {
none { ccx.external.insert(fn_id, none); fn_id }
some(ast::ii_item(item)) {
#debug["maybe_instantiate_inline(%s): inlining to local id %d",
ty::item_path_str(ccx.tcx, fn_id),
item.id];
alt check csearch::maybe_get_item_ast(ccx.tcx, ccx.maps, fn_id) {
csearch::not_found {
ccx.external.insert(fn_id, none);
fn_id
}
csearch::found(ast::ii_item(item)) {
ccx.external.insert(fn_id, some(item.id));
trans_item(ccx, *item);
local_def(item.id)
}
some(ast::ii_method(impl_did, mth)) {
#debug["maybe_instantiate_inline(%s): \
inlining method of %s to %d",
ty::item_path_str(ccx.tcx, fn_id),
ty::item_path_str(ccx.tcx, impl_did),
mth.id];
csearch::found_parent(parent_id, ast::ii_item(item)) {
ccx.external.insert(parent_id, some(item.id));
let my_id = 0;
alt check item.node {
ast::item_enum(_, _) {
let vs_here = ty::enum_variants(ccx.tcx, local_def(item.id));
let vs_there = ty::enum_variants(ccx.tcx, parent_id);
vec::iter2(*vs_here, *vs_there) {|here, there|
if there.id == fn_id { my_id = here.id.node; }
ccx.external.insert(there.id, some(here.id.node));
}
}
ast::item_res(_, _, _, _, ctor_id) { my_id = ctor_id; }
}
trans_item(ccx, *item);
local_def(my_id)
}
csearch::found(ast::ii_method(impl_did, mth)) {
ccx.external.insert(fn_id, some(mth.id));
compute_ii_method_info(ccx, impl_did, mth) {|ty, bounds, path|
if bounds.len() == 0u {
......@@ -2143,8 +2146,7 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
// monomorphized and non-monomorphized functions at the moment. If
// monomorphizing becomes the only approach, this'll be much simpler.
if (option::is_some(substs) || tys.len() > 0u) &&
fn_id.crate == ast::local_crate &&
!vec::any(tys, {|t| ty::type_has_params(t)}) {
fn_id.crate == ast::local_crate {
let mono = alt substs {
some((stys, vtables)) {
if (stys.len() + tys.len()) > 0u {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册