Skip to content

Commit 20eb0ca

Browse files
committed
---
yaml --- r: 7080 b: refs/heads/master c: 4f3171e h: refs/heads/master v: v3
1 parent 87aeb52 commit 20eb0ca

File tree

17 files changed

+279
-48
lines changed

17 files changed

+279
-48
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 6cfc196d424d50e39c3f697b213a62ff8df9979b
2+
refs/heads/master: 4f3171ea8150953b30b79aed9a3f35f14b40c0ba

trunk/mk/clean.mk

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ clean-misc:
4848
test/*/*.$(ext) \
4949
test/bench/*/*.$(ext)))
5050
$(Q)rm -Rf $(foreach ext, \
51-
css html js \
52-
aux cp fn ky log pdf pg toc tp vr cps, \
51+
html aux cp fn ky log pdf pg toc tp vr cps, \
5352
$(wildcard doc/*.$(ext) \
5453
doc/*/*.$(ext) \
5554
doc/*/*/*.$(ext)))

trunk/src/comp/back/upcall.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import driver::session;
33
import middle::trans;
44
import middle::trans_common::{T_fn, T_i1, T_i8, T_i32,
5-
T_int, T_nil,
5+
T_int, T_nil, T_dict,
66
T_opaque_vec, T_ptr,
77
T_size_t, T_void};
88
import lib::llvm::type_names;
@@ -20,6 +20,7 @@ type upcalls =
2020
create_shared_type_desc: ValueRef,
2121
free_shared_type_desc: ValueRef,
2222
get_type_desc: ValueRef,
23+
intern_dict: ValueRef,
2324
vec_grow: ValueRef,
2425
vec_push: ValueRef,
2526
cmp_type: ValueRef,
@@ -76,6 +77,8 @@ fn declare_upcalls(targ_cfg: @session::config,
7677
size_t, size_t,
7778
T_ptr(T_ptr(tydesc_type)), int_t],
7879
T_ptr(tydesc_type)),
80+
intern_dict:
81+
d("intern_dict", [size_t, T_ptr(T_dict())], T_ptr(T_dict())),
7982
vec_grow:
8083
dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t]),
8184
vec_push:

trunk/src/comp/middle/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,7 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
18921892

