@@ -33,13 +33,16 @@ use middle::cast::{CastTy,IntTy};
33
33
use middle:: subst:: Substs ;
34
34
use middle:: ty:: { self , Ty } ;
35
35
use util:: ppaux:: { Repr , ty_to_string} ;
36
+ use util:: nodemap:: NodeMap ;
36
37
37
38
use std:: iter:: repeat;
38
39
use libc:: c_uint;
39
40
use syntax:: { ast, ast_util} ;
40
41
use syntax:: parse:: token;
41
42
use syntax:: ptr:: P ;
42
43
44
+ type FnArgMap < ' a > = Option < & ' a NodeMap < ValueRef > > ;
45
+
43
46
pub fn const_lit ( cx : & CrateContext , e : & ast:: Expr , lit : & ast:: Lit )
44
47
-> ValueRef {
45
48
let _icx = push_ctxt ( "trans_lit" ) ;
@@ -163,6 +166,29 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
163
166
}
164
167
}
165
168
169
+ fn const_fn_call < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
170
+ node : ExprOrMethodCall ,
171
+ def_id : ast:: DefId ,
172
+ arg_vals : & [ ValueRef ] ,
173
+ param_substs : & ' tcx Substs < ' tcx > ) -> ValueRef {
174
+ let fn_like = const_eval:: lookup_const_fn_by_id ( ccx. tcx ( ) , def_id) ;
175
+ let fn_like = fn_like. expect ( "lookup_const_fn_by_id failed in const_fn_call" ) ;
176
+
177
+ let args = & fn_like. decl ( ) . inputs ;
178
+ assert_eq ! ( args. len( ) , arg_vals. len( ) ) ;
179
+
180
+ let arg_ids = args. iter ( ) . map ( |arg| arg. pat . id ) ;
181
+ let fn_args = arg_ids. zip ( arg_vals. iter ( ) . cloned ( ) ) . collect ( ) ;
182
+
183
+ let substs = ccx. tcx ( ) . mk_substs ( node_id_substs ( ccx, node, param_substs) ) ;
184
+ match fn_like. body ( ) . expr {
185
+ Some ( ref expr) => {
186
+ const_expr ( ccx, & * * expr, substs, Some ( & fn_args) ) . 0
187
+ }
188
+ None => C_nil ( ccx)
189
+ }
190
+ }
191
+
166
192
pub fn get_const_expr < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
167
193
def_id : ast:: DefId ,
168
194
ref_expr : & ast:: Expr )
@@ -221,9 +247,9 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
221
247
// references, even when only the latter are correct.
222
248
let ty = monomorphize:: apply_param_substs ( ccx. tcx ( ) , param_substs,
223
249
& ty:: expr_ty ( ccx. tcx ( ) , expr) ) ;
224
- const_expr_unadjusted ( ccx, expr, ty, param_substs)
250
+ const_expr_unadjusted ( ccx, expr, ty, param_substs, None )
225
251
} else {
226
- const_expr ( ccx, expr, param_substs) . 0
252
+ const_expr ( ccx, expr, param_substs, None ) . 0
227
253
} ;
228
254
229
255
// boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -243,11 +269,12 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
243
269
244
270
pub fn const_expr < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
245
271
e : & ast:: Expr ,
246
- param_substs : & ' tcx Substs < ' tcx > )
272
+ param_substs : & ' tcx Substs < ' tcx > ,
273
+ fn_args : FnArgMap )
247
274
-> ( ValueRef , Ty < ' tcx > ) {
248
275
let ety = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
249
276
& ty:: expr_ty ( cx. tcx ( ) , e) ) ;
250
- let llconst = const_expr_unadjusted ( cx, e, ety, param_substs) ;
277
+ let llconst = const_expr_unadjusted ( cx, e, ety, param_substs, fn_args ) ;
251
278
let mut llconst = llconst;
252
279
let mut ety_adjusted = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
253
280
& ty:: expr_ty_adjusted ( cx. tcx ( ) , e) ) ;
@@ -440,17 +467,19 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
440
467
fn const_expr_unadjusted < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
441
468
e : & ast:: Expr ,
442
469
ety : Ty < ' tcx > ,
443
- param_substs : & ' tcx Substs < ' tcx > )
470
+ param_substs : & ' tcx Substs < ' tcx > ,
471
+ fn_args : FnArgMap )
444
472
-> ValueRef
445
473
{
446
474
debug ! ( "const_expr_unadjusted(e={}, ety={}, param_substs={})" ,
447
475
e. repr( cx. tcx( ) ) ,
448
476
ety. repr( cx. tcx( ) ) ,
449
477
param_substs. repr( cx. tcx( ) ) ) ;
450
478
451
- let map_list = |exprs : & [ P < ast:: Expr > ] | {
452
- exprs. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
453
- . fold ( Vec :: new ( ) , |mut l, val| { l. push ( val) ; l } )
479
+ let map_list = |exprs : & [ P < ast:: Expr > ] | -> Vec < ValueRef > {
480
+ exprs. iter ( )
481
+ . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args) . 0 )
482
+ . collect ( )
454
483
} ;
455
484
unsafe {
456
485
let _icx = push_ctxt ( "const_expr" ) ;
@@ -461,7 +490,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
461
490
ast:: ExprBinary ( b, ref e1, ref e2) => {
462
491
/* Neither type is bottom, and we expect them to be unified
463
492
* already, so the following is safe. */
464
- let ( te1, ty) = const_expr ( cx, & * * e1, param_substs) ;
493
+ let ( te1, ty) = const_expr ( cx, & * * e1, param_substs, fn_args ) ;
465
494
debug ! ( "const_expr_unadjusted: te1={}, ty={}" ,
466
495
cx. tn( ) . val_to_string( te1) ,
467
496
ty. repr( cx. tcx( ) ) ) ;
@@ -474,7 +503,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
474
503
let is_float = ty:: type_is_fp ( intype) ;
475
504
let signed = ty:: type_is_signed ( intype) ;
476
505
477
- let ( te2, _) = const_expr ( cx, & * * e2, param_substs) ;
506
+ let ( te2, _) = const_expr ( cx, & * * e2, param_substs, fn_args ) ;
478
507
479
508
check_binary_expr_validity ( cx, e, ty, te1, te2) ;
480
509
@@ -534,7 +563,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
534
563
}
535
564
} ,
536
565
ast:: ExprUnary ( u, ref inner_e) => {
537
- let ( te, ty) = const_expr ( cx, & * * inner_e, param_substs) ;
566
+ let ( te, ty) = const_expr ( cx, & * * inner_e, param_substs, fn_args ) ;
538
567
539
568
check_unary_expr_validity ( cx, e, ty, te) ;
540
569
@@ -551,23 +580,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
551
580
}
552
581
}
553
582
ast:: ExprField ( ref base, field) => {
554
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
583
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
555
584
let brepr = adt:: represent_type ( cx, bt) ;
556
585
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, field_tys| {
557
586
let ix = ty:: field_idx_strict ( cx. tcx ( ) , field. node . name , field_tys) ;
558
587
adt:: const_get_field ( cx, & * brepr, bv, discr, ix)
559
588
} )
560
589
}
561
590
ast:: ExprTupField ( ref base, idx) => {
562
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
591
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
563
592
let brepr = adt:: represent_type ( cx, bt) ;
564
593
expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, _| {
565
594
adt:: const_get_field ( cx, & * brepr, bv, discr, idx. node )
566
595
} )
567
596
}
568
597
569
598
ast:: ExprIndex ( ref base, ref index) => {
570
- let ( bv, bt) = const_expr ( cx, & * * base, param_substs) ;
599
+ let ( bv, bt) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
571
600
let iv = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * index, None ) {
572
601
Ok ( const_eval:: const_int( i) ) => i as u64 ,
573
602
Ok ( const_eval:: const_uint( u) ) => u,
@@ -619,7 +648,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
619
648
ast:: ExprCast ( ref base, _) => {
620
649
let t_cast = ety;
621
650
let llty = type_of:: type_of ( cx, t_cast) ;
622
- let ( v, t_expr) = const_expr ( cx, & * * base, param_substs) ;
651
+ let ( v, t_expr) = const_expr ( cx, & * * base, param_substs, fn_args ) ;
623
652
debug ! ( "trans_const_cast({} as {})" , t_expr. repr( cx. tcx( ) ) , t_cast. repr( cx. tcx( ) ) ) ;
624
653
if expr:: cast_is_noop ( cx. tcx ( ) , base, t_expr, t_cast) {
625
654
return v;
@@ -707,12 +736,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
707
736
} else {
708
737
// If this isn't the address of a static, then keep going through
709
738
// normal constant evaluation.
710
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
739
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
711
740
addr_of ( cx, v, "ref" )
712
741
}
713
742
}
714
743
ast:: ExprAddrOf ( ast:: MutMutable , ref sub) => {
715
- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
744
+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
716
745
addr_of_mut ( cx, v, "ref_mut_slice" )
717
746
}
718
747
ast:: ExprTup ( ref es) => {
@@ -724,15 +753,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
724
753
let repr = adt:: represent_type ( cx, ety) ;
725
754
726
755
let base_val = match * base_opt {
727
- Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs) ) ,
756
+ Some ( ref base) => Some ( const_expr ( cx, & * * base, param_substs, fn_args ) ) ,
728
757
None => None
729
758
} ;
730
759
731
760
expr:: with_field_tys ( cx. tcx ( ) , ety, Some ( e. id ) , |discr, field_tys| {
732
761
let cs = field_tys. iter ( ) . enumerate ( )
733
762
. map ( |( ix, & field_ty) | {
734
763
match fs. iter ( ) . find ( |f| field_ty. name == f. ident . node . name ) {
735
- Some ( ref f) => const_expr ( cx, & * f. expr , param_substs) . 0 ,
764
+ Some ( ref f) => const_expr ( cx, & * f. expr , param_substs, fn_args ) . 0 ,
736
765
None => {
737
766
match base_val {
738
767
Some ( ( bv, _) ) => {
@@ -757,7 +786,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
757
786
ast:: ExprVec ( ref es) => {
758
787
let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
759
788
let llunitty = type_of:: type_of ( cx, unit_ty) ;
760
- let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs) . 0 )
789
+ let vs = es. iter ( ) . map ( |e| const_expr ( cx, & * * e, param_substs, fn_args ) . 0 )
761
790
. collect :: < Vec < _ > > ( ) ;
762
791
// If the vector contains enums, an LLVM array won't work.
763
792
if vs. iter ( ) . any ( |vi| val_ty ( * vi) != llunitty) {
@@ -770,7 +799,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
770
799
let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
771
800
let llunitty = type_of:: type_of ( cx, unit_ty) ;
772
801
let n = ty:: eval_repeat_count ( cx. tcx ( ) , count) ;
773
- let unit_val = const_expr ( cx, & * * elem, param_substs) . 0 ;
802
+ let unit_val = const_expr ( cx, & * * elem, param_substs, fn_args ) . 0 ;
774
803
let vs: Vec < _ > = repeat ( unit_val) . take ( n) . collect ( ) ;
775
804
if val_ty ( unit_val) != llunitty {
776
805
C_struct ( cx, & vs[ ..] , false )
@@ -781,6 +810,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
781
810
ast:: ExprPath ( ..) => {
782
811
let def = cx. tcx ( ) . def_map . borrow ( ) . get ( & e. id ) . unwrap ( ) . full_def ( ) ;
783
812
match def {
813
+ def:: DefLocal ( id) => {
814
+ if let Some ( val) = fn_args. and_then ( |args| args. get ( & id) . cloned ( ) ) {
815
+ val
816
+ } else {
817
+ cx. sess ( ) . span_bug ( e. span , "const fn argument not found" )
818
+ }
819
+ }
784
820
def:: DefFn ( ..) | def:: DefMethod ( ..) => {
785
821
expr:: trans_def_fn_unadjusted ( cx, e, def, param_substs) . val
786
822
}
@@ -816,18 +852,32 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
816
852
}
817
853
}
818
854
ast:: ExprCall ( ref callee, ref args) => {
819
- let opt_def = cx. tcx ( ) . def_map . borrow ( ) . get ( & callee. id ) . map ( |d| d. full_def ( ) ) ;
820
- let arg_vals = map_list ( & args[ ..] ) ;
821
- match opt_def {
822
- Some ( def:: DefStruct ( _) ) => {
855
+ let mut callee = & * * callee;
856
+ loop {
857
+ callee = match callee. node {
858
+ ast:: ExprParen ( ref inner) => & * * inner,
859
+ ast:: ExprBlock ( ref block) => match block. expr {
860
+ Some ( ref tail) => & * * tail,
861
+ None => break
862
+ } ,
863
+ _ => break
864
+ } ;
865
+ }
866
+ let def = cx. tcx ( ) . def_map . borrow ( ) [ callee. id ] . full_def ( ) ;
867
+ let arg_vals = map_list ( args) ;
868
+ match def {
869
+ def:: DefFn ( did, _) | def:: DefMethod ( did, _) => {
870
+ const_fn_call ( cx, ExprId ( callee. id ) , did, & arg_vals, param_substs)
871
+ }
872
+ def:: DefStruct ( _) => {
823
873
if ty:: type_is_simd ( cx. tcx ( ) , ety) {
824
874
C_vector ( & arg_vals[ ..] )
825
875
} else {
826
876
let repr = adt:: represent_type ( cx, ety) ;
827
877
adt:: trans_const ( cx, & * repr, 0 , & arg_vals[ ..] )
828
878
}
829
879
}
830
- Some ( def:: DefVariant ( enum_did, variant_did, _) ) => {
880
+ def:: DefVariant ( enum_did, variant_did, _) => {
831
881
let repr = adt:: represent_type ( cx, ety) ;
832
882
let vinfo = ty:: enum_variant_with_id ( cx. tcx ( ) ,
833
883
enum_did,
@@ -837,13 +887,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
837
887
vinfo. disr_val ,
838
888
& arg_vals[ ..] )
839
889
}
840
- _ => cx. sess ( ) . span_bug ( e. span , "expected a struct or variant def" )
890
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a struct, variant, or const fn def" )
841
891
}
842
892
}
843
- ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs) . 0 ,
893
+ ast:: ExprMethodCall ( _, _, ref args) => {
894
+ let arg_vals = map_list ( args) ;
895
+ let method_call = ty:: MethodCall :: expr ( e. id ) ;
896
+ let method_did = match cx. tcx ( ) . method_map . borrow ( ) [ method_call] . origin {
897
+ ty:: MethodStatic ( did) => did,
898
+ _ => cx. sess ( ) . span_bug ( e. span , "expected a const method def" )
899
+ } ;
900
+ const_fn_call ( cx, MethodCallKey ( method_call) ,
901
+ method_did, & arg_vals, param_substs)
902
+ }
903
+ ast:: ExprParen ( ref e) => const_expr ( cx, & * * e, param_substs, fn_args) . 0 ,
844
904
ast:: ExprBlock ( ref block) => {
845
905
match block. expr {
846
- Some ( ref expr) => const_expr ( cx, & * * expr, param_substs) . 0 ,
906
+ Some ( ref expr) => const_expr ( cx, & * * expr, param_substs, fn_args ) . 0 ,
847
907
None => C_nil ( cx)
848
908
}
849
909
}
0 commit comments