Skip to content

Commit 6182579

Browse files
committed
---
yaml --- r: 7198 b: refs/heads/master c: 56fe4c2 h: refs/heads/master v: v3
1 parent e8a33c9 commit 6182579

File tree

6 files changed

+161
-78
lines changed

6 files changed

+161
-78
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: ca72a8300b2781b8267e0afffcc5a7692c25d366
2+
refs/heads/master: 56fe4c2681f7ef467d8b3405279acbcfc6b0ebcf

trunk/src/comp/middle/trans.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5443,24 +5443,10 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
54435443
}
54445444
ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) {
54455445
let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id));
5446-
let ty = ty::lookup_item_type(ccx.tcx, i_did).ty;
5447-
let new_pt = pt + [it.ident + int::str(it.id), "wrap"];
5448-
let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
5449-
let tbl = C_struct(vec::map(*ty::iface_methods(ccx.tcx, i_did), {|im|
5450-
alt vec::find(ms, {|m| m.ident == im.ident}) {
5451-
some(m) {
5452-
trans_impl::trans_wrapper(ccx, new_pt, extra_tps, m)
5453-
}
5454-
}
5455-
}));
5456-
let s = mangle_exported_name(ccx, new_pt + ["!vtable"], ty);
5457-
let vt_gvar = str::as_buf(s, {|buf|
5458-
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
5459-
});
5460-
llvm::LLVMSetInitializer(vt_gvar, tbl);
5461-
llvm::LLVMSetGlobalConstant(vt_gvar, True);
5462-
ccx.item_ids.insert(it.id, vt_gvar);
5463-
ccx.item_symbols.insert(it.id, s);
5446+
trans_impl::trans_impl_vtable(ccx, pt, i_did, ms, tps, it);
5447+
}
5448+
ast::item_iface(_, _) {
5449+
trans_impl::trans_iface_vtable(ccx, pt, it);
54645450
}
54655451
_ { }
54665452
}