18931893
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
18941894
alt x.node {
1895-
ast::expr_field(_, _, _) | ast::expr_path(_) {
1895+
ast::expr_field(_, _, _) | ast::expr_path(_) | ast::expr_cast(_, _) {
18961896
e.impl_map.insert(x.id, sc);
18971897
}
18981898
_ {}

trunk/src/comp/middle/trans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5689,6 +5689,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
56895689
discrim_symbols: new_int_hash::<str>(),
56905690
consts: new_int_hash::<ValueRef>(),
56915691
tydescs: ty::new_ty_hash(),
5692+
dicts: map::mk_hashmap(hash_dict_id, {|a, b| a == b}),
56925693
module_data: new_str_hash::<ValueRef>(),
56935694
lltypes: ty::new_ty_hash(),
56945695
names: namegen(0),

trunk/src/comp/middle/trans_closure.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,18 +461,24 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
461461
let (outgoing_fty_real, lltydescs, param_bounds) = alt f_res.generic {
462462
none. { (outgoing_fty, [], @[]) }
463463
some(ginfo) {
464-
for bounds in *ginfo.param_bounds {
464+
let tds = [], orig = 0u;
465+
vec::iter2(ginfo.tydescs, *ginfo.param_bounds) {|td, bounds|
466+
tds += [td];
465467
for bound in *bounds {
466468
alt bound {
467469
ty::bound_iface(_) {
468-
fail "FIXME[impl] binding bounded types not implemented";
470+
let dict = trans_impl::get_dict(
471+
bcx, option::get(ginfo.origins)[orig]);
472+
tds += [PointerCast(bcx, dict.val, val_ty(td))];
473+
orig += 1u;
474+
bcx = dict.bcx;
469475
}
470476
_ {}
471477
}
472478
}
473479
}
474480
lazily_emit_all_generic_info_tydesc_glues(cx, ginfo);
475-
(ginfo.item_type, ginfo.tydescs, ginfo.param_bounds)
481+
(ginfo.item_type, tds, ginfo.param_bounds)
476482
}
477483
};
478484

trunk/src/comp/middle/trans_common.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ type crate_ctxt =
9393
discrim_symbols: hashmap<ast::node_id, str>,
9494
consts: hashmap<ast::node_id, ValueRef>,
9595
tydescs: hashmap<ty::t, @tydesc_info>,
96+
dicts: hashmap<dict_id, ValueRef>,
9697
module_data: hashmap<str, ValueRef>,
9798
lltypes: hashmap<ty::t, TypeRef>,
9899
names: namegen,
@@ -925,6 +926,24 @@ pure fn type_is_tup_like(cx: @block_ctxt, t: ty::t) -> bool {
925926
ty::type_is_tup_like(tcx, t)
926927
}
927928

929+
// Used to identify cached dictionaries
930+
tag dict_param {
931+
dict_param_dict(dict_id);
932+
dict_param_ty(ty::t);
933+
}
934+
type dict_id = @{impl_def: ast::def_id, params: [dict_param]};
935+
fn hash_dict_id(&&dp: dict_id) -> uint {
936+
let h = syntax::ast_util::hash_def_id(dp.impl_def);
937+
for param in dp.params {
938+
h = h << 2u;
939+
alt param {
940+
dict_param_dict(d) { h += hash_dict_id(d); }
941+
dict_param_ty(t) { h += t; }
942+
}
943+
}
944+
h
945+
}
946+
928947
//
929948
// Local Variables:
930949
// mode: rust

trunk/src/comp/middle/trans_impl.rs

Lines changed: 125 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,38 @@ import option::{some, none};
55
import syntax::{ast, ast_util};
66
import metadata::csearch;
77
import back::link;
8-
import lib::llvm;
9-
import llvm::llvm::{ValueRef, TypeRef, LLVMGetParam};
8+
import lib::llvm::llvm;
9+
import llvm::{ValueRef, TypeRef, LLVMGetParam};
10+
11+
// Translation functionality related to impls and ifaces
12+
//
13+
// Terminology:
14+
// vtable: a table of function pointers pointing to method wrappers
15+
// of an impl that implements an iface
16+
// dict: a record containing a vtable pointer along with pointers to
17+
// all tydescs and other dicts needed to run methods in this vtable
18+
// (i.e. corresponding to the type parameters of the impl)
19+
// wrapper: a function that takes a dict as first argument, along
20+
// with the method-specific tydescs for a method (and all
21+
// other args the method expects), which fetches the extra
22+
// tydescs and dicts from the dict, splices them into the
23+
// arglist, and calls through to the actual method
24+
//
25+
// Generic functions take, along with their normal arguments, a number
26+
// of extra tydesc and dict arguments -- one tydesc for each type
27+
// parameter, one dict (following the tydesc in the arg order) for
28+
// each interface bound on a type parameter.
29+
//
30+
// Most dicts are completely static, and are allocated and filled at
31+
// compile time. Dicts that depend on run-time values (tydescs or
32+
// dicts for type parameter types) are built at run-time, and interned
33+
// through upcall_intern_dict in the runtime. This means that dict
34+
// pointers are self-contained things that do not need to be cleaned
35+
// up.
36+
//
37+
// The trans_constants pass in trans.rs outputs the vtables. Typeck
38+
// annotates notes with information about the methods and dicts that
39+
// are referenced (ccx.method_map and ccx.dict_map).
1040

1141
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
1242
id: ast::node_id, tps: [ast::ty_param]) {
@@ -55,7 +85,8 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
5585
let generic = none;
5686
if vec::len(*method.tps) > 0u {
5787
let tydescs = [], tis = [];
58-
for t in ty::node_id_to_type_params(tcx, e.id) {
88+
let tptys = ty::node_id_to_type_params(tcx, e.id);
89+
for t in vec::tail_n(tptys, vec::len(tptys) - vec::len(*method.tps)) {
5990
// TODO: Doesn't always escape.
6091
let ti = none;
6192
let td = get_tydesc(bcx, t, true, tps_normal, ti).result;
@@ -75,18 +106,18 @@ fn trans_dict_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
75106
}
76107

77108
fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} {
78-
let out_ty = llvm::llvm::LLVMGetReturnType(ft);
79-
let n_args = llvm::llvm::LLVMCountParamTypes(ft);
109+
let out_ty = llvm::LLVMGetReturnType(ft);
110+
let n_args = llvm::LLVMCountParamTypes(ft);
80111
let args = vec::init_elt(0 as TypeRef, n_args);
81-
unsafe { llvm::llvm::LLVMGetParamTypes(ft, vec::to_ptr(args)); }
112+
unsafe { llvm::LLVMGetParamTypes(ft, vec::to_ptr(args)); }
82113
{inputs: args, output: out_ty}
83114
}
84115

85116
fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
86117
extra_tps: [ty::param_bounds], m: @ast::method) -> ValueRef {
87118
let real_fn = ccx.item_ids.get(m.id);
88119
let {inputs: real_args, output: real_ret} =
89-
llfn_arg_tys(llvm::llvm::LLVMGetElementType(val_ty(real_fn)));
120+
llfn_arg_tys(llvm::LLVMGetElementType(val_ty(real_fn)));
90121
let extra_ptrs = [];
91122
for tp in extra_tps {
92123
extra_ptrs += [T_ptr(ccx.tydesc_type)];
@@ -120,7 +151,7 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
120151
args += [load_inbounds(bcx, dict, [0, i as int])];
121152
}
122153
// the rest of the parameters
123-
let i = 3u, params_total = llvm::llvm::LLVMCountParamTypes(llfn_ty);
154+
let i = 3u, params_total = llvm::LLVMCountParamTypes(llfn_ty);
124155
while i < params_total {
125156
args += [LLVMGetParam(llfn, i)];
126157
i += 1u;
@@ -131,9 +162,88 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
131162
ret llfn;
132163
}
133164

134-
// FIXME[impl] cache these on the function level somehow
165+
fn dict_is_static(tcx: ty::ctxt, origin: typeck::dict_origin) -> bool {
166+
alt origin {
167+
typeck::dict_static(_, ts, origs) {
168+
vec::all(ts, {|t| !ty::type_contains_params(tcx, t)}) &&
169+
vec::all(*origs, {|o| dict_is_static(tcx, o)})
170+
}
171+
typeck::dict_param(_, _) { false }
172+
}
173+
}
174+
135175
fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
136-
let bcx = bcx, ccx = bcx_ccx(bcx);
176+
let ccx = bcx_ccx(bcx);
177+
alt origin {
178+
typeck::dict_static(impl_did, tys, sub_origins) {
179+
if dict_is_static(ccx.tcx, origin) {
180+
ret rslt(bcx, get_static_dict(bcx, origin));
181+
}
182+
let {bcx, ptrs} = get_dict_ptrs(bcx, origin);
183+
let pty = T_ptr(T_i8()), dict_ty = T_array(pty, vec::len(ptrs));
184+
let dict = alloca(bcx, dict_ty), i = 0;
185+
for ptr in ptrs {
186+
Store(bcx, PointerCast(bcx, ptr, pty), GEPi(bcx, dict, [0, i]));
187+
i += 1;
188+
}
189+
dict = Call(bcx, ccx.upcalls.intern_dict,
190+
[C_uint(ccx, vec::len(ptrs)),
191+
PointerCast(bcx, dict, T_ptr(T_dict()))]);
192+
rslt(bcx, dict)
193+
}
194+
typeck::dict_param(n_param, n_bound) {
195+
rslt(bcx, option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound])
196+
}
197+
}
198+
}
199+
200+
fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
201+
alt origin {
202+
typeck::dict_static(did, ts, origs) {
203+
let d_params = [], orig = 0u;
204+
if vec::len(ts) == 0u { ret @{impl_def: did, params: d_params}; }
205+
let impl_params = ty::lookup_item_type(tcx, did).bounds;
206+
vec::iter2(ts, *impl_params) {|t, bounds|
207+
d_params += [dict_param_ty(t)];
208+
for bound in *bounds {
209+
alt bound {
210+
ty::bound_iface(_) {
211+
d_params += [dict_param_dict(dict_id(tcx, origs[orig]))];
212+
orig += 1u;
213+
}
214+
}
215+
}
216+
}
217+
@{impl_def: did, params: d_params}
218+
}
219+
}
220+
}
221+
222+
fn get_static_dict(bcx: @block_ctxt, origin: typeck::dict_origin)
223+
-> ValueRef {
224+
let ccx = bcx_ccx(bcx);
225+
let id = dict_id(ccx.tcx, origin);
226+
alt ccx.dicts.find(id) {
227+
some(d) { ret d; }
228+
none. {}
229+
}
230+
let ptrs = C_struct(get_dict_ptrs(bcx, origin).ptrs);
231+
let name = ccx.names.next("dict");
232+
let gvar = str::as_buf(name, {|buf|
233+
llvm::LLVMAddGlobal(ccx.llmod, val_ty(ptrs), buf)
234+
});
235+
llvm::LLVMSetGlobalConstant(gvar, lib::llvm::True);
236+
llvm::LLVMSetInitializer(gvar, ptrs);
237+
llvm::LLVMSetLinkage(gvar,
238+
lib::llvm::LLVMInternalLinkage as llvm::Linkage);
239+
let cast = llvm::LLVMConstPointerCast(gvar, T_ptr(T_dict()));
240+
ccx.dicts.insert(id, cast);
241+
cast
242+
}
243+
244+
fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
245+
-> {bcx: @block_ctxt, ptrs: [ValueRef]} {
246+
let ccx = bcx_ccx(bcx);
137247
alt origin {
138248
typeck::dict_static(impl_did, tys, sub_origins) {
139249
let vtable = if impl_did.crate == ast::local_crate {
@@ -143,9 +253,9 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
143253
get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
144254
};
145255
let impl_params = ty::lookup_item_type(ccx.tcx, impl_did).bounds;
146-
let ptrs = [vtable], i = 0u, origin = 0u, ti = none;
147-
for param in *impl_params {
148-
let rslt = get_tydesc(bcx, tys[i], false, tps_normal, ti).result;
256+
let ptrs = [vtable], origin = 0u, ti = none, bcx = bcx;
257+
vec::iter2(*impl_params, tys) {|param, ty|
258+
let rslt = get_tydesc(bcx, ty, true, tps_normal, ti).result;
149259
ptrs += [rslt.val];
150260
bcx = rslt.bcx;
151261
for bound in *param {
@@ -159,18 +269,8 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
159269
_ {}
160270
}
161271
}
162-
i += 1u;
163272
}
164-
let pty = T_ptr(T_i8()), dict_ty = T_array(pty, vec::len(ptrs));
165-
let dict = alloca(bcx, dict_ty), i = 0;
166-
for ptr in ptrs {
167-
Store(bcx, PointerCast(bcx, ptr, pty), GEPi(bcx, dict, [0, i]));
168-
i += 1;
169-
}
170-
rslt(bcx, PointerCast(bcx, dict, T_ptr(T_dict())))
171-
}
172-
typeck::dict_param(n_param, n_bound) {
173-
rslt(bcx, option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound])
273+
{bcx: bcx, ptrs: ptrs}
174274
}
175275
}
176-
}
276+
}

0 commit comments

Comments
 (0)