This commit is contained in:
2026-06-23 17:22:41 +02:00
parent f16f352d1e
commit 2f68fc966a
16 changed files with 809 additions and 38 deletions
+72 -13
View File
@@ -65,6 +65,7 @@ Kind :: enum u8 {
Named,
Alias,
Distinct,
Enum,
Struct,
Union,
}
@@ -91,6 +92,7 @@ Node :: struct {
c_layout: bool,
opaque: bool,
declared: bool,
explicit_backing: bool,
}
Field :: struct {
@@ -99,17 +101,24 @@ Field :: struct {
offset: u64,
}
Enum_Member :: struct {
name: u32,
value: i128,
}
Store :: struct {
nodes: [dynamic]Node,
fields: [dynamic]Field,
selected: target.Target,
allocator: mem.Allocator,
nodes: [dynamic]Node,
fields: [dynamic]Field,
enum_members: [dynamic]Enum_Member,
selected: target.Target,
allocator: mem.Allocator,
}
init_store :: proc(allocator := context.allocator) -> Store {
store: Store
store.nodes.allocator = allocator
store.fields.allocator = allocator
store.enum_members.allocator = allocator
store.selected = target.DEFAULT
store.allocator = allocator
return store
@@ -118,19 +127,21 @@ init_store :: proc(allocator := context.allocator) -> Store {
destroy_store :: proc(store: ^Store) {
delete(store.nodes)
delete(store.fields)
delete(store.enum_members)
}
clone_store :: proc(source: ^Store, allocator := context.allocator) -> Store {
store := init_store(allocator)
append(&store.nodes, ..source.nodes[:])
append(&store.fields, ..source.fields[:])
append(&store.enum_members, ..source.enum_members[:])
store.selected = source.selected
return store
}
intern :: proc(store: ^Store, candidate: Node) -> Type {
if candidate.kind != .Struct && candidate.kind != .Union &&
candidate.kind != .Named && candidate.kind != .Distinct {
candidate.kind != .Named && candidate.kind != .Distinct && candidate.kind != .Enum {
for existing, index in store.nodes {
if existing == candidate {
return DYNAMIC_START+Type(index)
@@ -146,7 +157,7 @@ named :: proc(store: ^Store, pkg, name: u32, qualifier: u32 = 0, file: u32 = 0xf
normalized_file := file if qualifier != 0 else u32(0)
for existing, index in store.nodes {
if (existing.kind == .Named || existing.kind == .Alias || existing.kind == .Distinct ||
existing.kind == .Struct || existing.kind == .Union) &&
existing.kind == .Enum || existing.kind == .Struct || existing.kind == .Union) &&
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier &&
existing.file == normalized_file {
return DYNAMIC_START+Type(index)
@@ -158,7 +169,7 @@ 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 == .Distinct ||
existing.kind == .Struct || existing.kind == .Union) &&
existing.kind == .Enum || existing.kind == .Struct || existing.kind == .Union) &&
existing.pkg == pkg && existing.name == name && existing.qualifier == qualifier {
return DYNAMIC_START+Type(index)
}
@@ -190,6 +201,22 @@ define_distinct :: proc(store: ^Store, id, child: Type) -> bool {
return true
}
define_enum :: proc(store: ^Store, id, backing: Type, members: []Enum_Member, explicit_backing: bool) -> bool {
existing, ok := node(store, id)
if !ok || existing.kind != .Named || existing.declared {
return false
}
index := int(id-DYNAMIC_START)
store.nodes[index].kind = .Enum
store.nodes[index].child = backing
store.nodes[index].field_start = u32(len(store.enum_members))
store.nodes[index].field_count = u32(len(members))
store.nodes[index].explicit_backing = explicit_backing
store.nodes[index].declared = true
append(&store.enum_members, ..members)
return true
}
define_record :: proc(
store: ^Store,
id: Type,
@@ -247,6 +274,19 @@ params_for :: proc(store: ^Store, value: Type) -> []Field {
return store.fields[start:end]
}
enum_members_for :: proc(store: ^Store, value: Type) -> []Enum_Member {
item, ok := node(store, value)
if !ok || item.kind != .Enum {
return nil
}
start := int(item.field_start)
end := start+int(item.field_count)
if start < 0 || end > len(store.enum_members) {
return nil
}
return store.enum_members[start:end]
}
kind :: proc(value: Type, store: ^Store = nil) -> Kind {
switch value {
case INVALID:
@@ -409,7 +449,8 @@ is_concrete_scalar :: proc(value: Type) -> bool {
is_concrete :: proc(value: Type, store: ^Store = nil) -> bool {
value_kind := kind(value, store)
if value_kind == .Scalar || value_kind == .Array || value_kind == .Pointer ||
value_kind == .Slice || value_kind == .Range || value_kind == .Optional {
value_kind == .Slice || value_kind == .Range || value_kind == .Optional ||
value_kind == .Enum {
return true
}
if value_kind == .Struct || value_kind == .Union {
@@ -460,6 +501,10 @@ is_distinct :: proc(value: Type, store: ^Store) -> bool {
return kind(value, store) == .Distinct
}
is_enum :: proc(value: Type, store: ^Store) -> bool {
return kind(value, store) == .Enum
}
resolve_alias :: proc(value: Type, store: ^Store, depth := 0) -> Type {
if depth > 64 {
return INVALID
@@ -486,6 +531,9 @@ is_c_record_field_type :: proc(value: Type, store: ^Store, depth := 0) -> bool {
if !ok {
return false
}
if item.kind == .Enum {
return item.explicit_backing && is_concrete_integer(item.child)
}
if item.kind == .Array {
return item.count > 0 && !item.has_sentinel && !item.inferred_count &&
is_c_record_field_type(item.child, store, depth+1)
@@ -524,7 +572,7 @@ is_runtime_value :: proc(value: Type, store: ^Store, depth := 0) -> bool {
item, ok := node(store, value)
return ok && item.declared && !item.opaque && (!item.c_layout || item.field_count > 0)
}
if value_kind == .Distinct {
if value_kind == .Distinct || value_kind == .Enum {
item, ok := node(store, value)
return ok && item.declared && is_runtime_value(item.child, store, depth+1)
}
@@ -541,7 +589,7 @@ runtime_representation :: proc(value: Type, store: ^Store, depth := 0) -> Type {
return INVALID
}
item, ok := node(store, value)
if !ok || item.kind != .Distinct {
if !ok || (item.kind != .Distinct && item.kind != .Enum) {
return value
}
return runtime_representation(item.child, store, depth+1)
@@ -585,6 +633,9 @@ is_c_signature_type :: proc(value: Type, store: ^Store, allow_void := false) ->
if contains_distinct(value, store) {
return false
}
if item, ok := node(store, value); ok && item.kind == .Enum {
return item.explicit_backing && is_concrete_integer(item.child)
}
return is_concrete_scalar(value) || is_pointer(value, store) || is_optional_pointer(value, store) ||
(is_c_struct(value, store) && is_runtime_value(value, store))
}
@@ -621,7 +672,12 @@ is_c_integer_promotion_candidate :: proc(value: Type) -> bool {
return value >= C_CHAR && value <= C_USHORT
}
c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT) -> Type {
c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT, store: ^Store = nil) -> Type {
if store != nil {
if item, ok := node(store, value); ok && item.kind == .Enum {
return c_vararg_promotion(item.child, selected, store)
}
}
if !is_concrete_scalar(value) {
return value
}
@@ -642,6 +698,9 @@ c_vararg_promotion :: proc(value: Type, selected := target.DEFAULT) -> Type {
}
is_c_vararg_type :: proc(value: Type, store: ^Store) -> bool {
if item, ok := node(store, value); ok && item.kind == .Enum {
return item.explicit_backing && is_concrete_integer(item.child)
}
return is_concrete_scalar(value) || is_pointer(value, store) || is_optional_pointer(value, store)
}
@@ -909,7 +968,7 @@ 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:
case .Distinct, .Enum:
return size(child_type(value, store), store, selected)
case .Struct:
item, _ := node(store, value)
@@ -952,7 +1011,7 @@ 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:
case .Distinct, .Enum:
return alignment_of(child_type(value, store), store, selected)
case .Struct:
item, _ := node(store, value)