trunk/src/comp/middle/trans_common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -916,9 +916,9 @@ tag dict_param {
916916
dict_param_dict(dict_id);
917917
dict_param_ty(ty::t);
918918
}
919-
type dict_id = @{impl_def: ast::def_id, params: [dict_param]};
919+
type dict_id = @{def: ast::def_id, params: [dict_param]};
920920
fn hash_dict_id(&&dp: dict_id) -> uint {
921-
let h = syntax::ast_util::hash_def_id(dp.impl_def);
921+
let h = syntax::ast_util::hash_def_id(dp.def);
922922
for param in dp.params {
923923
h = h << 2u;
924924
alt param {

trunk/src/comp/middle/trans_impl.rs

Lines changed: 135 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,23 @@ fn trans_static_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
6868
{env: obj_env(val) with lval_static_fn(bcx, did, e.id)}
6969
}
7070

71+
fn wrapper_fn_ty(ccx: @crate_ctxt, dict_ty: TypeRef, m: ty::method)
72+
-> {ty: ty::t, llty: TypeRef} {
73+
let fty = ty::mk_fn(ccx.tcx, m.fty);
74+
let bare_fn_ty = type_of_fn_from_ty(ccx, ast_util::dummy_sp(),
75+
fty, *m.tps);
76+
let {inputs, output} = llfn_arg_tys(bare_fn_ty);
77+
{ty: fty, llty: T_fn([dict_ty] + inputs, output)}
78+
}
79+
7180
fn trans_vtable_callee(bcx: @block_ctxt, self: ValueRef, dict: ValueRef,
7281
fld_expr: @ast::expr, iface_id: ast::def_id,
7382
n_method: uint) -> lval_maybe_callee {
7483
let bcx = bcx, ccx = bcx_ccx(bcx), tcx = ccx.tcx;
7584
let method = ty::iface_methods(tcx, iface_id)[n_method];
76-
let fty = ty::mk_fn(tcx, method.fty);
77-
let bare_fn_ty = type_of_fn_from_ty(ccx, ast_util::dummy_sp(),
78-
fty, *method.tps);
79-
let {inputs: bare_inputs, output} = llfn_arg_tys(bare_fn_ty);
80-
let fn_ty = T_fn([val_ty(dict)] + bare_inputs, output);
85+
let {ty: fty, llty: llfty} = wrapper_fn_ty(ccx, val_ty(dict), method);
8186
let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
82-
T_ptr(T_array(T_ptr(fn_ty), n_method + 1u)));
87+
T_ptr(T_array(T_ptr(llfty), n_method + 1u)));
8388
let mptr = Load(bcx, GEPi(bcx, vtable, [0, n_method as int]));
8489
let generic = none;
8590
if vec::len(*method.tps) > 0u || ty::type_contains_params(tcx, fty) {
@@ -138,9 +143,36 @@ fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} {
138143
{inputs: args, output: out_ty}
139144
}
140145

141-
fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
142-
extra_tps: [ty::param_bounds], m: @ast::method) -> ValueRef {
143-
let real_fn = ccx.item_ids.get(m.id);
146+
fn trans_vtable(ccx: @crate_ctxt, id: ast::node_id, name: str,
147+
ptrs: [ValueRef]) {
148+
let tbl = C_struct(ptrs);
149+
let vt_gvar = str::as_buf(name, {|buf|
150+
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
151+
});
152+
llvm::LLVMSetInitializer(vt_gvar, tbl);
153+
llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
154+
ccx.item_ids.insert(id, vt_gvar);
155+
ccx.item_symbols.insert(id, name);
156+
}
157+
158+
fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident], llfty: TypeRef,
159+
fill: block(ValueRef, @block_ctxt) -> @block_ctxt)
160+
-> ValueRef {
161+
let lcx = @{path: pt, module_path: [],
162+
obj_typarams: [], obj_fields: [], ccx: ccx};
163+
let name = link::mangle_internal_name_by_path(ccx, pt);
164+
let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfty);
165+
let fcx = new_fn_ctxt(lcx, ast_util::dummy_sp(), llfn);
166+
let bcx = new_top_block_ctxt(fcx), lltop = bcx.llbb;
167+
let bcx = fill(llfn, bcx);
168+
build_return(bcx);
169+
finish_fn(fcx, lltop);
170+
ret llfn;
171+
}
172+
173+
fn trans_impl_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
174+
extra_tps: [ty::param_bounds], real_fn: ValueRef)
175+
-> ValueRef {
144176
let {inputs: real_args, output: real_ret} =
145177
llfn_arg_tys(llvm::LLVMGetElementType(val_ty(real_fn)));
146178
let extra_ptrs = [];
@@ -159,32 +191,80 @@ fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
159191
let wrap_args = [T_ptr(T_dict())] + vec::slice(real_args, 0u, 2u) +
160192
vec::slice(real_args, 2u + vec::len(extra_ptrs), vec::len(real_args));
161193
let llfn_ty = T_fn(wrap_args, real_ret);
194+
trans_wrapper(ccx, pt, llfn_ty, {|llfn, bcx|
195+
let dict = PointerCast(bcx, LLVMGetParam(llfn, 0u), env_ty);
196+
// retptr, self
197+
let args = [LLVMGetParam(llfn, 1u), LLVMGetParam(llfn, 2u)], i = 0u;
198+
// saved tydescs/dicts
199+
while i < n_extra_ptrs {
200+
i += 1u;
201+
args += [load_inbounds(bcx, dict, [0, i as int])];
202+
}
203+
// the rest of the parameters
204+
let i = 3u, params_total = llvm::LLVMCountParamTypes(llfn_ty);
205+
while i < params_total {
206+
args += [LLVMGetParam(llfn, i)];
207+
i += 1u;
208+
}
209+
Call(bcx, real_fn, args);
210+
bcx
211+
})
212+
}
162213

