| 1 | // Copyright (c) 2026 Alexander Medvednikov. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | |
| 5 | module ssa |
| 6 | |
| 7 | pub type TypeID = int |
| 8 | |
| 9 | pub fn (id TypeID) str() string { |
| 10 | return int(id).str() |
| 11 | } |
| 12 | |
| 13 | pub enum TypeKind { |
| 14 | void_t |
| 15 | int_t |
| 16 | float_t |
| 17 | ptr_t |
| 18 | array_t |
| 19 | struct_t |
| 20 | func_t |
| 21 | label_t |
| 22 | metadata_t |
| 23 | } |
| 24 | |
| 25 | // str returns the symbolic name for an SSA type kind. |
| 26 | pub fn (k TypeKind) str() string { |
| 27 | return match k { |
| 28 | .void_t { 'void_t' } |
| 29 | .int_t { 'int_t' } |
| 30 | .float_t { 'float_t' } |
| 31 | .ptr_t { 'ptr_t' } |
| 32 | .array_t { 'array_t' } |
| 33 | .struct_t { 'struct_t' } |
| 34 | .func_t { 'func_t' } |
| 35 | .label_t { 'label_t' } |
| 36 | .metadata_t { 'metadata_t' } |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | pub struct Type { |
| 41 | pub: |
| 42 | kind TypeKind |
| 43 | width int // Bit width |
| 44 | elem_type TypeID // For Ptr, Array |
| 45 | len int // For Array |
| 46 | fields []TypeID // For Structs |
| 47 | field_names []string // Field names for Structs |
| 48 | params []TypeID // For Funcs |
| 49 | ret_type TypeID |
| 50 | is_c_struct bool // True for C interop structs (use raw field names, typedef to C struct) |
| 51 | is_union bool // True for union types (all fields overlap at offset 0) |
| 52 | is_unsigned bool // True for unsigned integer types (u8, u16, u32, u64) |
| 53 | } |
| 54 | |
| 55 | pub struct TypeStore { |
| 56 | pub mut: |
| 57 | types []Type |
| 58 | cache map[string]TypeID |
| 59 | } |
| 60 | |
| 61 | pub fn TypeStore.new() &TypeStore { |
| 62 | mut ts := &TypeStore{} |
| 63 | ts.register(Type{ kind: .void_t }) // ID 0 = Void |
| 64 | return ts |
| 65 | } |
| 66 | |
| 67 | pub fn (mut ts TypeStore) get_int(width int) TypeID { |
| 68 | key := 'i${width}' |
| 69 | if id := map_get_type_id(ts.cache, key) { |
| 70 | return id |
| 71 | } |
| 72 | id := ts.register(Type{ kind: .int_t, width: width }) |
| 73 | ts.cache[key] = id |
| 74 | return id |
| 75 | } |
| 76 | |
| 77 | pub fn (mut ts TypeStore) get_uint(width int) TypeID { |
| 78 | key := 'u${width}' |
| 79 | if id := map_get_type_id(ts.cache, key) { |
| 80 | return id |
| 81 | } |
| 82 | id := ts.register(Type{ kind: .int_t, width: width, is_unsigned: true }) |
| 83 | ts.cache[key] = id |
| 84 | return id |
| 85 | } |
| 86 | |
| 87 | pub fn (mut ts TypeStore) get_float(width int) TypeID { |
| 88 | key := 'f${width}' |
| 89 | if id := map_get_type_id(ts.cache, key) { |
| 90 | return id |
| 91 | } |
| 92 | id := ts.register(Type{ kind: .float_t, width: width }) |
| 93 | ts.cache[key] = id |
| 94 | return id |
| 95 | } |
| 96 | |
| 97 | pub fn (mut ts TypeStore) get_ptr(elem TypeID) TypeID { |
| 98 | key := 'p${elem}' |
| 99 | if id := map_get_type_id(ts.cache, key) { |
| 100 | return id |
| 101 | } |
| 102 | id := ts.register(Type{ kind: .ptr_t, elem_type: elem }) |
| 103 | ts.cache[key] = id |
| 104 | return id |
| 105 | } |
| 106 | |
| 107 | pub fn (mut ts TypeStore) get_array(elem TypeID, length int) TypeID { |
| 108 | key := 'a${elem}_${length}' |
| 109 | if id := map_get_type_id(ts.cache, key) { |
| 110 | return id |
| 111 | } |
| 112 | id := ts.register(Type{ kind: .array_t, elem_type: elem, len: length }) |
| 113 | ts.cache[key] = id |
| 114 | return id |
| 115 | } |
| 116 | |
| 117 | pub fn (mut ts TypeStore) get_tuple(elem_types []TypeID) TypeID { |
| 118 | // Create a cache key from element types |
| 119 | mut key := 'tuple' |
| 120 | for t in elem_types { |
| 121 | key += '_${t}' |
| 122 | } |
| 123 | if id := map_get_type_id(ts.cache, key) { |
| 124 | return id |
| 125 | } |
| 126 | id := ts.register(Type{ |
| 127 | kind: .struct_t |
| 128 | fields: elem_types |
| 129 | }) |
| 130 | ts.cache[key] = id |
| 131 | return id |
| 132 | } |
| 133 | |
| 134 | pub fn (mut ts TypeStore) register(t Type) TypeID { |
| 135 | id := ts.types.len |
| 136 | ts.types << t |
| 137 | return id |
| 138 | } |
| 139 | |