builder_spirv: split out the type field from SpirvConst.

This commit is contained in:
Eduard-Mihai Burtescu 2021-04-08 13:38:51 +03:00 committed by Eduard-Mihai Burtescu
parent aa444f007e
commit 84350e31d3
4 changed files with 58 additions and 53 deletions

View File

@ -38,8 +38,8 @@ macro_rules! simple_op {
let size = Size::from_bits(bits);
let as_u128 = |const_val| {
let x = match const_val {
SpirvConst::U32(_, x) => x as u128,
SpirvConst::U64(_, x) => x as u128,
SpirvConst::U32(x) => x as u128,
SpirvConst::U64(x) => x as u128,
_ => return None,
};
Some(if signed {

View File

@ -171,16 +171,22 @@ impl SpirvValueExt for Word {
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum SpirvConst {
U32(Word, u32),
U64(Word, u64),
U32(u32),
U64(u64),
/// f32 isn't hash, so store bits
F32(Word, u32),
F32(u32),
/// f64 isn't hash, so store bits
F64(Word, u64),
Bool(Word, bool),
Composite(Word, Vec<Word>),
Null(Word),
Undef(Word),
F64(u64),
Bool(bool),
Composite(Vec<Word>),
Null,
Undef,
}
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
struct WithType<V> {
ty: Word,
val: V,
}
/// Cursor system:
@ -214,7 +220,7 @@ pub struct BuilderCursor {
pub struct BuilderSpirv {
builder: RefCell<Builder>,
constants: RefCell<BiHashMap<SpirvConst, SpirvValue>>,
constants: RefCell<BiHashMap<WithType<SpirvConst>, SpirvValue>>,
}
impl BuilderSpirv {
@ -329,44 +335,44 @@ impl BuilderSpirv {
bug!("Function not found: {}", id);
}
pub fn def_constant(&self, val: SpirvConst) -> SpirvValue {
pub fn def_constant(&self, ty: Word, val: SpirvConst) -> SpirvValue {
let val_with_type = WithType { ty, val };
let mut builder = self.builder(BuilderCursor::default());
if let Some(value) = self.constants.borrow_mut().get_by_left(&val) {
if let Some(value) = self.constants.borrow_mut().get_by_left(&val_with_type) {
return *value;
}
let id = match val {
SpirvConst::U32(ty, v) => builder.constant_u32(ty, v).with_type(ty),
SpirvConst::U64(ty, v) => builder.constant_u64(ty, v).with_type(ty),
SpirvConst::F32(ty, v) => builder.constant_f32(ty, f32::from_bits(v)).with_type(ty),
SpirvConst::F64(ty, v) => builder.constant_f64(ty, f64::from_bits(v)).with_type(ty),
SpirvConst::Bool(ty, v) => {
let id = match val_with_type.val {
SpirvConst::U32(v) => builder.constant_u32(ty, v),
SpirvConst::U64(v) => builder.constant_u64(ty, v),
SpirvConst::F32(v) => builder.constant_f32(ty, f32::from_bits(v)),
SpirvConst::F64(v) => builder.constant_f64(ty, f64::from_bits(v)),
SpirvConst::Bool(v) => {
if v {
builder.constant_true(ty).with_type(ty)
builder.constant_true(ty)
} else {
builder.constant_false(ty).with_type(ty)
builder.constant_false(ty)
}
}
SpirvConst::Composite(ty, ref v) => builder
.constant_composite(ty, v.iter().copied())
.with_type(ty),
SpirvConst::Null(ty) => builder.constant_null(ty).with_type(ty),
SpirvConst::Undef(ty) => builder.undef(ty, None).with_type(ty),
SpirvConst::Composite(ref v) => builder.constant_composite(ty, v.iter().copied()),
SpirvConst::Null => builder.constant_null(ty),
SpirvConst::Undef => builder.undef(ty, None),
};
let spirv_value = id.with_type(ty);
self.constants
.borrow_mut()
.insert_no_overwrite(val, id)
.insert_no_overwrite(val_with_type, spirv_value)
.unwrap();
id
spirv_value
}
pub fn lookup_const(&self, def: SpirvValue) -> Option<SpirvConst> {
self.constants.borrow().get_by_right(&def).cloned()
Some(self.constants.borrow().get_by_right(&def)?.val.clone())
}
pub fn lookup_const_u64(&self, def: SpirvValue) -> Option<u64> {
match self.lookup_const(def)? {
SpirvConst::U32(_, v) => Some(v as u64),
SpirvConst::U64(_, v) => Some(v),
SpirvConst::U32(v) => Some(v as u64),
SpirvConst::U64(v) => Some(v),
_ => None,
}
}

View File

@ -16,27 +16,27 @@ use rustc_target::abi::{self, AddressSpace, HasDataLayout, Integer, LayoutOf, Pr
impl<'tcx> CodegenCx<'tcx> {
pub fn constant_u8(&self, span: Span, val: u8) -> SpirvValue {
let ty = SpirvType::Integer(8, false).def(span, self);
self.builder.def_constant(SpirvConst::U32(ty, val as u32))
self.builder.def_constant(ty, SpirvConst::U32(val as u32))
}
pub fn constant_u16(&self, span: Span, val: u16) -> SpirvValue {
let ty = SpirvType::Integer(16, false).def(span, self);
self.builder.def_constant(SpirvConst::U32(ty, val as u32))
self.builder.def_constant(ty, SpirvConst::U32(val as u32))
}
pub fn constant_i32(&self, span: Span, val: i32) -> SpirvValue {
let ty = SpirvType::Integer(32, !self.kernel_mode).def(span, self);
self.builder.def_constant(SpirvConst::U32(ty, val as u32))
self.builder.def_constant(ty, SpirvConst::U32(val as u32))
}
pub fn constant_u32(&self, span: Span, val: u32) -> SpirvValue {
let ty = SpirvType::Integer(32, false).def(span, self);
self.builder.def_constant(SpirvConst::U32(ty, val))
self.builder.def_constant(ty, SpirvConst::U32(val))
}
pub fn constant_u64(&self, span: Span, val: u64) -> SpirvValue {
let ty = SpirvType::Integer(64, false).def(span, self);
self.builder.def_constant(SpirvConst::U64(ty, val))
self.builder.def_constant(ty, SpirvConst::U64(val))
}
pub fn constant_int(&self, ty: Word, val: u64) -> SpirvValue {
@ -44,18 +44,18 @@ impl<'tcx> CodegenCx<'tcx> {
SpirvType::Integer(bits @ 8..=32, signed) => {
let size = Size::from_bits(bits);
let val = val as u128;
self.builder.def_constant(SpirvConst::U32(
self.builder.def_constant(
ty,
if signed {
SpirvConst::U32(if signed {
size.sign_extend(val)
} else {
size.truncate(val)
} as u32,
))
} as u32),
)
}
SpirvType::Integer(64, _) => self.builder.def_constant(SpirvConst::U64(ty, val)),
SpirvType::Integer(64, _) => self.builder.def_constant(ty, SpirvConst::U64(val)),
SpirvType::Bool => match val {
0 | 1 => self.builder.def_constant(SpirvConst::Bool(ty, val != 0)),
0 | 1 => self.builder.def_constant(ty, SpirvConst::Bool(val != 0)),
_ => self
.tcx
.sess
@ -76,23 +76,23 @@ impl<'tcx> CodegenCx<'tcx> {
pub fn constant_f32(&self, span: Span, val: f32) -> SpirvValue {
let ty = SpirvType::Float(32).def(span, self);
self.builder
.def_constant(SpirvConst::F32(ty, val.to_bits()))
.def_constant(ty, SpirvConst::F32(val.to_bits()))
}
pub fn constant_f64(&self, span: Span, val: f64) -> SpirvValue {
let ty = SpirvType::Float(64).def(span, self);
self.builder
.def_constant(SpirvConst::F64(ty, val.to_bits()))
.def_constant(ty, SpirvConst::F64(val.to_bits()))
}
pub fn constant_float(&self, ty: Word, val: f64) -> SpirvValue {
match self.lookup_type(ty) {
SpirvType::Float(32) => self
.builder
.def_constant(SpirvConst::F32(ty, (val as f32).to_bits())),
.def_constant(ty, SpirvConst::F32((val as f32).to_bits())),
SpirvType::Float(64) => self
.builder
.def_constant(SpirvConst::F64(ty, val.to_bits())),
.def_constant(ty, SpirvConst::F64(val.to_bits())),
other => self.tcx.sess.fatal(&format!(
"constant_float invalid on type {}",
other.debug(ty, self)
@ -102,19 +102,19 @@ impl<'tcx> CodegenCx<'tcx> {
pub fn constant_bool(&self, span: Span, val: bool) -> SpirvValue {
let ty = SpirvType::Bool.def(span, self);
self.builder.def_constant(SpirvConst::Bool(ty, val))
self.builder.def_constant(ty, SpirvConst::Bool(val))
}
pub fn constant_composite(&self, ty: Word, val: Vec<Word>) -> SpirvValue {
self.builder.def_constant(SpirvConst::Composite(ty, val))
self.builder.def_constant(ty, SpirvConst::Composite(val))
}
pub fn constant_null(&self, ty: Word) -> SpirvValue {
self.builder.def_constant(SpirvConst::Null(ty))
self.builder.def_constant(ty, SpirvConst::Null)
}
pub fn undef(&self, ty: Word) -> SpirvValue {
self.builder.def_constant(SpirvConst::Undef(ty))
self.builder.def_constant(ty, SpirvConst::Undef)
}
}

View File

@ -264,9 +264,8 @@ impl<'tcx> StaticMethods for CodegenCx<'tcx> {
let mut v = self.create_const_alloc(alloc, value_ty);
if self.lookup_type(v.ty) == SpirvType::Bool {
let val = self.builder.lookup_const(v).unwrap();
let val_int = match val {
SpirvConst::Bool(_, val) => val as u8,
let val_int = match self.builder.lookup_const(v).unwrap() {
SpirvConst::Bool(val) => val as u8,
_ => bug!(),
};
v = self.constant_u8(span, val_int);