Main part of the type system rewrite:

Change the type of all objects to be { {}*, {}* }.
This commit is contained in:
Rafael Ávila de Espíndola 2011-07-14 00:34:45 -04:00
parent 8c94d8fd54
commit 40f617390d

View File

@ -159,7 +159,6 @@
// Types used for llself.
type val_self_pair = rec(ValueRef v, ty::t t);
type ty_self_pair = tup(TypeRef, ty::t);
// Function context. Every LLVM function we create will have one of these.
@ -477,6 +476,13 @@ fn T_struct(&TypeRef[] elts) -> TypeRef {
fn T_opaque() -> TypeRef { ret llvm::LLVMOpaqueType(); }
fn T_empty_struct() -> TypeRef { ret T_struct(~[]); }
fn T_rust_object() -> TypeRef {
auto e = T_ptr(T_empty_struct());
ret T_struct(~[e, e]);
}
fn T_task() -> TypeRef {
auto t =
T_struct(~[T_int(), // Refcount
@ -511,8 +517,8 @@ fn T_glue_fn(&crate_ctxt cx) -> TypeRef {
ret t;
}
fn T_dtor(&@crate_ctxt ccx, &span sp, TypeRef llself_ty) -> TypeRef {
ret type_of_fn_full(ccx, sp, ast::proto_fn, some[TypeRef](llself_ty),
fn T_dtor(&@crate_ctxt ccx, &span sp) -> TypeRef {
ret type_of_fn_full(ccx, sp, ast::proto_fn, true,
~[], ty::mk_nil(ccx.tcx), 0u);
}
@ -751,7 +757,7 @@ fn type_of_explicit_args(&@crate_ctxt cx, &span sp, &ty::arg[] inputs)
// - new_fn_ctxt
// - trans_args
fn type_of_fn_full(&@crate_ctxt cx, &span sp, ast::proto proto,
&option::t[TypeRef] obj_self, &ty::arg[] inputs,
bool is_method, &ty::arg[] inputs,
&ty::t output, uint ty_param_count) -> TypeRef {
let TypeRef[] atys = ~[];
@ -766,13 +772,14 @@ fn type_of_fn_full(&@crate_ctxt cx, &span sp, ast::proto proto,
atys += ~[T_taskptr(*cx)];
// Arg 2: Env (closure-bindings / self-obj)
alt (obj_self) {
case (some(?t)) { assert (t as int != 0); atys += ~[t]; }
case (_) { atys += ~[T_opaque_closure_ptr(*cx)]; }
if (is_method) {
atys += ~[T_rust_object()];
} else {
atys += ~[T_opaque_closure_ptr(*cx)];
}
// Args >3: ty params, if not acquired via capture...
if (obj_self == none[TypeRef]) {
if (!is_method) {
auto i = 0u;
while (i < ty_param_count) {
atys += ~[T_ptr(cx.tydesc_type)];
@ -785,7 +792,7 @@ fn type_of_fn_full(&@crate_ctxt cx, &span sp, ast::proto proto,
// argument.
atys +=
~[T_fn_pair(*cx,
type_of_fn_full(cx, sp, ast::proto_fn, none[TypeRef],
type_of_fn_full(cx, sp, ast::proto_fn, false,
~[rec(mode=ty::mo_alias(false),
ty=output)], ty::mk_nil(cx.tcx),
0u))];
@ -799,7 +806,7 @@ fn type_of_fn_full(&@crate_ctxt cx, &span sp, ast::proto proto,
fn type_of_fn(&@crate_ctxt cx, &span sp, ast::proto proto,
&ty::arg[] inputs, &ty::t output, uint ty_param_count) ->
TypeRef {
ret type_of_fn_full(cx, sp, proto, none[TypeRef], inputs, output,
ret type_of_fn_full(cx, sp, proto, false, inputs, output,
ty_param_count);
}
@ -894,22 +901,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
llty = T_fn_pair(*cx, nft);
}
case (ty::ty_obj(?meths)) {
auto th = mk_type_handle();
auto self_ty = llvm::LLVMResolveTypeHandle(th.llth);
let TypeRef[] mtys = ~[T_ptr(T_i8())];
for (ty::method m in meths) {
let TypeRef mty =
type_of_fn_full(cx, sp, m.proto, some[TypeRef](self_ty),
m.inputs, m.output, 0u);
mtys += ~[T_ptr(mty)];
}
let TypeRef vtbl = T_struct(mtys);
let TypeRef pair =
T_struct(~[T_ptr(vtbl), T_opaque_obj_ptr(*cx)]);
auto abs_pair = llvm::LLVMResolveTypeHandle(th.llth);
llvm::LLVMRefineType(abs_pair, pair);
abs_pair = llvm::LLVMResolveTypeHandle(th.llth);
llty = abs_pair;
llty = T_rust_object();
}
case (ty::ty_res(_, ?sub, ?tps)) {
auto sub1 = ty::substitute_type_params(cx.tcx, tps, sub);
@ -2071,6 +2063,11 @@ fn make_free_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
auto box_cell =
cx.build.GEP(v0, ~[C_int(0), C_int(abi::obj_field_box)]);
auto b = cx.build.Load(box_cell);
auto ccx = cx.fcx.lcx.ccx;
auto llbox_ty = T_opaque_obj_ptr(*ccx);
b = cx.build.PointerCast(b, llbox_ty);
auto body =
cx.build.GEP(b, ~[C_int(0), C_int(abi::box_rc_field_body)]);
auto tydescptr =
@ -2245,11 +2242,14 @@ fn trans_res_drop(@block_ctxt cx, ValueRef rs, &ast::def_id did,
fn decr_refcnt_maybe_free(&@block_ctxt cx, ValueRef box_ptr_alias,
ValueRef full_alias, &ty::t t) -> result {
auto ccx = cx.fcx.lcx.ccx;
auto load_rc_cx = new_sub_block_ctxt(cx, "load rc");
auto rc_adj_cx = new_sub_block_ctxt(cx, "rc--");
auto free_cx = new_sub_block_ctxt(cx, "free");
auto next_cx = new_sub_block_ctxt(cx, "next");
auto box_ptr = cx.build.Load(box_ptr_alias);
auto llbox_ty = T_opaque_obj_ptr(*ccx);
box_ptr = cx.build.PointerCast(box_ptr, llbox_ty);
auto null_test = cx.build.IsNull(box_ptr);
cx.build.CondBr(null_test, next_cx.llbb, load_rc_cx.llbb);
auto rc_ptr =
@ -3102,12 +3102,14 @@ fn call_tydesc_glue(&@block_ctxt cx, ValueRef v, &ty::t t, int field) ->
fn maybe_call_dtor(&@block_ctxt cx, ValueRef v) -> @block_ctxt {
auto vtbl = cx.build.GEP(v, ~[C_int(0), C_int(abi::obj_field_vtbl)]);
vtbl = cx.build.Load(vtbl);
auto vtbl_type = T_ptr(T_array(T_ptr(T_nil()), 1u));
vtbl = cx.build.PointerCast(vtbl, vtbl_type);
auto dtor_ptr = cx.build.GEP(vtbl, ~[C_int(0), C_int(0)]);
dtor_ptr = cx.build.Load(dtor_ptr);
auto self_t = llvm::LLVMGetElementType(val_ty(v));
dtor_ptr =
cx.build.BitCast(dtor_ptr,
T_ptr(T_dtor(cx.fcx.lcx.ccx, cx.sp, self_t)));
T_ptr(T_dtor(cx.fcx.lcx.ccx, cx.sp)));
auto dtor_cx = new_sub_block_ctxt(cx, "dtor");
auto after_cx = new_sub_block_ctxt(cx, "after_dtor");
auto test =
@ -4660,7 +4662,7 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
// pointer along with the foreach-body-fn pointer into a 'normal' fn pair
// and pass it in as a first class fn-arg to the iterator.
auto iter_body_llty =
type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn, none[TypeRef],
type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn, false,
~[rec(mode=ty::mo_alias(false), ty=decl_ty)],
ty::mk_nil(lcx.ccx.tcx), 0u);
let ValueRef lliterbody =
@ -4932,12 +4934,23 @@ fn trans_field(&@block_ctxt cx, &span sp, ValueRef v, &ty::t t0,
~[C_int(0), C_int(abi::obj_field_vtbl)]);
vtbl = r.bcx.build.Load(vtbl);
auto vtbl_type = T_ptr(T_array(T_ptr(T_nil()), ix + 2u));
vtbl = cx.build.PointerCast(vtbl, vtbl_type);
// +1 because slot #0 contains the destructor
auto v = r.bcx.build.GEP(vtbl,
~[C_int(0), C_int(ix + 1u as int)]);
auto lvo = lval_mem(r.bcx, v);
let ty::t fn_ty =
ty::method_ty_to_fn_ty(cx.fcx.lcx.ccx.tcx, methods.(ix));
auto tcx = cx.fcx.lcx.ccx.tcx;
auto ll_fn_ty = type_of_fn_full(cx.fcx.lcx.ccx, sp,
ty::ty_fn_proto(tcx, fn_ty),
true,
ty::ty_fn_args(tcx, fn_ty),
ty::ty_fn_ret(tcx, fn_ty),
0u);
v = r.bcx.build.PointerCast(v, T_ptr(T_ptr(ll_fn_ty)));
auto lvo = lval_mem(r.bcx, v);
ret rec(llobj=some[ValueRef](r.val), method_ty=some[ty::t](fn_ty)
with lvo);
}
@ -6046,7 +6059,7 @@ fn trans_expr_out(&@block_ctxt cx, &@ast::expr e, out_method output) ->
let TypeRef llfnty =
alt (ty::struct(ccx.tcx, node_id_type(ccx, e.id))) {
case (ty::ty_fn(?proto, ?inputs, ?output, _, _)) {
type_of_fn_full(ccx, e.span, proto, none, inputs,
type_of_fn_full(ccx, e.span, proto, false, inputs,
output, 0u)
}
};
@ -6892,7 +6905,6 @@ fn trans_anon_obj(@block_ctxt bcx, &span sp, &ast::anon_obj anon_obj,
// Get the type of the eventual entire anonymous object, possibly with
// extensions. NB: This type includes both inner and outer methods.
auto outer_obj_ty = ty::node_id_to_type(ccx.tcx, id);
auto llouter_obj_ty = type_of(ccx, sp, outer_obj_ty);
// Create a vtable for the anonymous object.
@ -6925,7 +6937,7 @@ fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
// create_vtbl() with no "additional methods". What's happening
// is that, since *all* of the methods are "additional", we can
// get away with acting like none of them are.
vtbl = create_vtbl(bcx.fcx.lcx, sp, llouter_obj_ty, outer_obj_ty,
vtbl = create_vtbl(bcx.fcx.lcx, sp, outer_obj_ty,
wrapper_obj, ty_params, none,
additional_field_tys);
}
@ -6943,19 +6955,15 @@ fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
// one with a matching name and type being added, we'll need to
// create a forwarding slot. And, of course, we need to create a
// normal vtable entry for every method being added.
vtbl = create_vtbl(bcx.fcx.lcx, sp, llouter_obj_ty, outer_obj_ty,
vtbl = create_vtbl(bcx.fcx.lcx, sp, outer_obj_ty,
wrapper_obj, ty_params,
some(with_obj_ty),
additional_field_tys);
}
}
// Allocate the object that we're going to return. It's a two-word pair
// containing a vtable pointer and a body pointer.
auto pair =
alloca(bcx,
T_struct(~[val_ty(vtbl),
T_obj_ptr(*ccx, std::ivec::len(ty_params))]));
// Allocate the object that we're going to return.
auto pair = alloca(bcx, T_rust_object());
// Take care of cleanups.
auto t = node_id_type(ccx, id);
@ -6969,12 +6977,13 @@ fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
auto pair_box =
bcx.build.GEP(pair, ~[C_int(0), C_int(abi::obj_field_box)]);
vtbl = bcx.build.PointerCast(vtbl, T_ptr(T_empty_struct()));
bcx.build.Store(vtbl, pair_vtbl);
// Next we have to take care of the other half of the pair we're
// returning: a boxed (reference-counted) tuple containing a tydesc,
// typarams, fields, and a pointer to our with_obj.
let TypeRef llbox_ty = T_opaque_obj_ptr(*ccx);
let TypeRef llbox_ty = T_ptr(T_empty_struct());
if (std::ivec::len[ast::ty_param](ty_params) == 0u &&
std::ivec::len[ast::anon_obj_field](additional_fields) == 0u &&
@ -7115,7 +7124,7 @@ fn anon_obj_field_to_obj_field(&ast::anon_obj_field f)
}
// Cast the final object to how we want its type to appear.
pair = bcx.build.PointerCast(pair, T_ptr(llouter_obj_ty));
pair = bcx.build.PointerCast(pair, T_ptr(T_rust_object()));
// Return the object we built.
ret rslt(bcx, pair);
@ -7493,7 +7502,7 @@ fn new_fn_ctxt(@local_ctxt cx, &span sp, ValueRef llfndecl) -> @fn_ctxt {
// 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(&@fn_ctxt cx, ast::proto proto,
option::t[ty_self_pair] ty_self, ty::t ret_ty,
option::t[ty::t] ty_self, ty::t ret_ty,
&ast::arg[] args,
&ast::ty_param[] ty_params) {
// Skip the implicit arguments 0, 1, and 2. TODO: Pull out 3u and define
@ -7503,7 +7512,7 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, ast::proto proto,
auto arg_n = 3u;
alt (ty_self) {
case (some(?tt)) {
cx.llself = some[val_self_pair](rec(v=cx.llenv, t=tt._1));
cx.llself = some[val_self_pair](rec(v=cx.llenv, t=tt));
}
case (none) {
auto i = 0u;
@ -7541,17 +7550,13 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx, ast::proto proto,
// Recommended LLVM style, strange though this is, is to copy from args to
// allocas immediately upon entry; this permits us to GEP into structures we
// were passed and whatnot. Apparently mem2reg will mop up.
fn copy_any_self_to_alloca(@fn_ctxt fcx, option::t[ty_self_pair] ty_self) {
fn copy_any_self_to_alloca(@fn_ctxt fcx) {
auto bcx = llstaticallocas_block_ctxt(fcx);
alt ({ fcx.llself }) {
case (some(?pair)) {
alt (ty_self) {
case (some[ty_self_pair](?tt)) {
auto a = alloca(bcx, tt._0);
bcx.build.Store(pair.v, a);
fcx.llself = some[val_self_pair](rec(v=a, t=pair.t));
}
}
auto a = alloca(bcx, T_rust_object());
bcx.build.Store(pair.v, a);
fcx.llself = some[val_self_pair](rec(v=a, t=pair.t));
}
case (_) { }
}
@ -7673,7 +7678,7 @@ fn finish_fn(&@fn_ctxt fcx, BasicBlockRef lltop) {
// trans_fn: creates an LLVM function corresponding to a source language
// function.
fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
option::t[ty_self_pair] ty_self, &ast::ty_param[] ty_params,
option::t[ty::t] ty_self, &ast::ty_param[] ty_params,
ast::node_id id) {
set_uwtable(llfndecl);
@ -7682,7 +7687,7 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
create_llargs_for_fn_args(fcx, f.proto, ty_self,
ty::ret_ty_of_fn(cx.ccx.tcx, id),
f.decl.inputs, ty_params);
copy_any_self_to_alloca(fcx, ty_self);
copy_any_self_to_alloca(fcx);
alt ({ fcx.llself }) {
case (some(?llself)) { populate_fn_ctxt_from_llself(fcx, llself); }
case (_) { }
@ -7720,7 +7725,7 @@ fn trans_fn(@local_ctxt cx, &span sp, &ast::_fn f, ValueRef llfndecl,
// vtable slot for method calls that "fall through" to an inner object. A
// helper function for create_vtbl.
fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
TypeRef llself_ty, ty::t self_ty,
ty::t self_ty,
&ast::ty_param[] ty_params,
ty::t with_obj_ty,
&ty::t[] additional_field_tys) -> ValueRef {
@ -7751,7 +7756,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
let TypeRef llforwarding_fn_ty =
type_of_fn_full(
cx.ccx, sp, m.proto,
some[TypeRef](llself_ty), m.inputs, m.output,
true, m.inputs, m.output,
std::ivec::len[ast::ty_param](ty_params));
let ValueRef llforwarding_fn =
decl_internal_fastcall_fn(cx.ccx.llmod, s, llforwarding_fn_ty);
@ -7764,7 +7769,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
// The outer object will arrive in the forwarding function via the llenv
// argument. Put it in an alloca so that we can GEP into it later.
auto llself_obj_ptr = alloca(bcx, llself_ty);
auto llself_obj_ptr = alloca(bcx, T_rust_object());
bcx.build.Store(fcx.llenv, llself_obj_ptr);
// Grab hold of the outer object so we can pass it into the inner object,
@ -7791,6 +7796,10 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
C_int(abi::obj_field_box)]);
llself_obj_box = bcx.build.Load(llself_obj_box);
auto ccx = bcx.fcx.lcx.ccx;
auto llbox_ty = T_opaque_obj_ptr(*ccx);
llself_obj_box = bcx.build.PointerCast(llself_obj_box, llbox_ty);
// Now, reach into the box and grab the body.
auto llself_obj_body =
bcx.build.GEP(llself_obj_box, ~[C_int(0),
@ -7859,6 +7868,9 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
// Pick out the original method from the vtable. The +1 is because slot
// #0 contains the destructor.
auto vtbl_type = T_ptr(T_array(T_ptr(T_nil()), ix + 2u));
llwith_obj_vtbl = bcx.build.PointerCast(llwith_obj_vtbl, vtbl_type);
auto llorig_mthd = bcx.build.GEP(llwith_obj_vtbl,
~[C_int(0), C_int(ix + 1u as int)]);
@ -7867,7 +7879,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
auto llorig_mthd_ty =
type_of_fn_full(bcx.fcx.lcx.ccx, sp,
ty::ty_fn_proto(bcx.fcx.lcx.ccx.tcx, orig_mthd_ty),
some[TypeRef](llself_ty),
true,
m.inputs,
m.output,
std::ivec::len[ast::ty_param](ty_params));
@ -7903,7 +7915,7 @@ fn process_fwding_mthd(@local_ctxt cx, &span sp, @ty::method m,
// process_normal_mthd: Create the contents of a normal vtable slot. A helper
// function for create_vtbl.
fn process_normal_mthd(@local_ctxt cx, @ast::method m, TypeRef llself_ty,
fn process_normal_mthd(@local_ctxt cx, @ast::method m,
ty::t self_ty, &ast::ty_param[] ty_params)
-> ValueRef {
@ -7913,7 +7925,7 @@ fn process_normal_mthd(@local_ctxt cx, @ast::method m, TypeRef llself_ty,
llfnty =
type_of_fn_full(
cx.ccx, m.span, proto,
some[TypeRef](llself_ty), inputs, output,
true, inputs, output,
std::ivec::len[ast::ty_param](ty_params));
}
}
@ -7929,7 +7941,7 @@ fn process_normal_mthd(@local_ctxt cx, @ast::method m, TypeRef llself_ty,
cx.ccx.item_ids.insert(m.node.id, llfn);
cx.ccx.item_symbols.insert(m.node.id, s);
trans_fn(mcx, m.span, m.node.meth, llfn,
some[ty_self_pair](tup(llself_ty, self_ty)),
some(self_ty),
ty_params, m.node.id);
ret llfn;
@ -7937,7 +7949,7 @@ fn process_normal_mthd(@local_ctxt cx, @ast::method m, TypeRef llself_ty,
// Create a vtable for an object being translated. Returns a pointer into
// read-only memory.
fn create_vtbl(@local_ctxt cx, &span sp, TypeRef llself_ty, ty::t self_ty,
fn create_vtbl(@local_ctxt cx, &span sp, ty::t self_ty,
&ast::_obj ob, &ast::ty_param[] ty_params,
option::t[ty::t] with_obj_ty,
&ty::t[] additional_field_tys) -> ValueRef {
@ -7954,7 +7966,7 @@ fn create_vtbl(@local_ctxt cx, &span sp, TypeRef llself_ty, ty::t self_ty,
auto dtor = C_null(T_ptr(T_i8()));
alt (ob.dtor) {
case (some(?d)) {
auto dtor_1 = trans_dtor(cx, llself_ty, self_ty, ty_params, d);
auto dtor_1 = trans_dtor(cx, self_ty, ty_params, d);
dtor = llvm::LLVMConstBitCast(dtor_1, val_ty(dtor));
}
case (none) { }
@ -8076,7 +8088,7 @@ fn vtbl_mthd_lteq(&vtbl_mthd a, &vtbl_mthd b) -> bool {
for (vtbl_mthd m in meths) {
alt (m) {
case (normal_mthd(?nm)) {
llmethods += ~[process_normal_mthd(cx, nm, llself_ty, self_ty,
llmethods += ~[process_normal_mthd(cx, nm, self_ty,
ty_params)];
}
// If we have to process a forwarding method, then we need to know
@ -8093,7 +8105,7 @@ fn vtbl_mthd_lteq(&vtbl_mthd a, &vtbl_mthd b) -> bool {
}
case (some(?t)) {
llmethods += ~[process_fwding_mthd(
cx, sp, fm, llself_ty,
cx, sp, fm,
self_ty, ty_params,
t,
additional_field_tys)];
@ -8115,15 +8127,15 @@ fn vtbl_mthd_lteq(&vtbl_mthd a, &vtbl_mthd b) -> bool {
ret gvar;
}
fn trans_dtor(@local_ctxt cx, TypeRef llself_ty, ty::t self_ty,
fn trans_dtor(@local_ctxt cx, ty::t self_ty,
&ast::ty_param[] ty_params, &@ast::method dtor) -> ValueRef {
auto llfnty = T_dtor(cx.ccx, dtor.span, llself_ty);
auto llfnty = T_dtor(cx.ccx, dtor.span);
let str s = mangle_internal_name_by_path(cx.ccx, cx.path + ~["drop"]);
let ValueRef llfn = decl_internal_fastcall_fn(cx.ccx.llmod, s, llfnty);
cx.ccx.item_ids.insert(dtor.node.id, llfn);
cx.ccx.item_symbols.insert(dtor.node.id, s);
trans_fn(cx, dtor.span, dtor.node.meth, llfn,
some[ty_self_pair](tup(llself_ty, self_ty)), ty_params,
some(self_ty), ty_params,
dtor.node.id);
ret llfn;
}
@ -8157,7 +8169,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
// Both regular arguments and type parameters are handled here.
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty::t],
ty::ret_ty_of_fn(ccx.tcx, ctor_id),
fn_args, ty_params);
let ty::arg[] arg_tys = arg_tys_of_fn(ccx, ctor_id);
@ -8171,7 +8183,6 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
// Pick up the type of this object by looking at our own output type, that
// is, the output type of the object constructor we're building.
auto self_ty = ty::ret_ty_of_fn(ccx.tcx, ctor_id);
auto llself_ty = type_of(ccx, sp, self_ty);
// Set up the two-word pair that we're going to return from the object
// constructor we're building. The two elements of this pair will be a
@ -8192,8 +8203,9 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
// It will be located in the read-only memory of the executable we're
// creating and will contain ValueRefs for all of this object's methods.
// create_vtbl returns a pointer to the vtable, which we store.
auto vtbl = create_vtbl(cx, sp, llself_ty, self_ty, ob, ty_params, none,
auto vtbl = create_vtbl(cx, sp, self_ty, ob, ty_params, none,
~[]);
vtbl = bcx.build.PointerCast(vtbl, T_ptr(T_empty_struct()));
bcx.build.Store(vtbl, pair_vtbl);
@ -8204,7 +8216,7 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::node_id ctor_id,
// FIXME: What about with_obj? Do we have to think about it here?
// (Pertains to issues #538/#539/#540/#543.)
let TypeRef llbox_ty = T_opaque_obj_ptr(*ccx);
let TypeRef llbox_ty = T_ptr(T_empty_struct());
// FIXME: we should probably also allocate a box for empty objs that have
// a dtor, since otherwise they are never dropped, and the dtor never
@ -8345,7 +8357,7 @@ fn trans_res_ctor(@local_ctxt cx, &span sp, &ast::_fn dtor,
}
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
auto ret_t = ty::ret_ty_of_fn(cx.ccx.tcx, ctor_id);
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty::t],
ret_t, dtor.decl.inputs, ty_params);
auto bcx = new_top_block_ctxt(fcx);
auto lltop = bcx.llbb;
@ -8404,7 +8416,7 @@ fn trans_tag_variant(@local_ctxt cx, ast::node_id tag_id,
}
}
auto fcx = new_fn_ctxt(cx, variant.span, llfndecl);
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty_self_pair],
create_llargs_for_fn_args(fcx, ast::proto_fn, none[ty::t],
ty::ret_ty_of_fn(cx.ccx.tcx, variant.node.id),
fn_args, ty_params);
let ty::t[] ty_param_substs = ~[];
@ -8501,7 +8513,7 @@ fn trans_item(@local_ctxt cx, &ast::item item) {
alt (cx.ccx.item_ids.find(item.id)) {
case (some(?llfndecl)) {
trans_fn(sub_cx, item.span, f, llfndecl,
none[ty_self_pair], tps, item.id);
none, tps, item.id);
}
case (_) {
cx.ccx.sess.span_fatal(item.span,