@@ -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,19 @@ 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+ } => {
933+ let mut arg = |expr| self . check_and_get ( expr) ;
934+
935+ let reject = arg ( reject) ?;
936+ let accept = arg ( accept) ?;
937+ let condition = arg ( condition) ?;
938+
939+ self . select ( reject, accept, condition, span)
940+ }
910941 Expression :: Relational { fun, argument } => {
911942 let argument = self . check_and_get ( argument) ?;
912943 self . relational ( fun, argument, span)
@@ -2497,6 +2528,116 @@ impl<'a> ConstantEvaluator<'a> {
24972528
24982529 Ok ( resolution)
24992530 }
2531+
2532+ fn select (
2533+ & mut self ,
2534+ reject : Handle < Expression > ,
2535+ accept : Handle < Expression > ,
2536+ condition : Handle < Expression > ,
2537+ span : Span ,
2538+ ) -> Result < Handle < Expression > , ConstantEvaluatorError > {
2539+ let mut arg = |arg| self . eval_zero_value_and_splat ( arg, span) ;
2540+
2541+ let reject = arg ( reject) ?;
2542+ let accept = arg ( accept) ?;
2543+ let condition = arg ( condition) ?;
2544+
2545+ let select_single_component =
2546+ |this : & mut Self , reject_scalar, reject, accept, condition| {
2547+ let accept = this. cast ( accept, reject_scalar, span) ?;
2548+ if condition {
2549+ Ok ( accept)
2550+ } else {
2551+ Ok ( reject)
2552+ }
2553+ } ;
2554+
2555+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
2556+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( _accept_lit) ) => {
2557+ let reject_scalar = reject_lit. scalar ( ) ;
2558+ let & Expression :: Literal ( Literal :: Bool ( condition) ) = & self . expressions [ condition]
2559+ else {
2560+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
2561+ } ;
2562+ select_single_component ( self , reject_scalar, reject, accept, condition)
2563+ }
2564+ (
2565+ & Expression :: Compose {
2566+ ty : reject_ty,
2567+ components : ref reject_components,
2568+ } ,
2569+ & Expression :: Compose {
2570+ ty : accept_ty,
2571+ components : ref accept_components,
2572+ } ,
2573+ ) => {
2574+ let ty_deets = |ty| {
2575+ let ( size, scalar) = self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
2576+ ( size. unwrap ( ) , scalar)
2577+ } ;
2578+
2579+ let expected_vec_size = {
2580+ let [ ( reject_vec_size, _) , ( accept_vec_size, _) ] =
2581+ [ reject_ty, accept_ty] . map ( ty_deets) ;
2582+
2583+ if reject_vec_size != accept_vec_size {
2584+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptSizeMismatch {
2585+ reject : reject_vec_size,
2586+ accept : accept_vec_size,
2587+ } ) ;
2588+ }
2589+ reject_vec_size
2590+ } ;
2591+
2592+ let condition_components = match self . expressions [ condition] {
2593+ Expression :: Literal ( Literal :: Bool ( condition) ) => {
2594+ vec ! [ condition; ( expected_vec_size as u8 ) . into( ) ]
2595+ }
2596+ Expression :: Compose {
2597+ ty : condition_ty,
2598+ components : ref condition_components,
2599+ } => {
2600+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
2601+ if condition_scalar. kind != ScalarKind :: Bool {
2602+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2603+ }
2604+ if condition_vec_size != expected_vec_size {
2605+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
2606+ }
2607+ condition_components
2608+ . iter ( )
2609+ . copied ( )
2610+ . map ( |component| match & self . expressions [ component] {
2611+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
2612+ _ => unreachable ! ( ) ,
2613+ } )
2614+ . collect ( )
2615+ }
2616+
2617+ _ => return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ,
2618+ } ;
2619+
2620+ let evaluated = Expression :: Compose {
2621+ ty : reject_ty,
2622+ components : reject_components
2623+ . clone ( )
2624+ . into_iter ( )
2625+ . zip ( accept_components. clone ( ) . into_iter ( ) )
2626+ . zip ( condition_components. into_iter ( ) )
2627+ . map ( |( ( reject, accept) , condition) | {
2628+ let reject_scalar = match & self . expressions [ reject] {
2629+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
2630+ _ => unreachable ! ( ) ,
2631+ } ;
2632+ select_single_component ( self , reject_scalar, reject, accept, condition)
2633+ } )
2634+ . collect :: < Result < _ , _ > > ( ) ?,
2635+ } ;
2636+ self . register_evaluated_expr ( evaluated, span)
2637+ }
2638+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
2639+ }
2640+ }
25002641}
25012642
25022643fn first_trailing_bit ( concrete_int : ConcreteInt < 1 > ) -> ConcreteInt < 1 > {
0 commit comments