64 bit switches

This commit is contained in:
khyperia 2020-09-02 16:36:54 +02:00
parent e1f1d88d33
commit b6d2c0972b
4 changed files with 75 additions and 23 deletions

View File

@ -162,14 +162,58 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> {
else_llbb: Self::BasicBlock,
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)>,
) {
// pass in signed into the closure to be able to unify closure types
let (signed, construct_case) = match self.lookup_type(v.ty) {
SpirvType::Integer(width, signed) => {
let construct_case = match width {
// TODO: How are negative values represented? sign-extended? if so, they'll be >MAX
8 => |signed, v| {
if v > u8::MAX as u128 {
panic!("Switches to values above u8::MAX not supported: {:?}", v)
} else if signed {
// this cast chain can probably be collapsed, but, whatever, be safe
Operand::LiteralInt32(v as u8 as i8 as i32 as u32)
} else {
Operand::LiteralInt32(v as u8 as u32)
}
},
16 => |signed, v| {
if v > u16::MAX as u128 {
panic!("Switches to values above u16::MAX not supported: {:?}", v)
} else if signed {
Operand::LiteralInt32(v as u16 as i16 as i32 as u32)
} else {
Operand::LiteralInt32(v as u16 as u32)
}
},
32 => |_signed, v| {
if v > u32::MAX as u128 {
panic!("Switches to values above u32::MAX not supported: {:?}", v)
} else {
Operand::LiteralInt32(v as u32)
}
},
64 => |_signed, v| {
if v > u64::MAX as u128 {
panic!("Switches to values above u64::MAX not supported: {:?}", v)
} else {
Operand::LiteralInt64(v as u64)
}
},
other => panic!(
"switch selector cannot have width {} (only 32 and 64 bits allowed)",
other
),
};
(signed, construct_case)
}
other => panic!(
"switch selector cannot have non-integer type {}",
other.debug(self)
),
};
let cases = cases
.map(|(i, b)| {
if i > u32::MAX as u128 {
panic!("Switches to values above u32::MAX not supported: {:?}", i)
} else {
(i as u32, b)
}
})
.map(|(i, b)| (construct_case(signed, i), b))
.collect::<Vec<_>>();
self.emit().switch(v.def, else_llbb, cases).unwrap()
}

View File

@ -216,20 +216,22 @@ impl BuilderSpirv {
pub fn set_global_initializer(&self, global: Word, initialiezr: Word) {
let mut builder = self.builder.borrow_mut();
for inst in &mut builder.module_mut().types_global_values {
if inst.class.opcode == Op::Variable {
if let Some(&Operand::IdRef(id_ref)) = inst.operands.get(1) {
if id_ref == global {
assert_eq!(
inst.operands.len(),
1,
"global already has initializer defined: {}",
global
);
inst.operands.push(Operand::IdRef(initialiezr));
}
}
if inst.result_id == Some(global) {
assert_eq!(inst.class.opcode, Op::Variable);
assert_eq!(
inst.operands.len(),
1,
"global already has initializer defined: {}",
global
);
inst.operands.push(Operand::IdRef(initialiezr));
return;
}
}
panic!(
"set_global_initializer global not found: {} with init {}",
global, initialiezr
);
}
pub fn select_block_by_id(&self, id: Word) -> BuilderCursor {

View File

@ -67,6 +67,8 @@ pub struct CodegenCx<'spv, 'tcx> {
pub type_defs: RefCell<HashMap<Word, SpirvType>>,
/// Inverse of type_defs (used to cache generating types)
pub type_cache: RefCell<HashMap<SpirvType, Word>>,
/// Cache generated vtables
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), SpirvValue>>,
}
impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
@ -85,6 +87,7 @@ impl<'spv, 'tcx> CodegenCx<'spv, 'tcx> {
function_parameter_values: RefCell::new(HashMap::new()),
type_defs: RefCell::new(HashMap::new()),
type_cache: RefCell::new(HashMap::new()),
vtables: RefCell::new(Default::default()),
}
}
@ -531,7 +534,7 @@ impl<'spv, 'tcx> MiscMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), Self::Value>> {
todo!()
&self.vtables
}
fn check_overflow(&self) -> bool {
@ -702,7 +705,7 @@ impl<'spv, 'tcx> DeclareMethods<'tcx> for CodegenCx<'spv, 'tcx> {
impl<'spv, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'spv, 'tcx> {
fn create_vtable_metadata(&self, _ty: Ty<'tcx>, _vtable: Self::Value) {
todo!()
// Ignore.
}
fn create_function_debug_context(
@ -989,8 +992,9 @@ impl<'spv, 'tcx> ConstMethods<'tcx> for CodegenCx<'spv, 'tcx> {
PlaceRef::new_sized(result, layout)
}
fn const_ptrcast(&self, _val: Self::Value, _ty: Self::Type) -> Self::Value {
todo!()
fn const_ptrcast(&self, val: Self::Value, ty: Self::Type) -> Self::Value {
// TODO: hack to get things working, this *will* fail spirv-val
val.def.with_type(ty)
}
}

View File

@ -117,6 +117,8 @@ impl CodegenBackend for SsaBackend {
};
providers.is_reachable_non_generic = |_tcx, _defid| true;
providers.exported_symbols = |_tcx, _crate| &[];
// Temp hack to make wasm target work
providers.wasm_import_module_map = |_tcx, _crate| Default::default();
}
fn provide_extern(&self, providers: &mut Providers) {