authorgravatar for ben@happyspork.comBen Anderman <ben@happyspork.com> 2026-08-20 01:22:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-08-26 20:54:49-07:00
logfb6cce8cf3f2977d1828cff4aa3a9cb1b6ff6b5f
treeb9dd12d84c90e412ceed0dcf18aa346625f47431
parent3cd05f8a1b6fdb39f0ad5aaea4665af908c7840a

Update spork8 backend to modern internal compiler APIs


5 files changed, 166 insertions(+), 65 deletions(-)

src/codegen.zig+4
...@@ -80,6 +80,7 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co...@@ -80,6 +80,7 @@ pub fn legalizeFeatures(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) ?*co
80 .stage2_x86,80 .stage2_x86,
81 .stage2_riscv64,81 .stage2_riscv64,
82 .stage2_sparc64,82 .stage2_sparc64,
83 .stage2_spork8,
83 .stage2_spirv,84 .stage2_spirv,
84 => |backend| {85 => |backend| {
85 dev.check(devFeatureForBackend(backend));86 dev.check(devFeatureForBackend(backend));
...@@ -121,6 +122,7 @@ pub const AnyMir = union {...@@ -121,6 +122,7 @@ pub const AnyMir = union {
121 .stage2_wasm => "wasm",122 .stage2_wasm => "wasm",
122 .stage2_c => "c",123 .stage2_c => "c",
123 .stage2_spirv => "spirv",124 .stage2_spirv => "spirv",
125 .stage2_spork8 => "spork8",
124 else => unreachable,126 else => unreachable,
125 };127 };
126 }128 }
...@@ -138,6 +140,7 @@ pub const AnyMir = union {...@@ -138,6 +140,7 @@ pub const AnyMir = union {
138 .stage2_wasm,140 .stage2_wasm,
139 .stage2_c,141 .stage2_c,
140 .stage2_spirv,142 .stage2_spirv,
143 .stage2_spork8,
141 => |backend_ct| @field(mir, tag(backend_ct)).deinit(gpa),144 => |backend_ct| @field(mir, tag(backend_ct)).deinit(gpa),
142 }145 }
143 }146 }
...@@ -167,6 +170,7 @@ pub fn generateFunction(...@@ -167,6 +170,7 @@ pub fn generateFunction(
167 .stage2_x86_64,170 .stage2_x86_64,
168 .stage2_wasm,171 .stage2_wasm,
169 .stage2_c,172 .stage2_c,
173 .stage2_spork8,
170 .stage2_spirv,174 .stage2_spirv,
171 => |backend| {175 => |backend| {
172 dev.check(devFeatureForBackend(backend));176 dev.check(devFeatureForBackend(backend));
src/codegen/spork8/CodeGen.zig+152-60
...@@ -14,87 +14,163 @@ const Mir = @import("Mir.zig");...@@ -14,87 +14,163 @@ const Mir = @import("Mir.zig");
14air: Air,14air: Air,
15liveness: Liveness,15liveness: Liveness,
16gpa: Allocator,16gpa: Allocator,
17spork8: *Spork8,
18pt: Zcu.PerThread,17pt: Zcu.PerThread,
19owner_nav: InternPool.Nav.Index,18owner_nav: InternPool.Nav.Index,
20func_index: InternPool.Index,19func_index: InternPool.Index,
21mir_instructions: *std.MultiArrayList(Mir.Inst),20mir_instructions: std.MultiArrayList(Mir.Inst),
22/// Contains extra data for MIR21/// Contains extra data for MIR
23mir_extra: *std.ArrayListUnmanaged(u32),22mir_extra: std.ArrayListUnmanaged(u32),
24start_mir_extra_off: u32,23
2524pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features {
26pub const Error = error{25 return comptime &.initMany(&.{
27 OutOfMemory,26 .expand_bit_cast_safe,
28 /// Compiler was asked to operate on a number larger than supported.27 .expand_int_cast_safe,
29 Overflow,28 .expand_int_from_float_safe,
30 /// Indicates the error is already stored in Zcu `failed_codegen`.29 .expand_int_from_float_optimized_safe,
31 CodegenFail,30 .expand_add_safe,
32};31 .expand_sub_safe,
3332 .expand_mul_safe,
34pub const Function = extern struct {33
35 /// Index into `Spork8.mir_instructions`.34 .expand_packed_load,
36 mir_off: u32,35 .expand_packed_store,
37 /// This is unused except for as a safety slice bound and could be removed.36 .expand_packed_agg_field_val,
38 mir_len: u32,37 .expand_packed_aggregate_init,
39 /// Index into `Spork8.mir_extra`.38 .expand_array_to_vector,
40 mir_extra_off: u32,39
41 /// This is unused except for as a safety slice bound and could be removed.40 .scalarize_add,
42 mir_extra_len: u32,41 .scalarize_add_optimized,
43};42 .scalarize_add_wrap,
43 .scalarize_add_sat,
44 .scalarize_sub,
45 .scalarize_sub_optimized,
46 .scalarize_sub_wrap,
47 .scalarize_sub_sat,
48 .scalarize_mul,
49 .scalarize_mul_optimized,
50 .scalarize_mul_wrap,
51 .scalarize_mul_sat,
52 .scalarize_div_float,
53 .scalarize_div_float_optimized,
54 .scalarize_div_trunc,
55 .scalarize_div_trunc_optimized,
56 .scalarize_div_floor,
57 .scalarize_div_floor_optimized,
58 .scalarize_div_ceil,
59 .scalarize_div_ceil_optimized,
60 .scalarize_div_exact,
61 .scalarize_div_exact_optimized,
62 .scalarize_rem,
63 .scalarize_rem_optimized,
64 .scalarize_mod,
65 .scalarize_mod_optimized,
66 .scalarize_max,
67 .scalarize_min,
68 .scalarize_add_with_overflow,
69 .scalarize_sub_with_overflow,
70 .scalarize_mul_with_overflow,
71 .scalarize_shl_with_overflow,
72 .scalarize_bit_and,
73 .scalarize_bit_or,
74 .scalarize_shr,
75 .scalarize_shr_exact,
76 .scalarize_shl,
77 .scalarize_shl_exact,
78 .scalarize_shl_sat,
79 .scalarize_xor,
80 .scalarize_not,
81 .scalarize_clz,
82 .scalarize_ctz,
83 .scalarize_popcount,
84 .scalarize_byte_swap,
85 .scalarize_bit_reverse,
86 .scalarize_sqrt,
87 .scalarize_sin,
88 .scalarize_cos,
89 .scalarize_tan,
90 .scalarize_exp,
91 .scalarize_exp2,
92 .scalarize_log,
93 .scalarize_log2,
94 .scalarize_log10,
95 .scalarize_abs,
96 .scalarize_floor,
97 .scalarize_ceil,
98 .scalarize_round,
99 .scalarize_trunc_float,
100 .scalarize_neg,
101 .scalarize_neg_optimized,
102 .scalarize_cmp_vector,
103 .scalarize_cmp_vector_optimized,
104 .scalarize_fptrunc,
105 .scalarize_fpext,
106 .scalarize_int_cast,
107 .scalarize_ptr_cast,
108 .scalarize_ptr_from_int,
109 .scalarize_int_from_ptr,
110 .scalarize_trunc,
111 .scalarize_int_from_float,
112 .scalarize_int_from_float_optimized,
113 .scalarize_float_from_int,
114 .scalarize_reduce,
115 .scalarize_reduce_optimized,
116 .scalarize_shuffle_one,
117 .scalarize_shuffle_two,
118 .scalarize_select,
119 .scalarize_mul_add,
120
121 .scalarize_bit_cast_padded_elems,
122 });
123}
44124
45pub fn function(125pub fn generate(
46 spork8: *Spork8,126 bin_file: *link.File,
47 pt: Zcu.PerThread,127 pt: Zcu.PerThread,
48 func_index: InternPool.Index,128 func_index: InternPool.Index,
49 air: Air,129 air: *const Air,
50 liveness: Liveness,130 liveness: *const ?Air.Liveness,
51) Error!Function {131) link.Error!Mir {
132 _ = bin_file;
52 const zcu = pt.zcu;133 const zcu = pt.zcu;
53 const gpa = zcu.gpa;134 const gpa = zcu.gpa;
54 const func_info = zcu.funcInfo(func_index);135 const cg = zcu.funcInfo(func_index);
55136
56 var code_gen: CodeGen = .{137 var code_gen: CodeGen = .{
57 .gpa = gpa,138 .gpa = gpa,
58 .pt = pt,139 .pt = pt,
59 .air = air,140 .air = air.*,
60 .liveness = liveness,141 .liveness = liveness.*.?,
61 .owner_nav = func_info.owner_nav,142 .owner_nav = cg.owner_nav,
62 .spork8 = spork8,
63 .func_index = func_index,143 .func_index = func_index,
64 .mir_instructions = &spork8.mir_instructions,144 .mir_instructions = .empty,
65 .mir_extra = &spork8.mir_extra,145 .mir_extra = .empty,
66 .start_mir_extra_off = @intCast(spork8.mir_extra.items.len),
67 };146 };
68 defer code_gen.deinit();147 defer code_gen.deinit();
69148
70 return functionInner(&code_gen) catch |err| switch (err) {149 return generateInner(&code_gen) catch |err| switch (err) {
71 error.CodegenFail => return error.CodegenFail,150 error.AlreadyReported,
72 else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}),151 error.OutOfMemory,
152 => |e| return e,
73 };153 };
74}154}
75155
76fn deinit(cg: *CodeGen) void {156pub fn deinit(cg: *CodeGen) void {
77 cg.* = undefined;157 cg.* = undefined;
78}158}
79159
80const InnerError = error{160const InnerError = error{
81 CodegenFail,161 AlreadyReported,
82 OutOfMemory,162 OutOfMemory,
83};163};
84164
85fn functionInner(cg: *CodeGen) InnerError!Function {165fn generateInner(cg: *CodeGen) InnerError!Mir {
86 const spork8 = cg.spork8;
87
88 const start_mir_off: u32 = @intCast(spork8.mir_instructions.len);
89
90 // Generate MIR for function body166 // Generate MIR for function body
91 try cg.genBody(cg.air.getMainBody());167 try cg.genBody(cg.air.getMainBody());
92168
169 try cg.mir_extra.shrinkToLen(cg.gpa);
170
93 return .{171 return .{
94 .mir_off = start_mir_off,172 .instructions = cg.mir_instructions.toOwnedSlice(),
95 .mir_len = @intCast(spork8.mir_instructions.len - start_mir_off),173 .extra = cg.mir_extra.toOwnedSliceAssert(),
96 .mir_extra_off = cg.start_mir_extra_off,
97 .mir_extra_len = cg.extraLen(),
98 };174 };
99}175}
100176
...@@ -130,8 +206,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -130,8 +206,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
130 .div_floor,206 .div_floor,
131 .bit_and,207 .bit_and,
132 .bit_or,208 .bit_or,
133 .bool_and,
134 .bool_or,
135 .rem,209 .rem,
136 .mod,210 .mod,
137 .shl,211 .shl,
...@@ -177,13 +251,11 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -177,13 +251,11 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
177 .cmp_neq,251 .cmp_neq,
178252
179 .cmp_vector,253 .cmp_vector,
180 .cmp_lt_errors_len,
181254
182 .array_elem_val,255 .array_elem_val,
183 .array_to_slice,256 .array_to_slice,
184 .alloc,257 .alloc,
185 .arg,258 .arg,
186 .bitcast,
187 .block,259 .block,
188 .trap,260 .trap,
189 .breakpoint,261 .breakpoint,
...@@ -191,7 +263,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -191,7 +263,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
191 .repeat,263 .repeat,
192 .switch_dispatch,264 .switch_dispatch,
193 .cond_br,265 .cond_br,
194 .intcast,
195 .fptrunc,266 .fptrunc,
196 .fpext,267 .fpext,
197 .int_from_float,268 .int_from_float,
...@@ -241,7 +312,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -241,7 +312,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
241 .ret_load,312 .ret_load,
242 .splat,313 .splat,
243 .select,314 .select,
244 .shuffle,
245 .reduce,315 .reduce,
246 .aggregate_init,316 .aggregate_init,
247 .union_init,317 .union_init,
...@@ -266,7 +336,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -266,7 +336,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
266 .struct_field_ptr_index_1,336 .struct_field_ptr_index_1,
267 .struct_field_ptr_index_2,337 .struct_field_ptr_index_2,
268 .struct_field_ptr_index_3,338 .struct_field_ptr_index_3,
269 .struct_field_val,
270 .field_parent_ptr,339 .field_parent_ptr,
271340
272 .switch_br,341 .switch_br,
...@@ -303,7 +372,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -303,7 +372,6 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
303 .save_err_return_trace_index,372 .save_err_return_trace_index,
304 .is_named_enum_value,373 .is_named_enum_value,
305 .addrspace_cast,374 .addrspace_cast,
306 .vector_store_elem,
307 .c_va_arg,375 .c_va_arg,
308 .c_va_copy,376 .c_va_copy,
309 .c_va_end,377 .c_va_end,
...@@ -341,7 +409,31 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -341,7 +409,31 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
341 .add_safe,409 .add_safe,
342 .sub_safe,410 .sub_safe,
343 .mul_safe,411 .mul_safe,
344 .intcast_safe,412 .div_ceil,
413 .div_ceil_optimized,
414 .bit_cast,
415 .bit_cast_safe,
416 .ptr_cast,
417 .ptr_from_int,
418 .int_from_ptr,
419 .error_cast,
420 .error_from_int,
421 .int_from_error,
422 .union_from_enum,
423 .int_cast,
424 .int_cast_safe,
425 .agg_field_val,
426 .array_to_vector,
427 .int_from_float_safe,
428 .int_from_float_optimized_safe,
429 .shuffle_one,
430 .shuffle_two,
431 .cmp_lte_errors_len,
432 .runtime_nav_ptr,
433 .spirv_runtime_array_len,
434 .legalize_vec_store_elem,
435 .legalize_vec_elem_val,
436 .legalize_compiler_rt_call,
345 => |tag| return cg.fail("TODO: implement spork8 inst: {s}", .{@tagName(tag)}),437 => |tag| return cg.fail("TODO: implement spork8 inst: {s}", .{@tagName(tag)}),
346438
347 .work_item_id,439 .work_item_id,
...@@ -356,7 +448,7 @@ fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {...@@ -356,7 +448,7 @@ fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void {
356 _ = inst;448 _ = inst;
357}449}
358450
359fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } {451fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, AlreadyReported } {
360 const zcu = cg.pt.zcu;452 const zcu = cg.pt.zcu;
361 const func = zcu.funcInfo(cg.func_index);453 const func = zcu.funcInfo(cg.func_index);
362 return zcu.codegenFail(func.owner_nav, fmt, args);454 return zcu.codegenFail(func.owner_nav, fmt, args);
src/codegen/spork8/Mir.zig+9-4
...@@ -5,8 +5,8 @@ const builtin = @import("builtin");...@@ -5,8 +5,8 @@ const builtin = @import("builtin");
5const std = @import("std");5const std = @import("std");
6const assert = std.debug.assert;6const assert = std.debug.assert;
77
8instruction_tags: []const Inst.Tag,8instructions: std.MultiArrayList(Inst).Slice,
9instruction_datas: []const Inst.Data,9
10extra: []const u32,10extra: []const u32,
1111
12pub const Inst = struct {12pub const Inst = struct {
...@@ -24,9 +24,9 @@ pub const Inst = struct {...@@ -24,9 +24,9 @@ pub const Inst = struct {
24 /// imm824 /// imm8
25 set_addr_i = 0x09,25 set_addr_i = 0x09,
26 /// imm826 /// imm8
27 load_i = 0x10,27 load_i = 0x11,
28 /// index28 /// index
29 jump,29 jump = 0x68,
30 };30 };
3131
32 /// All instructions contain a 4-byte payload, which is contained within32 /// All instructions contain a 4-byte payload, which is contained within
...@@ -44,3 +44,8 @@ pub const Inst = struct {...@@ -44,3 +44,8 @@ pub const Inst = struct {
44 }44 }
45 };45 };
46};46};
47
48pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
49 mir.instructions.deinit(gpa);
50 mir.* = undefined;
51}
src/dev.zig+1
...@@ -248,6 +248,7 @@ pub const Env = enum {...@@ -248,6 +248,7 @@ pub const Env = enum {
248 .spork8 => switch (feature) {248 .spork8 => switch (feature) {
249 .stdio_listen,249 .stdio_listen,
250 .incremental,250 .incremental,
251 .legalize,
251 .spork8_backend,252 .spork8_backend,
252 .spork8_linker,253 .spork8_linker,
253 => true,254 => true,
src/link/Spork8.zig-1
...@@ -22,7 +22,6 @@ const dev = @import("../dev.zig");...@@ -22,7 +22,6 @@ const dev = @import("../dev.zig");
22const Value = @import("../Value.zig");22const Value = @import("../Value.zig");
2323
24base: link.File,24base: link.File,
25funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, CodeGen.Function) = .empty,
26/// All MIR instructions for all Zcu functions.25/// All MIR instructions for all Zcu functions.
27mir_instructions: std.MultiArrayList(Mir.Inst) = .{},26mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
28/// Corresponds to `mir_instructions`.27/// Corresponds to `mir_instructions`.