@@ -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+ SelectVecRejectAcceptTypeMismatch {
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,114 @@ 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. eval_zero_value_and_splat ( expr, span) ?;
2533+ let expr: & Expression = & this. expressions [ expr] ;
2534+ this. try_eval_and_append ( expr. clone ( ) , span)
2535+ } ;
2536+
2537+ let reject = arg ( self , reject) ?;
2538+ let accept = arg ( self , accept) ?;
2539+ let condition = arg ( self , condition) ?;
2540+
2541+ let select_single_component =
2542+ |this : & mut Self , reject_scalar, reject, accept, condition| {
2543+ let accept = this. cast ( accept, reject_scalar, span) ?;
2544+ if condition {
2545+ Ok ( accept)
2546+ } else {
2547+ Ok ( reject)
2548+ }
2549+ } ;
2550+
2551+ match ( & self . expressions [ reject] , & self . expressions [ accept] ) {
2552+ ( & Expression :: Literal ( reject_lit) , & Expression :: Literal ( _accept_lit) ) => {
2553+ let reject_scalar = reject_lit. scalar ( ) ;
2554+ let & Expression :: Literal ( Literal :: Bool ( condition) ) = & self . expressions [ condition]
2555+ else {
2556+ return Err ( ConstantEvaluatorError :: SelectScalarConditionNotABool ) ;
2557+ } ;
2558+ select_single_component ( self , reject_scalar, reject, accept, condition)
2559+ }
2560+ (
2561+ & Expression :: Compose {
2562+ ty : reject_ty,
2563+ components : ref reject_components,
2564+ } ,
2565+ & Expression :: Compose {
2566+ ty : accept_ty,
2567+ components : ref accept_components,
2568+ } ,
2569+ ) => {
2570+ let ty_deets = |ty| {
2571+ let ( size, scalar) = self . types [ ty] . inner . vector_size_and_scalar ( ) . unwrap ( ) ;
2572+ ( size. unwrap ( ) , scalar)
2573+ } ;
2574+
2575+ let expected_vec_size = {
2576+ let [ ( reject_vec_size, _) , ( accept_vec_size, _) ] =
2577+ [ reject_ty, accept_ty] . map ( ty_deets) ;
2578+
2579+ if reject_vec_size != accept_vec_size {
2580+ return Err ( ConstantEvaluatorError :: SelectVecRejectAcceptTypeMismatch {
2581+ reject : reject_vec_size,
2582+ accept : accept_vec_size,
2583+ } ) ;
2584+ }
2585+ reject_vec_size
2586+ } ;
2587+
2588+ let & Expression :: Compose {
2589+ ty : condition_ty,
2590+ components : ref condition_components,
2591+ } = & self . expressions [ condition]
2592+ else {
2593+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2594+ } ;
2595+
2596+ {
2597+ let ( condition_vec_size, condition_scalar) = ty_deets ( condition_ty) ;
2598+ if condition_scalar. kind != ScalarKind :: Bool {
2599+ return Err ( ConstantEvaluatorError :: SelectConditionNotAVecBool ) ;
2600+ }
2601+ if condition_vec_size != expected_vec_size {
2602+ return Err ( ConstantEvaluatorError :: SelectConditionVecSizeMismatch ) ;
2603+ }
2604+ }
2605+
2606+ let evaluated = Expression :: Compose {
2607+ ty : reject_ty,
2608+ components : reject_components
2609+ . clone ( )
2610+ . into_iter ( )
2611+ . zip ( accept_components. clone ( ) . into_iter ( ) )
2612+ . zip ( condition_components. clone ( ) . into_iter ( ) )
2613+ . map ( |( ( reject, accept) , condition) | {
2614+ let reject_scalar = match & self . expressions [ reject] {
2615+ & Expression :: Literal ( lit) => lit. scalar ( ) ,
2616+ _ => unreachable ! ( ) ,
2617+ } ;
2618+ let condition = match & self . expressions [ condition] {
2619+ & Expression :: Literal ( Literal :: Bool ( condition) ) => condition,
2620+ _ => unreachable ! ( ) ,
2621+ } ;
2622+ select_single_component ( self , reject_scalar, reject, accept, condition)
2623+ } )
2624+ . collect :: < Result < _ , _ > > ( ) ?,
2625+ } ;
2626+ self . register_evaluated_expr ( evaluated, span)
2627+ }
2628+ _ => Err ( ConstantEvaluatorError :: SelectAcceptRejectTypeMismatch ) ,
2629+ }
2630+ }
25002631}
25012632
25022633fn first_trailing_bit ( concrete_int : ConcreteInt < 1 > ) -> ConcreteInt < 1 > {
0 commit comments