Skip to content

Commit 1741ef7

Browse files
committed
Write out vtables for interface implementations
Issue #1227
1 parent 371b61a commit 1741ef7

File tree

3 files changed

+78
-13
lines changed

3 files changed

+78
-13
lines changed

src/comp/middle/trans.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,12 @@ fn type_of_explicit_args(cx: @crate_ctxt, sp: span, inputs: [ty::arg]) ->
8080
// - create_llargs_for_fn_args.
8181
// - new_fn_ctxt
8282
// - trans_args
83-
fn type_of_fn(cx: @crate_ctxt, sp: span,
84-
is_method: bool, inputs: [ty::arg],
85-
output: ty::t, params: [ty::param_bounds])
86-
: non_ty_var(cx, output) -> TypeRef {
83+
fn type_of_fn(cx: @crate_ctxt, sp: span, is_method: bool, inputs: [ty::arg],
84+
output: ty::t, params: [ty::param_bounds]) -> TypeRef {
8785
let atys: [TypeRef] = [];
8886

8987
// Arg 0: Output pointer.
88+
check non_ty_var(cx, output);
9089
let out_ty = T_ptr(type_of_inner(cx, sp, output));
9190
atys += [out_ty];
9291

@@ -117,7 +116,6 @@ fn type_of_fn_from_ty(cx: @crate_ctxt, sp: span, fty: ty::t,
117116
// by returns_non_ty_var(t). Make that a postcondition
118117
// (see Issue #586)
119118
let ret_ty = ty::ty_fn_ret(cx.tcx, fty);
120-
check non_ty_var(cx, ret_ty);
121119
ret type_of_fn(cx, sp, false, ty::ty_fn_args(cx.tcx, fty),
122120
ret_ty, param_bounds);
123121
}
@@ -2771,8 +2769,6 @@ fn trans_object_field_inner(bcx: @block_ctxt, o: ValueRef,
27712769
let fn_ty: ty::t = ty::mk_fn(tcx, mths[ix].fty);
27722770
let ret_ty = ty::ty_fn_ret(tcx, fn_ty);
27732771
// FIXME: constrain ty_obj?
2774-
check non_ty_var(ccx, ret_ty);
2775-
27762772
let ll_fn_ty = type_of_fn(ccx, bcx.sp, true,
27772773
ty::ty_fn_args(tcx, fn_ty), ret_ty, []);
27782774
v = Load(bcx, PointerCast(bcx, v, T_ptr(T_ptr(ll_fn_ty))));
@@ -5123,8 +5119,6 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef,
51235119
ty: ty::mk_vec(ccx.tcx, {ty: unit_ty, mut: ast::imm})};
51245120
// FIXME: mk_nil should have a postcondition
51255121
let nt = ty::mk_nil(ccx.tcx);
5126-
check non_ty_var(ccx, nt);
5127-
51285122
let llfty = type_of_fn(ccx, sp, false, [vecarg_ty], nt, []);
51295123
let llfdecl = decl_fn(ccx.llmod, "_rust_main",
51305124
lib::llvm::LLVMCCallConv, llfty);
@@ -5223,7 +5217,6 @@ fn native_fn_wrapper_type(cx: @crate_ctxt, sp: span,
52235217
x: ty::t) -> TypeRef {
52245218
alt ty::struct(cx.tcx, x) {
52255219
ty::ty_native_fn(args, out) {
5226-
check non_ty_var(cx, out);
52275220
ret type_of_fn(cx, sp, false, args, out, param_bounds);
52285221
}
52295222
}
@@ -5377,7 +5370,7 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
53775370
ast::item_tag(variants, _) {
53785371
let i = 0u;
53795372
for variant in variants {
5380-
let p = new_pt + [it.ident, variant.node.name, "discrim"];
5373+
let p = new_pt + [variant.node.name, "discrim"];
53815374
let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx));
53825375
let discrim_gvar = str::as_buf(s, {|buf|
53835376
llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf)
@@ -5390,6 +5383,28 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str],
53905383
i += 1u;
53915384
}
53925385
}
5386+
ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) {
5387+
let i_did = ast_util::def_id_of_def(ccx.tcx.def_map.get(id));
5388+
let ty = ty::lookup_item_type(ccx.tcx, i_did).ty;
5389+
// FIXME[impl] use the same name as used in collect_items, for
5390+
// slightly more consistent symbol names?
5391+
let new_pt = pt + [ccx.names.next(it.ident)];
5392+
let extra_tps = vec::map(tps, {|p| param_bounds(ccx, p)});
5393+
let tbl = C_struct(vec::map(*ty::iface_methods(ccx.tcx, i_did), {|im|
5394+
alt vec::find(ms, {|m| m.ident == im.ident}) {
5395+
some(m) {
5396+
trans_impl::trans_wrapper(ccx, new_pt, extra_tps, m)
5397+
}
5398+
}
5399+
}));
5400+
let s = mangle_exported_name(ccx, new_pt + ["!vtable"], ty);
5401+
let vt_gvar = str::as_buf(s, {|buf|
5402+
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
5403+
});
5404+
llvm::LLVMSetInitializer(vt_gvar, tbl);
5405+
llvm::LLVMSetGlobalConstant(vt_gvar, True);
5406+
ccx.item_ids.insert(it.id, vt_gvar);
5407+
}
53935408
_ { }
53945409
}
53955410
}

