Some work on backwarding for issue #702.
This commit is contained in:
parent
54c1c07ab1
commit
7073ee4e31
@ -6534,6 +6534,7 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
|
||||
// helper function for create_vtbl.
|
||||
fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
|
||||
ty_params: &ast::ty_param[], with_obj_ty: ty::t,
|
||||
backwarding_vtbl: option::t[ValueRef],
|
||||
additional_field_tys: &ty::t[]) -> ValueRef {
|
||||
|
||||
|
||||
@ -6552,9 +6553,14 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
|
||||
let mcx: @local_ctxt = @{path: cx.path + ~["method", m.ident] with *cx};
|
||||
|
||||
// Make up a name for the forwarding function.
|
||||
let s: str =
|
||||
mangle_internal_name_by_path_and_seq(mcx.ccx, mcx.path,
|
||||
"forwarding_fn");
|
||||
let fn_name: str;
|
||||
alt (backwarding_vtbl) {
|
||||
none. { fn_name = "forwarding_fn"; }
|
||||
some(_) { fn_name = "backwarding_fn"; }
|
||||
}
|
||||
|
||||
let s: str = mangle_internal_name_by_path_and_seq(mcx.ccx, mcx.path,
|
||||
fn_name);
|
||||
|
||||
// Get the forwarding function's type and declare it.
|
||||
let llforwarding_fn_ty: TypeRef =
|
||||
@ -6574,6 +6580,21 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
|
||||
let llself_obj_ptr = alloca(bcx, fcx.lcx.ccx.rust_object_type);
|
||||
bcx.build.Store(fcx.llenv, llself_obj_ptr);
|
||||
|
||||
// Do backwarding if necessary.
|
||||
alt (backwarding_vtbl) {
|
||||
none. { /* fall through */ }
|
||||
some(bv) {
|
||||
// Grab the vtable out of the self-object.
|
||||
let llself_obj_vtbl =
|
||||
bcx.build.GEP(llself_obj_ptr, ~[C_int(0),
|
||||
C_int(abi::obj_field_vtbl)]);
|
||||
|
||||
// And replace it with the backwarding vtbl.
|
||||
let llbv = bcx.build.PointerCast(bv, T_ptr(T_empty_struct()));
|
||||
bcx.build.Store(llbv, llself_obj_vtbl);
|
||||
}
|
||||
}
|
||||
|
||||
// Grab hold of the outer object so we can pass it into the inner object,
|
||||
// in case that inner object needs to make any self-calls. (Such calls
|
||||
// will need to dispatch back through the outer object.)
|
||||
@ -6733,22 +6754,21 @@ fn process_normal_mthd(cx: @local_ctxt, m: @ast::method, self_ty: ty::t,
|
||||
ret llfn;
|
||||
}
|
||||
|
||||
// Used only inside create_vtbl and create_backwarding_vtbl to distinguish
|
||||
// different kinds of slots we'll have to create.
|
||||
tag vtbl_mthd {
|
||||
// Normal methods are complete AST nodes, but for forwarding methods,
|
||||
// the only information we'll have about them is their type.
|
||||
normal_mthd(@ast::method);
|
||||
fwding_mthd(@ty::method);
|
||||
}
|
||||
|
||||
// Create a vtable for an object being translated. Returns a pointer into
|
||||
// read-only memory.
|
||||
fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
ty_params: &ast::ty_param[], with_obj_ty: option::t[ty::t],
|
||||
additional_field_tys: &ty::t[]) -> ValueRef {
|
||||
|
||||
// Used only inside create_vtbl to distinguish different kinds of slots
|
||||
// we'll have to create.
|
||||
tag vtbl_mthd {
|
||||
|
||||
// Normal methods are complete AST nodes, but for forwarding methods,
|
||||
// the only information we'll have about them is their type.
|
||||
normal_mthd(@ast::method);
|
||||
fwding_mthd(@ty::method);
|
||||
}
|
||||
|
||||
let dtor = C_null(T_ptr(T_i8()));
|
||||
alt ob.dtor {
|
||||
some(d) {
|
||||
@ -6760,6 +6780,7 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
|
||||
let llmethods: ValueRef[] = ~[dtor];
|
||||
let meths: vtbl_mthd[] = ~[];
|
||||
let backwarding_vtbl: option::t[ValueRef] = none;
|
||||
|
||||
alt with_obj_ty {
|
||||
none. {
|
||||
@ -6794,8 +6815,8 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
}
|
||||
_ {
|
||||
// Shouldn't happen.
|
||||
cx.ccx.sess.bug("create_vtbl(): trying to extend a " +
|
||||
"non-object");
|
||||
cx.ccx.sess.bug("create_vtbl(): trying to extend a \
|
||||
non-object");
|
||||
}
|
||||
}
|
||||
|
||||
@ -6805,7 +6826,6 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
addtl_meths: (@ast::method)[]) ->
|
||||
option::t[vtbl_mthd] {
|
||||
|
||||
|
||||
alt m {
|
||||
fwding_mthd(fm) {
|
||||
// Since fm is a fwding_mthd, and we're checking to
|
||||
@ -6863,7 +6883,7 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
meths);
|
||||
|
||||
// Now that we have our list of methods, we can process them in order.
|
||||
for m: vtbl_mthd in meths {
|
||||
for m: vtbl_mthd in meths {
|
||||
alt m {
|
||||
normal_mthd(nm) {
|
||||
llmethods += ~[process_normal_mthd(cx, nm, self_ty, ty_params)];
|
||||
@ -6877,13 +6897,14 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
|
||||
// This shouldn't happen; if we're trying to process a
|
||||
// forwarding method, then we should always have a
|
||||
// with_obj_ty.
|
||||
cx.ccx.sess.bug("create_vtbl(): trying to create " +
|
||||
"forwarding method without a type " +
|
||||
"of object to forward to");
|
||||
cx.ccx.sess.bug("create_vtbl(): trying to create \
|
||||
forwarding method without a type \
|
||||
of object to forward to");
|
||||
}
|
||||
some(t) {
|
||||
llmethods +=
|
||||
~[process_fwding_mthd(cx, sp, fm, ty_params, t,
|
||||
backwarding_vtbl,
|
||||
additional_field_tys)];
|
||||
}
|
||||
}
|
||||
@ -6914,6 +6935,65 @@ fn trans_dtor(cx: @local_ctxt, self_ty: ty::t, ty_params: &ast::ty_param[],
|
||||
ret llfn;
|
||||
}
|
||||
|
||||
fn create_backwarding_vtbl(cx: @local_ctxt, sp: &span, with_obj_ty: ty::t,
|
||||
outer_obj_ty: ty::t) -> ValueRef {
|
||||
|
||||
// This vtbl needs to have slots for all of the methods on an inner
|
||||
// object, and it needs to forward them to the corresponding slots on the
|
||||
// outer object. All we know about either one are their types.
|
||||
|
||||
let dtor = C_null(T_ptr(T_i8()));
|
||||
let llmethods: ValueRef[] = ~[dtor];
|
||||
let meths: vtbl_mthd[]= ~[];
|
||||
|
||||
// Gather up methods on the inner object.
|
||||
alt ty::struct(cx.ccx.tcx, with_obj_ty) {
|
||||
ty::ty_obj(with_obj_methods) {
|
||||
for m: ty::method in with_obj_methods {
|
||||
meths += ~[fwding_mthd(@m)];
|
||||
}
|
||||
}
|
||||
_ {
|
||||
// Shouldn't happen.
|
||||
cx.ccx.sess.bug("create_backwarding_vtbl(): trying to extend a \
|
||||
non-object");
|
||||
}
|
||||
}
|
||||
|
||||
// Methods should have already been sorted, so no need to do so again.
|
||||
|
||||
for m: vtbl_mthd in meths {
|
||||
alt m {
|
||||
normal_mthd(nm) {
|
||||
cx.ccx.sess.bug("backwarding vtables shouldn't contain \
|
||||
normal methods");
|
||||
}
|
||||
fwding_mthd(fm) {
|
||||
// We pass outer_obj_ty to process_fwding_mthd() because it's
|
||||
// the one being forwarded to.
|
||||
llmethods += ~[process_fwding_mthd(
|
||||
cx, sp, fm, ~[], outer_obj_ty,
|
||||
none,
|
||||
~[])];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let vtbl = C_struct(llmethods);
|
||||
let vtbl_name =
|
||||
mangle_internal_name_by_path(cx.ccx,
|
||||
cx.path + ~["backwarding_vtbl"]);
|
||||
let gvar =
|
||||
llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl), str::buf(vtbl_name));
|
||||
llvm::LLVMSetInitializer(gvar, vtbl);
|
||||
llvm::LLVMSetGlobalConstant(gvar, True);
|
||||
llvm::LLVMSetLinkage(gvar,
|
||||
lib::llvm::LLVMInternalLinkage as llvm::Linkage);
|
||||
|
||||
ret gvar;
|
||||
|
||||
}
|
||||
|
||||
// trans_obj: creates an LLVM function that is the object constructor for the
|
||||
// object being translated.
|
||||
fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
|
||||
|
Loading…
x
Reference in New Issue
Block a user