1616 * closure.
1717 */
1818
19+ use arena:: TypedArena ;
1920use back:: abi;
21+ use back:: link;
2022use driver:: session;
2123use lib:: llvm:: ValueRef ;
2224use lib:: llvm:: llvm;
@@ -33,28 +35,26 @@ use middle::trans::cleanup::CleanupMethods;
3335use middle:: trans:: common;
3436use middle:: trans:: common:: * ;
3537use middle:: trans:: datum:: * ;
36- use middle:: trans:: datum:: Datum ;
38+ use middle:: trans:: datum:: { Datum , KindOps } ;
3739use middle:: trans:: expr;
3840use middle:: trans:: glue;
3941use middle:: trans:: inline;
42+ use middle:: trans:: foreign;
4043use middle:: trans:: meth;
4144use middle:: trans:: monomorphize;
45+ use middle:: trans:: type_:: Type ;
4246use middle:: trans:: type_of;
43- use middle:: trans:: foreign;
4447use middle:: ty;
4548use middle:: typeck;
4649use middle:: typeck:: coherence:: make_substs_for_receiver_types;
4750use middle:: typeck:: MethodCall ;
4851use util:: ppaux:: Repr ;
4952
50- use middle:: trans:: type_:: Type ;
51-
53+ use std:: gc:: Gc ;
5254use syntax:: ast;
5355use synabi = syntax:: abi;
5456use syntax:: ast_map;
5557
56- use std:: gc:: Gc ;
57-
5858pub struct MethodData {
5959 pub llfn : ValueRef ,
6060 pub llself : ValueRef ,
@@ -224,6 +224,134 @@ fn resolve_default_method_vtables(bcx: &Block,
224224 param_vtables
225225}
226226
227+ /// Translates the adapter that deconstructs a `Box<Trait>` object into
228+ /// `Trait` so that a by-value self method can be called.
229+ pub fn trans_unboxing_shim ( bcx : & Block ,
230+ llshimmedfn : ValueRef ,
231+ method : & ty:: Method ,
232+ method_id : ast:: DefId ,
233+ substs : subst:: Substs )
234+ -> ValueRef {
235+ let _icx = push_ctxt ( "trans_unboxing_shim" ) ;
236+ let ccx = bcx. ccx ( ) ;
237+ let tcx = bcx. tcx ( ) ;
238+
239+ // Transform the self type to `Box<self_type>`.
240+ let self_type = * method. fty . sig . inputs . get ( 0 ) ;
241+ let boxed_self_type = ty:: mk_uniq ( tcx, self_type) ;
242+ let boxed_function_type = ty:: FnSig {
243+ binder_id : method. fty . sig . binder_id ,
244+ inputs : method. fty . sig . inputs . iter ( ) . enumerate ( ) . map ( |( i, typ) | {
245+ if i == 0 {
246+ boxed_self_type
247+ } else {
248+ * typ
249+ }
250+ } ) . collect ( ) ,
251+ output : method. fty . sig . output ,
252+ variadic : false ,
253+ } ;
254+ let boxed_function_type = ty:: BareFnTy {
255+ fn_style : method. fty . fn_style ,
256+ abi : method. fty . abi ,
257+ sig : boxed_function_type,
258+ } ;
259+ let boxed_function_type =
260+ ty:: mk_bare_fn ( tcx, boxed_function_type) . subst ( tcx, & substs) ;
261+ let function_type =
262+ ty:: mk_bare_fn ( tcx, method. fty . clone ( ) ) . subst ( tcx, & substs) ;
263+
264+ let function_name = tcx. map . with_path ( method_id. node , |path| {
265+ link:: mangle_internal_name_by_path_and_seq ( path, "unboxing_shim" )
266+ } ) ;
267+ let llfn = decl_internal_rust_fn ( ccx,
268+ boxed_function_type,
269+ function_name. as_slice ( ) ) ;
270+
271+ let block_arena = TypedArena :: new ( ) ;
272+ let empty_param_substs = param_substs:: empty ( ) ;
273+ let return_type = ty:: ty_fn_ret ( boxed_function_type) ;
274+ let fcx = new_fn_ctxt ( ccx,
275+ llfn,
276+ -1 ,
277+ false ,
278+ return_type,
279+ & empty_param_substs,
280+ None ,
281+ & block_arena) ;
282+ init_function ( & fcx, false , return_type) ;
283+
284+ // Create the substituted versions of the self type.
285+ let mut bcx = fcx. entry_bcx . borrow ( ) . clone ( ) . unwrap ( ) ;
286+ let arg_scope = fcx. push_custom_cleanup_scope ( ) ;
287+ let arg_scope_id = cleanup:: CustomScope ( arg_scope) ;
288+ let boxed_arg_types = ty:: ty_fn_args ( boxed_function_type) ;
289+ let boxed_self_type = * boxed_arg_types. get ( 0 ) ;
290+ let arg_types = ty:: ty_fn_args ( function_type) ;
291+ let self_type = * arg_types. get ( 0 ) ;
292+ let boxed_self_kind = arg_kind ( & fcx, boxed_self_type) ;
293+
294+ // Create a datum for self.
295+ let llboxedself = unsafe {
296+ llvm:: LLVMGetParam ( fcx. llfn , fcx. arg_pos ( 0 ) as u32 )
297+ } ;
298+ let llboxedself = Datum :: new ( llboxedself,
299+ boxed_self_type,
300+ boxed_self_kind) ;
301+ let boxed_self =
302+ unpack_datum ! ( bcx,
303+ llboxedself. to_lvalue_datum_in_scope( bcx,
304+ "boxedself" ,
305+ arg_scope_id) ) ;
306+
307+ // This `Load` is needed because lvalue data are always by-ref.
308+ let llboxedself = Load ( bcx, boxed_self. val ) ;
309+
310+ let llself = if type_is_immediate ( ccx, self_type) {
311+ let llboxedself = Load ( bcx, llboxedself) ;
312+ immediate_rvalue ( llboxedself, self_type)
313+ } else {
314+ let llself = rvalue_scratch_datum ( bcx, self_type, "self" ) ;
315+ memcpy_ty ( bcx, llself. val , llboxedself, self_type) ;
316+ llself
317+ } ;
318+
319+ // Make sure we don't free the box twice!
320+ boxed_self. kind . post_store ( bcx, boxed_self. val , boxed_self_type) ;
321+
322+ // Schedule a cleanup to free the box.
323+ fcx. schedule_free_value ( arg_scope_id,
324+ llboxedself,
325+ cleanup:: HeapExchange ,
326+ self_type) ;
327+
328+ // Now call the function.
329+ let mut llshimmedargs = vec ! ( llself. val) ;
330+ for i in range ( 1 , arg_types. len ( ) ) {
331+ llshimmedargs. push ( unsafe {
332+ llvm:: LLVMGetParam ( fcx. llfn , fcx. arg_pos ( i) as u32 )
333+ } ) ;
334+ }
335+ bcx = trans_call_inner ( bcx,
336+ None ,
337+ function_type,
338+ |bcx, _| {
339+ Callee {
340+ bcx : bcx,
341+ data : Fn ( llshimmedfn) ,
342+ }
343+ } ,
344+ ArgVals ( llshimmedargs. as_slice ( ) ) ,
345+ match fcx. llretptr . get ( ) {
346+ None => None ,
347+ Some ( llretptr) => Some ( expr:: SaveIn ( llretptr) ) ,
348+ } ) . bcx ;
349+
350+ bcx = fcx. pop_and_trans_custom_cleanup_scope ( bcx, arg_scope) ;
351+ finish_fn ( & fcx, bcx) ;
352+
353+ llfn
354+ }
227355
228356pub fn trans_fn_ref_with_vtables (
229357 bcx : & Block , //
0 commit comments