From 291ee7a49c03c97c417569cfe7a0fae73625dd21 2022-02-15 14:58:17 From: mh Date: 2022-02-15 14:58:17 Subject: [PATCH] Add concept of TypeId for builtin types as well --- diff --git a/src/collections/string_pool.rs b/src/collections/string_pool.rs index 80ced6346d462aef57339049fc57f06395c1e473..ad281e630f0bba4c2d192f01f878509d7ae1b0cf 100644 --- a/src/collections/string_pool.rs +++ b/src/collections/string_pool.rs @@ -31,7 +31,7 @@ impl<'a> StringRef<'a> { /// `new_empty` creates a empty StringRef. It is a null pointer with a /// length of zero. - pub(crate) fn new_empty() -> StringRef<'static> { + pub(crate) const fn new_empty() -> StringRef<'static> { StringRef{ data: null(), length: 0, _phantom: PhantomData } } diff --git a/src/protocol/ast.rs b/src/protocol/ast.rs index 93833384855321f904980f02802bd594d93a4dca..782a5cbe5f3944cfaaaf6cafee08cde10226f41b 100644 --- a/src/protocol/ast.rs +++ b/src/protocol/ast.rs @@ -345,7 +345,7 @@ pub struct Identifier { } impl Identifier { - pub(crate) fn new_empty(span: InputSpan) -> Identifier { + pub(crate) const fn new_empty(span: InputSpan) -> Identifier { return Identifier{ span, value: StringRef::new_empty(), @@ -510,6 +510,7 @@ pub enum ConcreteTypePart { Slice, Input, Output, + Pointer, // Tuple: variable number of nested types, will never be 1 Tuple(u32), // User defined type with any number of nested types @@ -528,7 +529,7 @@ impl ConcreteTypePart { SInt8 | SInt16 | SInt32 | SInt64 | Character | String => 0, - Array | Slice | Input | Output => + Array | Slice | Input | Output | Pointer => 1, Tuple(num_embedded) => *num_embedded, Instance(_, num_embedded) => *num_embedded, @@ -635,6 +636,10 @@ impl ConcreteType { idx = Self::render_type_part_at(parts, heap, idx, target); target.push('>'); }, + CTP::Pointer => { + target.push('*'); + idx = Self::render_type_part_at(parts, heap, idx, target); + } CTP::Tuple(num_parts) => { target.push('('); if num_parts != 0 { diff --git a/src/protocol/ast_printer.rs b/src/protocol/ast_printer.rs index 67f99b1686f2b8397b4f6e911ab8f9312f1feee1..73f14dfd7e8a3552f0106030101aff683ceca2d6 100644 --- a/src/protocol/ast_printer.rs +++ b/src/protocol/ast_printer.rs @@ -957,7 +957,7 @@ fn write_concrete_type(target: &mut String, heap: &Heap, def_id: DefinitionId, t match &t.parts[idx] { CTP::Void => target.push_str("void"), CTP::Message => target.push_str("msg"), - CTP::Bool => target.push_str("bool"), + CTP::Bool => target.push_str(KW_TYPE_BOOL_STR), CTP::UInt8 => target.push_str(KW_TYPE_UINT8_STR), CTP::UInt16 => target.push_str(KW_TYPE_UINT16_STR), CTP::UInt32 => target.push_str(KW_TYPE_UINT32_STR), @@ -968,6 +968,7 @@ fn write_concrete_type(target: &mut String, heap: &Heap, def_id: DefinitionId, t CTP::SInt64 => target.push_str(KW_TYPE_SINT64_STR), CTP::Character => target.push_str(KW_TYPE_CHAR_STR), CTP::String => target.push_str(KW_TYPE_STRING_STR), + CTP::Pointer => target.push('*'), CTP::Array => { idx = write_concrete_part(target, heap, def_id, t, idx + 1); target.push_str("[]"); diff --git a/src/protocol/input_source.rs b/src/protocol/input_source.rs index 4940c2b17a6a2fe4468461bb360a8746ee671451..f2cf10693ae87bc134610829d91344bcc1f221f1 100644 --- a/src/protocol/input_source.rs +++ b/src/protocol/input_source.rs @@ -24,7 +24,7 @@ impl InputSpan { // This must only be used if you're sure that the span will not be involved // in creating an error message. #[inline] - pub fn new() -> InputSpan { + pub const fn new() -> InputSpan { InputSpan{ begin: InputPosition{ line: 0, offset: 0 }, end: InputPosition{ line: 0, offset: 0 }} } diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 1b22d31e02ca3dd2218e5327823727bb2a53e821..11a19bd3ffbdc35734f7290fdbe9bad6d3276054 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -147,7 +147,7 @@ impl ProtocolDescription { use ConcreteTypePart as CTP; match &expected.parts[expected_idx] { - CTP::Void | CTP::Message | CTP::Slice | CTP::Function(_, _) | CTP::Component(_, _) => unreachable!(), + CTP::Void | CTP::Message | CTP::Slice | CTP::Pointer | CTP::Function(_, _) | CTP::Component(_, _) => unreachable!(), CTP::Bool => if let Value::Bool(_) = argument { true } else { false }, CTP::UInt8 => if let Value::UInt8(_) = argument { true } else { false }, CTP::UInt16 => if let Value::UInt16(_) = argument { true } else { false }, diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index acd963e0feb294e292cbf95b758b73d0c18a421c..2a7a85099282418fbec1e42f3a71425cfc766919 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -25,12 +25,13 @@ use pass_typing::{PassTyping, ResolveQueue}; use pass_rewriting::PassRewriting; use pass_stack_size::PassStackSize; use symbol_table::*; -use type_table::TypeTable; +use type_table::*; use crate::protocol::ast::*; use crate::protocol::input_source::*; use crate::protocol::ast_printer::ASTWriter; +use crate::protocol::parser::type_table::PolymorphicVariable; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum ModuleCompilationPhase { @@ -57,16 +58,50 @@ pub struct Module { pub phase: ModuleCompilationPhase, } -// TODO: This is kind of wrong. Because when we're producing bytecode we would -// like the bytecode itself to not have the notion of the size of a pointer -// type. But until I figure out what we do want I'll just set everything -// to a 64-bit architecture. pub struct TargetArch { - pub array_size_alignment: (usize, usize), - pub slice_size_alignment: (usize, usize), - pub string_size_alignment: (usize, usize), - pub port_size_alignment: (usize, usize), - pub pointer_size_alignment: (usize, usize), + pub void_type_id: TypeId, + pub message_type_id: TypeId, + pub bool_type_id: TypeId, + pub uint8_type_id: TypeId, + pub uint16_type_id: TypeId, + pub uint32_type_id: TypeId, + pub uint64_type_id: TypeId, + pub sint8_type_id: TypeId, + pub sint16_type_id: TypeId, + pub sint32_type_id: TypeId, + pub sint64_type_id: TypeId, + pub char_type_id: TypeId, + pub string_type_id: TypeId, + pub array_type_id: TypeId, + pub slice_type_id: TypeId, + pub input_type_id: TypeId, + pub output_type_id: TypeId, + pub pointer_type_id: TypeId, +} + +impl TargetArch { + fn new() -> Self { + return Self{ + void_type_id: TypeId::new_invalid(), + bool_type_id: TypeId::new_invalid(), + message_type_id: TypeId::new_invalid(), + uint8_type_id: TypeId::new_invalid(), + uint16_type_id: TypeId::new_invalid(), + uint32_type_id: TypeId::new_invalid(), + uint64_type_id: TypeId::new_invalid(), + sint8_type_id: TypeId::new_invalid(), + sint16_type_id: TypeId::new_invalid(), + sint32_type_id: TypeId::new_invalid(), + sint64_type_id: TypeId::new_invalid(), + char_type_id: TypeId::new_invalid(), + string_type_id: TypeId::new_invalid(), + array_type_id: TypeId::new_invalid(), + slice_type_id: TypeId::new_invalid(), + input_type_id: TypeId::new_invalid(), + output_type_id: TypeId::new_invalid(), + pointer_type_id: TypeId::new_invalid(), + } + } } pub struct PassCtx<'a> { @@ -115,17 +150,33 @@ impl Parser { pass_rewriting: PassRewriting::new(), pass_stack_size: PassStackSize::new(), write_ast_to: None, - arch: TargetArch { - array_size_alignment: (3*8, 8), // pointer, length, capacity - slice_size_alignment: (2*8, 8), // pointer, length - string_size_alignment: (3*8, 8), // pointer, length, capacity - port_size_alignment: (3*4, 4), // two u32s: connector + port ID - pointer_size_alignment: (8, 8), - } + arch: TargetArch::new(), }; parser.symbol_table.insert_scope(None, SymbolScope::Global); + // Insert builtin types + // TODO: At some point use correct values for size/alignment + parser.arch.void_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Void], false, 0, 1); + parser.arch.message_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Message], false, 24, 8); + parser.arch.bool_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Bool], false, 1, 1); + parser.arch.uint8_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::UInt8], false, 1, 1); + parser.arch.uint16_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::UInt16], false, 2, 2); + parser.arch.uint32_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::UInt32], false, 4, 4); + parser.arch.uint64_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::UInt64], false, 8, 8); + parser.arch.sint8_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::SInt8], false, 1, 1); + parser.arch.sint16_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::SInt16], false, 2, 2); + parser.arch.sint32_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::SInt32], false, 4, 4); + parser.arch.sint64_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::SInt64], false, 8, 8); + parser.arch.char_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Character], false, 4, 4); + parser.arch.string_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::String], false, 24, 8); + parser.arch.array_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Array, ConcreteTypePart::Void], true, 24, 8); + parser.arch.slice_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Slice, ConcreteTypePart::Void], true, 16, 4); + parser.arch.input_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Input, ConcreteTypePart::Void], true, 8, 8); + parser.arch.output_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Output, ConcreteTypePart::Void], true, 8, 8); + parser.arch.pointer_type_id = insert_builtin_type(&mut parser.type_table, vec![ConcreteTypePart::Pointer, ConcreteTypePart::Void], true, 8, 8); + + // Insert builtin functions fn quick_type(variants: &[ParserTypeVariant]) -> ParserType { let mut t = ParserType{ elements: Vec::with_capacity(variants.len()), full_span: InputSpan::new() }; for variant in variants { @@ -288,10 +339,26 @@ impl Parser { } } +fn insert_builtin_type(type_table: &mut TypeTable, parts: Vec, has_poly_var: bool, size: usize, alignment: usize) -> TypeId { + const POLY_VARS: [PolymorphicVariable; 1] = [PolymorphicVariable{ + identifier: Identifier::new_empty(InputSpan::new()), + is_in_use: false, + }]; + + let concrete_type = ConcreteType{ parts }; + let poly_var = if has_poly_var { + POLY_VARS.as_slice() + } else { + &[] + }; + + return type_table.add_builtin_type(concrete_type, poly_var, size, alignment); +} + // Note: args and return type need to be a function because we need to know the function ID. fn insert_builtin_function (Vec<(&'static str, ParserType)>, ParserType)> ( - p: &mut Parser, func_name: &str, polymorphic: &[&str], arg_and_return_fn: T) { - + p: &mut Parser, func_name: &str, polymorphic: &[&str], arg_and_return_fn: T +) { let mut poly_vars = Vec::with_capacity(polymorphic.len()); for poly_var in polymorphic { poly_vars.push(Identifier{ span: InputSpan::new(), value: p.string_pool.intern(poly_var.as_bytes()) }); diff --git a/src/protocol/parser/pass_typing.rs b/src/protocol/parser/pass_typing.rs index b83adc287c4c02f7241be33d32ad7e1242939206..c4e82df63dfaff2f8ec920b893f1c9c5a3a98c45 100644 --- a/src/protocol/parser/pass_typing.rs +++ b/src/protocol/parser/pass_typing.rs @@ -3783,6 +3783,7 @@ impl PassTyping { CTP::Slice => parser_type.push(ITP::Slice), CTP::Input => parser_type.push(ITP::Input), CTP::Output => parser_type.push(ITP::Output), + CTP::Pointer => unreachable!("pointer type during concrete to inference type conversion"), CTP::Tuple(num) => parser_type.push(ITP::Tuple(*num)), CTP::Instance(id, num) => parser_type.push(ITP::Instance(*id, *num)), CTP::Function(_, _) => unreachable!("function type during concrete to inference type conversion"), diff --git a/src/protocol/parser/type_table.rs b/src/protocol/parser/type_table.rs index 97feb153fed8dacc202aa2241ae3e217899818c7..6279724617adbc3d434ce60f61653038ff177f6e 100644 --- a/src/protocol/parser/type_table.rs +++ b/src/protocol/parser/type_table.rs @@ -140,8 +140,8 @@ impl DefinedTypeVariant { } pub struct PolymorphicVariable { - identifier: Identifier, - is_in_use: bool, // a polymorphic argument may be defined, but not used by the type definition + pub(crate) identifier: Identifier, + pub(crate) is_in_use: bool, // a polymorphic argument may be defined, but not used by the type definition } /// `EnumType` is the classical C/C++ enum type. It has various variants with @@ -783,6 +783,7 @@ impl TypeTable { pub(crate) fn add_builtin_type(&mut self, concrete_type: ConcreteType, poly_vars: &[PolymorphicVariable], size: usize, alignment: usize) -> TypeId { self.mono_search_key.set(&concrete_type.parts, poly_vars); debug_assert!(!self.mono_type_lookup.contains_key(&self.mono_search_key)); + debug_assert_ne!(alignment, 0); let type_id = TypeId(self.mono_types.len() as i64); self.mono_type_lookup.insert(self.mono_search_key.clone(), type_id); self.mono_types.push(MonoType{ @@ -1794,6 +1795,8 @@ impl TypeTable { debug_assert!(self.memory_layout_breadcrumbs.is_empty()); debug_assert!(self.size_alignment_stack.is_empty()); + let (ptr_size, ptr_align) = self.mono_types[arch.pointer_type_id.0 as usize].get_size_alignment().unwrap(); + // Push the first entry (the type we originally started with when we // were detecting type loops) let first_entry = &self.encountered_types[0]; @@ -1876,7 +1879,6 @@ impl TypeTable { if variant.lives_on_heap { // Variant lives on heap, so just a pointer - let (ptr_size, ptr_align) = arch.pointer_size_alignment; align_offset_to(&mut variant_offset, ptr_align); variant_offset += ptr_size; @@ -2107,38 +2109,30 @@ impl TypeTable { use ConcreteTypePart as CTP; debug_assert!(!parts.is_empty()); - let (builtin_size, builtin_alignment) = match parts[0] { - CTP::Void => (0, 1), - CTP::Message => arch.array_size_alignment, - CTP::Bool => (1, 1), - CTP::UInt8 => (1, 1), - CTP::UInt16 => (2, 2), - CTP::UInt32 => (4, 4), - CTP::UInt64 => (8, 8), - CTP::SInt8 => (1, 1), - CTP::SInt16 => (2, 2), - CTP::SInt32 => (4, 4), - CTP::SInt64 => (8, 8), - CTP::Character => (4, 4), - CTP::String => arch.string_size_alignment, - CTP::Array => arch.array_size_alignment, - CTP::Slice => arch.array_size_alignment, - CTP::Input => arch.port_size_alignment, - CTP::Output => arch.port_size_alignment, + let type_id = match parts[0] { + CTP::Void => arch.void_type_id, + CTP::Message => arch.message_type_id, + CTP::Bool => arch.bool_type_id, + CTP::UInt8 => arch.uint8_type_id, + CTP::UInt16 => arch.uint16_type_id, + CTP::UInt32 => arch.uint32_type_id, + CTP::UInt64 => arch.uint64_type_id, + CTP::SInt8 => arch.sint8_type_id, + CTP::SInt16 => arch.sint16_type_id, + CTP::SInt32 => arch.sint32_type_id, + CTP::SInt64 => arch.sint64_type_id, + CTP::Character => arch.char_type_id, + CTP::String => arch.string_type_id, + CTP::Array => arch.array_type_id, + CTP::Slice => arch.slice_type_id, + CTP::Input => arch.input_type_id, + CTP::Output => arch.output_type_id, + CTP::Pointer => arch.pointer_type_id, CTP::Tuple(_) => { Self::set_search_key_to_tuple(search_key, definition_map, parts); let type_id = mono_type_map.get(&search_key).copied().unwrap(); - let mono_type = &mono_types[type_id.0 as usize]; - if let Some((size, alignment)) = mono_type.get_size_alignment() { - return MemoryLayoutResult::TypeExists(size, alignment); - } else { - return MemoryLayoutResult::PushBreadcrumb(MemoryBreadcrumb{ - type_id, - next_member: 0, - next_embedded: 0, - first_size_alignment_idx: size_alignment_stack_len as u32, - }) - } + + type_id }, CTP::Instance(definition_id, _) => { // Retrieve entry and the specific monomorph index by applying @@ -2146,25 +2140,25 @@ impl TypeTable { let definition_type = definition_map.get(&definition_id).unwrap(); search_key.set(parts, &definition_type.poly_vars); let type_id = mono_type_map.get(&search_key).copied().unwrap(); - let mono_type = &mono_types[type_id.0 as usize]; - if let Some((size, alignment)) = mono_type.get_size_alignment() { - return MemoryLayoutResult::TypeExists(size, alignment); - } else { - return MemoryLayoutResult::PushBreadcrumb(MemoryBreadcrumb{ - type_id, - next_member: 0, - next_embedded: 0, - first_size_alignment_idx: size_alignment_stack_len as u32, - }); - } + type_id }, CTP::Function(_, _) | CTP::Component(_, _) => { todo!("storage for 'function pointers'"); } }; - return MemoryLayoutResult::TypeExists(builtin_size, builtin_alignment); + let mono_type = &mono_types[type_id.0 as usize]; + if let Some((size, alignment)) = mono_type.get_size_alignment() { + return MemoryLayoutResult::TypeExists(size, alignment); + } else { + return MemoryLayoutResult::PushBreadcrumb(MemoryBreadcrumb{ + type_id, + next_member: 0, + next_embedded: 0, + first_size_alignment_idx: size_alignment_stack_len as u32, + }); + } } /// Returns tag concrete type (always a builtin integer type), the size of