1
1
// Translation of automatically-derived trait implementations. This handles
2
2
// enums and structs only; other types cannot be automatically derived.
3
3
4
- use lib:: llvm:: llvm;
4
+ use lib:: llvm:: llvm:: { LLVMCountParams , LLVMGetParam } ;
5
5
use middle:: trans:: base:: { GEP_enum , finish_fn, get_insn_ctxt, get_item_val} ;
6
6
use middle:: trans:: base:: { new_fn_ctxt, sub_block, top_scope_block} ;
7
7
use middle:: trans:: build:: { AddCase , Br , CondBr , GEPi , Load , PointerCast } ;
@@ -11,6 +11,7 @@ use middle::trans::callee::{ArgVals, Callee, DontAutorefArg, Method};
11
11
use middle:: trans:: callee:: { MethodData } ;
12
12
use middle:: trans:: common;
13
13
use middle:: trans:: common:: { C_bool , C_int , T_ptr , block, crate_ctxt} ;
14
+ use middle:: trans:: common:: { fn_ctxt} ;
14
15
use middle:: trans:: expr:: SaveIn ;
15
16
use middle:: trans:: type_of:: type_of;
16
17
use middle:: ty:: DerivedFieldInfo ;
@@ -21,6 +22,10 @@ use syntax::ast_map::path;
21
22
use syntax:: ast_util;
22
23
use syntax:: ast_util:: local_def;
23
24
25
+ use core:: dvec:: DVec ;
26
+ use core:: dvec;
27
+ use core:: libc:: c_uint;
28
+
24
29
/// The kind of deriving method this is.
25
30
enum DerivingKind {
26
31
BoolKind , // fn f(&self, other: &other) -> bool
@@ -93,6 +98,23 @@ pub fn trans_deriving_impl(ccx: @crate_ctxt,
93
98
}
94
99
}
95
100
101
+ fn get_extra_params ( llfn : ValueRef , kind : DerivingKind ) -> ~[ ValueRef ] {
102
+ let n_params = LLVMCountParams ( llfn) as uint ;
103
+
104
+ let initial_extra_param;
105
+ match kind {
106
+ BoolKind => initial_extra_param = 3 ,
107
+ UnitKind => initial_extra_param = 2 ,
108
+ }
109
+
110
+ let extra_params = DVec ( ) ;
111
+ for uint:: range( initial_extra_param, n_params) |i| {
112
+ extra_params. push ( LLVMGetParam ( llfn, i as c_uint ) ) ;
113
+ }
114
+
115
+ return dvec:: unwrap ( move extra_params) ;
116
+ }
117
+
96
118
fn trans_deriving_struct_method ( ccx : @crate_ctxt ,
97
119
llfn : ValueRef ,
98
120
impl_did : def_id ,
@@ -104,14 +126,16 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
104
126
let lltop = top_bcx. llbb ;
105
127
let mut bcx = top_bcx;
106
128
129
+ let llextraparams = get_extra_params ( llfn, kind) ;
130
+
107
131
let llselfty = type_of ( ccx, self_ty) ;
108
132
let llselfval = PointerCast ( bcx, fcx. llenv , T_ptr ( llselfty) ) ;
109
133
110
134
// If there is an "other" value, then get it. The "other" value is the
111
135
// value we're comparing against in the case of Eq and Ord.
112
136
let llotherval_opt;
113
137
match kind {
114
- BoolKind => llotherval_opt = Some ( llvm :: LLVMGetParam ( llfn, 2 ) ) ,
138
+ BoolKind => llotherval_opt = Some ( LLVMGetParam ( llfn, 2 ) ) ,
115
139
UnitKind => llotherval_opt = None
116
140
}
117
141
@@ -136,8 +160,12 @@ fn trans_deriving_struct_method(ccx: @crate_ctxt,
136
160
|llotherval| GEPi ( bcx, * llotherval, [ 0 , 0 , i] ) ) ;
137
161
138
162
let self_ty = struct_field_tys[ i] . mt . ty ;
139
- bcx = call_substructure_method ( bcx, derived_method_info, self_ty,
140
- llselfval, llotherval_opt) ;
163
+ bcx = call_substructure_method ( bcx,
164
+ derived_method_info,
165
+ self_ty,
166
+ llselfval,
167
+ llotherval_opt,
168
+ llextraparams) ;
141
169
142
170
// If this derived method is of boolean kind, return immediately if
143
171
// the call to the substructure method returned false.
@@ -176,13 +204,15 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
176
204
let lltop = top_bcx. llbb ;
177
205
let mut bcx = top_bcx;
178
206
207
+ let llextraparams = get_extra_params ( llfn, kind) ;
208
+
179
209
let llselfty = type_of ( ccx, self_ty) ;
180
210
let llselfval = PointerCast ( bcx, fcx. llenv , T_ptr ( llselfty) ) ;
181
211
182
212
let llotherval_opt;
183
213
match kind {
184
214
UnitKind => llotherval_opt = None ,
185
- BoolKind => llotherval_opt = Some ( llvm :: LLVMGetParam ( llfn, 2 ) )
215
+ BoolKind => llotherval_opt = Some ( LLVMGetParam ( llfn, 2 ) )
186
216
}
187
217
188
218
let enum_id, enum_substs, enum_variant_infos;
@@ -260,7 +290,8 @@ fn trans_deriving_enum_method(ccx: @crate_ctxt,
260
290
derived_method_info,
261
291
self_ty,
262
292
llselfval,
263
- llotherval_opt) ;
293
+ llotherval_opt,
294
+ llextraparams) ;
264
295
265
296
// If this is a boolean-kind deriving method, then return
266
297
// immediately if the call to the substructure returned false.
@@ -339,7 +370,8 @@ fn call_substructure_method(bcx: block,
339
370
derived_field_info : & DerivedFieldInfo ,
340
371
self_ty : ty:: t ,
341
372
llselfval : ValueRef ,
342
- llotherval_opt : Option < ValueRef > ) -> block {
373
+ llotherval_opt : Option < ValueRef > ,
374
+ llextraparams : & [ ValueRef ] ) -> block {
343
375
let fcx = bcx. fcx ;
344
376
let ccx = fcx. ccx ;
345
377
@@ -367,6 +399,7 @@ fn call_substructure_method(bcx: block,
367
399
vtable_result ) ;
368
400
let llfn = fn_data. llfn ;
369
401
402
+ // Create the callee.
370
403
let cb: & fn ( block ) -> Callee = |bloc| {
371
404
Callee {
372
405
bcx : bloc,
@@ -379,18 +412,18 @@ fn call_substructure_method(bcx: block,
379
412
}
380
413
} ;
381
414
382
- let arg_values;
383
- match llotherval_opt {
384
- None => arg_values = ArgVals ( ~[ ] ) ,
385
- Some ( copy llotherval) => arg_values = ArgVals ( ~[ llotherval] )
386
- }
415
+ // Build up the argument list.
416
+ let llargvals = DVec ( ) ;
417
+ for llotherval_opt. each |llotherval| { llargvals. push ( * llotherval) ; }
418
+ for llextraparams. each |llextraparam| { llargvals. push ( * llextraparam) ; }
387
419
420
+ // And perform the call.
388
421
callee:: trans_call_inner ( bcx,
389
422
None ,
390
423
fn_expr_tpbt. ty ,
391
424
ty:: mk_bool ( ccx. tcx ) ,
392
425
cb,
393
- move arg_values ,
426
+ ArgVals ( dvec :: unwrap ( move llargvals ) ) ,
394
427
SaveIn ( fcx. llretptr ) ,
395
428
DontAutorefArg )
396
429
}
0 commit comments