distinct type aliasing

This commit is contained in:
2026-06-23 12:29:21 +02:00
parent 6512ccd543
commit f16f352d1e
15 changed files with 525 additions and 58 deletions
+85 -4
View File
@@ -64,6 +64,7 @@ Kind :: enum u8 {
Function,
Named,
Alias,
Distinct,
Struct,
Union,
}
@@ -128,7 +129,8 @@ clone_store :: proc(source: ^Store, allocator := context.allocator) -> Store {
}
intern :: proc(store: ^Store, candidate: Node) -> Type {
if candidate.kind != .Struct && candidate.kind != .Union && candidate.kind != .Named {
if candidate.kind != .Struct && candidate.kind != .Union &&
candidate.kind != .Named && candidate.kind != .Distinct {
for existing, index in store.nodes {
if existing == candidate {
return DYNAMIC_START+Type(index)
@@ -143,7 +145,8 @@ intern :: proc(store: ^Store, candidate: Node) -> Type {
named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0, file: u32 = 0xffff_ffff) -> Type {
normalized_file := file if qualifier != 0 else u32(0)
for existing, index in store.nodes {
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Struct || existing.kind == .Union) &&
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Distinct ||
existing.kind == .Struct || existing.kind == .Union) &&
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier &&
existing.file == normalized_file {
return DYNAMIC_START+Type(index)
@@ -154,7 +157,8 @@ named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0, file: u32 = 0xf
find_named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0) -> Type {
for existing, index in store.nodes {
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Struct || existing.kind == .Union) &&
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Distinct ||
existing.kind == .Struct || existing.kind == .Union) &&
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier {
return DYNAMIC_START+Type(index)
}
@@ -174,6 +178,18 @@ define_alias :: proc(store: ^Store, id, child: Type) -> bool {
return true
}
define_distinct :: proc(store: ^Store, id, child: Type) -> bool {
existing, ok := node(store, id)
if !ok || existing.kind != .Named || existing.declared {
return false
}
index := int(id-DYNAMIC_START)
store.nodes[index].kind = .Distinct
store.nodes[index].child = child
store.nodes[index].declared = true
return true
}
define_record :: proc(
store: ^Store,
id: Type,
@@ -440,6 +456,10 @@ is_union :: proc(value: Type, store: ^Store) -> bool {
return kind(value, store) == .Union
}
is_distinct :: proc(value: Type, store: ^Store) -> bool {
return kind(value, store) == .Distinct
}
resolve_alias :: proc(value: Type, store: ^Store, depth := 0) -> Type {
if depth > 64 {
return INVALID
@@ -456,6 +476,9 @@ is_c_record_field_type :: proc(value: Type, store: ^Store, depth := 0) -> bool {
return false
}
resolved := resolve_alias(value, store)
if contains_distinct(resolved, store) {
return false
}
if is_concrete_scalar(resolved) || is_pointer(resolved, store) || is_optional_pointer(resolved, store) {
return true
}
@@ -486,7 +509,10 @@ is_optional_pointer :: proc(value: Type, store: ^Store) -> bool {
return ok && item.kind == .Optional && is_pointer(item.child, store)
}
is_runtime_value :: proc(value: Type, store: ^Store) -> bool {
is_runtime_value :: proc(value: Type, store: ^Store, depth := 0) -> bool {
if depth > 256 {
return false
}
value_kind := kind(value, store)
if value_kind == .Scalar || value_kind == .Pointer {
return true
@@ -498,9 +524,29 @@ is_runtime_value :: proc(value: Type, store: ^Store) -> bool {
item, ok := node(store, value)
return ok && item.declared && !item.opaque && (!item.c_layout || item.field_count > 0)
}
if value_kind == .Distinct {
item, ok := node(store, value)
return ok && item.declared && is_runtime_value(item.child, store, depth+1)
}
return false
}
can_construct_distinct :: proc(from, to: Type, store: ^Store) -> bool {
item, ok := node(store, to)
return ok && item.kind == .Distinct && item.declared && equal(from, item.child)
}
runtime_representation :: proc(value: Type, store: ^Store, depth := 0) -> Type {
if depth > 256 {
return INVALID
}
item, ok := node(store, value)
if !ok || item.kind != .Distinct {
return value
}
return runtime_representation(item.child, store, depth+1)
}
contains_c_struct_by_value :: proc(value: Type, store: ^Store, depth := 0) -> bool {
if depth > 256 {
return true
@@ -536,10 +582,41 @@ is_c_signature_type :: proc(value: Type, store: ^Store, allow_void := false) ->
if allow_void && is_void(value) {
return true
}
if contains_distinct(value, store) {
return false
}
return is_concrete_scalar(value) || is_pointer(value, store) || is_optional_pointer(value, store) ||
(is_c_struct(value, store) && is_runtime_value(value, store))
}
contains_distinct :: proc(value: Type, store: ^Store, depth := 0) -> bool {
if depth > 256 {
return true
}
item, ok := node(store, value)
if !ok {
return false
}
if item.kind == .Distinct {
return true
}
if item.kind == .Struct || item.kind == .Union {
for field in fields_for(store, value) {
if contains_distinct(field.type, store, depth+1) {
return true
}
}
}
if item.kind == .Function {
for param in params_for(store, value) {
if contains_distinct(param.type, store, depth+1) {
return true
}
}
}
return is_valid(item.child) && contains_distinct(item.child, store, depth+1)
}
is_c_integer_promotion_candidate :: proc(value: Type) -> bool {
return value >= C_CHAR && value <= C_USHORT
}
@@ -832,6 +909,8 @@ size :: proc(value: Type, store: ^Store, selected := target.DEFAULT) -> u64 {
return ((child_size+1+child_align-1)/child_align)*child_align
case .Function:
return 0
case .Distinct:
return size(child_type(value, store), store, selected)
case .Struct:
item, _ := node(store, value)
if item.explicit_size > 0 {
@@ -873,6 +952,8 @@ alignment_of :: proc(value: Type, store: ^Store, selected := target.DEFAULT) ->
return alignment_of(child_type(value, store), store, selected)
case .Function:
return 1
case .Distinct:
return alignment_of(child_type(value, store), store, selected)
case .Struct:
item, _ := node(store, value)
if item.explicit_alignment > 0 {