src/comp/middle/trans_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,7 @@ fn ty_str(tn: type_names, t: TypeRef) -> str {
405405
ret lib::llvm::type_to_str(tn, t);
406406
}
407407

408-
fn val_ty(v: ValueRef) -> TypeRef { ret llvm::LLVMTypeOf(v); }
408+
fn val_ty(&&v: ValueRef) -> TypeRef { ret llvm::LLVMTypeOf(v); }
409409

410410
fn val_str(tn: type_names, v: ValueRef) -> str { ret ty_str(tn, val_ty(v)); }
411411

src/comp/middle/trans_impl.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import trans::*;
22
import trans_common::*;
33
import trans_build::*;
44
import option::{some, none};
5-
import syntax::ast;
5+
import syntax::{ast, ast_util};
6+
import back::link;
67
import lib::llvm;
8+
import llvm::llvm::{ValueRef, TypeRef, LLVMGetParam};
79

810
fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
911
id: ast::node_id, tps: [ast::ty_param],
@@ -19,3 +21,51 @@ fn trans_impl(cx: @local_ctxt, name: ast::ident, methods: [@ast::method],
1921
}
2022
}
2123
}
24+
25+
fn llfn_arg_tys(ft: TypeRef) -> {inputs: [TypeRef], output: TypeRef} {
26+
let out_ty = llvm::llvm::LLVMGetReturnType(ft);
27+
let n_args = llvm::llvm::LLVMCountParamTypes(ft);
28+
let args = vec::init_elt(0 as TypeRef, n_args);
29+
unsafe { llvm::llvm::LLVMGetParamTypes(ft, vec::to_ptr(args)); }
30+
{inputs: args, output: out_ty}
31+
}
32+
33+
fn trans_wrapper(ccx: @crate_ctxt, pt: [ast::ident],
34+
extra_tps: [ty::param_bounds], m: @ast::method) -> ValueRef {
35+
let real_fn = ccx.item_ids.get(m.id);
36+
let {inputs: real_args, output: real_ret} =
37+
llfn_arg_tys(llvm::llvm::LLVMGetElementType(val_ty(real_fn)));
38+
let env_ty = T_ptr(T_struct([T_ptr(T_i8())] +
39+
vec::map(extra_tps,
40+
{|_p| T_ptr(ccx.tydesc_type)})));
41+
// FIXME[impl] filter and pass along dicts for bounds
42+
let wrap_args = [env_ty] + vec::slice(real_args, 0u, 2u) +
43+
vec::slice(real_args, 2u + vec::len(extra_tps), vec::len(real_args));
44+
let llfn_ty = T_fn(wrap_args, real_ret);
45+
46+
let lcx = @{path: pt + ["wrapper", m.ident], module_path: [],
47+
obj_typarams: [], obj_fields: [], ccx: ccx};
48+
let name = link::mangle_internal_name_by_path_and_seq(ccx, pt, m.ident);
49+
let llfn = decl_internal_cdecl_fn(ccx.llmod, name, llfn_ty);
50+
let fcx = new_fn_ctxt(lcx, ast_util::dummy_sp(), llfn);
51+
let bcx = new_top_block_ctxt(fcx), lltop = bcx.llbb;
52+
53+
let dict = LLVMGetParam(llfn, 0u);
54+
// retptr, self
55+
let args = [LLVMGetParam(llfn, 1u), LLVMGetParam(llfn, 2u)], i = 1;
56+
// saved tydescs/dicts
57+
for extra_tp in extra_tps {
58+
args += [load_inbounds(bcx, dict, [0, i])];
59+
i += 1;
60+
}
61+
// the rest of the parameters
62+
let i = 3u, params_total = llvm::llvm::LLVMCountParamTypes(llfn_ty);
63+
while i < params_total {
64+
args += [LLVMGetParam(llfn, i)];
65+
i += 1u;
66+
}
67+
Call(bcx, ccx.item_ids.get(m.id), args);
68+
finish_fn(fcx, lltop);
69+
ret llfn;
70+
}
71+

0 commit comments

Comments
 (0)