@@ -94,14 +94,47 @@ impl Pointer {
94
94
}
95
95
}
96
96
97
- #[ derive( Debug , Clone , Hash , Eq , PartialEq ) ]
98
- struct FunctionDefinition < ' tcx > {
97
+ #[ derive( Debug , Copy , Clone , Hash , Eq , PartialEq ) ]
98
+ /// Identifies a specific monomorphized function
99
+ pub struct FunctionDefinition < ' tcx > {
99
100
pub def_id : DefId ,
100
101
pub substs : & ' tcx Substs < ' tcx > ,
101
102
pub abi : Abi ,
102
103
pub sig : & ' tcx ty:: FnSig < ' tcx > ,
103
104
}
104
105
106
+ /// Either a concrete function, or a glue function
107
+ #[ derive( Debug , Copy , Clone , Hash , Eq , PartialEq ) ]
108
+ pub enum Function < ' tcx > {
109
+ /// A function or method created by compiling code
110
+ Concrete ( FunctionDefinition < ' tcx > ) ,
111
+ /// Glue required to call a regular function through a Fn(Mut|Once) trait object
112
+ FnDefAsTraitObject ( FunctionDefinition < ' tcx > ) ,
113
+ /// Glue required to call the actual drop impl's `drop` method.
114
+ /// Drop glue takes the `self` by value, while `Drop::drop` take `&mut self`
115
+ DropGlue ( FunctionDefinition < ' tcx > ) ,
116
+ /// Glue required to treat the ptr part of a fat pointer
117
+ /// as a function pointer
118
+ FnPtrAsTraitObject ( & ' tcx ty:: FnSig < ' tcx > ) ,
119
+ /// Glue for Closures
120
+ Closure ( FunctionDefinition < ' tcx > ) ,
121
+ }
122
+
123
+ impl < ' tcx > Function < ' tcx > {
124
+ pub fn expect_concrete ( self ) -> EvalResult < ' tcx , FunctionDefinition < ' tcx > > {
125
+ match self {
126
+ Function :: Concrete ( fn_def) => Ok ( fn_def) ,
127
+ other => Err ( EvalError :: ExpectedConcreteFunction ( other) ) ,
128
+ }
129
+ }
130
+ pub fn expect_drop_glue ( self ) -> EvalResult < ' tcx , FunctionDefinition < ' tcx > > {
131
+ match self {
132
+ Function :: DropGlue ( fn_def) => Ok ( fn_def) ,
133
+ other => Err ( EvalError :: ExpectedDropGlue ( other) ) ,
134
+ }
135
+ }
136
+ }
137
+
105
138
////////////////////////////////////////////////////////////////////////////////
106
139
// Top-level interpreter memory
107
140
////////////////////////////////////////////////////////////////////////////////
@@ -115,9 +148,9 @@ pub struct Memory<'a, 'tcx> {
115
148
memory_size : u64 ,
116
149
/// Function "allocations". They exist solely so pointers have something to point to, and
117
150
/// we can figure out what they point to.
118
- functions : HashMap < AllocId , FunctionDefinition < ' tcx > > ,
151
+ functions : HashMap < AllocId , Function < ' tcx > > ,
119
152
/// Inverse map of `functions` so we don't allocate a new pointer every time we need one
120
- function_alloc_cache : HashMap < FunctionDefinition < ' tcx > , AllocId > ,
153
+ function_alloc_cache : HashMap < Function < ' tcx > , AllocId > ,
121
154
next_id : AllocId ,
122
155
pub layout : & ' a TargetDataLayout ,
123
156
/// List of memory regions containing packed structures
@@ -160,35 +193,61 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
160
193
abi : fn_ty. abi ,
161
194
sig : fn_ty. sig ,
162
195
} ) ;
163
- self . create_fn_alloc ( FunctionDefinition {
196
+ self . create_fn_alloc ( Function :: Closure ( FunctionDefinition {
164
197
def_id,
165
198
substs : substs. substs ,
166
199
abi : fn_ty. abi ,
167
200
// FIXME: why doesn't this compile?
168
201
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
169
202
sig : fn_ty. sig . skip_binder ( ) ,
170
- } )
203
+ } ) )
204
+ }
205
+
206
+ pub fn create_fn_as_trait_glue ( & mut self , _tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId , substs : & ' tcx Substs < ' tcx > , fn_ty : & ' tcx BareFnTy < ' tcx > ) -> Pointer {
207
+ self . create_fn_alloc ( Function :: FnDefAsTraitObject ( FunctionDefinition {
208
+ def_id,
209
+ substs,
210
+ abi : fn_ty. abi ,
211
+ // FIXME: why doesn't this compile?
212
+ //sig: tcx.erase_late_bound_regions(&fn_ty.sig),
213
+ sig : fn_ty. sig . skip_binder ( ) ,
214
+ } ) )
215
+ }
216
+
217
+ pub fn create_fn_ptr_as_trait_glue ( & mut self , fn_ty : & ' tcx BareFnTy < ' tcx > ) -> Pointer {
218
+ self . create_fn_alloc ( Function :: FnPtrAsTraitObject ( fn_ty. sig . skip_binder ( ) ) )
219
+ }
220
+
221
+ pub fn create_drop_glue ( & mut self , _tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId , substs : & ' tcx Substs < ' tcx > , fn_ty : & ' tcx BareFnTy < ' tcx > ) -> Pointer {
222
+ self . create_fn_alloc ( Function :: DropGlue ( FunctionDefinition {
223
+ def_id,
224
+ substs,
225
+ abi : fn_ty. abi ,
226
+ // FIXME: why doesn't this compile?
227
+ //sig: tcx.erase_late_bound_regions(&fn_ty.sig),
228
+ sig : fn_ty. sig . skip_binder ( ) ,
229
+ } ) )
171
230
}
172
231
173
232
pub fn create_fn_ptr ( & mut self , _tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId , substs : & ' tcx Substs < ' tcx > , fn_ty : & ' tcx BareFnTy < ' tcx > ) -> Pointer {
174
- self . create_fn_alloc ( FunctionDefinition {
233
+ self . create_fn_alloc ( Function :: Concrete ( FunctionDefinition {
175
234
def_id,
176
235
substs,
177
236
abi : fn_ty. abi ,
178
237
// FIXME: why doesn't this compile?
179
238
//sig: tcx.erase_late_bound_regions(&fn_ty.sig),
180
239
sig : fn_ty. sig . skip_binder ( ) ,
181
- } )
240
+ } ) )
182
241
}
183
242
184
- fn create_fn_alloc ( & mut self , def : FunctionDefinition < ' tcx > ) -> Pointer {
243
+ fn create_fn_alloc ( & mut self , def : Function < ' tcx > ) -> Pointer {
185
244
if let Some ( & alloc_id) = self . function_alloc_cache . get ( & def) {
186
245
return Pointer :: new ( alloc_id, 0 ) ;
187
246
}
188
247
let id = self . next_id ;
189
248
debug ! ( "creating fn ptr: {}" , id) ;
190
249
self . next_id . 0 += 1 ;
191
- self . functions . insert ( id, def. clone ( ) ) ;
250
+ self . functions . insert ( id, def) ;
192
251
self . function_alloc_cache . insert ( def, id) ;
193
252
Pointer :: new ( id, 0 )
194
253
}
@@ -381,15 +440,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
381
440
}
382
441
}
383
442
384
- pub fn get_fn ( & self , id : AllocId ) -> EvalResult < ' tcx , ( DefId , & ' tcx Substs < ' tcx > , Abi , & ' tcx ty :: FnSig < ' tcx > ) > {
443
+ pub fn get_fn ( & self , id : AllocId ) -> EvalResult < ' tcx , Function < ' tcx > > {
385
444
debug ! ( "reading fn ptr: {}" , id) ;
386
445
match self . functions . get ( & id) {
387
- Some ( & FunctionDefinition {
388
- def_id,
389
- substs,
390
- abi,
391
- sig,
392
- } ) => Ok ( ( def_id, substs, abi, sig) ) ,
446
+ Some ( & fndef) => Ok ( fndef) ,
393
447
None => match self . alloc_map . get ( & id) {
394
448
Some ( _) => Err ( EvalError :: ExecuteMemory ) ,
395
449
None => Err ( EvalError :: InvalidFunctionPointer ) ,
@@ -418,14 +472,24 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
418
472
419
473
let alloc = match ( self . alloc_map . get ( & id) , self . functions . get ( & id) ) {
420
474
( Some ( a) , None ) => a,
421
- ( None , Some ( fn_def) ) => {
422
- let name = ty:: tls:: with ( |tcx| tcx. item_path_str ( fn_def. def_id ) ) ;
423
- let abi = if fn_def. abi == Abi :: Rust {
424
- format ! ( "" )
425
- } else {
426
- format ! ( "extern {} " , fn_def. abi)
427
- } ;
428
- trace ! ( "{} function pointer: {}: {}{}" , msg, name, abi, fn_def. sig) ;
475
+ ( None , Some ( & Function :: Concrete ( fn_def) ) ) => {
476
+ trace ! ( "{} {}" , msg, dump_fn_def( fn_def) ) ;
477
+ continue ;
478
+ } ,
479
+ ( None , Some ( & Function :: DropGlue ( fn_def) ) ) => {
480
+ trace ! ( "{} drop glue for {}" , msg, dump_fn_def( fn_def) ) ;
481
+ continue ;
482
+ } ,
483
+ ( None , Some ( & Function :: FnDefAsTraitObject ( fn_def) ) ) => {
484
+ trace ! ( "{} fn as Fn glue for {}" , msg, dump_fn_def( fn_def) ) ;
485
+ continue ;
486
+ } ,
487
+ ( None , Some ( & Function :: FnPtrAsTraitObject ( fn_def) ) ) => {
488
+ trace ! ( "{} fn ptr as Fn glue (signature: {:?})" , msg, fn_def) ;
489
+ continue ;
490
+ } ,
491
+ ( None , Some ( & Function :: Closure ( fn_def) ) ) => {
492
+ trace ! ( "{} closure glue for {}" , msg, dump_fn_def( fn_def) ) ;
429
493
continue ;
430
494
} ,
431
495
( None , None ) => {
@@ -476,6 +540,16 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
476
540
}
477
541
}
478
542
543
+ fn dump_fn_def < ' tcx > ( fn_def : FunctionDefinition < ' tcx > ) -> String {
544
+ let name = ty:: tls:: with ( |tcx| tcx. item_path_str ( fn_def. def_id ) ) ;
545
+ let abi = if fn_def. abi == Abi :: Rust {
546
+ format ! ( "" )
547
+ } else {
548
+ format ! ( "extern {} " , fn_def. abi)
549
+ } ;
550
+ format ! ( "function pointer: {}: {}{}" , name, abi, fn_def. sig)
551
+ }
552
+
479
553
/// Byte accessors
480
554
impl < ' a , ' tcx > Memory < ' a , ' tcx > {
481
555
fn get_bytes_unchecked ( & self , ptr : Pointer , size : u64 , align : u64 ) -> EvalResult < ' tcx , & [ u8 ] > {
0 commit comments