+struct TypeCache<'ctx, 'tb, C: shader_compiler_backend::Context<'ctx>>
+where
+ C::TypeBuilder: 'tb,
+{
+ table: HashMap<(Rc<FrontendType>, CrossLaneBehavior), Option<C::Type>>,
+ type_builder: &'tb C::TypeBuilder,
+}
+
+impl<'ctx, 'tb, C: shader_compiler_backend::Context<'ctx>> TypeCache<'ctx, 'tb, C> {
+ fn get(
+ &mut self,
+ frontend_type: Rc<FrontendType>,
+ cross_lane_behavior: CrossLaneBehavior,
+ ) -> C::Type {
+ match self
+ .table
+ .entry((frontend_type.clone(), cross_lane_behavior))
+ {
+ hash_map::Entry::Occupied(retval) => {
+ return retval
+ .get()
+ .clone()
+ .expect("recursive types not implemented");
+ }
+ hash_map::Entry::Vacant(v) => {
+ v.insert(None);
+ }
+ }
+ let retval = match *frontend_type {
+ FrontendType::Scalar(ScalarType::Bool) => self.type_builder.build_bool(),
+ FrontendType::Scalar(ScalarType::I8) => self.type_builder.build_i8(),
+ FrontendType::Scalar(ScalarType::I16) => self.type_builder.build_i16(),
+ FrontendType::Scalar(ScalarType::I32) => self.type_builder.build_i32(),
+ FrontendType::Scalar(ScalarType::I64) => self.type_builder.build_i64(),
+ FrontendType::Scalar(ScalarType::U8) => self.type_builder.build_u8(),
+ FrontendType::Scalar(ScalarType::U16) => self.type_builder.build_u16(),
+ FrontendType::Scalar(ScalarType::U32) => self.type_builder.build_u32(),
+ FrontendType::Scalar(ScalarType::U64) => self.type_builder.build_u64(),
+ FrontendType::Scalar(ScalarType::F32) => self.type_builder.build_f32(),
+ FrontendType::Scalar(ScalarType::F64) => self.type_builder.build_f64(),
+ _ => unimplemented!("unimplemented type translation: {:?}", frontend_type),
+ };
+ *self
+ .table
+ .get_mut(&(frontend_type, cross_lane_behavior))
+ .unwrap() = Some(retval.clone());
+ retval
+ }
+}
+