wasm2spirv 0.1.0

Compile your WebAssembly programs into SPIR-V shaders
Documentation
#![allow(clippy::should_implement_trait)]

use super::{
    float::Float,
    integer::{ConstantSource, ConversionSource, Integer, IntegerKind, IntegerSource},
    pointer::Pointer,
};
use crate::error::Result;
use std::{cell::Cell, rc::Rc};

#[derive(Debug, Clone, PartialEq)]
pub struct Bool {
    pub(crate) translation: Cell<Option<rspirv::spirv::Word>>,
    pub source: BoolSource,
}

#[derive(Debug, Clone, PartialEq)]
pub enum BoolSource {
    Constant(bool),
    FromInteger(Rc<Integer>),
    Negated(Rc<Bool>),
    IntEquality {
        kind: Equality,
        op1: Rc<Integer>,
        op2: Rc<Integer>,
    },
    FloatEquality {
        kind: Equality,
        op1: Rc<Float>,
        op2: Rc<Float>,
    },
    IntComparison {
        kind: Comparison,
        signed: bool,
        op1: Rc<Integer>,
        op2: Rc<Integer>,
    },
    FloatComparison {
        kind: Comparison,
        op1: Rc<Float>,
        op2: Rc<Float>,
    },
    Loaded {
        pointer: Rc<Pointer>,
        log2_alignment: Option<u32>,
    },
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Comparison {
    Le,
    Lt,
    Gt,
    Ge,
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Equality {
    Eq,
    Ne,
}

impl Bool {
    pub fn new(source: BoolSource) -> Self {
        return Self {
            translation: Cell::new(None),
            source,
        };
    }

    pub fn to_integer(self: Rc<Self>, kind: IntegerKind) -> Result<Rc<Integer>> {
        return Ok(match (kind, self.get_constant_value()?) {
            (IntegerKind::Long, Some(true)) => Integer::new_constant_u64(1),
            (IntegerKind::Short, Some(true)) => Integer::new_constant_u32(1),
            (IntegerKind::Long, Some(false)) => Integer::new_constant_u64(0),
            (IntegerKind::Short, Some(false)) => Integer::new_constant_u32(0),
            (kind, None) => Integer::new(IntegerSource::Conversion(ConversionSource::FromBool(
                self, kind,
            ))),
        }
        .into());
    }

    pub fn get_constant_value(&self) -> Result<Option<bool>> {
        match &self.source {
            BoolSource::Constant(x) => Ok(Some(*x)),
            BoolSource::FromInteger(x) => match x.get_constant_value()? {
                Some(ConstantSource::Long(0) | ConstantSource::Short(0)) => Ok(Some(false)),
                Some(_) => Ok(Some(true)),
                None => Ok(None),
            },
            BoolSource::Negated(x) => Ok(x.get_constant_value()?.map(|x| !x)),
            _ => return Ok(None),
        }
    }
}