diff options
| author | Lindsey Kuper <lkuper@mozilla.com> | 2011-07-27 18:55:15 -0700 |
|---|---|---|
| committer | Lindsey Kuper <lkuper@mozilla.com> | 2011-07-27 19:43:21 -0700 |
| commit | 7073ee4e31d32cfdc1401cfefaa2e3ed07b43f48 (patch) | |
| tree | de98c87b5648c3956b88827e76608112ec559104 /src | |
| parent | 54c1c07ab1a9ba311bde3a1f80687a7e64c7edae (diff) | |
| download | rust-7073ee4e31d32cfdc1401cfefaa2e3ed07b43f48.tar.gz rust-7073ee4e31d32cfdc1401cfefaa2e3ed07b43f48.zip | |
Some work on backwarding for issue #702.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp/middle/trans.rs | 120 |
1 files changed, 100 insertions, 20 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 2e3c2a41446..0b0b31b2064 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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, |
