Skip to content

Commit 7073ee4

Browse files
committed
Some work on backwarding for issue #702.
1 parent 54c1c07 commit 7073ee4

File tree

1 file changed

+100
-20
lines changed

1 file changed

+100
-20
lines changed

src/comp/middle/trans.rs

+100-20
Original file line numberDiff line numberDiff line change
@@ -6534,6 +6534,7 @@ fn trans_fn(cx: @local_ctxt, sp: &span, f: &ast::_fn, llfndecl: ValueRef,
65346534
// helper function for create_vtbl.
65356535
fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65366536
ty_params: &ast::ty_param[], with_obj_ty: ty::t,
6537+
backwarding_vtbl: option::t[ValueRef],
65376538
additional_field_tys: &ty::t[]) -> ValueRef {
65386539

65396540

@@ -6552,9 +6553,14 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65526553
let mcx: @local_ctxt = @{path: cx.path + ~["method", m.ident] with *cx};
65536554

65546555
// Make up a name for the forwarding function.
6555-
let s: str =
6556-
mangle_internal_name_by_path_and_seq(mcx.ccx, mcx.path,
6557-
"forwarding_fn");
6556+
let fn_name: str;
6557+
alt (backwarding_vtbl) {
6558+
none. { fn_name = "forwarding_fn"; }
6559+
some(_) { fn_name = "backwarding_fn"; }
6560+
}
6561+
6562+
let s: str = mangle_internal_name_by_path_and_seq(mcx.ccx, mcx.path,
6563+
fn_name);
65586564

65596565
// Get the forwarding function's type and declare it.
65606566
let llforwarding_fn_ty: TypeRef =
@@ -6574,6 +6580,21 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: &span, m: @ty::method,
65746580
let llself_obj_ptr = alloca(bcx, fcx.lcx.ccx.rust_object_type);
65756581
bcx.build.Store(fcx.llenv, llself_obj_ptr);
65766582

6583+
// Do backwarding if necessary.
6584+
alt (backwarding_vtbl) {
6585+
none. { /* fall through */ }
6586+
some(bv) {
6587+
// Grab the vtable out of the self-object.
6588+
let llself_obj_vtbl =
6589+
bcx.build.GEP(llself_obj_ptr, ~[C_int(0),
6590+
C_int(abi::obj_field_vtbl)]);
6591+
6592+
// And replace it with the backwarding vtbl.
6593+
let llbv = bcx.build.PointerCast(bv, T_ptr(T_empty_struct()));
6594+
bcx.build.Store(llbv, llself_obj_vtbl);
6595+
}
6596+
}
6597+
65776598
// Grab hold of the outer object so we can pass it into the inner object,
65786599
// in case that inner object needs to make any self-calls. (Such calls
65796600
// 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,
67336754
ret llfn;
67346755
}
67356756

