@@ -33,13 +33,16 @@ use middle::cast::{CastTy,IntTy};
3333use middle:: subst:: Substs ;
3434use middle:: ty:: { self , Ty } ;
3535use util:: ppaux:: { Repr , ty_to_string} ;
36+ use util:: nodemap:: NodeMap ;
3637
3738use std:: iter:: repeat;
3839use libc:: c_uint;
3940use syntax:: { ast, ast_util} ;
4041use syntax:: parse:: token;
4142use syntax:: ptr:: P ;
4243
44+ type FnArgMap < ' a > = Option < & ' a NodeMap < ValueRef > > ;
45+
4346pub fn const_lit ( cx : & CrateContext , e : & ast:: Expr , lit : & ast:: Lit )
4447 -> ValueRef {
4548 let _icx = push_ctxt ( "trans_lit" ) ;
@@ -163,6 +166,29 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
163166 }
164167}
165168
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+
166192pub fn get_const_expr < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
167193 def_id : ast:: DefId ,
168194 ref_expr : & ast:: Expr )
@@ -221,9 +247,9 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
221247 // references, even when only the latter are correct.
222248 let ty = monomorphize:: apply_param_substs ( ccx. tcx ( ) , param_substs,
223249 & 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 )
225251 } else {
226- const_expr ( ccx, expr, param_substs) . 0
252+ const_expr ( ccx, expr, param_substs, None ) . 0
227253 } ;
228254
229255 // 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>,
243269
244270pub fn const_expr < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
245271 e : & ast:: Expr ,
246- param_substs : & ' tcx Substs < ' tcx > )
272+ param_substs : & ' tcx Substs < ' tcx > ,
273+ fn_args : FnArgMap )
247274 -> ( ValueRef , Ty < ' tcx > ) {
248275 let ety = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
249276 & 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 ) ;
251278 let mut llconst = llconst;
252279 let mut ety_adjusted = monomorphize:: apply_param_substs ( cx. tcx ( ) , param_substs,
253280 & ty:: expr_ty_adjusted ( cx. tcx ( ) , e) ) ;
@@ -440,17 +467,19 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
440467fn const_expr_unadjusted < ' a , ' tcx > ( cx : & CrateContext < ' a , ' tcx > ,
441468 e : & ast:: Expr ,
442469 ety : Ty < ' tcx > ,
443- param_substs : & ' tcx Substs < ' tcx > )
470+ param_substs : & ' tcx Substs < ' tcx > ,
471+ fn_args : FnArgMap )
444472 -> ValueRef
445473{
446474 debug ! ( "const_expr_unadjusted(e={}, ety={}, param_substs={})" ,
447475 e. repr( cx. tcx( ) ) ,
448476 ety. repr( cx. tcx( ) ) ,
449477 param_substs. repr( cx. tcx( ) ) ) ;
450478
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 ( )
454483 } ;
455484 unsafe {
456485 let _icx = push_ctxt ( "const_expr" ) ;
@@ -461,7 +490,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
461490 ast:: ExprBinary ( b, ref e1, ref e2) => {
462491 /* Neither type is bottom, and we expect them to be unified
463492 * 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 ) ;
465494 debug ! ( "const_expr_unadjusted: te1={}, ty={}" ,
466495 cx. tn( ) . val_to_string( te1) ,
467496 ty. repr( cx. tcx( ) ) ) ;
@@ -474,7 +503,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
474503 let is_float = ty:: type_is_fp ( intype) ;
475504 let signed = ty:: type_is_signed ( intype) ;
476505
477- let ( te2, _) = const_expr ( cx, & * * e2, param_substs) ;
506+ let ( te2, _) = const_expr ( cx, & * * e2, param_substs, fn_args ) ;
478507
479508 check_binary_expr_validity ( cx, e, ty, te1, te2) ;
480509
@@ -534,7 +563,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
534563 }
535564 } ,
536565 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 ) ;
538567
539568 check_unary_expr_validity ( cx, e, ty, te) ;
540569
@@ -551,23 +580,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
551580 }
552581 }
553582 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 ) ;
555584 let brepr = adt:: represent_type ( cx, bt) ;
556585 expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, field_tys| {
557586 let ix = ty:: field_idx_strict ( cx. tcx ( ) , field. node . name , field_tys) ;
558587 adt:: const_get_field ( cx, & * brepr, bv, discr, ix)
559588 } )
560589 }
561590 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 ) ;
563592 let brepr = adt:: represent_type ( cx, bt) ;
564593 expr:: with_field_tys ( cx. tcx ( ) , bt, None , |discr, _| {
565594 adt:: const_get_field ( cx, & * brepr, bv, discr, idx. node )
566595 } )
567596 }
568597
569598 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 ) ;
571600 let iv = match const_eval:: eval_const_expr_partial ( cx. tcx ( ) , & * * index, None ) {
572601 Ok ( const_eval:: const_int( i) ) => i as u64 ,
573602 Ok ( const_eval:: const_uint( u) ) => u,
@@ -619,7 +648,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
619648 ast:: ExprCast ( ref base, _) => {
620649 let t_cast = ety;
621650 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 ) ;
623652 debug ! ( "trans_const_cast({} as {})" , t_expr. repr( cx. tcx( ) ) , t_cast. repr( cx. tcx( ) ) ) ;
624653 if expr:: cast_is_noop ( cx. tcx ( ) , base, t_expr, t_cast) {
625654 return v;
@@ -707,12 +736,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
707736 } else {
708737 // If this isn't the address of a static, then keep going through
709738 // normal constant evaluation.
710- let ( v, _) = const_expr ( cx, & * * sub, param_substs) ;
739+ let ( v, _) = const_expr ( cx, & * * sub, param_substs, fn_args ) ;
711740 addr_of ( cx, v, "ref" )
712741 }
713742 }
714743 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 ) ;
716745 addr_of_mut ( cx, v, "ref_mut_slice" )
717746 }
718747 ast:: ExprTup ( ref es) => {
@@ -724,15 +753,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
724753 let repr = adt:: represent_type ( cx, ety) ;
725754
726755 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 ) ) ,
728757 None => None
729758 } ;
730759
731760 expr:: with_field_tys ( cx. tcx ( ) , ety, Some ( e. id ) , |discr, field_tys| {
732761 let cs = field_tys. iter ( ) . enumerate ( )
733762 . map ( |( ix, & field_ty) | {
734763 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 ,
736765 None => {
737766 match base_val {
738767 Some ( ( bv, _) ) => {
@@ -757,7 +786,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
757786 ast:: ExprVec ( ref es) => {
758787 let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
759788 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 )
761790 . collect :: < Vec < _ > > ( ) ;
762791 // If the vector contains enums, an LLVM array won't work.
763792 if vs. iter ( ) . any ( |vi| val_ty ( * vi) != llunitty) {
@@ -770,7 +799,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
770799 let unit_ty = ty:: sequence_element_type ( cx. tcx ( ) , ety) ;
771800 let llunitty = type_of:: type_of ( cx, unit_ty) ;
772801 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 ;
774803 let vs: Vec < _ > = repeat ( unit_val) . take ( n) . collect ( ) ;
775804 if val_ty ( unit_val) != llunitty {
776805 C_struct ( cx, & vs[ ..] , false )
@@ -781,6 +810,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
781810 ast:: ExprPath ( ..) => {
782811 let def = cx. tcx ( ) . def_map . borrow ( ) . get ( & e. id ) . unwrap ( ) . full_def ( ) ;
783812 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+ }
784820 def:: DefFn ( ..) | def:: DefMethod ( ..) => {
785821 expr:: trans_def_fn_unadjusted ( cx, e, def, param_substs) . val
786822 }
@@ -816,18 +852,32 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
816852 }
817853 }
818854 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 ( _) => {
823873 if ty:: type_is_simd ( cx. tcx ( ) , ety) {
824874 C_vector ( & arg_vals[ ..] )
825875 } else {
826876 let repr = adt:: represent_type ( cx, ety) ;
827877 adt:: trans_const ( cx, & * repr, 0 , & arg_vals[ ..] )
828878 }
829879 }
830- Some ( def:: DefVariant ( enum_did, variant_did, _) ) => {
880+ def:: DefVariant ( enum_did, variant_did, _) => {
831881 let repr = adt:: represent_type ( cx, ety) ;
832882 let vinfo = ty:: enum_variant_with_id ( cx. tcx ( ) ,
833883 enum_did,
@@ -837,13 +887,23 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
837887 vinfo. disr_val ,
838888 & arg_vals[ ..] )
839889 }
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" )
841891 }
842892 }
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 ,
844904 ast:: ExprBlock ( ref block) => {
845905 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 ,
847907 None => C_nil ( cx)
848908 }
849909 }
0 commit comments