restructure to better support method inlining

This commit is contained in:
Niko Matsakis 2012-03-01 19:37:52 -08:00
parent def72bda47
commit 6473a87cec
13 changed files with 274 additions and 192 deletions

View File

@ -2,6 +2,7 @@ import syntax::ast;
import syntax::fold;
import syntax::visit;
import syntax::ast_util;
import syntax::ast_util::inlined_item_methods;
import syntax::codemap::span;
import std::map::map;
import std::smallintmap::map;
@ -31,8 +32,6 @@ import syntax::print::pprust;
export encode_inlined_item;
export decode_inlined_item;
export encode_inlined_method;
export decode_inlined_method;
type decode_ctxt = @{
cdata: cstore::crate_metadata,
@ -53,123 +52,49 @@ iface tr {
// ______________________________________________________________________
// Top-level methods.
// The type inline_fn should be a type that can represent both methods
// and top-level items. As it happens, the type ast::method is perfect
// for this purpose, but I use this typedef just to keep clear when
// the thing may not, in fact, be an actual method in the AST but
// rather some sort of function.
enum inline_fn = @ast::method;
fn encode_inlined_item(ecx: @e::encode_ctxt,
ebml_w: ebml::writer,
path: ast_map::path,
item: @ast::item) {
let ifn = inline_fn(alt item.node {
ast::item_fn(decl, tps, body) {
@{ident: item.ident,
attrs: item.attrs,
tps: tps,
decl: decl,
body: body,
id: item.id,
span: item.span}
}
ii: ast::inlined_item) {
#debug["> Encoding inlined item: %s::%s (%u)",
ast_map::path_to_str(path), ii.ident(),
ebml_w.writer.tell()];
_ {
ecx.ccx.sess.span_bug(item.span, "Cannot inline non-function")
}
});
let id_range = compute_id_range(ii);
ebml_w.wr_tag(c::tag_ast as uint) {||
encode_id_range(ebml_w, id_range);
encode_ast(ebml_w, ii);
encode_side_tables_for_ii(ecx, ebml_w, ii);
}
encode_inlined_fn(ecx, ebml_w, path, ifn);
#debug["< Encoded inlined fn: %s::%s (%u)",
ast_map::path_to_str(path), ii.ident(),
ebml_w.writer.tell()];
}
fn decode_inlined_item(cdata: cstore::crate_metadata,
tcx: ty::ctxt,
maps: maps,
path: ast_map::path,
par_doc: ebml::doc) -> option<@ast::item> {
let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc);
option::map(oifn) {|ifn|
let item = @{ident: ifn.ident,
attrs: ifn.attrs,
id: ifn.id,
node: ast::item_fn(ifn.decl, ifn.tps, ifn.body),
span: ifn.span};
ast_map::map_decoded_item(tcx.items, path, item);
item
}
}
fn encode_inlined_method(ecx: @e::encode_ctxt,
ebml_w: ebml::writer,
path: ast_map::path,
mthd: @ast::method) {
encode_inlined_fn(ecx, ebml_w, path, inline_fn(mthd))
}
fn decode_inlined_method(cdata: cstore::crate_metadata,
tcx: ty::ctxt,
maps: maps,
path: ast_map::path,
par_doc: ebml::doc) -> option<@ast::method> {
let oifn = decode_inlined_fn(cdata, tcx, maps, path, par_doc);
option::map(oifn) {|ifn|
ast_map::map_decoded_method(tcx.items, path, *ifn);
*ifn
}
}
fn encode_inlined_fn(ecx: @e::encode_ctxt,
ebml_w: ebml::writer,
path: ast_map::path,
ifn: inline_fn) {
#debug["> Encoding inlined item: %s::%s (%u)",
ast_map::path_to_str(path),
ifn.ident,
ebml_w.writer.tell()];
let id_range = compute_id_range(ifn);
ebml_w.wr_tag(c::tag_ast as uint) {||
encode_id_range(ebml_w, id_range);
encode_ast(ebml_w, ifn);
encode_side_tables_for_ifn(ecx, ebml_w, ifn);
}
#debug["< Encoded inlined fn: %s::%s (%u)",
ast_map::path_to_str(path),
ifn.ident,
ebml_w.writer.tell()];
}
// Decodes the inlined function and associated side tables. Does
// *not* insert the function into the ast_map, since the correct way
// to do this depends on whether this is an inlined item or method;
// therefore, you ought to be invoking decode_inlined_item() or
// decode_inlined_method() and not this helper function.
fn decode_inlined_fn(cdata: cstore::crate_metadata,
tcx: ty::ctxt,
maps: maps,
path: ast_map::path,
par_doc: ebml::doc) -> option<inline_fn> {
par_doc: ebml::doc) -> option<ast::inlined_item> {
let dcx = @{cdata: cdata, tcx: tcx, maps: maps};
alt par_doc.opt_child(c::tag_ast) {
none { none }
some(ast_doc) {
#debug["> Decoding inlined fn: %s", ast_map::path_to_str(path)];
#debug["> Decoding inlined fn: %s::?", ast_map::path_to_str(path)];
let from_id_range = decode_id_range(ast_doc);
let to_id_range = reserve_id_range(dcx.tcx.sess, from_id_range);
let xcx = @{dcx: dcx,
from_id_range: from_id_range,
to_id_range: to_id_range};
let raw_ifn = decode_ast(ast_doc);
let ifn = renumber_ast(xcx, raw_ifn);
#debug["Fn named: %s", ifn.ident];
let raw_ii = decode_ast(ast_doc);
let ii = renumber_ast(xcx, raw_ii);
ast_map::map_decoded_item(dcx.tcx.items, path, ii);
#debug["Fn named: %s", ii.ident()];
decode_side_tables(xcx, ast_doc);
#debug["< Decoded inlined fn: %s::%s",
ast_map::path_to_str(path),
ifn.ident];
some(ifn)
ast_map::path_to_str(path), ii.ident()];
some(ii)
}
}
}
@ -183,7 +108,7 @@ fn empty(range: id_range) -> bool {
range.min >= range.max
}
fn visit_ids(ifn: inline_fn, vfn: fn@(ast::node_id)) {
fn visit_ids(item: ast::inlined_item, vfn: fn@(ast::node_id)) {
let visitor = visit::mk_simple_visitor(@{
visit_mod: fn@(_m: ast::_mod, _sp: span, id: ast::node_id) {
vfn(id)
@ -292,13 +217,13 @@ fn visit_ids(ifn: inline_fn, vfn: fn@(ast::node_id)) {
}
});
visit::visit_method_helper(*ifn, (), visitor);
item.accept((), visitor)
}
fn compute_id_range(ifn: inline_fn) -> id_range {
fn compute_id_range(item: ast::inlined_item) -> id_range {
let min = @mutable int::max_value;
let max = @mutable int::min_value;
visit_ids(ifn) {|id|
visit_ids(item) {|id|
*min = int::min(*min, id);
*max = int::max(*max, id + 1);
}
@ -395,25 +320,34 @@ impl deserializer_helpers<D: serialization::deserializer> for D {
// We also have to adjust the spans: for now we just insert a dummy span,
// but eventually we should add entries to the local codemap as required.
fn encode_ast(ebml_w: ebml::writer, ifn: inline_fn) {
fn encode_ast(ebml_w: ebml::writer, item: ast::inlined_item) {
ebml_w.wr_tag(c::tag_tree as uint) {||
astencode_gen::serialize_syntax_ast_method(ebml_w, **ifn)
astencode_gen::serialize_syntax_ast_inlined_item(ebml_w, item)
}
}
fn decode_ast(par_doc: ebml::doc) -> inline_fn {
fn decode_ast(par_doc: ebml::doc) -> ast::inlined_item {
let chi_doc = par_doc[c::tag_tree];
let d = serialization::mk_ebml_deserializer(chi_doc);
inline_fn(@astencode_gen::deserialize_syntax_ast_method(d))
astencode_gen::deserialize_syntax_ast_inlined_item(d)
}
fn renumber_ast(xcx: extended_decode_ctxt, ifn: inline_fn) -> inline_fn {
fn renumber_ast(xcx: extended_decode_ctxt, ii: ast::inlined_item)
-> ast::inlined_item {
let fld = fold::make_fold({
new_id: xcx.tr_id(_),
new_span: xcx.tr_span(_)
with *fold::default_ast_fold()
});
inline_fn(fld.fold_method(*ifn))
alt ii {
ast::ii_item(i) {
ast::ii_item(fld.fold_item(i))
}
ast::ii_method(d, m) {
ast::ii_method(xcx.tr_def_id(d), fld.fold_method(m))
}
}
}
// ______________________________________________________________________
@ -664,11 +598,11 @@ impl writer for ebml::writer {
}
}
fn encode_side_tables_for_ifn(ecx: @e::encode_ctxt,
ebml_w: ebml::writer,
ifn: inline_fn) {
fn encode_side_tables_for_ii(ecx: @e::encode_ctxt,
ebml_w: ebml::writer,
ii: ast::inlined_item) {
ebml_w.wr_tag(c::tag_table as uint) {||
visit_ids(ifn, fn@(id: ast::node_id) {
visit_ids(ii, fn@(id: ast::node_id) {
// Note: this will cause a copy of ebml_w, which is bad as
// it has mutable fields. But I believe it's harmless since
// we generate balanced EBML.

View File

@ -8748,12 +8748,84 @@ fn deserialize_syntax_ast_def_id<S: std::serialization::deserializer>(s: S) ->
syntax::ast::def_id {
deserialize_162(s)
}
fn serialize_syntax_ast_method<S: std::serialization::serializer>(s: S,
v:
syntax::ast::method) {
serialize_160(s, v);
/*syntax::ast::inlined_item*/
fn serialize_168<S: std::serialization::serializer>(s: S,
v:
syntax::ast::inlined_item) {
s.emit_enum("syntax::ast::inlined_item",
/*@syntax::ast::item*/
/*syntax::ast::def_id*//*@syntax::ast::method*/
{||
alt v {
syntax::ast::ii_item(v0) {
s.emit_enum_variant("syntax::ast::ii_item", 0u, 1u,
{||
{
s.emit_enum_variant_arg(0u,
{||
serialize_117(s,
v0)
})
}
})
}
syntax::ast::ii_method(v0, v1) {
s.emit_enum_variant("syntax::ast::ii_method", 1u, 2u,
{||
{
s.emit_enum_variant_arg(0u,
{||
serialize_162(s,
v0)
});
s.emit_enum_variant_arg(1u,
{||
serialize_159(s,
v1)
})
}
})
}
}
});
}
fn deserialize_syntax_ast_method<S: std::serialization::deserializer>(s: S) ->
syntax::ast::method {
deserialize_160(s)
fn serialize_syntax_ast_inlined_item<S: std::serialization::serializer>(s: S,
v:
syntax::ast::inlined_item) {
serialize_168(s, v);
}
/*syntax::ast::inlined_item*/
fn deserialize_168<S: std::serialization::deserializer>(s: S) ->
syntax::ast::inlined_item {
s.read_enum("syntax::ast::inlined_item",
/*@syntax::ast::item*/
/*syntax::ast::def_id*//*@syntax::ast::method*/
{||
s.read_enum_variant({|v_id|
alt check v_id {
0u {
syntax::ast::ii_item(s.read_enum_variant_arg(0u,
{||
deserialize_117(s)
}))
}
1u {
syntax::ast::ii_method(s.read_enum_variant_arg(0u,
{||
deserialize_162(s)
}),
s.read_enum_variant_arg(1u,
{||
deserialize_159(s)
}))
}
}
})
})
}
fn deserialize_syntax_ast_inlined_item<S: std::serialization::deserializer>(s:
S)
-> syntax::ast::inlined_item {
deserialize_168(s)
}

View File

@ -79,7 +79,7 @@ fn get_item_path(tcx: ty::ctxt, def: ast::def_id) -> ast_map::path {
// 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::item> {
-> option<ast::inlined_item> {
let cstore = tcx.sess.cstore;
let cdata = cstore::get_crate_data(cstore, def.crate);
decoder::maybe_get_item_ast(cdata, tcx, maps, def.node)

View File

@ -264,7 +264,7 @@ 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::item> {
id: ast::node_id) -> option<ast::inlined_item> {
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)

View File

@ -352,7 +352,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
encode_symbol(ecx, ebml_w, item.id);
encode_path(ebml_w, path, ast_map::path_name(item.ident));
if should_inline(path, item) {
astencode::encode_inlined_item(ecx, ebml_w, path, item);
astencode::encode_inlined_item(ecx, ebml_w, path, ii_item(item));
}
ebml_w.end_tag();
}

View File

@ -1,6 +1,7 @@
import std::map;
import syntax::ast::*;
import syntax::ast_util;
import syntax::ast_util::inlined_item_methods;
import syntax::{visit, codemap};
enum path_elt { path_mod(str), path_name(str) }
@ -23,7 +24,7 @@ fn path_to_str(p: path) -> str {
enum ast_node {
node_item(@item, @path),
node_native_item(@native_item, @path),
node_method(@method, node_id, @path),
node_method(@method, def_id, @path),
node_variant(variant, def_id, @path),
node_expr(@expr),
// Locals are numbered, because the alias analysis needs to know in which
@ -59,7 +60,7 @@ fn map_crate(c: crate) -> map {
// Used for items loaded from external crate that are being inlined into this
// crate:
fn map_decoded_item(map: map, path: path, i: @item) {
fn map_decoded_item(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
@ -70,16 +71,7 @@ fn map_decoded_item(map: map, path: path, i: @item) {
mutable path: path,
mutable local_id: 0u};
let v = mk_ast_map_visitor();
v.visit_item(i, cx, v);
}
fn map_decoded_method(map: map, path: path, m: @method) {
// As above.
let cx = {map: map,
mutable path: path,
mutable local_id: 0u};
let v = mk_ast_map_visitor();
visit::visit_method_helper(m, cx, v);
ii.accept(cx, v);
}
fn map_fn(fk: visit::fn_kind, decl: fn_decl, body: blk,
@ -117,7 +109,8 @@ fn map_item(i: @item, cx: ctx, v: vt) {
cx.map.insert(i.id, node_item(i, @cx.path));
alt i.node {
item_impl(_, _, _, ms) {
for m in ms { cx.map.insert(m.id, node_method(m, i.id, @cx.path)); }
let implid = ast_util::local_def(i.id);
for m in ms { cx.map.insert(m.id, node_method(m, implid, @cx.path)); }
}
item_res(_, _, _, dtor_id, ctor_id) {
cx.map.insert(ctor_id, node_res_ctor(i));

View File

@ -1,6 +1,7 @@
import std::map::hashmap;
import syntax::ast;
import syntax::ast_util;
import syntax::ast_util::inlined_item_methods;
import syntax::visit;
import middle::typeck::method_map;
import middle::trans::common::maps;
@ -9,13 +10,13 @@ import metadata::csearch;
export inline_map;
export instantiate_inlines;
type inline_map = hashmap<ast::def_id, @ast::item>;
type inline_map = hashmap<ast::def_id, ast::inlined_item>;
enum ctxt = {
tcx: ty::ctxt,
maps: maps,
inline_map: inline_map,
mutable to_process: [@ast::item]
mut to_process: [ast::inlined_item]
};
fn instantiate_inlines(enabled: bool,
@ -37,7 +38,9 @@ fn instantiate_inlines(enabled: bool,
let to_process = [];
to_process <-> cx.to_process;
#debug["Recursively looking at inlined items"];
vec::iter(to_process, {|i| visit::visit_item(i, cx, vt)});
vec::iter(to_process) {|ii|
ii.accept(cx, vt);
}
}
ret inline_map;
}
@ -78,20 +81,20 @@ impl methods for ctxt {
#debug["No AST attached to def %s",
ty::item_path_str(self.tcx, did)];
}
some(item) { /* Found an AST, add to table: */
some(ii) { /* Found an AST, add to table: */
#debug["Inlining def %s", ty::item_path_str(self.tcx, did)];
self.to_process += [item];
self.inline_map.insert(did, item);
self.to_process += [ii];
self.inline_map.insert(did, ii);
}
}
}
fn maybe_enqueue_impl_method(_origin: typeck::method_origin) {
// alt method_origin {
// method_static(did) { self.maybe_enqueue_fn(did); }
// method_param(_, _, _, _) | method_iface(_, _) {
// /* fallthrough */
// }
// }
fn maybe_enqueue_impl_method(method_origin: typeck::method_origin) {
alt method_origin {
typeck::method_static(did) { self.maybe_enqueue_fn(did); }
typeck::method_param(_, _, _, _) | typeck::method_iface(_, _) {
/* fallthrough */
}
}
}
}

View File

@ -23,6 +23,7 @@ import front::attr;
import middle::inline::inline_map;
import back::{link, abi, upcall};
import syntax::{ast, ast_util, codemap};
import ast_util::inlined_item_methods;
import ast_util::local_def;
import syntax::visit;
import syntax::codemap::span;
@ -2105,8 +2106,8 @@ fn monomorphic_fn(ccx: crate_ctxt, fn_id: ast::def_id, substs: [ty::t],
trans_enum_variant(ccx, enum_id.node, v, this_tv.disr_val,
(*tvs).len() == 1u, [], psubsts, lldecl);
}
ast_map::node_method(mth, impl_id, _) {
let selfty = ty::node_id_to_type(ccx.tcx, impl_id);
ast_map::node_method(mth, impl_def_id, _) {
let selfty = ty::lookup_item_type(ccx.tcx, impl_def_id).ty;
let selfty = ty::substitute_type_params(ccx.tcx, substs, selfty);
trans_fn(ccx, pt, mth.decl, mth.body, lldecl,
impl_self(selfty), [], psubsts, fn_id.node);
@ -2131,12 +2132,12 @@ fn lval_static_fn(bcx: block, fn_id: ast::def_id, id: ast::node_id,
} else {
alt ccx.inline_map.find(fn_id) {
none { fn_id }
some(item) {
some(ii) {
#debug["Found inlined version of %s with id %d",
ty::item_path_str(tcx, fn_id),
item.id];
ii.id()];
{crate: ast::local_crate,
node: item.id}
node: ii.id()}
}
}
}
@ -3882,8 +3883,10 @@ fn new_fn_ctxt(ccx: crate_ctxt, path: path, llfndecl: ValueRef,
// spaces that have been created for them (by code in the llallocas field of
// the function's fn_ctxt). create_llargs_for_fn_args populates the llargs
// field of the fn_ctxt with
fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg,
args: [ast::arg], ty_params: [ast::ty_param]) {
fn create_llargs_for_fn_args(cx: fn_ctxt,
ty_self: self_arg,
args: [ast::arg],
tps_bounds: [ty::param_bounds]) {
// Skip the implicit arguments 0, and 1.
let arg_n = first_tp_arg;
alt ty_self {
@ -3892,11 +3895,11 @@ fn create_llargs_for_fn_args(cx: fn_ctxt, ty_self: self_arg,
}
no_self {}
}
for tp in ty_params {
for bounds in tps_bounds {
let lltydesc = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint);
let dicts = none;
arg_n += 1u;
for bound in *cx.ccx.tcx.ty_param_bounds.get(tp.id) {
for bound in *bounds {
alt bound {
ty::bound_iface(_) {
let dict = llvm::LLVMGetParam(cx.llfn, arg_n as c_uint);
@ -3983,7 +3986,8 @@ enum self_arg { impl_self(ty::t), no_self, }
// returned.
fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
body: ast::blk, llfndecl: ValueRef,
ty_self: self_arg, ty_params: [ast::ty_param],
ty_self: self_arg,
tps_bounds: [ty::param_bounds],
param_substs: option<param_substs>,
id: ast::node_id, maybe_load_env: fn(fn_ctxt)) {
set_uwtable(llfndecl);
@ -3991,7 +3995,7 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
// Set up arguments to the function.
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, param_substs,
some(body.span));
create_llargs_for_fn_args(fcx, ty_self, decl.inputs, ty_params);
create_llargs_for_fn_args(fcx, ty_self, decl.inputs, tps_bounds);
// Create the first basic block in the function and keep a handle on it to
// pass to finish_fn later.
@ -4023,15 +4027,20 @@ fn trans_closure(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
// trans_fn: creates an LLVM function corresponding to a source language
// function.
fn trans_fn(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
body: ast::blk, llfndecl: ValueRef, ty_self: self_arg,
ty_params: [ast::ty_param], param_substs: option<param_substs>,
fn trans_fn(ccx: crate_ctxt,
path: path,
decl: ast::fn_decl,
body: ast::blk,
llfndecl: ValueRef,
ty_self: self_arg,
tps_bounds: [ty::param_bounds],
param_substs: option<param_substs>,
id: ast::node_id) {
let do_time = ccx.sess.opts.stats;
let start = if do_time { time::get_time() }
else { {sec: 0u32, usec: 0u32} };
trans_closure(ccx, path, decl, body, llfndecl, ty_self,
ty_params, param_substs, id, {|fcx|
tps_bounds, param_substs, id, {|fcx|
if ccx.sess.opts.extra_debuginfo {
debuginfo::create_function(fcx);
}
@ -4043,12 +4052,12 @@ fn trans_fn(ccx: crate_ctxt, path: path, decl: ast::fn_decl,
}
fn trans_res_ctor(ccx: crate_ctxt, path: path, dtor: ast::fn_decl,
ctor_id: ast::node_id, ty_params: [ast::ty_param],
ctor_id: ast::node_id, tps_bounds: [ty::param_bounds],
param_substs: option<param_substs>, llfndecl: ValueRef) {
// Create a function for the constructor
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, ctor_id,
param_substs, none);
create_llargs_for_fn_args(fcx, no_self, dtor.inputs, ty_params);
create_llargs_for_fn_args(fcx, no_self, dtor.inputs, tps_bounds);
let bcx = top_scope_block(fcx, none), lltop = bcx.llbb;
let fty = node_id_type(bcx, ctor_id);
let arg_t = ty::ty_fn_args(fty)[0].ty;
@ -4091,7 +4100,8 @@ fn trans_enum_variant(ccx: crate_ctxt, enum_id: ast::node_id,
}
let fcx = new_fn_ctxt_w_id(ccx, [], llfndecl, variant.node.id,
param_substs, none);
create_llargs_for_fn_args(fcx, no_self, fn_args, ty_params);
create_llargs_for_fn_args(fcx, no_self, fn_args,
param_bounds(ccx, ty_params));
let ty_param_substs = alt param_substs {
some(substs) { substs.tys }
none {
@ -4248,7 +4258,8 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
};
if decl.purity != ast::crust_fn {
trans_fn(ccx, *path + [path_name(item.ident)], decl, body,
llfndecl, no_self, tps, none, item.id);
llfndecl, no_self, param_bounds(ccx, tps),
none, item.id);
} else {
native::trans_crust_fn(ccx, *path + [path_name(item.ident)],
decl, body, llfndecl, item.id);
@ -4259,13 +4270,15 @@ fn trans_item(ccx: crate_ctxt, item: ast::item) {
}
ast::item_res(decl, tps, body, dtor_id, ctor_id) {
let llctor_decl = ccx.item_ids.get(ctor_id);
trans_res_ctor(ccx, *path, decl, ctor_id, tps, none, llctor_decl);
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, tps, none, dtor_id);
lldtor_decl, no_self, param_bounds(ccx, tps),
none, dtor_id);
}
_ {
ccx.sess.span_fatal(item.span, "unbound dtor in trans_item");
@ -4309,9 +4322,34 @@ fn trans_mod(ccx: crate_ctxt, m: ast::_mod) {
for item in m.items { trans_item(ccx, *item); }
}
fn compute_ii_method_info(ccx: crate_ctxt,
impl_did: ast::def_id,
m: @ast::method,
f: fn(ty::t, [ty::param_bounds], ast_map::path)) {
let {bounds: impl_bnds, ty: impl_ty} =
ty::lookup_item_type(ccx.tcx, impl_did);
let m_bounds = *impl_bnds + param_bounds(ccx, m.tps);
let impl_path = ty::item_path(ccx.tcx, impl_did);
let m_path = impl_path + [path_name(m.ident)];
f(impl_ty, m_bounds, m_path);
}
fn trans_inlined_items(ccx: crate_ctxt, inline_map: inline_map) {
inline_map.values {|item|
trans_item(ccx, *item)
inline_map.values {|ii|
alt ii {
ast::ii_item(item) {
trans_item(ccx, *item)
}
ast::ii_method(impl_did, m) {
compute_ii_method_info(ccx, impl_did, m) {
|impl_ty, m_bounds, m_path|
let llfndecl = ccx.item_ids.get(m.id);
trans_fn(ccx, m_path, m.decl, m.body,
llfndecl, impl_self(impl_ty), m_bounds,
none, m.id);
}
}
}
}
}
@ -4323,18 +4361,18 @@ fn get_pair_fn_ty(llpairty: TypeRef) -> TypeRef {
fn register_fn(ccx: crate_ctxt, sp: span, path: path, flav: str,
ty_params: [ast::ty_param], node_id: ast::node_id) {
let t = ty::node_id_to_type(ccx.tcx, node_id);
register_fn_full(ccx, sp, path, flav, ty_params, node_id, t);
let bnds = param_bounds(ccx, ty_params);
register_fn_full(ccx, sp, path, flav, bnds, node_id, t);
}
fn param_bounds(ccx: crate_ctxt, tp: ast::ty_param) -> ty::param_bounds {
ccx.tcx.ty_param_bounds.get(tp.id)
fn param_bounds(ccx: crate_ctxt, tps: [ast::ty_param]) -> [ty::param_bounds] {
vec::map(tps) {|tp| ccx.tcx.ty_param_bounds.get(tp.id) }
}
fn register_fn_full(ccx: crate_ctxt, sp: span, path: path, flav: str,
tps: [ast::ty_param], node_id: ast::node_id,
bnds: [ty::param_bounds], node_id: ast::node_id,
node_type: ty::t) {
let llfty = type_of_fn_from_ty(ccx, node_type,
vec::map(tps, {|p| param_bounds(ccx, p)}));
let llfty = type_of_fn_from_ty(ccx, node_type, bnds);
register_fn_fuller(ccx, sp, path, flav, node_id, node_type,
lib::llvm::CCallConv, llfty);
}
@ -4480,8 +4518,7 @@ fn collect_native_item(ccx: crate_ctxt,
// For intrinsics: link the function directly to the intrinsic
// function itself.
let fn_type = type_of_fn_from_ty(
ccx, node_type,
vec::map(tps, {|p| param_bounds(ccx, p)}));
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,
@ -4555,7 +4592,7 @@ fn collect_item(ccx: crate_ctxt, abi: @mutable option<ast::native_abi>,
// -- 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", tps, i.id, t);
"res_dtor", param_bounds(ccx, tps), i.id, t);
}
ast::item_enum(variants, tps) {
for variant in variants {
@ -4581,14 +4618,26 @@ fn collect_items(ccx: crate_ctxt, crate: @ast::crate) {
fn collect_inlined_items(ccx: crate_ctxt, inline_map: inline::inline_map) {
let abi = @mutable none::<ast::native_abi>;
inline_map.values {|item|
collect_item(ccx, abi, item);
alt item.node {
ast::item_fn(_, _, _) {
set_always_inline(ccx.item_ids.get(item.id));
inline_map.values {|ii|
alt ii {
ast::ii_item(item) {
collect_item(ccx, abi, item);
alt item.node {
ast::item_fn(_, _, _) {
set_always_inline(ccx.item_ids.get(item.id));
}
_ { /* fallthrough */ }
}
}
ast::ii_method(impl_did, m) {
compute_ii_method_info(ccx, impl_did, m) {
|_impl_ty, m_bounds, m_path|
let mthd_ty = ty::node_id_to_type(ccx.tcx, m.id);
register_fn_full(ccx, m.span, m_path, "impl_method",
m_bounds, m.id, mthd_ty);
}
}
_ { /* fallthrough */ }
}
}
}

View File

@ -49,9 +49,10 @@ fn trans_impl(ccx: crate_ctxt, path: path, name: ast::ident,
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)),
tps + m.tps, none, m.id);
m_bounds, none, m.id);
}
_ {
ccx.sess.bug("Unbound id in trans_impl");
@ -337,13 +338,13 @@ fn trans_impl_vtable(ccx: crate_ctxt, pt: path,
tps: [ast::ty_param], it: @ast::item) {
let new_pt = pt + [path_name(it.ident), path_name(int::str(it.id)),
path_name("wrap")];
let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
let extra_tps = param_bounds(ccx, tps);
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)
trans_impl_wrapper(ccx, new_pt + [path_name(m.ident)],
extra_tps, target)
}
_ {
ccx.sess.span_bug(it.span, "No matching method \

View File

@ -534,6 +534,14 @@ enum native_item_ {
native_item_fn(fn_decl, [ty_param]),
}
// The data we save and restore about an inlined item or method. This is not
// part of the AST that we parse from a file, but it becomes part of the tree
// that we trans.
enum inlined_item {
ii_item(@item),
ii_method(def_id /* impl id */, @method)
}
//
// Local Variables:
// mode: rust

View File

@ -411,6 +411,29 @@ pure fn class_item_ident(ci: @class_item) -> ident {
}
}
impl inlined_item_methods for inlined_item {
fn ident() -> ident {
alt self {
ii_item(i) { i.ident }
ii_method(_, m) { m.ident }
}
}
fn id() -> ast::node_id {
alt self {
ii_item(i) { i.id }
ii_method(_, m) { m.id }
}
}
fn accept<E>(e: E, v: visit::vt<E>) {
alt self {
ii_item(i) { v.visit_item(i, e, v) }
ii_method(_, m) { visit::visit_method_helper(m, e, v) }
}
}
}
// Local Variables:
// mode: rust
// fill-column: 78;

View File

@ -750,7 +750,6 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
ret result;
}
//
// Local Variables:
// mode: rust

View File

@ -17,7 +17,7 @@ function msg {
M=src/comp/metadata
GEN_TYPES="syntax::ast::item syntax::ast::def middle::typeck::method_origin \
middle::freevars::freevar_entry syntax::ast::def_id
syntax::ast::method"
syntax::ast::inlined_item"
# Find serializer tool:
for S in build/*/stage1/bin/serializer; do