16
16
* closure.
17
17
*/
18
18
19
+ use arena:: TypedArena ;
19
20
use back:: abi;
21
+ use back:: link;
20
22
use driver:: session;
21
23
use lib:: llvm:: ValueRef ;
22
24
use lib:: llvm:: llvm;
@@ -33,28 +35,26 @@ use middle::trans::cleanup::CleanupMethods;
33
35
use middle:: trans:: common;
34
36
use middle:: trans:: common:: * ;
35
37
use middle:: trans:: datum:: * ;
36
- use middle:: trans:: datum:: Datum ;
38
+ use middle:: trans:: datum:: { Datum , KindOps } ;
37
39
use middle:: trans:: expr;
38
40
use middle:: trans:: glue;
39
41
use middle:: trans:: inline;
42
+ use middle:: trans:: foreign;
40
43
use middle:: trans:: meth;
41
44
use middle:: trans:: monomorphize;
45
+ use middle:: trans:: type_:: Type ;
42
46
use middle:: trans:: type_of;
43
- use middle:: trans:: foreign;
44
47
use middle:: ty;
45
48
use middle:: typeck;
46
49
use middle:: typeck:: coherence:: make_substs_for_receiver_types;
47
50
use middle:: typeck:: MethodCall ;
48
51
use util:: ppaux:: Repr ;
49
52
50
- use middle:: trans:: type_:: Type ;
51
-
53
+ use std:: gc:: Gc ;
52
54
use syntax:: ast;
53
55
use synabi = syntax:: abi;
54
56
use syntax:: ast_map;
55
57
56
- use std:: gc:: Gc ;
57
-
58
58
pub struct MethodData {
59
59
pub llfn : ValueRef ,
60
60
pub llself : ValueRef ,
@@ -224,6 +224,134 @@ fn resolve_default_method_vtables(bcx: &Block,
224
224
param_vtables
225
225
}
226
226
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
+ }
227
355
228
356
pub fn trans_fn_ref_with_vtables (
229
357
bcx : & Block , //
0 commit comments