@@ -23,12 +23,15 @@ use trans::type_of;
23
23
use middle:: subst:: Substs ;
24
24
use middle:: ty:: { self , Ty } ;
25
25
use util:: ppaux:: { Repr , ty_to_string} ;
26
+ use util:: nodemap:: NodeMap ;
26
27
27
28
use std:: iter:: repeat;
28
29
use libc:: c_uint;
29
30
use syntax:: { ast, ast_util} ;
30
31
use syntax:: ptr:: P ;
31
32
33
+ type FnArgMap < ' a > = Option < & ' a NodeMap < ValueRef > > ;
34
+
32
35
pub fn const_lit ( cx : & CrateContext , e : & ast:: Expr , lit : & ast:: Lit )
33
36
-> ValueRef {
34
37
let _icx = push_ctxt ( "trans_lit" ) ;
@@ -157,6 +160,29 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
157
160
}
158
161
}
159
162
163
+ fn const_fn_call < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
164
+ node : ExprOrMethodCall ,
165
+ def_id : ast:: DefId ,
166
+ arg_vals : & [ ValueRef ] ,
167
+ param_substs : & ' tcx Substs < ' tcx > ) -> ValueRef {
168
+ let fn_like = const_eval:: lookup_const_fn_by_id ( ccx. tcx ( ) , def_id) ;
169
+ let fn_like = fn_like. expect ( "lookup_const_fn_by_id failed in const_fn_call" ) ;
170
+
171
+ let args = & fn_like. decl ( ) . inputs ;
172
+ assert_eq ! ( args. len( ) , arg_vals. len( ) ) ;
173
+
174
+ let arg_ids = args. iter ( ) . map ( |arg| arg. pat . id ) ;
175
+ let fn_args = arg_ids. zip ( arg_vals. iter ( ) . cloned ( ) ) . collect ( ) ;
176
+
177
+ let substs = ccx. tcx ( ) . mk_substs ( node_id_substs ( ccx, node, param_substs) ) ;
178
+ match fn_like. body ( ) . expr {
179
+ Some ( ref expr) => {
180
+ const_expr ( ccx, & * * expr, substs, Some ( & fn_args) ) . 0
181
+ }
182
+ None => C_nil ( ccx)
183
+ }
184
+ }
185
+
160
186
pub fn get_const_expr < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
161
187
def_id : ast:: DefId ,
162
188
ref_expr : & ast:: Expr )
@@ -217,9 +243,9 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
217
243
// references, even when only the latter are correct.
218
244
let ty = monomorphize:: apply_param_substs ( ccx. tcx ( ) , param_substs,
219
245
& ty:: expr_ty ( ccx. tcx ( ) , expr) ) ;
220
- const_expr_unadjusted ( ccx, expr, ty, param_substs)
246
+ const_expr_unadjusted ( ccx, expr, ty, param_substs, None )
221
247
} else {
222
- const_expr ( ccx, expr, param_substs) . 0
248
+ const_expr ( ccx, expr, param_substs, None ) . 0
223
249
} ;
224
250
225
251
// boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -239,11 +265,12 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
239
265
240
266
pub fn const_expr < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
241
267
e : & ast:: Expr ,
242
- param_substs : & ' tcx Substs < ' tcx > )
268
+ param_substs : & ' tcx Substs < ' tcx > ,
269
+ fn_args : FnArgMap )
243
270
-> ( ValueRef , Ty < ' tcx > ) {
244
271
let ety = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
245
272
& ty:: expr_ty ( cx. tcx ( ) , e) ) ;
246
- let llconst = const_expr_unadjusted ( cx, e, ety, param_substs) ;
273
+ let llconst = const_expr_unadjusted ( cx, e, ety, param_substs, fn_args ) ;
247
274
let mut llconst = llconst;
248
275
let mut ety_adjusted = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
249
276
& ty:: expr_ty_adjusted ( cx. tcx ( ) , e) ) ;
@@ -352,10 +379,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
352
379
fn const_expr_unadjusted < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
353
380
e : & ast:: Expr ,
354
381
ety : Ty < ' tcx > ,
355
- param_substs : & ' tcx Substs < ' tcx > ) -> ValueRef {
356
- let map_list = |exprs : & [ P < ast:: Expr > ] | {
357
- exprs. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
358
- . fold ( Vec :: new ( ) , |mut l, val| { l. push ( val) ; l } )
382
+ param_substs : & ' tcx Substs < ' tcx > ,
383
+ fn_args : FnArgMap )
384
+ -> ValueRef {
385
+ let map_list = |exprs : & [ P < ast:: Expr > ] | -> Vec < ValueRef > {
386
+ exprs. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args) . 0 )
387
+ . collect ( )
359
388
} ;
360
389
unsafe {
361
390
let _icx = push_ctxt ( "const_expr" ) ;
@@ -366,7 +395,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
366
395
ast:: ExprBinary ( b, ref e1, ref e2) => {
367
396
/* Neither type is bottom, and we expect them to be unified
368
397
* already, so the following is safe. */
369
- let ( te1, ty) = const_expr ( cx, & * * e1, param_substs) ;
398
+ let ( te1, ty) = const_expr ( cx, & * * e1, param_substs, fn_args ) ;
370
399
let is_simd = ty:: type_is_simd ( cx. tcx ( ) , ty) ;
371
400
let intype = if is_simd {
372
401
ty:: simd_type ( cx. tcx ( ) , ty)
@@ -376,7 +405,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
376
405
let is_float = ty:: type_is_fp ( intype) ;
377
406
let signed = ty:: type_is_signed ( intype) ;
378
407
379
- let ( te2, _) = const_expr ( cx, & * * e2, param_substs) ;
408
+ let ( te2, _) = const_expr ( cx, & * * e2, param_substs, fn_args ) ;
380
409
let te2 = base:: cast_shift_const_rhs ( b, te1, te2) ;
381
410
382
411
match b. node {
@@ -431,7 +460,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
431
460
}
432
461
} ,
433
462
ast:: ExprUnary ( u, ref e) => {
434
- let ( te, ty) = const_expr ( cx, & * * e, param_substs) ;
463
+ let ( te, ty) = const_expr ( cx, & * * e, param_substs, fn_args ) ;
435
464
let is_float = ty:: type_is_fp ( ty) ;
436
465
match u {
437
466
ast:: UnUniq | ast:: UnDeref => {
@@ -445,23 +474,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
445
474
}
446
475
}
447
476
ast:: ExprField ( ref base, field) => {
448
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
477
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
449
478
let brepr = adt:: represent_type ( cx, bt) ;
450
479
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, field_tys| {
451
480
let ix = ty:: field_idx_strict ( cx. tcx ( ) , field. node . name , field_tys) ;
452
481
adt:: const_get_field ( cx, & * brepr, bv, discr, ix)
453
482
} )
454
483
}
455
484
ast:: ExprTupField ( ref base, idx) => {
456
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
485
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
457
486
let brepr = adt:: represent_type ( cx, bt) ;
458
487
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, _| {
459
488
adt:: const_get_field ( cx, & * brepr, bv, discr, idx. node )
460
489
} )
461
490
}
462
491
463
492
ast:: ExprIndex ( ref base, ref index) => {
464
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
493
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
465
494
let iv = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * index, None ) {
466
495
Ok ( const_eval:: const_int( i) ) => i as u64 ,
467
496
Ok ( const_eval:: const_uint( u) ) => u,
@@ -512,7 +541,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
512
541
}
513
542
ast:: ExprCast ( ref base, _) => {
514
543
let llty = type_of:: type_of ( cx, ety) ;
515
- let ( v, basety) = const_expr ( cx, & * * base, param_substs) ;
544
+ let ( v, basety) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
516
545
if expr:: cast_is_noop ( basety, ety) {
517
546
return v;
518
547
}
@@ -590,12 +619,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
590
619
} else {
591
620
// If this isn't the address of a static, then keep going through
592
621
// normal constant evaluation.
593
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
622
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
594
623
addr_of ( cx, v, "ref" , e. id )
595
624
}
596
625
}
597
626
ast:: ExprAddrOf ( ast:: MutMutable , ref sub) => {
598
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
627
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
599
628
addr_of_mut ( cx, v, "ref_mut_slice" , e. id )
600
629
}
601
630
ast:: ExprTup ( ref es) => {
@@ -607,15 +636,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
607
636
let repr = adt:: represent_type ( cx, ety) ;
608
637
609
638
let base_val = match * base_opt {
610
- Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs) ) ,
639
+ Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs, fn_args ) ) ,
611
640
None => None
612
641
} ;
613
642
614
643
expr:: with_field_tys ( cx. tcx ( ) , ety, Some ( e. id ) , |discr, field_tys| {
615
644
let cs = field_tys. iter ( ) . enumerate ( )
616
645
. map ( |( ix, & field_ty) | {
617
646
match fs. iter ( ) . find ( |f| field_ty. name == f. ident . node . name ) {
618
- Some ( ref f) => const_expr ( cx, & * f. expr , param_substs) . 0 ,
647
+ Some ( ref f) => const_expr ( cx, & * f. expr , param_substs, fn_args ) . 0 ,
619
648
None => {
620
649
match base_val {
621
650
Some ( ( bv, _) ) => {
@@ -640,7 +669,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
640
669
ast:: ExprVec ( ref es) => {
641
670
let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
642
671
let llunitty = type_of:: type_of ( cx, unit_ty) ;
643
- let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
672
+ let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args ) . 0 )
644
673
. collect :: < Vec < _ > > ( ) ;
645
674
// If the vector contains enums, an LLVM array won't work.
646
675
if vs. iter ( ) . any ( |vi| val_ty ( * vi) != llunitty) {
@@ -657,7 +686,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
657
686
Ok ( const_eval:: const_uint( i) ) => i as uint ,
658
687
_ => cx. sess ( ) . span_bug ( count. span , "count must be integral const expression." )
659
688
} ;
660
- let unit_val = const_expr ( cx, & * * elem, param_substs) . 0 ;
689
+ let unit_val = const_expr ( cx, & * * elem, param_substs, fn_args ) . 0 ;
661
690
let vs: Vec < _ > = repeat ( unit_val) . take ( n) . collect ( ) ;
662
691
if val_ty ( unit_val) != llunitty {
663
692
C_struct ( cx, & vs[ ..] , false )
@@ -668,6 +697,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
668
697
ast:: ExprPath ( ..) => {
669
698
let def = cx. tcx ( ) . def_map . borrow ( ) [ e. id ] . full_def ( ) ;
670
699
match def {
700
+ def:: DefLocal ( id) => {
701
+ if let Some ( val) = fn_args. and_then ( |args| args. get ( & id) . cloned ( ) ) {
702
+ val
703
+ } else {
704
+ cx. sess ( ) . span_bug ( e. span , "const fn argument not found" )
705
+ }
706
+ }
671
707
def:: DefFn ( ..) | def:: DefMethod ( ..) => {
672
708
expr:: trans_def_fn_unadjusted ( cx, e, def, param_substs) . val
673
709
}
@@ -703,18 +739,32 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
703
739
}
704
740
}
705
741
ast:: ExprCall ( ref callee, ref args) => {
706
- let opt_def = cx. tcx ( ) . def_map . borrow ( ) . get ( & callee. id ) . map ( |d| d. full_def ( ) ) ;
707
- let arg_vals = map_list ( & args[ ..] ) ;
708
- match opt_def {
709
- Some ( def:: DefStruct ( _) ) => {
742
+ let mut callee = & * * callee;
743
+ loop {
744
+ callee = match callee. node {
745
+ ast:: ExprParen ( ref inner) => & * * inner,
746
+ ast:: ExprBlock ( ref block) => match block. expr {
747
+ Some ( ref tail) => & * * tail,
748
+ None => break
749
+ } ,
750
+ _ => break
751
+ } ;
752
+ }
753
+ let def = cx. tcx ( ) . def_map . borrow ( ) [ callee. id ] . full_def ( ) ;
754
+ let arg_vals = map_list ( args) ;
755
+ match def {
756
+ def:: DefFn ( did, _) | def:: DefMethod ( did, _) => {
757
+ const_fn_call ( cx, ExprId ( callee. id ) , did, & arg_vals, param_substs)
758
+ }
759
+ def:: DefStruct ( _) => {
710
760
if ty:: type_is_simd ( cx. tcx ( ) , ety) {
711
761
C_vector ( & arg_vals[ ..] )
712
762
} else {
713
763
let repr = adt:: represent_type ( cx, ety) ;
714
764
adt:: trans_const ( cx, & * repr, 0 , & arg_vals[ ..] )
715
765
}
716
766
}
717
- Some ( def:: DefVariant ( enum_did, variant_did, _) ) => {
767
+ def:: DefVariant ( enum_did, variant_did, _) => {
718
768
let repr = adt:: represent_type ( cx, ety) ;
719
769
let vinfo = ty:: enum_variant_with_id ( cx. tcx ( ) ,
720
770
enum_did,
@@ -724,13 +774,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
724
774
vinfo. disr_val ,
725
775
& arg_vals[ ..] )
726
776
}
727
- _ => cx. sess ( ) . span_bug ( e. span , "expected a struct or variant def" )
777
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a struct, variant, or const fn def" )
728
778
}
729
779
}
730
- ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs) . 0 ,
780
+ ast:: ExprMethodCall ( _, _, ref args) => {
781
+ let arg_vals = map_list ( args) ;
782
+ let method_call = ty:: MethodCall :: expr ( e. id ) ;
783
+ let method_did = match cx. tcx ( ) . method_map . borrow ( ) [ method_call] . origin {
784
+ ty:: MethodStatic ( did) => did,
785
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a const method def" )
786
+ } ;
787
+ const_fn_call ( cx, MethodCallKey ( method_call) ,
788
+ method_did, & arg_vals, param_substs)
789
+ }
790
+ ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs, fn_args) . 0 ,
731
791
ast:: ExprBlock ( ref block) => {
732
792
match block. expr {
733
- Some ( ref expr) => const_expr ( cx, & * * expr, param_substs) . 0 ,
793
+ Some ( ref expr) => const_expr ( cx, & * * expr, param_substs, fn_args ) . 0 ,
734
794
None => C_nil ( cx)
735
795
}
736
796
}
0 commit comments