@@ -4803,6 +4803,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
4803
4803
Op :: ConstantFalse | Op :: SpecConstantFalse => {
4804
4804
self . parse_bool_constant ( inst, false , & mut module)
4805
4805
}
4806
+ Op :: SpecConstantOp => self . parse_spec_constant_op ( inst, & mut module) ,
4806
4807
Op :: Variable => self . parse_global_variable ( inst, & mut module) ,
4807
4808
Op :: Function => {
4808
4809
self . switch ( ModuleState :: Function , inst. op ) ?;
@@ -5897,6 +5898,273 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
5897
5898
self . insert_parsed_constant ( module, id, type_id, ty, init, span)
5898
5899
}
5899
5900
5901
+ fn parse_spec_constant_op (
5902
+ & mut self ,
5903
+ inst : Instruction ,
5904
+ module : & mut crate :: Module ,
5905
+ ) -> Result < ( ) , Error > {
5906
+ use spirv:: Op ;
5907
+
5908
+ let start = self . data_offset ;
5909
+ self . switch ( ModuleState :: Type , inst. op ) ?;
5910
+ inst. expect_at_least ( 4 ) ?;
5911
+
5912
+ let result_type_id = self . next ( ) ?;
5913
+ let result_id = self . next ( ) ?;
5914
+ let opcode_word = self . next ( ) ?;
5915
+
5916
+ let type_lookup = self . lookup_type . lookup ( result_type_id) ?;
5917
+ let ty = type_lookup. handle ;
5918
+ let span = self . span_from_with_op ( start) ;
5919
+
5920
+ let opcode = Op :: from_u32 ( opcode_word) . ok_or ( Error :: UnsupportedInstruction (
5921
+ self . state ,
5922
+ Op :: SpecConstantOp ,
5923
+ ) ) ?;
5924
+
5925
+ let mut get_const_expr =
5926
+ |frontend : & Self , const_id : spirv:: Word | -> Result < Handle < crate :: Expression > , Error > {
5927
+ let lookup = frontend. lookup_constant . lookup ( const_id) ?;
5928
+ Ok ( module
5929
+ . global_expressions
5930
+ . append ( lookup. inner . to_expr ( ) , span) )
5931
+ } ;
5932
+
5933
+ let init = match opcode {
5934
+ Op :: SConvert | Op :: UConvert | Op :: FConvert => {
5935
+ let value_id = self . next ( ) ?;
5936
+ let value_expr = get_const_expr ( self , value_id) ?;
5937
+
5938
+ let scalar = match module. types [ ty] . inner {
5939
+ crate :: TypeInner :: Scalar ( scalar)
5940
+ | crate :: TypeInner :: Vector { scalar, .. }
5941
+ | crate :: TypeInner :: Matrix { scalar, .. } => scalar,
5942
+ _ => return Err ( Error :: InvalidAsType ( ty) ) ,
5943
+ } ;
5944
+
5945
+ module. global_expressions . append (
5946
+ crate :: Expression :: As {
5947
+ expr : value_expr,
5948
+ kind : scalar. kind ,
5949
+ convert : Some ( scalar. width ) ,
5950
+ } ,
5951
+ span,
5952
+ )
5953
+ }
5954
+
5955
+ Op :: SNegate | Op :: Not | Op :: LogicalNot => {
5956
+ let value_id = self . next ( ) ?;
5957
+ let value_expr = get_const_expr ( self , value_id) ?;
5958
+
5959
+ let op = match opcode {
5960
+ Op :: SNegate => crate :: UnaryOperator :: Negate ,
5961
+ Op :: Not => crate :: UnaryOperator :: BitwiseNot ,
5962
+ Op :: LogicalNot => crate :: UnaryOperator :: LogicalNot ,
5963
+ _ => unreachable ! ( ) ,
5964
+ } ;
5965
+
5966
+ module. global_expressions . append (
5967
+ crate :: Expression :: Unary {
5968
+ op,
5969
+ expr : value_expr,
5970
+ } ,
5971
+ span,
5972
+ )
5973
+ }
5974
+
5975
+ Op :: IAdd
5976
+ | Op :: ISub
5977
+ | Op :: IMul
5978
+ | Op :: UDiv
5979
+ | Op :: SDiv
5980
+ | Op :: SRem
5981
+ | Op :: UMod
5982
+ | Op :: BitwiseOr
5983
+ | Op :: BitwiseXor
5984
+ | Op :: BitwiseAnd
5985
+ | Op :: ShiftLeftLogical
5986
+ | Op :: ShiftRightLogical
5987
+ | Op :: ShiftRightArithmetic
5988
+ | Op :: LogicalOr
5989
+ | Op :: LogicalAnd
5990
+ | Op :: LogicalEqual
5991
+ | Op :: LogicalNotEqual
5992
+ | Op :: IEqual
5993
+ | Op :: INotEqual
5994
+ | Op :: ULessThan
5995
+ | Op :: SLessThan
5996
+ | Op :: UGreaterThan
5997
+ | Op :: SGreaterThan
5998
+ | Op :: ULessThanEqual
5999
+ | Op :: SLessThanEqual
6000
+ | Op :: UGreaterThanEqual
6001
+ | Op :: SGreaterThanEqual => {
6002
+ let left_id = self . next ( ) ?;
6003
+ let right_id = self . next ( ) ?;
6004
+ let left_expr = get_const_expr ( self , left_id) ?;
6005
+ let right_expr = get_const_expr ( self , right_id) ?;
6006
+
6007
+ let op = match opcode {
6008
+ Op :: IAdd => crate :: BinaryOperator :: Add ,
6009
+ Op :: ISub => crate :: BinaryOperator :: Subtract ,
6010
+ Op :: IMul => crate :: BinaryOperator :: Multiply ,
6011
+ Op :: UDiv | Op :: SDiv => crate :: BinaryOperator :: Divide ,
6012
+ Op :: SRem | Op :: UMod => crate :: BinaryOperator :: Modulo ,
6013
+ Op :: BitwiseOr => crate :: BinaryOperator :: InclusiveOr ,
6014
+ Op :: BitwiseXor => crate :: BinaryOperator :: ExclusiveOr ,
6015
+ Op :: BitwiseAnd => crate :: BinaryOperator :: And ,
6016
+ Op :: ShiftLeftLogical => crate :: BinaryOperator :: ShiftLeft ,
6017
+ Op :: ShiftRightLogical | Op :: ShiftRightArithmetic => {
6018
+ crate :: BinaryOperator :: ShiftRight
6019
+ }
6020
+ Op :: LogicalOr => crate :: BinaryOperator :: LogicalOr ,
6021
+ Op :: LogicalAnd => crate :: BinaryOperator :: LogicalAnd ,
6022
+ Op :: LogicalEqual => crate :: BinaryOperator :: Equal ,
6023
+ Op :: LogicalNotEqual => crate :: BinaryOperator :: NotEqual ,
6024
+ Op :: IEqual => crate :: BinaryOperator :: Equal ,
6025
+ Op :: INotEqual => crate :: BinaryOperator :: NotEqual ,
6026
+ Op :: ULessThan | Op :: SLessThan => crate :: BinaryOperator :: Less ,
6027
+ Op :: UGreaterThan | Op :: SGreaterThan => crate :: BinaryOperator :: Greater ,
6028
+ Op :: ULessThanEqual | Op :: SLessThanEqual => crate :: BinaryOperator :: LessEqual ,
6029
+ Op :: UGreaterThanEqual | Op :: SGreaterThanEqual => {
6030
+ crate :: BinaryOperator :: GreaterEqual
6031
+ }
6032
+ _ => unreachable ! ( ) ,
6033
+ } ;
6034
+
6035
+ module. global_expressions . append (
6036
+ crate :: Expression :: Binary {
6037
+ op,
6038
+ left : left_expr,
6039
+ right : right_expr,
6040
+ } ,
6041
+ span,
6042
+ )
6043
+ }
6044
+
6045
+ Op :: SMod => {
6046
+ // x - y * int(floor(float(x) / float(y)))
6047
+
6048
+ let left_id = self . next ( ) ?;
6049
+ let right_id = self . next ( ) ?;
6050
+ let left = get_const_expr ( self , left_id) ?;
6051
+ let right = get_const_expr ( self , right_id) ?;
6052
+
6053
+ let scalar = match module. types [ ty] . inner {
6054
+ crate :: TypeInner :: Scalar ( scalar) => scalar,
6055
+ crate :: TypeInner :: Vector { scalar, .. } => scalar,
6056
+ _ => return Err ( Error :: InvalidAsType ( ty) ) ,
6057
+ } ;
6058
+
6059
+ let left_cast = module. global_expressions . append (
6060
+ crate :: Expression :: As {
6061
+ expr : left,
6062
+ kind : crate :: ScalarKind :: Float ,
6063
+ convert : Some ( scalar. width ) ,
6064
+ } ,
6065
+ span,
6066
+ ) ;
6067
+ let right_cast = module. global_expressions . append (
6068
+ crate :: Expression :: As {
6069
+ expr : right,
6070
+ kind : crate :: ScalarKind :: Float ,
6071
+ convert : Some ( scalar. width ) ,
6072
+ } ,
6073
+ span,
6074
+ ) ;
6075
+ let div = module. global_expressions . append (
6076
+ crate :: Expression :: Binary {
6077
+ op : crate :: BinaryOperator :: Divide ,
6078
+ left : left_cast,
6079
+ right : right_cast,
6080
+ } ,
6081
+ span,
6082
+ ) ;
6083
+ let floor = module. global_expressions . append (
6084
+ crate :: Expression :: Math {
6085
+ fun : crate :: MathFunction :: Floor ,
6086
+ arg : div,
6087
+ arg1 : None ,
6088
+ arg2 : None ,
6089
+ arg3 : None ,
6090
+ } ,
6091
+ span,
6092
+ ) ;
6093
+ let cast = module. global_expressions . append (
6094
+ crate :: Expression :: As {
6095
+ expr : floor,
6096
+ kind : scalar. kind ,
6097
+ convert : Some ( scalar. width ) ,
6098
+ } ,
6099
+ span,
6100
+ ) ;
6101
+ let mult = module. global_expressions . append (
6102
+ crate :: Expression :: Binary {
6103
+ op : crate :: BinaryOperator :: Multiply ,
6104
+ left : cast,
6105
+ right,
6106
+ } ,
6107
+ span,
6108
+ ) ;
6109
+ module. global_expressions . append (
6110
+ crate :: Expression :: Binary {
6111
+ op : crate :: BinaryOperator :: Subtract ,
6112
+ left,
6113
+ right : mult,
6114
+ } ,
6115
+ span,
6116
+ )
6117
+ }
6118
+
6119
+ Op :: Select => {
6120
+ let condition_id = self . next ( ) ?;
6121
+ let o1_id = self . next ( ) ?;
6122
+ let o2_id = self . next ( ) ?;
6123
+
6124
+ let cond = get_const_expr ( self , condition_id) ?;
6125
+ let o1 = get_const_expr ( self , o1_id) ?;
6126
+ let o2 = get_const_expr ( self , o2_id) ?;
6127
+
6128
+ module. global_expressions . append (
6129
+ crate :: Expression :: Select {
6130
+ condition : cond,
6131
+ accept : o1,
6132
+ reject : o2,
6133
+ } ,
6134
+ span,
6135
+ )
6136
+ }
6137
+
6138
+ Op :: VectorShuffle | Op :: CompositeExtract | Op :: CompositeInsert | Op :: QuantizeToF16 => {
6139
+ // Nothing stops us from implementing these cases in general.
6140
+ // I just couldn't get them to work properly.
6141
+ return Err ( Error :: UnsupportedSpecConstantOp ( opcode) ) ;
6142
+ }
6143
+
6144
+ _ => return Err ( Error :: InvalidSpecConstantOp ( opcode) ) ,
6145
+ } ;
6146
+
6147
+ // IMPORTANT: Overrides must have either a name or an id to be processed correctly
6148
+ // by process_overrides(). OpSpecConstantOp results don't have a SpecId (they're
6149
+ // not user-overridable), so we assign them a name based on the result_id.
6150
+ let op_override = crate :: Override {
6151
+ name : Some ( format ! ( "_spec_const_op_{result_id}" ) ) ,
6152
+ id : None ,
6153
+ ty,
6154
+ init : Some ( init) ,
6155
+ } ;
6156
+
6157
+ self . lookup_constant . insert (
6158
+ result_id,
6159
+ LookupConstant {
6160
+ inner : Constant :: Override ( module. overrides . append ( op_override, span) ) ,
6161
+ type_id : result_type_id,
6162
+ } ,
6163
+ ) ;
6164
+
6165
+ Ok ( ( ) )
6166
+ }
6167
+
5900
6168
fn insert_parsed_constant (
5901
6169
& mut self ,
5902
6170
module : & mut crate :: Module ,
0 commit comments