restructure to better support method inlining
This commit is contained in:
parent
def72bda47
commit
6473a87cec
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -750,7 +750,6 @@ fn make_fold(afp: ast_fold_precursor) -> ast_fold {
|
||||
ret result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: rust
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user