From 5b9f5c93fbf0e576f70204f2080d67165e4ee800 Mon Sep 17 00:00:00 2001 From: Kbz-8 Date: Sat, 10 Jan 2026 02:23:15 +0100 Subject: [PATCH] refactoring constant creation --- src/Result.zig | 200 +++++++++++++++++++++++++++++++++++++++--------- src/opcodes.zig | 146 ++++++++++++++++++++--------------- 2 files changed, 248 insertions(+), 98 deletions(-) diff --git a/src/Result.zig b/src/Result.zig index 1185f20..56db38a 100644 --- a/src/Result.zig +++ b/src/Result.zig @@ -55,9 +55,9 @@ const Decoration = struct { }; pub const Value = union(Type) { - Void: noreturn, + Void, Bool: bool, - Int: union { + Int: extern union { sint8: i8, sint16: i16, sint32: i32, @@ -67,7 +67,7 @@ pub const Value = union(Type) { uint32: u32, uint64: u64, }, - Float: union { + Float: extern union { float16: f16, float32: f32, float64: f64, @@ -76,24 +76,103 @@ pub const Value = union(Type) { Matrix: []Value, Array: struct {}, RuntimeArray: struct {}, - Structure: struct {}, - Function: noreturn, + Structure: []Value, + Function, Image: struct {}, Sampler: struct {}, SampledImage: struct {}, - Pointer: noreturn, + Pointer, + + fn initMembers(self: *Value, allocator: std.mem.Allocator, results: []const Self, target: SpvWord) RuntimeError!void { + const resolved = results[target].resolveType(results); + const member_count = resolved.getMemberCounts(); + + switch (resolved.variant.?) { + .Type => |t| switch (t) { + .Bool, .Int, .Float => std.debug.assert(member_count == 1), + .Structure => |s| { + _ = s; + //self.Structure = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory; + //for (self.Structure, s.members) |*value, member_id| { + // value.* = switch (results[member_id].variant.?.Type) { // wtf ? + // inline else => |tag| @unionInit(Value, @tagName(tag), undefined), + // }; + //} + }, + .Matrix => |m| { + self.Matrix = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory; + for (self.Matrix) |*value| { + value.* = switch (m.column_type) { + inline else => |tag| @unionInit(Value, @tagName(tag), undefined), + }; + } + }, + .Array => |a| { + _ = a; + }, + .Vector => |v| { + self.Vector = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory; + for (self.Vector) |*value| { + value.* = switch (v.components_type) { + inline else => |tag| @unionInit(Value, @tagName(tag), undefined), + }; + } + }, + else => {}, + }, + else => {}, + } + } }; +//void spvm_member_allocate_typed_value(spvm_member_t val, spvm_result* results, spvm_word type) +//{ +// spvm_result_t type_info = spvm_state_get_type_info(results, &results[type]); +// assert(type != 0); +// +// if (type_info->value_type == spvm_value_type_void || +// type_info->value_type == spvm_value_type_int || +// type_info->value_type == spvm_value_type_float || +// type_info->value_type == spvm_value_type_bool) { +// assert(type_info->member_count == 1u); +// } else { +// spvm_member_allocate_value(val, type_info->member_count); +// } +// +// val->type = type; +// +// if (type_info->value_type == spvm_value_type_struct) { +// for (spvm_word i = 0; i < val->member_count; i++) { +// spvm_member_allocate_typed_value(&val->members[i], results, type_info->params[i]); +// } +// } +// else if (type_info->value_type == spvm_value_type_matrix) { +// for (spvm_word i = 0; i < val->member_count; i++) +// spvm_member_allocate_typed_value(&val->members[i], results, type_info->pointer); +// } +// else if (type_info->value_type == spvm_value_type_array) { +// if (results[type_info->pointer].member_count > 0) +// for (spvm_word i = 0; i < val->member_count; i++) +// spvm_member_allocate_typed_value(&val->members[i], results, type_info->pointer); +// } else if (type_info->value_type == spvm_value_type_vector) { +// for (spvm_word i = 0; i < val->member_count; ++i) +// val->members[i].type = type_info->pointer; +// } else { +// // having nested images/samplers is not supported +// assert(type_info->value_type != spvm_value_type_sampled_image); +// assert(type_info->value_type != spvm_value_type_image); +// assert(type_info->value_type != spvm_value_type_sampler); +// } +//} + const Self = @This(); name: ?[]const u8, -parent: ?*const Self, - -member_names: std.ArrayList([]const u8), - decorations: std.ArrayList(Decoration), +parent: ?*const Self, + variant: ?union(Variant) { String: []const u8, Extension: struct {}, @@ -112,18 +191,18 @@ variant: ?union(Variant) { member_count: SpvWord, }, Matrix: struct { + column_type_word: SpvWord, column_type: Type, member_count: SpvWord, }, Array: struct {}, RuntimeArray: struct {}, Structure: struct { - /// Allocated array members: []const SpvWord, + member_names: std.ArrayList([]const u8), }, Function: struct { return_type: SpvWord, - /// Allocated array params: []const SpvWord, }, Image: struct {}, @@ -136,13 +215,12 @@ variant: ?union(Variant) { }, Variable: struct { storage_class: spv.SpvStorageClass, - value: Value, + values: []Value, }, - Constant: Value, + Constant: []Value, Function: struct { return_type: SpvWord, function_type: SpvWord, - /// Allocated array params: []const SpvWord, }, AccessChain: struct {}, @@ -154,7 +232,6 @@ pub fn init() Self { return .{ .name = null, .parent = null, - .member_names = .empty, .decorations = .empty, .variant = null, }; @@ -164,22 +241,23 @@ pub fn deinit(self: *Self, allocator: std.mem.Allocator) void { if (self.name) |name| { allocator.free(name); } - for (self.member_names.items) |name| { - allocator.free(name); - } - if (self.variant) |variant| { - switch (variant) { - .Type => |t| { - switch (t) { - .Function => |data| allocator.free(data.params), - .Structure => |data| allocator.free(data.members), - else => {}, - } + if (self.variant) |*variant| { + switch (variant.*) { + .Type => |*t| switch (t.*) { + .Function => |data| allocator.free(data.params), + .Structure => |*data| { + allocator.free(data.members); + for (data.member_names.items) |name| { + allocator.free(name); + } + data.member_names.deinit(allocator); + }, + else => {}, }, + .Constant => |values| allocator.free(values), else => {}, } } - self.member_names.deinit(allocator); self.decorations.deinit(allocator); } @@ -196,17 +274,67 @@ pub fn resolveType(self: *const Self, results: []const Self) *const Self { self; } -pub fn initConstantValue(self: *Self, results: []const Self, target: SpvWord) RuntimeError!void { - _ = self; - const resolved = results[target].resolveType(results); - if (resolved.variant) |variant| { +pub fn getMemberCounts(self: *const Self) usize { + if (self.variant) |variant| { switch (variant) { .Type => |t| switch (t) { - //.Structure => |s| - else => return RuntimeError.InvalidSpirV, + .Bool, .Int, .Float, .Image, .Sampler => return 1, + .Vector => |v| return v.member_count, + .Matrix => |m| return m.member_count, + .SampledImage => return 2, + .Structure => |s| return s.members.len, + .Function => |f| return f.params.len, + else => {}, }, - else => return RuntimeError.InvalidSpirV, + else => {}, } } - return RuntimeError.InvalidSpirV; + return 0; +} + +pub fn initConstantValue(self: *Self, allocator: std.mem.Allocator, results: []const Self, target: SpvWord) RuntimeError!void { + const resolved = results[target].resolveType(results); + const member_count = resolved.getMemberCounts(); + + if (member_count == 0) return; + + self.variant = .{ .Constant = allocator.alloc(Value, member_count) catch return RuntimeError.OutOfMemory }; + errdefer switch (self.variant.?) { + .Constant => |c| allocator.free(c), + else => unreachable, + }; + const values = self.variant.?.Constant; + + switch (resolved.variant.?) { + .Type => |t| switch (t) { + .Bool => values[0] = .{ .Bool = undefined }, + .Int => values[0] = .{ .Int = undefined }, + .Float => values[0] = .{ .Float = undefined }, + .Vector => |v| { + for (values) |*value| { + value.* = switch (v.components_type) { + inline else => |tag| @unionInit(Value, @tagName(tag), undefined), + }; + } + }, + .Matrix => |m| { + for (values) |*value| { + try value.initMembers(allocator, results, m.column_type_word); + } + }, + .Array => |a| { + _ = a; + }, + .Structure => |s| { + for (values, s.members) |*value, member_type| { + try value.initMembers(allocator, results, member_type); + } + }, + .Image => {}, + .Sampler => {}, // No op + .SampledImage => {}, + else => return RuntimeError.InvalidSpirV, + }, + else => return RuntimeError.InvalidSpirV, + } } diff --git a/src/opcodes.zig b/src/opcodes.zig index c3f989d..fc9a746 100644 --- a/src/opcodes.zig +++ b/src/opcodes.zig @@ -157,12 +157,30 @@ fn opMemberName(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) var result = &rt.mod.results.items[id]; - if (memb + 1 > result.member_names.items.len) { - _ = result.member_names.resize(allocator, memb + 1) catch return RuntimeError.OutOfMemory; + if (result.variant == null) { + result.variant = .{ + .Type = .{ + .Structure = .{ + .members = undefined, + .member_names = .empty, + }, + }, + }; } - const slen = word_count - 2; - result.member_names.items[memb] = try readStringN(allocator, &rt.it, slen); + switch (result.variant.?) { + .Type => |*t| switch (t.*) { + .Structure => |*s| { + if (memb + 1 > s.member_names.items.len) { + _ = s.member_names.resize(allocator, memb + 1) catch return RuntimeError.OutOfMemory; + } + const slen = word_count - 2; + s.member_names.items[memb] = try readStringN(allocator, &rt.it, slen); + }, + else => unreachable, + }, + else => unreachable, + } } fn opMemoryModel(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { @@ -260,10 +278,12 @@ fn opTypeVector(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!voi fn opTypeMatrix(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void { const id = try rt.it.next(); + const column_type_word = try rt.it.next(); rt.mod.results.items[id].variant = .{ .Type = .{ .Matrix = .{ - .column_type = switch (rt.mod.results.items[try rt.it.next()].variant.?) { + .column_type_word = column_type_word, + .column_type = switch (rt.mod.results.items[column_type_word].variant.?) { .Type => |t| @as(Result.Type, t), else => return RuntimeError.InvalidSpirV, }, @@ -287,20 +307,33 @@ fn opTypePointer(_: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!vo fn opTypeStruct(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { const id = try rt.it.next(); - rt.mod.results.items[id].variant = .{ - .Type = .{ - .Structure = .{ - .members = blk: { - const members = allocator.alloc(SpvWord, word_count - 1) catch return RuntimeError.OutOfMemory; - errdefer allocator.free(members); - for (members) |*member| { - member.* = try rt.it.next(); - } - break :blk members; + const members = blk: { + const members = allocator.alloc(SpvWord, word_count - 1) catch return RuntimeError.OutOfMemory; + errdefer allocator.free(members); + for (members) |*member| { + member.* = try rt.it.next(); + } + break :blk members; + }; + + if (rt.mod.results.items[id].variant) |*variant| { + switch (variant.*) { + .Type => |*t| switch (t.*) { + .Structure => |*s| s.members = members, + else => unreachable, + }, + else => unreachable, + } + } else { + rt.mod.results.items[id].variant = .{ + .Type = .{ + .Structure = .{ + .members = members, + .member_names = .empty, }, }, - }, - }; + }; + } } fn opTypeFunction(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { @@ -322,45 +355,31 @@ fn opTypeFunction(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtim }; } -fn opConstant(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { +fn opConstant(allocator: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { const var_type = try rt.it.next(); const id = try rt.it.next(); - rt.mod.results.items[id].variant = .{ - .Constant = value: { - const resolved = rt.mod.results.items[var_type].resolveType(rt.mod.results.items); - if (resolved.variant) |variant| { - switch (variant) { - .Type => |t| switch (t) { - .Int => { - break :value if (word_count - 2 != 1) .{ - .Int = .{ - .uint64 = @as(u64, try rt.it.next()) | (@as(u64, try rt.it.next()) >> 32), - }, - } else .{ - .Int = .{ - .uint32 = try rt.it.next(), - }, - }; - }, - .Float => { - break :value if (word_count - 2 != 1) .{ - .Float = .{ - .float64 = @bitCast(@as(u64, try rt.it.next()) | (@as(u64, try rt.it.next()) >> 32)), - }, - } else .{ - .Float = .{ - .float32 = @bitCast(try rt.it.next()), - }, - }; - }, - else => {}, // Will fallback on error, - }, - else => {}, // Will fallback on error - } + + const target = &rt.mod.results.items[id]; + try target.initConstantValue(allocator, rt.mod.results.items, var_type); + + // No check on null and sizes, absolute trust in this shit + switch (target.variant.?.Constant[0]) { + .Int => |*i| { + if (word_count - 2 != 1) { + i.uint64 = @as(u64, try rt.it.next()) | (@as(u64, try rt.it.next()) >> 32); + } else { + i.uint32 = try rt.it.next(); } - return RuntimeError.InvalidSpirV; }, - }; + .Float => |*f| { + if (word_count - 2 != 1) { + f.float64 = @bitCast(@as(u64, try rt.it.next()) | (@as(u64, try rt.it.next()) >> 32)); + } else { + f.float32 = @bitCast(try rt.it.next()); + } + }, + else => return RuntimeError.InvalidSpirV, + } } fn opVariable(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeError!void { @@ -368,18 +387,21 @@ fn opVariable(_: std.mem.Allocator, word_count: SpvWord, rt: *Runtime) RuntimeEr const id = try rt.it.next(); const storage_class = try rt.it.nextAs(spv.SpvStorageClass); const initializer: ?SpvWord = if (word_count >= 4) try rt.it.next() else null; + _ = var_type; + _ = id; + _ = storage_class; _ = initializer; - rt.mod.results.items[id].variant = .{ - .Variable = .{ - .storage_class = storage_class, - .value = value: { - const resolved = rt.mod.results.items[var_type].resolveType(rt.mod.results.items); - _ = resolved; - break :value undefined; - }, - }, - }; + //rt.mod.results.items[id].variant = .{ + // .Variable = .{ + // .storage_class = storage_class, + // .value = value: { + // const resolved = rt.mod.results.items[var_type].resolveType(rt.mod.results.items); + // _ = resolved; + // break :value undefined; + // }, + // }, + //}; } fn opFunction(allocator: std.mem.Allocator, _: SpvWord, rt: *Runtime) RuntimeError!void {