@@ -563,6 +563,27 @@ pub enum ConstantEvaluatorError {
563563 RuntimeExpr ,
564564 #[ error( "Unexpected override-expression" ) ]
565565 OverrideExpr ,
566+ #[ error( "Expected boolean expression for condition argument of `select`, got something else" ) ]
567+ SelectScalarConditionNotABool ,
568+ #[ error(
569+ "Expected vectors of the same size for reject and accept args., got {:?} and {:?}" ,
570+ reject,
571+ accept
572+ ) ]
573+ SelectVecRejectAcceptSizeMismatch {
574+ reject : crate :: VectorSize ,
575+ accept : crate :: VectorSize ,
576+ } ,
577+ #[ error( "Expected boolean vector for condition arg., got something else" ) ]
578+ SelectConditionNotAVecBool ,
579+ #[ error(
580+ "Expected same number of vector components between condition, accept, and reject args., got something else" ,
581+ ) ]
582+ SelectConditionVecSizeMismatch ,
583+ #[ error(
584+ "Expected reject and accept args. to be scalars of vectors of the same type, got something else" ,
585+ ) ]
586+ SelectAcceptRejectTypeMismatch ,
566587}
567588
568589impl < ' a > ConstantEvaluator < ' a > {
@@ -904,9 +925,11 @@ impl<'a> ConstantEvaluator<'a> {
904925 ) ) ,
905926 }
906927 }
907- Expression :: Select { .. } => Err ( ConstantEvaluatorError :: NotImplemented (
908- "select built-in function" . into ( ) ,
909- ) ) ,
928+ Expression :: Select {
929+ reject,
930+ accept,
931+ condition,
932+ } => self . select ( reject, accept, condition, span) ,
910933 Expression :: Relational { fun, argument } => {
911934 let argument = self . check_and_get ( argument) ?;
912935 self . relational ( fun, argument, span)
@@ -2497,6 +2520,115 @@ impl<'a> ConstantEvaluator<'a> {
24972520
24982521 Ok ( resolution)
24992522 }
2523+
2524+ fn select (
2525+ & mut self ,
2526+ reject : Handle < Expression > ,
2527+ accept : Handle < Expression > ,
2528+ condition : Handle < Expression > ,
2529+ span : Span ,
2530+ ) -> Result < Handle < Expression > , ConstantEvaluatorError > {
2531+ let arg = |this : & mut Self , expr| {
2532+ let expr = this. check_and_get ( expr) ?;
2533+ let expr = this. eval_zero_value_and_splat ( expr, span) ?;
2534+ let expr: & Expression = & this. expressions [ expr] ;
2535+ this. try_eval_and_append ( expr. clone ( ) , span)
2536+ } ;
2537+
2538+ let reject = arg ( self , reject) ?;
2539+ let accept = arg ( self , accept) ?;
2540+ let condition = arg ( self , condition) ?;
2541+
2542+ let select_single_component =
2543+ |this : & mut Self , reject_scalar, reject, accept, condition| {
2544+ let accept = this. cast ( accept, reject_scalar, span) ?;
2545+ if condition {
2546+ Ok ( accept)
2547+ } else {
2548+ Ok ( reject)
2549+ }
2550+ } ;
2551+
2552+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
2553+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( _accept_lit) ) => {
2554+ let reject_scalar = reject_lit. scalar ( ) ;
2555+ let & Expression :: Literal ( Literal :: Bool ( condition) ) = & self . expressions [ condition]
2556+ else {
2557+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
2558+ } ;
2559+ select_single_component ( self , reject_scalar, reject, accept, condition)
2560+ }
2561+ (
2562+ & Expression :: Compose {
2563+ ty : reject_ty,
2564+ components : ref reject_components,
2565+ } ,
2566+ & Expression :: Compose {
2567+ ty : accept_ty,
2568+ components : ref accept_components,
2569+ } ,
2570+ ) => {
2571+ let ty_deets = |ty| {
2572+ let ( size, scalar) = self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
2573+ ( size. unwrap ( ) , scalar)
2574+ } ;
2575+
2576+ let expected_vec_size = {
2577+ let [ ( reject_vec_size, _) , ( accept_vec_size, _) ] =
2578+ [ reject_ty, accept_ty] . map ( ty_deets) ;
2579+
2580+ if reject_vec_size != accept_vec_size {
2581+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptSizeMismatch {
2582+ reject : reject_vec_size,
2583+ accept : accept_vec_size,
2584+ } ) ;
2585+ }
2586+ reject_vec_size
2587+ } ;
2588+
2589+ let & Expression :: Compose {
2590+ ty : condition_ty,
2591+ components : ref condition_components,
2592+ } = & self . expressions [ condition]
2593+ else {
2594+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2595+ } ;
2596+
2597+ {
2598+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
2599+ if condition_scalar. kind != ScalarKind :: Bool {
2600+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2601+ }
2602+ if condition_vec_size != expected_vec_size {
2603+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
2604+ }
2605+ }
2606+
2607+ let evaluated = Expression :: Compose {
2608+ ty : reject_ty,
2609+ components : reject_components
2610+ . clone ( )
2611+ . into_iter ( )
2612+ . zip ( accept_components. clone ( ) . into_iter ( ) )
2613+ . zip ( condition_components. clone ( ) . into_iter ( ) )
2614+ . map ( |( ( reject, accept) , condition) | {
2615+ let reject_scalar = match & self . expressions [ reject] {
2616+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
2617+ _ => unreachable ! ( ) ,
2618+ } ;
2619+ let condition = match & self . expressions [ condition] {
2620+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
2621+ _ => unreachable ! ( ) ,
2622+ } ;
2623+ select_single_component ( self , reject_scalar, reject, accept, condition)
2624+ } )
2625+ . collect :: < Result < _ , _ > > ( ) ?,
2626+ } ;
2627+ self . register_evaluated_expr ( evaluated, span)
2628+ }
2629+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
2630+ }
2631+ }
25002632}
25012633
25022634fn first_trailing_bit ( concrete_int : ConcreteInt < 1 > ) -> ConcreteInt < 1 > {
0 commit comments