6757+
// Used only inside create_vtbl and create_backwarding_vtbl to distinguish
6758+
// different kinds of slots we'll have to create.
6759+
tag vtbl_mthd {
6760+
// Normal methods are complete AST nodes, but for forwarding methods,
6761+
// the only information we'll have about them is their type.
6762+
normal_mthd(@ast::method);
6763+
fwding_mthd(@ty::method);
6764+
}
6765+
67366766
// Create a vtable for an object being translated. Returns a pointer into
67376767
// read-only memory.
67386768
fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
67396769
ty_params: &ast::ty_param[], with_obj_ty: option::t[ty::t],
67406770
additional_field_tys: &ty::t[]) -> ValueRef {
67416771

6742-
// Used only inside create_vtbl to distinguish different kinds of slots
6743-
// we'll have to create.
6744-
tag vtbl_mthd {
6745-
6746-
// Normal methods are complete AST nodes, but for forwarding methods,
6747-
// the only information we'll have about them is their type.
6748-
normal_mthd(@ast::method);
6749-
fwding_mthd(@ty::method);
6750-
}
6751-
67526772
let dtor = C_null(T_ptr(T_i8()));
67536773
alt ob.dtor {
67546774
some(d) {
@@ -6760,6 +6780,7 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
67606780

67616781
let llmethods: ValueRef[] = ~[dtor];
67626782
let meths: vtbl_mthd[] = ~[];
6783+
let backwarding_vtbl: option::t[ValueRef] = none;
67636784

67646785
alt with_obj_ty {
67656786
none. {
@@ -6794,8 +6815,8 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
67946815
}
67956816
_ {
67966817
// Shouldn't happen.
6797-
cx.ccx.sess.bug("create_vtbl(): trying to extend a " +
6798-
"non-object");
6818+
cx.ccx.sess.bug("create_vtbl(): trying to extend a \
6819+
non-object");
67996820
}
68006821
}
68016822

@@ -6805,7 +6826,6 @@ fn create_vtbl(cx: @local_ctxt, sp: &span, self_ty: ty::t, ob: &ast::_obj,
68056826
addtl_meths: (@ast::method)[]) ->
68066827
option::t[vtbl_mthd] {
68076828

6808-
68096829
alt m {
68106830
fwding_mthd(fm) {
68116831
// 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,
68636883
meths);
68646884

68656885
// Now that we have our list of methods, we can process them in order.
6866-
for m: vtbl_mthd in meths {
6886+
for m: vtbl_mthd in meths {
68676887
alt m {
68686888
normal_mthd(nm) {
68696889
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,
68776897
// This shouldn't happen; if we're trying to process a
68786898
// forwarding method, then we should always have a
68796899
// with_obj_ty.
6880-
cx.ccx.sess.bug("create_vtbl(): trying to create " +
6881-
"forwarding method without a type " +
6882-
"of object to forward to");
6900+
cx.ccx.sess.bug("create_vtbl(): trying to create \
6901+
forwarding method without a type \
6902+
of object to forward to");
68836903
}
68846904
some(t) {
68856905
llmethods +=
68866906
~[process_fwding_mthd(cx, sp, fm, ty_params, t,
6907+
backwarding_vtbl,
68876908
additional_field_tys)];
68886909
}
68896910
}
@@ -6914,6 +6935,65 @@ fn trans_dtor(cx: @local_ctxt, self_ty: ty::t, ty_params: &ast::ty_param[],
69146935
ret llfn;
69156936
}
69166937

6938+
fn create_backwarding_vtbl(cx: @local_ctxt, sp: &span, with_obj_ty: ty::t,
6939+
outer_obj_ty: ty::t) -> ValueRef {
6940+
6941+
// This vtbl needs to have slots for all of the methods on an inner
6942+
// object, and it needs to forward them to the corresponding slots on the
6943+
// outer object. All we know about either one are their types.
6944+
6945+
let dtor = C_null(T_ptr(T_i8()));
6946+
let llmethods: ValueRef[] = ~[dtor];
6947+
let meths: vtbl_mthd[]= ~[];
6948+
6949+
// Gather up methods on the inner object.
6950+
alt ty::struct(cx.ccx.tcx, with_obj_ty) {
6951+
ty::ty_obj(with_obj_methods) {
6952+
for m: ty::method in with_obj_methods {
6953+
meths += ~[fwding_mthd(@m)];
6954+
}
6955+
}
6956+
_ {
6957+
// Shouldn't happen.
6958+
cx.ccx.sess.bug("create_backwarding_vtbl(): trying to extend a \
6959+
non-object");
6960+
}
6961+
}
6962+
6963+
// Methods should have already been sorted, so no need to do so again.
6964+
6965+
for m: vtbl_mthd in meths {
6966+
alt m {
6967+
normal_mthd(nm) {
6968+
cx.ccx.sess.bug("backwarding vtables shouldn't contain \
6969+
normal methods");
6970+
}
6971+
fwding_mthd(fm) {
6972+
// We pass outer_obj_ty to process_fwding_mthd() because it's
6973+
// the one being forwarded to.
6974+
llmethods += ~[process_fwding_mthd(
6975+
cx, sp, fm, ~[], outer_obj_ty,
6976+
none,
6977+
~[])];
6978+
}
6979+
}
6980+
}
6981+
6982+
let vtbl = C_struct(llmethods);
6983+
let vtbl_name =
6984+
mangle_internal_name_by_path(cx.ccx,
6985+
cx.path + ~["backwarding_vtbl"]);
6986+
let gvar =
6987+
llvm::LLVMAddGlobal(cx.ccx.llmod, val_ty(vtbl), str::buf(vtbl_name));
6988+
llvm::LLVMSetInitializer(gvar, vtbl);
6989+
llvm::LLVMSetGlobalConstant(gvar, True);
6990+
llvm::LLVMSetLinkage(gvar,
6991+
lib::llvm::LLVMInternalLinkage as llvm::Linkage);
6992+
6993+
ret gvar;
6994+
6995+
}
6996+
69176997
// trans_obj: creates an LLVM function that is the object constructor for the
69186998
// object being translated.
69196999
fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,

0 commit comments

Comments
 (0)