163-
let lcx = @{path: pt + ["wrapper", m.ident], module_path: [],
164-
obj_typarams: [], obj_fields: [], ccx: ccx};
165-
let name = link::mangle_internal_name_by_path_and_seq(ccx, pt, m.ident);
166-
let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfn_ty);
167-
let fcx = new_fn_ctxt(lcx, ast_util::dummy_sp(), llfn);
168-
let bcx = new_top_block_ctxt(fcx), lltop = bcx.llbb;
214+
fn trans_impl_vtable(ccx: @crate_ctxt, pt: [ast::ident],
215+
iface_id: ast::def_id, ms: [@ast::method],
216+
tps: [ast::ty_param], it: @ast::item) {
217+
let new_pt = pt + [it.ident + int::str(it.id), "wrap"];
218+
let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
219+
let ptrs = vec::map(*ty::iface_methods(ccx.tcx, iface_id), {|im|
220+
alt vec::find(ms, {|m| m.ident == im.ident}) {
221+
some(m) {
222+
let target = ccx.item_ids.get(m.id);
223+
trans_impl_wrapper(ccx, new_pt + [m.ident], extra_tps, target)
224+
}
225+
}
226+
});
227+
let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
228+
trans_vtable(ccx, it.id, s, ptrs);
229+
}
169230

170-
let dict = PointerCast(bcx, LLVMGetParam(llfn, 0u), env_ty);
171-
// retptr, self
172-
let args = [LLVMGetParam(llfn, 1u), LLVMGetParam(llfn, 2u)], i = 0u;
173-
// saved tydescs/dicts
174-
while i < n_extra_ptrs {
175-
i += 1u;
176-
args += [load_inbounds(bcx, dict, [0, i as int])];
177-
}
178-
// the rest of the parameters
179-
let i = 3u, params_total = llvm::LLVMCountParamTypes(llfn_ty);
180-
while i < params_total {
181-
args += [LLVMGetParam(llfn, i)];
231+
fn trans_iface_wrapper(ccx: @crate_ctxt, pt: [ast::ident], m: ty::method,
232+
n: uint) -> ValueRef {
233+
let {llty: llfty, _} = wrapper_fn_ty(ccx, T_ptr(T_i8()), m);
234+
trans_wrapper(ccx, pt, llfty, {|llfn, bcx|
235+
let self = Load(bcx, PointerCast(bcx, LLVMGetParam(llfn, 2u),
236+
T_ptr(T_opaque_iface_ptr(ccx))));
237+
let boxed = GEPi(bcx, self, [0, abi::box_rc_field_body]);
238+
let dict = Load(bcx, PointerCast(bcx, GEPi(bcx, boxed, [0, 1]),
239+
T_ptr(T_ptr(T_dict()))));
240+
let vtable = PointerCast(bcx, Load(bcx, GEPi(bcx, dict, [0, 0])),
241+
T_ptr(T_array(T_ptr(llfty), n + 1u)));
242+
let mptr = Load(bcx, GEPi(bcx, vtable, [0, n as int]));
243+
// FIXME[impl] This doesn't account for more-than-ptr-sized alignment
244+
let inner_self = GEPi(bcx, boxed, [0, 2]);
245+
let args = [PointerCast(bcx, dict, T_ptr(T_i8())),
246+
LLVMGetParam(llfn, 1u),
247+
PointerCast(bcx, inner_self, T_opaque_cbox_ptr(ccx))];
248+
let i = 3u, total = llvm::LLVMCountParamTypes(llfty);
249+
while i < total {
250+
args += [LLVMGetParam(llfn, i)];
251+
i += 1u;
252+
}
253+
Call(bcx, mptr, args);
254+
bcx
255+
})
256+
}
257+
258+
fn trans_iface_vtable(ccx: @crate_ctxt, pt: [ast::ident], it: @ast::item) {
259+
let new_pt = pt + [it.ident + int::str(it.id)];
260+
let i_did = ast_util::local_def(it.id), i = 0u;
261+
let ptrs = vec::map(*ty::iface_methods(ccx.tcx, i_did), {|m|
262+
let w = trans_iface_wrapper(ccx, new_pt + [m.ident], m, i);
182263
i += 1u;
183-
}
184-
Call(bcx, ccx.item_ids.get(m.id), args);
185-
build_return(bcx);
186-
finish_fn(fcx, lltop);
187-
ret llfn;
264+
w
265+
});
266+
let s = link::mangle_internal_name_by_path(ccx, new_pt + ["!vtable"]);
267+
trans_vtable(ccx, it.id, s, ptrs);
188268
}
189269

