diff --git a/lib/codegen/meta-python/cdsl/types.py b/lib/codegen/meta-python/cdsl/types.py index 13bc5deab1..26777152da 100644 --- a/lib/codegen/meta-python/cdsl/types.py +++ b/lib/codegen/meta-python/cdsl/types.py @@ -179,7 +179,7 @@ class SpecialType(ValueType): def __init__(self, name, membytes, doc): # type: (str, int, str) -> None super(SpecialType, self).__init__(name, membytes, doc) - # Assign numbers starting from 1. (0 is VOID) + # Assign numbers starting from 1. (0 is INVALID) ValueType.all_special_types.append(self) self.number = len(ValueType.all_special_types) assert self.number < LANE_BASE, 'Too many special types' diff --git a/lib/codegen/meta-python/gen_encoding.py b/lib/codegen/meta-python/gen_encoding.py index a81b66dcca..59875bf489 100644 --- a/lib/codegen/meta-python/gen_encoding.py +++ b/lib/codegen/meta-python/gen_encoding.py @@ -22,8 +22,8 @@ This is the information available to us: ## Level 1 table lookup The CPU mode provides the first table. The key is the instruction's controlling -type variable. If the instruction is not polymorphic, use `VOID` for the type -variable. The table values are level 2 tables. +type variable. If the instruction is not polymorphic, use `INVALID` for the +type variable. The table values are level 2 tables. ## Level 2 table lookup @@ -682,7 +682,7 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt): # Empty hash table entry. Include the default legalization action. if not level2: fmt.format( - 'Level1Entry {{ ty: ir::types::VOID, log2len: !0, ' + 'Level1Entry {{ ty: ir::types::INVALID, log2len: !0, ' 'offset: 0, legalize: {} }},', level1.legalize_code) continue @@ -690,7 +690,7 @@ def emit_level1_hashtable(cpumode, level1, offt, fmt): if level2.ty is not None: tyname = level2.ty.rust_name() else: - tyname = 'ir::types::VOID' + tyname = 'ir::types::INVALID' lcode = cpumode.isa.legalize_code(level2.legalize) diff --git a/lib/codegen/meta-python/gen_instr.py b/lib/codegen/meta-python/gen_instr.py index 4b73b95bc6..2f5eeae93d 100644 --- a/lib/codegen/meta-python/gen_instr.py +++ b/lib/codegen/meta-python/gen_instr.py @@ -705,7 +705,7 @@ def gen_inst_builder(inst, fmt): args.append(inst.ctrl_typevar.name) elif not inst.is_polymorphic: # No controlling type variable needed. - args.append('types::VOID') + args.append('types::INVALID') else: assert inst.is_polymorphic and inst.use_typevar_operand # Infer the controlling type variable from the input operands. diff --git a/lib/codegen/src/ir/builder.rs b/lib/codegen/src/ir/builder.rs index 5cd2bfe36d..9128092f67 100644 --- a/lib/codegen/src/ir/builder.rs +++ b/lib/codegen/src/ir/builder.rs @@ -28,7 +28,7 @@ pub trait InstBuilderBase<'f>: Sized { /// Insert an instruction and return a reference to it, consuming the builder. /// /// The result types may depend on a controlling type variable. For non-polymorphic - /// instructions with multiple results, pass `VOID` for the `ctrl_typevar` argument. + /// instructions with multiple results, pass `INVALID` for the `ctrl_typevar` argument. fn build(self, data: InstructionData, ctrl_typevar: Type) -> (Inst, &'f mut DataFlowGraph); } diff --git a/lib/codegen/src/ir/dfg.rs b/lib/codegen/src/ir/dfg.rs index 6d799a43c9..08bec5d624 100644 --- a/lib/codegen/src/ir/dfg.rs +++ b/lib/codegen/src/ir/dfg.rs @@ -157,7 +157,7 @@ pub struct Values<'a> { /// Check for non-values fn valid_valuedata(data: &ValueData) -> bool { if let &ValueData::Alias { - ty: types::VOID, + ty: types::INVALID, original, } = data { @@ -288,7 +288,7 @@ impl DataFlowGraph { self.value_type(dest), ty ); - debug_assert_ne!(ty, types::VOID); + debug_assert_ne!(ty, types::INVALID); self.values[dest] = ValueData::Alias { ty, original }; } @@ -332,7 +332,7 @@ impl DataFlowGraph { self.value_type(dest), ty ); - debug_assert_ne!(ty, types::VOID); + debug_assert_ne!(ty, types::INVALID); self.values[dest] = ValueData::Alias { ty, original }; } @@ -461,7 +461,7 @@ impl DataFlowGraph { /// /// The result value types are determined from the instruction's value type constraints and the /// provided `ctrl_typevar` type for polymorphic instructions. For non-polymorphic - /// instructions, `ctrl_typevar` is ignored, and `VOID` can be used. + /// instructions, `ctrl_typevar` is ignored, and `INVALID` can be used. /// /// The type of the first result value is also set, even if it was already set in the /// `InstructionData` passed to `make_inst`. If this function is called with a single-result @@ -679,12 +679,12 @@ impl DataFlowGraph { }) } - /// Get the controlling type variable, or `VOID` if `inst` isn't polymorphic. + /// Get the controlling type variable, or `INVALID` if `inst` isn't polymorphic. pub fn ctrl_typevar(&self, inst: Inst) -> Type { let constraints = self[inst].opcode().constraints(); if !constraints.is_polymorphic() { - types::VOID + types::INVALID } else if constraints.requires_typevar_operand() { // Not all instruction formats have a designated operand, but in that case // `requires_typevar_operand()` should never be true. @@ -897,7 +897,7 @@ impl<'a> fmt::Display for DisplayInst<'a> { } let typevar = dfg.ctrl_typevar(inst); - if typevar.is_void() { + if typevar.is_invalid() { write!(f, "{}", dfg[inst].opcode())?; } else { write!(f, "{}.{}", dfg[inst].opcode(), typevar)?; @@ -914,7 +914,7 @@ impl DataFlowGraph { fn set_value_type_for_parser(&mut self, v: Value, t: Type) { assert_eq!( self.value_type(v), - types::VOID, + types::INVALID, "this function is only for assigning types to previously invalid values" ); match self.values[v] { @@ -980,9 +980,9 @@ impl DataFlowGraph { let ty = if self.values.is_valid(src) { self.value_type(src) } else { - // As a special case, if we can't resolve the aliasee yet, use VOID + // As a special case, if we can't resolve the aliasee yet, use INVALID // temporarily. It will be resolved later in parsing. - types::VOID + types::INVALID }; let data = ValueData::Alias { ty, original: src }; self.values[dest] = data; @@ -1007,7 +1007,7 @@ impl DataFlowGraph { if let Some(resolved) = maybe_resolve_aliases(&self.values, v) { let old_ty = self.value_type(v); let new_ty = self.value_type(resolved); - if old_ty == types::VOID { + if old_ty == types::INVALID { self.set_value_type_for_parser(v, new_ty); } else { assert_eq!(old_ty, new_ty); @@ -1023,7 +1023,7 @@ impl DataFlowGraph { #[cold] pub fn make_invalid_value_for_parser(&mut self) { let data = ValueData::Alias { - ty: types::VOID, + ty: types::INVALID, original: Value::reserved_value(), }; self.make_value(data); @@ -1037,7 +1037,7 @@ impl DataFlowGraph { return false; } if let ValueData::Alias { ty, .. } = self.values[v] { - ty != types::VOID + ty != types::INVALID } else { true } diff --git a/lib/codegen/src/ir/types.rs b/lib/codegen/src/ir/types.rs index 195d90968a..1d19f5c6d7 100644 --- a/lib/codegen/src/ir/types.rs +++ b/lib/codegen/src/ir/types.rs @@ -5,8 +5,9 @@ use std::fmt::{self, Debug, Display, Formatter}; /// The type of an SSA value. /// -/// The `VOID` type is only used for instructions that produce no value. It can't be part of a SIMD -/// vector. +/// The `INVALID` type isn't a real type, and is used as a placeholder in the IR where a type +/// field is present put no type is needed, such as the controlling type variable for a +/// non-polymorphic instruction. /// /// Basic integer types: `I8`, `I16`, `I32`, and `I64`. These types are sign-agnostic. /// @@ -20,9 +21,8 @@ use std::fmt::{self, Debug, Display, Formatter}; #[derive(Copy, Clone, PartialEq, Eq, Hash)] pub struct Type(u8); -/// No type. Used for functions without a return value. Can't be loaded or stored. Can't be part of -/// a SIMD vector. -pub const VOID: Type = Type(0); +/// Not a valid type. Can't be loaded or stored. Can't be part of a SIMD vector. +pub const INVALID: Type = Type(0); /// Start of the lane types. See also `meta-python/cdsl.types.py`. const LANE_BASE: u8 = 0x70; @@ -146,9 +146,9 @@ impl Type { })) } - /// Is this the VOID type? - pub fn is_void(self) -> bool { - self == VOID + /// Is this the INVALID type? + pub fn is_invalid(self) -> bool { + self == INVALID } /// Is this a special type? @@ -285,10 +285,10 @@ impl Display for Type { write!(f, "{}x{}", self.lane_type(), self.lane_count()) } else { f.write_str(match *self { - VOID => "void", IFLAGS => "iflags", FFLAGS => "fflags", - _ => panic!("Invalid Type(0x{:x})", self.0), + INVALID => panic!("INVALID encountered"), + _ => panic!("Unknown Type(0x{:x})", self.0), }) } } @@ -306,7 +306,7 @@ impl Debug for Type { write!(f, "{:?}X{}", self.lane_type(), self.lane_count()) } else { match *self { - VOID => write!(f, "types::VOID"), + INVALID => write!(f, "types::INVALID"), IFLAGS => write!(f, "types::IFLAGS"), FFLAGS => write!(f, "types::FFLAGS"), _ => write!(f, "Type(0x{:x})", self.0), @@ -317,7 +317,7 @@ impl Debug for Type { impl Default for Type { fn default() -> Self { - VOID + INVALID } } @@ -328,8 +328,8 @@ mod tests { #[test] fn basic_scalars() { - assert_eq!(VOID, VOID.lane_type()); - assert_eq!(0, VOID.bits()); + assert_eq!(INVALID, INVALID.lane_type()); + assert_eq!(0, INVALID.bits()); assert_eq!(IFLAGS, IFLAGS.lane_type()); assert_eq!(0, IFLAGS.bits()); assert_eq!(FFLAGS, FFLAGS.lane_type()); @@ -346,7 +346,7 @@ mod tests { assert_eq!(F32, F32.lane_type()); assert_eq!(F64, F64.lane_type()); - assert_eq!(VOID.lane_bits(), 0); + assert_eq!(INVALID.lane_bits(), 0); assert_eq!(IFLAGS.lane_bits(), 0); assert_eq!(FFLAGS.lane_bits(), 0); assert_eq!(B1.lane_bits(), 1); @@ -364,8 +364,8 @@ mod tests { #[test] fn typevar_functions() { - assert_eq!(VOID.half_width(), None); - assert_eq!(IFLAGS.half_width(), None); + assert_eq!(INVALID.half_width(), None); + assert_eq!(INVALID.half_width(), None); assert_eq!(FFLAGS.half_width(), None); assert_eq!(B1.half_width(), None); assert_eq!(B8.half_width(), None); @@ -380,7 +380,7 @@ mod tests { assert_eq!(F32.half_width(), None); assert_eq!(F64.half_width(), Some(F32)); - assert_eq!(VOID.double_width(), None); + assert_eq!(INVALID.double_width(), None); assert_eq!(IFLAGS.double_width(), None); assert_eq!(FFLAGS.double_width(), None); assert_eq!(B1.double_width(), None); @@ -407,7 +407,7 @@ mod tests { assert_eq!(big.half_vector().unwrap().to_string(), "f64x128"); assert_eq!(B1.by(2).unwrap().half_vector().unwrap().to_string(), "b1"); assert_eq!(I32.half_vector(), None); - assert_eq!(VOID.half_vector(), None); + assert_eq!(INVALID.half_vector(), None); // Check that the generated constants match the computed vector types. assert_eq!(I32.by(4), Some(I32X4)); @@ -416,7 +416,6 @@ mod tests { #[test] fn format_scalars() { - assert_eq!(VOID.to_string(), "void"); assert_eq!(IFLAGS.to_string(), "iflags"); assert_eq!(FFLAGS.to_string(), "fflags"); assert_eq!(B1.to_string(), "b1"); @@ -443,7 +442,7 @@ mod tests { assert_eq!(F64.by(2).unwrap().to_string(), "f64x2"); assert_eq!(I8.by(3), None); assert_eq!(I8.by(512), None); - assert_eq!(VOID.by(4), None); + assert_eq!(INVALID.by(4), None); } #[test] diff --git a/lib/codegen/src/isa/enc_tables.rs b/lib/codegen/src/isa/enc_tables.rs index 0a98ace71a..1d8ed94780 100644 --- a/lib/codegen/src/isa/enc_tables.rs +++ b/lib/codegen/src/isa/enc_tables.rs @@ -30,7 +30,7 @@ pub type LegalizeCode = u8; /// Level 1 hash table entry. /// /// One level 1 hash table is generated per CPU mode. This table is keyed by the controlling type -/// variable, using `VOID` for non-polymorphic instructions. +/// variable, using `INVALID` for non-polymorphic instructions. /// /// The hash table values are references to level 2 hash tables, encoded as an offset in `LEVEL2` /// where the table begins, and the binary logarithm of its length. All the level 2 hash tables diff --git a/lib/codegen/src/verifier/mod.rs b/lib/codegen/src/verifier/mod.rs index 16e21565ac..51aa484525 100644 --- a/lib/codegen/src/verifier/mod.rs +++ b/lib/codegen/src/verifier/mod.rs @@ -1106,8 +1106,8 @@ impl<'a> Verifier<'a> { ctrl_type } else { // Non-polymorphic instructions don't check the controlling type variable, so `Option` - // is unnecessary and we can just make it `VOID`. - types::VOID + // is unnecessary and we can just make it `INVALID`. + types::INVALID }; // Typechecking instructions is never fatal diff --git a/lib/codegen/src/write.rs b/lib/codegen/src/write.rs index 24cfdbe284..2e9faf6b40 100644 --- a/lib/codegen/src/write.rs +++ b/lib/codegen/src/write.rs @@ -44,13 +44,17 @@ pub trait FuncWriter { } for (heap, heap_data) in &func.heaps { - any = true; - self.write_entity_definition(w, func, heap.into(), heap_data)?; + if !heap_data.index_type.is_invalid() { + any = true; + self.write_entity_definition(w, func, heap.into(), heap_data)?; + } } for (table, table_data) in &func.tables { - any = true; - self.write_entity_definition(w, func, table.into(), table_data)?; + if !table_data.index_type.is_invalid() { + any = true; + self.write_entity_definition(w, func, table.into(), table_data)?; + } } // Write out all signatures before functions since function declarations can refer to @@ -61,8 +65,8 @@ pub trait FuncWriter { } for (fnref, ext_func) in &func.dfg.ext_funcs { - any = true; if ext_func.signature != SigRef::reserved_value() { + any = true; self.write_entity_definition(w, func, fnref.into(), ext_func)?; } } @@ -265,7 +269,7 @@ fn type_suffix(func: &Function, inst: Inst) -> Option { let rtype = func.dfg.ctrl_typevar(inst); assert!( - !rtype.is_void(), + !rtype.is_invalid(), "Polymorphic instruction must produce a result" ); Some(rtype) diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 5358109a2e..4a116699b8 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -5,7 +5,7 @@ use cranelift_codegen::ir; use cranelift_codegen::ir::entities::AnyEntity; use cranelift_codegen::ir::immediates::{Ieee32, Ieee64, Imm64, Offset32, Uimm32}; use cranelift_codegen::ir::instructions::{InstructionData, InstructionFormat, VariableArgs}; -use cranelift_codegen::ir::types::VOID; +use cranelift_codegen::ir::types::INVALID; use cranelift_codegen::ir::{ AbiParam, ArgumentExtension, ArgumentLoc, Ebb, ExtFuncData, ExternalName, FuncRef, Function, GlobalValue, GlobalValueData, Heap, HeapData, HeapStyle, JumpTable, JumpTableData, MemFlags, @@ -194,7 +194,7 @@ impl<'a> Context<'a> { style: HeapStyle::Static { bound: Imm64::new(0), }, - index_type: VOID, + index_type: INVALID, }); } self.function.heaps[heap] = data; @@ -218,7 +218,7 @@ impl<'a> Context<'a> { min_size: Imm64::new(0), bound_gv: GlobalValue::reserved_value(), element_size: Imm64::new(0), - index_type: VOID, + index_type: INVALID, }); } self.function.tables[table] = data; @@ -1951,7 +1951,7 @@ impl<'a> Parser<'a> { // The controlling type variable can be specified explicitly as 'splat.i32x4 v5', or it can be // inferred from `inst_data.typevar_operand` for some opcodes. // - // Returns the controlling typevar for a polymorphic opcode, or `VOID` for a non-polymorphic + // Returns the controlling typevar for a polymorphic opcode, or `INVALID` for a non-polymorphic // opcode. fn infer_typevar( &self, @@ -2006,7 +2006,7 @@ impl<'a> Parser<'a> { ); } else { // This is a non-polymorphic opcode. No typevar needed. - VOID + INVALID } } }; @@ -2025,7 +2025,7 @@ impl<'a> Parser<'a> { ); } // Treat it as a syntax error to speficy a typevar on a non-polymorphic opcode. - } else if ctrl_type != VOID { + } else if ctrl_type != INVALID { return err!(self.loc, "{} does not take a typevar", opcode); } diff --git a/lib/wasm/src/environ/dummy.rs b/lib/wasm/src/environ/dummy.rs index d7c9c47c10..229e2a7274 100644 --- a/lib/wasm/src/environ/dummy.rs +++ b/lib/wasm/src/environ/dummy.rs @@ -277,7 +277,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ Ok(pos .ins() - .CallIndirect(ir::Opcode::CallIndirect, VOID, sig_ref, args) + .CallIndirect(ir::Opcode::CallIndirect, INVALID, sig_ref, args) .0) } @@ -300,7 +300,7 @@ impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environ args.extend(call_args.iter().cloned(), &mut pos.func.dfg.value_lists); args.push(vmctx, &mut pos.func.dfg.value_lists); - Ok(pos.ins().Call(ir::Opcode::Call, VOID, callee, args).0) + Ok(pos.ins().Call(ir::Opcode::Call, INVALID, callee, args).0) } fn translate_memory_grow(