From b6d2c0972bfe067902a5e9cfcd949f62d479c4a5 Mon Sep 17 00:00:00 2001 From: khyperia Date: Wed, 2 Sep 2020 16:36:54 +0200 Subject: [PATCH] 64 bit switches --- .../src/builder/builder_methods.rs | 58 ++++++++++++++++--- rustc_codegen_spirv/src/builder_spirv.rs | 26 +++++---- rustc_codegen_spirv/src/codegen_cx.rs | 12 ++-- rustc_codegen_spirv/src/lib.rs | 2 + 4 files changed, 75 insertions(+), 23 deletions(-) diff --git a/rustc_codegen_spirv/src/builder/builder_methods.rs b/rustc_codegen_spirv/src/builder/builder_methods.rs index b884e0ac2b..c38fad6193 100644 --- a/rustc_codegen_spirv/src/builder/builder_methods.rs +++ b/rustc_codegen_spirv/src/builder/builder_methods.rs @@ -162,14 +162,58 @@ impl<'a, 'spv, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'spv, 'tcx> { else_llbb: Self::BasicBlock, cases: impl ExactSizeIterator, ) { + // 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::>(); self.emit().switch(v.def, else_llbb, cases).unwrap() } diff --git a/rustc_codegen_spirv/src/builder_spirv.rs b/rustc_codegen_spirv/src/builder_spirv.rs index 5d16a202df..7a25d24ade 100644 --- a/rustc_codegen_spirv/src/builder_spirv.rs +++ b/rustc_codegen_spirv/src/builder_spirv.rs @@ -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 { diff --git a/rustc_codegen_spirv/src/codegen_cx.rs b/rustc_codegen_spirv/src/codegen_cx.rs index 9fbd07dd95..0dfeccfb19 100644 --- a/rustc_codegen_spirv/src/codegen_cx.rs +++ b/rustc_codegen_spirv/src/codegen_cx.rs @@ -67,6 +67,8 @@ pub struct CodegenCx<'spv, 'tcx> { pub type_defs: RefCell>, /// Inverse of type_defs (used to cache generating types) pub type_cache: RefCell>, + /// Cache generated vtables + pub vtables: RefCell, Option>), 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, Option>), 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) } } diff --git a/rustc_codegen_spirv/src/lib.rs b/rustc_codegen_spirv/src/lib.rs index a1631b3401..950eaef646 100644 --- a/rustc_codegen_spirv/src/lib.rs +++ b/rustc_codegen_spirv/src/lib.rs @@ -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) {