190270
fn dict_is_static(tcx: ty::ctxt, origin: typeck::dict_origin) -> bool {
@@ -193,7 +273,8 @@ fn dict_is_static(tcx: ty::ctxt, origin: typeck::dict_origin) -> bool {
193273
vec::all(ts, {|t| !ty::type_contains_params(tcx, t)}) &&
194274
vec::all(*origs, {|o| dict_is_static(tcx, o)})
195275
}
196-
typeck::dict_param(_, _) { false }
276+
typeck::dict_iface(_) { true }
277+
_ { false }
197278
}
198279
}
199280

@@ -219,14 +300,17 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
219300
typeck::dict_param(n_param, n_bound) {
220301
rslt(bcx, option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound])
221302
}
303+
typeck::dict_iface(did) {
304+
ret rslt(bcx, get_static_dict(bcx, origin));
305+
}
222306
}
223307
}
224308

225309
fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
226310
alt origin {
227311
typeck::dict_static(did, ts, origs) {
228312
let d_params = [], orig = 0u;
229-
if vec::len(ts) == 0u { ret @{impl_def: did, params: d_params}; }
313+
if vec::len(ts) == 0u { ret @{def: did, params: d_params}; }
230314
let impl_params = ty::lookup_item_type(tcx, did).bounds;
231315
vec::iter2(ts, *impl_params) {|t, bounds|
232316
d_params += [dict_param_ty(t)];
@@ -239,7 +323,10 @@ fn dict_id(tcx: ty::ctxt, origin: typeck::dict_origin) -> dict_id {
239323
}
240324
}
241325
}
242-
@{impl_def: did, params: d_params}
326+
@{def: did, params: d_params}
327+
}
328+
typeck::dict_iface(did) {
329+
@{def: did, params: []}
243330
}
244331
}
245332
}
@@ -269,16 +356,19 @@ fn get_static_dict(bcx: @block_ctxt, origin: typeck::dict_origin)
269356
fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
270357
-> {bcx: @block_ctxt, ptrs: [ValueRef]} {
271358
let ccx = bcx_ccx(bcx);
272-
alt origin {
273-
typeck::dict_static(impl_did, tys, sub_origins) {
274-
let vtable = if impl_did.crate == ast::local_crate {
275-
ccx.item_ids.get(impl_did.node)
359+
fn get_vtable(ccx: @crate_ctxt, did: ast::def_id) -> ValueRef {
360+
if did.crate == ast::local_crate {
361+
ccx.item_ids.get(did.node)
276362
} else {
277-
let name = csearch::get_symbol(ccx.sess.get_cstore(), impl_did);
363+
let name = csearch::get_symbol(ccx.sess.get_cstore(), did);
278364
get_extern_const(ccx.externs, ccx.llmod, name, T_ptr(T_i8()))
279-
};
365+
}
366+
}
367+
alt origin {
368+
typeck::dict_static(impl_did, tys, sub_origins) {
280369
let impl_params = ty::lookup_item_type(ccx.tcx, impl_did).bounds;
281-
let ptrs = [vtable], origin = 0u, ti = none, bcx = bcx;
370+
let ptrs = [get_vtable(ccx, impl_did)];
371+
let origin = 0u, ti = none, bcx = bcx;
282372
vec::iter2(*impl_params, tys) {|param, ty|
283373
let rslt = get_tydesc(bcx, ty, true, tps_normal, ti).result;
284374
ptrs += [rslt.val];
@@ -297,6 +387,9 @@ fn get_dict_ptrs(bcx: @block_ctxt, origin: typeck::dict_origin)
297387
}
298388
{bcx: bcx, ptrs: ptrs}
299389
}
390+
typeck::dict_iface(did) {
391+
{bcx: bcx, ptrs: [get_vtable(ccx, did)]}
392+
}
300393
}
301394
}
302395

trunk/src/comp/middle/typeck.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import syntax::print::pprust::*;
2020

2121
export check_crate;
2222
export method_map, method_origin, method_static, method_param, method_iface;
23-
export dict_map, dict_res, dict_origin, dict_static, dict_param;
23+
export dict_map, dict_res, dict_origin, dict_static, dict_param, dict_iface;
2424

2525
tag method_origin {
2626
method_static(ast::def_id);
@@ -36,6 +36,7 @@ tag dict_origin {
3636
dict_static(ast::def_id, [ty::t], dict_res);
3737
// Param number, bound number
3838
dict_param(uint, uint);
39+
dict_iface(ast::def_id);
3940
}
4041
type dict_map = hashmap<ast::node_id, dict_res>;
4142

@@ -2197,24 +2198,20 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
21972198
let t_1 = ast_ty_to_ty_crate(fcx.ccx, t);
21982199
let t_e = ty::expr_ty(tcx, e);
21992200

2200-
if ty::type_is_nil(tcx, t_e) {
2201-
tcx.sess.span_err(expr.span,
2202-
"cast from nil: " +
2201+
alt ty::struct(tcx, t_1) {
2202+
// This will be looked up later on
2203+
ty::ty_iface(_, _) {}
2204+
_ {
2205+
if ty::type_is_nil(tcx, t_e) {
2206+
tcx.sess.span_err(expr.span, "cast from nil: " +
22032207
ty_to_str(tcx, t_e) + " as " +
22042208
ty_to_str(tcx, t_1));
2205-
}
2206-
2207-
if ty::type_is_nil(tcx, t_1) {
2208-
tcx.sess.span_err(expr.span,
2209-
"cast to nil: " +
2209+
} else if ty::type_is_nil(tcx, t_1) {
2210+
tcx.sess.span_err(expr.span, "cast to nil: " +
22102211
ty_to_str(tcx, t_e) + " as " +
22112212
ty_to_str(tcx, t_1));
2212-
}
2213+
}
22132214

2214-
alt ty::struct(tcx, t_1) {
2215-
// This will be looked up later on
2216-
ty::ty_iface(_, _) {}
2217-
_ {
22182215
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
22192216
if type_is_c_like_enum(fcx,expr.span,t_e) && t_1_is_scalar {
22202217
/* this case is allowed */
@@ -2942,6 +2939,9 @@ mod dict {
29422939
}
29432940
}
29442941
}
2942+
ty::ty_iface(did, _) {
2943+
ret dict_iface(did);
2944+
}
29452945
_ {
29462946
let found = none;
29472947
std::list::iter(isc) {|impls|

trunk/src/test/run-pass/iface-cast.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,17 @@ impl of to_str for Tree {
3333
}
3434
}
3535

36+
fn foo<T: to_str>(x: T) -> str { x.to_str() }
37+
3638
fn main() {
3739
let t1 = Tree(@{mutable left: none,
3840
mutable right: none,
3941
val: 1 as to_str });
4042
let t2 = Tree(@{mutable left: some(t1),
4143
mutable right: some(t1),
4244
val: 2 as to_str });
43-
assert t2.to_str() == "[2, some([1, none, none]), some([1, none, none])]";
45+
let expected = "[2, some([1, none, none]), some([1, none, none])]";
46+
assert t2.to_str() == expected;
47+
assert foo(t2 as to_str) == expected;
4448
t1.left = some(t2); // create cycle
4549
}

0 commit comments

Comments
 (0)