diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 9072f3fd4d..b6091225a7 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -104,6 +104,7 @@ pub const Os = struct { .plan9 => arch.plan9Ext(), else => switch (arch) { .wasm32, .wasm64 => ".wasm", + .spork8 => ".spork8", else => "", }, }; @@ -780,6 +781,22 @@ pub const x86 = @import("Target/x86.zig"); pub const xcore = @import("Target/xcore.zig"); pub const xtensa = @import("Target/xtensa.zig"); +pub const spork8 = struct { + pub const Feature = enum {}; + pub const featureSet = Cpu.Feature.FeatureSetFns(Feature).featureSet; + pub const featureSetHas = Cpu.Feature.FeatureSetFns(Feature).featureSetHas; + pub const featureSetHasAny = Cpu.Feature.FeatureSetFns(Feature).featureSetHasAny; + pub const featureSetHasAll = Cpu.Feature.FeatureSetFns(Feature).featureSetHasAll; + + pub const cpu = struct { + pub const generic: Cpu.Model = .{ + .name = "generic", + .llvm_name = null, + .features = .empty, + }; + }; +}; + pub const Abi = enum { none, gnu, @@ -1018,6 +1035,7 @@ pub const ObjectFormat = enum { hex, /// The Mach object format used by macOS and other Apple platforms. macho, + spork8, /// The a.out format used by Plan 9 from Bell Labs. plan9, /// Machine code with no metadata. @@ -1038,6 +1056,7 @@ pub const ObjectFormat = enum { .coff => ".obj", .elf, .goff, .macho, .wasm, .xcoff => ".o", .hex => ".ihex", + .spork8 => ".spork8", .plan9 => arch.plan9Ext(), .raw => ".bin", .spirv => ".spv", @@ -1054,6 +1073,7 @@ pub const ObjectFormat = enum { else => switch (arch) { .spirv, .spirv32, .spirv64 => .spirv, .wasm32, .wasm64 => .wasm, + .spork8 => .spork8, else => .elf, }, }; @@ -1097,6 +1117,7 @@ pub fn toElfMachine(target: Target) std.elf.EM { .spirv64, .wasm32, .wasm64, + .spork8, => .NONE, }; } @@ -1150,6 +1171,7 @@ pub fn toCoffMachine(target: Target) std.coff.MachineType { .xcore, .xtensa, .propeller, + .spork8, => .UNKNOWN, }; } @@ -1369,6 +1391,7 @@ pub const Cpu = struct { s390x, sparc, sparc64, + spork8, spirv, spirv32, spirv64, @@ -1573,6 +1596,7 @@ pub const Cpu = struct { .sparc64, .lanai, .s390x, + .spork8, => .big, }; } @@ -1916,6 +1940,7 @@ pub const Cpu = struct { .kalimba, .or1k, + .spork8, => &S.generic_model, }; } @@ -2593,6 +2618,7 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { return switch (cpu.arch) { .avr, .msp430, + .spork8, => 16, .arc, @@ -3080,7 +3106,7 @@ pub fn cTypeBitSize(target: Target, c_type: CType) u16 { pub fn cTypeAlignment(target: Target, c_type: CType) u16 { // Overrides for unusual alignments switch (target.cpu.arch) { - .avr => return 1, + .avr, .spork8 => return 1, .x86 => switch (target.os.tag) { .windows, .uefi => switch (c_type) { .longlong, .ulonglong, .double => return 8, @@ -3167,6 +3193,7 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 { => 16, .avr, + .spork8, => unreachable, // Handled above. }), ); @@ -3267,7 +3294,9 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { pub fn cMaxIntAlignment(target: std.Target) u16 { return switch (target.cpu.arch) { - .avr => 1, + .avr, + .spork8, + => 1, .msp430 => 2, @@ -3390,6 +3419,7 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { .amdgcn => .{ .amdgcn_device = .{} }, .nvptx, .nvptx64 => .nvptx_device, .spirv, .spirv32, .spirv64 => .spirv_device, + .spork8 => .naked, }; } diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index de2d8b2156..73054d9fe7 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -1110,6 +1110,7 @@ pub const CompilerBackend = enum(u64) { /// The reference implementation self-hosted compiler of Zig, using the /// spirv backend. stage2_spirv64 = 11, + stage2_spork8 = 12, _, }; diff --git a/lib/std/start.zig b/lib/std/start.zig index 6495db1c51..82d290efd8 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -26,7 +26,9 @@ comptime { // decls there get run. _ = root; - if (simplified_logic) { + if (builtin.cpu.arch == .spork8) { + // always freestanding, even exes + } else if (simplified_logic) { if (builtin.output_mode == .Exe) { if ((builtin.link_libc or builtin.object_format == .c) and @hasDecl(root, "main")) { if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) { diff --git a/lib/std/zig.zig b/lib/std/zig.zig index a946fe5e8b..51c5abecb2 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -223,6 +223,7 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe .spirv => return std.fmt.allocPrint(allocator, "{s}.spv", .{root_name}), .hex => return std.fmt.allocPrint(allocator, "{s}.ihex", .{root_name}), .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}), + .spork8 => return std.fmt.allocPrint(allocator, "{s}.spork8", .{root_name}), .plan9 => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 493c63f34f..91a27136a3 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -449,7 +449,7 @@ pub fn resolve(options: Options) ResolveError!Config { .windows, .uefi => .code_view, else => .{ .dwarf = .@"32" }, }, - .spirv, .hex, .raw, .plan9 => .strip, + .spirv, .hex, .raw, .plan9, .spork8 => .strip, }; }; diff --git a/src/Zcu.zig b/src/Zcu.zig index fab40763e8..7fcdc22649 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -3675,6 +3675,8 @@ pub fn atomicPtrAlignment( ) AtomicPtrAlignmentError!Alignment { const target = zcu.getTarget(); const max_atomic_bits: u16 = switch (target.cpu.arch) { + .spork8 => 8, + .avr, .msp430, => 16, @@ -4368,6 +4370,10 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu .spirv_fragment, .spirv_vertex => target.os.tag == .vulkan, else => false, }, + .stage2_spork8 => switch (cc) { + .naked => true, + else => false, + }, }; if (!backend_ok) return .{ .bad_backend = backend }; return .ok; diff --git a/src/arch/spork8/CodeGen.zig b/src/arch/spork8/CodeGen.zig new file mode 100644 index 0000000000..6c9ddb4b71 --- /dev/null +++ b/src/arch/spork8/CodeGen.zig @@ -0,0 +1,367 @@ +const std = @import("std"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; + +const CodeGen = @This(); +const link = @import("../../link.zig"); +const Spork8 = link.File.Spork8; +const Zcu = @import("../../Zcu.zig"); +const InternPool = @import("../../InternPool.zig"); +const Air = @import("../../Air.zig"); +const Liveness = @import("../../Liveness.zig"); +const Mir = @import("Mir.zig"); + +air: Air, +liveness: Liveness, +gpa: Allocator, +spork8: *Spork8, +pt: Zcu.PerThread, +owner_nav: InternPool.Nav.Index, +func_index: InternPool.Index, +mir_instructions: *std.MultiArrayList(Mir.Inst), +/// Contains extra data for MIR +mir_extra: *std.ArrayListUnmanaged(u32), +start_mir_extra_off: u32, + +pub const Error = error{ + OutOfMemory, + /// Compiler was asked to operate on a number larger than supported. + Overflow, + /// Indicates the error is already stored in Zcu `failed_codegen`. + CodegenFail, +}; + +pub const Function = extern struct { + /// Index into `Spork8.mir_instructions`. + mir_off: u32, + /// This is unused except for as a safety slice bound and could be removed. + mir_len: u32, + /// Index into `Spork8.mir_extra`. + mir_extra_off: u32, + /// This is unused except for as a safety slice bound and could be removed. + mir_extra_len: u32, +}; + +pub fn function( + spork8: *Spork8, + pt: Zcu.PerThread, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, +) Error!Function { + const zcu = pt.zcu; + const gpa = zcu.gpa; + const func_info = zcu.funcInfo(func_index); + + var code_gen: CodeGen = .{ + .gpa = gpa, + .pt = pt, + .air = air, + .liveness = liveness, + .owner_nav = func_info.owner_nav, + .spork8 = spork8, + .func_index = func_index, + .mir_instructions = &spork8.mir_instructions, + .mir_extra = &spork8.mir_extra, + .start_mir_extra_off = @intCast(spork8.mir_extra.items.len), + }; + defer code_gen.deinit(); + + return functionInner(&code_gen) catch |err| switch (err) { + error.CodegenFail => return error.CodegenFail, + else => |e| return code_gen.fail("failed to generate function: {s}", .{@errorName(e)}), + }; +} + +fn deinit(cg: *CodeGen) void { + cg.* = undefined; +} + +const InnerError = error{ + CodegenFail, + OutOfMemory, +}; + +fn functionInner(cg: *CodeGen) InnerError!Function { + const spork8 = cg.spork8; + + const start_mir_off: u32 = @intCast(spork8.mir_instructions.len); + + // Generate MIR for function body + try cg.genBody(cg.air.getMainBody()); + + return .{ + .mir_off = start_mir_off, + .mir_len = @intCast(spork8.mir_instructions.len - start_mir_off), + .mir_extra_off = cg.start_mir_extra_off, + .mir_extra_len = cg.extraLen(), + }; +} + +fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { + const zcu = cg.pt.zcu; + const ip = &zcu.intern_pool; + + for (body) |inst| { + if (cg.liveness.isUnused(inst) and !cg.air.mustLower(inst, ip)) continue; + try cg.genInst(inst); + } +} + +fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const air_tags = cg.air.instructions.items(.tag); + return switch (air_tags[@intFromEnum(inst)]) { + .inferred_alloc, .inferred_alloc_comptime => unreachable, + + .unreach => cg.airUnreachable(inst), + + .add, + .add_sat, + .add_wrap, + .sub, + .sub_sat, + .sub_wrap, + .mul, + .mul_sat, + .mul_wrap, + .div_float, + .div_exact, + .div_trunc, + .div_floor, + .bit_and, + .bit_or, + .bool_and, + .bool_or, + .rem, + .mod, + .shl, + .shl_exact, + .shl_sat, + .shr, + .shr_exact, + .xor, + .max, + .min, + .mul_add, + + .sqrt, + .sin, + .cos, + .tan, + .exp, + .exp2, + .log, + .log2, + .log10, + .floor, + .ceil, + .round, + .trunc_float, + .neg, + + .abs, + + .add_with_overflow, + .sub_with_overflow, + .shl_with_overflow, + .mul_with_overflow, + + .clz, + .ctz, + + .cmp_eq, + .cmp_gte, + .cmp_gt, + .cmp_lte, + .cmp_lt, + .cmp_neq, + + .cmp_vector, + .cmp_lt_errors_len, + + .array_elem_val, + .array_to_slice, + .alloc, + .arg, + .bitcast, + .block, + .trap, + .breakpoint, + .br, + .repeat, + .switch_dispatch, + .cond_br, + .intcast, + .fptrunc, + .fpext, + .int_from_float, + .float_from_int, + .get_union_tag, + + .@"try", + .try_cold, + .try_ptr, + .try_ptr_cold, + + .dbg_stmt, + .dbg_empty_stmt, + .dbg_inline_block, + .dbg_var_ptr, + .dbg_var_val, + .dbg_arg_inline, + + .call, + .call_always_tail, + .call_never_tail, + .call_never_inline, + + .is_err, + .is_non_err, + + .is_null, + .is_non_null, + .is_null_ptr, + .is_non_null_ptr, + + .load, + .loop, + .memset, + .memset_safe, + .not, + .optional_payload, + .optional_payload_ptr, + .optional_payload_ptr_set, + .ptr_add, + .ptr_sub, + .ptr_elem_ptr, + .ptr_elem_val, + .ret, + .ret_safe, + .ret_ptr, + .ret_load, + .splat, + .select, + .shuffle, + .reduce, + .aggregate_init, + .union_init, + .prefetch, + .popcount, + .byte_swap, + .bit_reverse, + + .slice, + .slice_len, + .slice_elem_val, + .slice_elem_ptr, + .slice_ptr, + .ptr_slice_len_ptr, + .ptr_slice_ptr_ptr, + .store, + .store_safe, + + .set_union_tag, + .struct_field_ptr, + .struct_field_ptr_index_0, + .struct_field_ptr_index_1, + .struct_field_ptr_index_2, + .struct_field_ptr_index_3, + .struct_field_val, + .field_parent_ptr, + + .switch_br, + .loop_switch_br, + .trunc, + + .wrap_optional, + .unwrap_errunion_payload, + .unwrap_errunion_payload_ptr, + .unwrap_errunion_err, + .unwrap_errunion_err_ptr, + .wrap_errunion_payload, + .wrap_errunion_err, + .errunion_payload_ptr_set, + .error_name, + + .wasm_memory_size, + .wasm_memory_grow, + + .memcpy, + + .ret_addr, + .tag_name, + + .error_set_has_value, + .frame_addr, + + .assembly, + .is_err_ptr, + .is_non_err_ptr, + + .err_return_trace, + .set_err_return_trace, + .save_err_return_trace_index, + .is_named_enum_value, + .addrspace_cast, + .vector_store_elem, + .c_va_arg, + .c_va_copy, + .c_va_end, + .c_va_start, + .memmove, + + .atomic_load, + .atomic_store_unordered, + .atomic_store_monotonic, + .atomic_store_release, + .atomic_store_seq_cst, + .atomic_rmw, + .cmpxchg_weak, + .cmpxchg_strong, + + .add_optimized, + .sub_optimized, + .mul_optimized, + .div_float_optimized, + .div_trunc_optimized, + .div_floor_optimized, + .div_exact_optimized, + .rem_optimized, + .mod_optimized, + .neg_optimized, + .cmp_lt_optimized, + .cmp_lte_optimized, + .cmp_eq_optimized, + .cmp_gte_optimized, + .cmp_gt_optimized, + .cmp_neq_optimized, + .cmp_vector_optimized, + .reduce_optimized, + .int_from_float_optimized, + .add_safe, + .sub_safe, + .mul_safe, + .intcast_safe, + => |tag| return cg.fail("TODO: implement spork8 inst: {s}", .{@tagName(tag)}), + + .work_item_id, + .work_group_size, + .work_group_id, + => unreachable, + }; +} + +fn airUnreachable(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { + _ = cg; + _ = inst; +} + +fn fail(cg: *CodeGen, comptime fmt: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { + const zcu = cg.pt.zcu; + const func = zcu.funcInfo(cg.func_index); + return zcu.codegenFail(func.owner_nav, fmt, args); +} + +fn extraLen(cg: *const CodeGen) u32 { + return @intCast(cg.mir_extra.items.len - cg.start_mir_extra_off); +} diff --git a/src/arch/spork8/Mir.zig b/src/arch/spork8/Mir.zig new file mode 100644 index 0000000000..c049dd2089 --- /dev/null +++ b/src/arch/spork8/Mir.zig @@ -0,0 +1,46 @@ +const Mir = @This(); +const InternPool = @import("../../InternPool.zig"); + +const builtin = @import("builtin"); +const std = @import("std"); +const assert = std.debug.assert; + +instruction_tags: []const Inst.Tag, +instruction_datas: []const Inst.Data, +extra: []const u32, + +pub const Inst = struct { + tag: Tag, + data: Data, + + /// The position of a given MIR isntruction with the instruction list. + pub const Index = enum(u32) { + _, + }; + + pub const Tag = enum(u8) { + /// imm8 + set_page_i = 0x04, + /// imm8 + set_addr_i = 0x09, + /// imm8 + load_i = 0x10, + /// index + jump, + }; + + /// All instructions contain a 4-byte payload, which is contained within + /// this union. `Tag` determines which union tag is active, as well as + /// how to interpret the data within. + pub const Data = union { + imm8: u8, + index: Index, + + comptime { + switch (builtin.mode) { + .Debug, .ReleaseSafe => {}, + .ReleaseFast, .ReleaseSmall => assert(@sizeOf(Data) == 4), + } + } + }; +}; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 050e47b68a..4fd0d5a912 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -100,6 +100,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { .kalimba, .or1k, .propeller, + .spork8, => unreachable, // Gated by hasLlvmSupport(). }; @@ -457,6 +458,7 @@ pub fn dataLayout(target: std.Target) []const u8 { .kalimba, .or1k, .propeller, + .spork8, => unreachable, // Gated by hasLlvmSupport(). }; } diff --git a/src/dev.zig b/src/dev.zig index 11b8be785c..457d7337a9 100644 --- a/src/dev.zig +++ b/src/dev.zig @@ -34,6 +34,10 @@ pub const Env = enum { /// - `zig build-* -fno-llvm -fno-lld -target wasm32-* --listen=-` wasm, + /// - sema + /// - `zig build-* -fno-llvm -fno-lld -target spork8-* --listen=-` + spork8, + pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool { return switch (dev_env) { .full => true, @@ -73,6 +77,7 @@ pub const Env = enum { .riscv64_backend, .sparc64_backend, .spirv64_backend, + .spork8_backend, .lld_linker, .coff_linker, .elf_linker, @@ -83,6 +88,7 @@ pub const Env = enum { .plan9_linker, .goff_linker, .xcoff_linker, + .spork8_linker, => true, .cc_command, .translate_c_command, @@ -158,6 +164,14 @@ pub const Env = enum { => true, else => Env.sema.supports(feature), }, + .spork8 => switch (feature) { + .stdio_listen, + .incremental, + .spork8_backend, + .spork8_linker, + => true, + else => Env.sema.supports(feature), + }, }; } @@ -219,6 +233,7 @@ pub const Feature = enum { riscv64_backend, sparc64_backend, spirv64_backend, + spork8_backend, lld_linker, coff_linker, @@ -230,6 +245,7 @@ pub const Feature = enum { plan9_linker, goff_linker, xcoff_linker, + spork8_linker, }; /// Makes the code following the call to this function unreachable if `feature` is disabled. diff --git a/src/link.zig b/src/link.zig index d418705e70..57f623959f 100644 --- a/src/link.zig +++ b/src/link.zig @@ -598,6 +598,7 @@ pub const File = struct { }); }, .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }), + .spork8 => dev.check(.spork8_linker), } } @@ -671,6 +672,7 @@ pub const File = struct { } }, .c, .spirv => dev.checkAny(&.{ .c_linker, .spirv_linker }), + .spork8 => dev.check(.spork8_linker), } } @@ -1245,6 +1247,7 @@ pub const File = struct { c, wasm, spirv, + spork8, plan9, goff, xcoff, @@ -1260,6 +1263,7 @@ pub const File = struct { .plan9 => Plan9, .goff => Goff, .xcoff => Xcoff, + .spork8 => Spork8, }; } @@ -1274,6 +1278,7 @@ pub const File = struct { .spirv => .spirv, .goff => .goff, .xcoff => .xcoff, + .spork8 => .spork8, .hex => @panic("TODO implement hex object format"), .raw => @panic("TODO implement raw object format"), }; @@ -1373,6 +1378,7 @@ pub const File = struct { pub const C = @import("link/C.zig"); pub const Coff = @import("link/Coff.zig"); + pub const Spork8 = @import("link/Spork8.zig"); pub const Plan9 = @import("link/Plan9.zig"); pub const Elf = @import("link/Elf.zig"); pub const MachO = @import("link/MachO.zig"); diff --git a/src/link/Spork8.zig b/src/link/Spork8.zig new file mode 100644 index 0000000000..9c7884dc9e --- /dev/null +++ b/src/link/Spork8.zig @@ -0,0 +1,228 @@ +const Spork8 = @This(); +const builtin = @import("builtin"); +const build_options = @import("build_options"); + +const std = @import("std"); +const Allocator = std.mem.Allocator; +const assert = std.debug.assert; +const Path = std.Build.Cache.Path; +const log = std.log.scoped(.link); + +const Air = @import("../Air.zig"); +const InternPool = @import("../InternPool.zig"); +const Zcu = @import("../Zcu.zig"); +const CodeGen = @import("../arch/spork8/CodeGen.zig"); +const Mir = @import("../arch/spork8/Mir.zig"); +const link = @import("../link.zig"); +const Compilation = @import("../Compilation.zig"); +const Liveness = @import("../Liveness.zig"); +const dev = @import("../dev.zig"); +const Value = @import("../Value.zig"); + +base: link.File, +funcs: std.AutoArrayHashMapUnmanaged(InternPool.Index, CodeGen.Function) = .empty, +/// All MIR instructions for all Zcu functions. +mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, +/// Corresponds to `mir_instructions`. +mir_extra: std.ArrayListUnmanaged(u32) = .empty, + +pub fn open( + arena: Allocator, + comp: *Compilation, + emit: Path, + options: link.File.OpenOptions, +) !*Spork8 { + // TODO: restore saved linker state, don't truncate the file, and + // participate in incremental compilation. + return createEmpty(arena, comp, emit, options); +} + +pub fn createEmpty( + arena: Allocator, + comp: *Compilation, + emit: Path, + options: link.File.OpenOptions, +) !*Spork8 { + const target = comp.root_mod.resolved_target.result; + assert(target.ofmt == .spork8); + assert(comp.config.output_mode == .Exe); + + const spork8 = try arena.create(Spork8); + spork8.* = .{ + .base = .{ + .tag = .spork8, + .comp = comp, + .emit = emit, + .zcu_object_sub_path = null, + .gc_sections = options.gc_sections orelse true, + .print_gc_sections = options.print_gc_sections, + .stack_size = options.stack_size orelse switch (target.os.tag) { + .freestanding => 1 * 1024 * 1024, // 1 MiB + else => 16 * 1024 * 1024, // 16 MiB + }, + .allow_shlib_undefined = options.allow_shlib_undefined orelse false, + .file = null, + .disable_lld_caching = options.disable_lld_caching, + .build_id = options.build_id, + }, + }; + errdefer spork8.base.destroy(); + + spork8.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{ + .truncate = true, + .read = true, + }); + + return spork8; +} + +pub fn deinit(spork8: *Spork8) void { + const gpa = spork8.base.comp.gpa; + _ = gpa; +} + +pub fn updateFunc( + spork8: *Spork8, + pt: Zcu.PerThread, + func_index: InternPool.Index, + air: Air, + liveness: Liveness, +) !void { + if (build_options.skip_non_native and builtin.object_format != .spork8) { + @panic("Attempted to compile for object format that was disabled by build configuration"); + } + + dev.check(.spork8_backend); + + const zcu = pt.zcu; + const gpa = spork8.base.comp.gpa; + + const ip = &zcu.intern_pool; + const owner_nav = zcu.funcInfo(func_index).owner_nav; + log.debug("updateFunc {}", .{ip.getNav(owner_nav).fqn.fmt(ip)}); + + const function = try CodeGen.function(spork8, pt, func_index, air, liveness); + try spork8.funcs.put(gpa, func_index, function); +} + +// Generate code for the "Nav", storing it in memory to be later written to +// the file on flush(). +pub fn updateNav(spork8: *Spork8, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { + _ = spork8; + if (build_options.skip_non_native and builtin.object_format != .spork8) { + @panic("Attempted to compile for object format that was disabled by build configuration"); + } + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + const nav = ip.getNav(nav_index); + + const nav_init, const chased_nav_index = switch (ip.indexToKey(nav.status.fully_resolved.val)) { + .func => return, // global const which is a function alias + .@"extern" => |ext| { + _ = ext; + @panic("TODO updateNav extern func"); + }, + .variable => |variable| .{ variable.init, variable.owner_nav }, + else => .{ nav.status.fully_resolved.val, nav_index }, + }; + log.debug("updateNav {} {d}", .{ nav.fqn.fmt(ip), chased_nav_index }); + + if (nav_init != .none and !Value.fromInterned(nav_init).typeOf(zcu).hasRuntimeBits(zcu)) { + return; + } +} + +pub fn updateLineNumber(spork8: *Spork8, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) !void { + _ = spork8; + _ = pt; + _ = ti_id; +} + +pub fn deleteExport( + spork8: *Spork8, + exported: Zcu.Exported, + name: InternPool.NullTerminatedString, +) void { + const zcu = spork8.base.comp.zcu.?; + const ip = &zcu.intern_pool; + const name_slice = name.toSlice(ip); + switch (exported) { + .nav => |nav_index| { + log.debug("deleteExport '{s}' nav={d}", .{ name_slice, @intFromEnum(nav_index) }); + }, + .uav => |uav_index| { + log.debug("deleteExport '{s}' uav={d}", .{ name_slice, @intFromEnum(uav_index) }); + }, + } +} + +pub fn updateExports( + spork8: *Spork8, + pt: Zcu.PerThread, + exported: Zcu.Exported, + export_indices: []const Zcu.Export.Index, +) !void { + _ = spork8; + if (build_options.skip_non_native and builtin.object_format != .spork8) { + @panic("Attempted to compile for object format that was disabled by build configuration"); + } + + const zcu = pt.zcu; + const ip = &zcu.intern_pool; + for (export_indices) |export_idx| { + const exp = export_idx.ptr(zcu); + const name_slice = exp.opts.name.toSlice(ip); + switch (exported) { + .nav => |nav_index| { + log.debug("updateExports '{s}' nav={d}", .{ name_slice, @intFromEnum(nav_index) }); + }, + .uav => |uav_index| { + log.debug("updateExports '{s}' uav={d}", .{ name_slice, @intFromEnum(uav_index) }); + }, + } + } +} + +pub fn loadInput(spork8: *Spork8, input: link.Input) !void { + _ = input; + const comp = spork8.base.comp; + const diags = &comp.link_diags; + return diags.failParse("spork8 does not support linking files together", .{}); +} + +pub fn flush( + spork8: *Spork8, + arena: Allocator, + tid: Zcu.PerThread.Id, + prog_node: std.Progress.Node, +) link.File.FlushError!void { + return spork8.flushModule(arena, tid, prog_node); +} + +pub fn prelink(spork8: *Spork8, prog_node: std.Progress.Node) link.File.FlushError!void { + const sub_prog_node = prog_node.start("Spork8 Prelink", 0); + defer sub_prog_node.end(); + + _ = spork8; +} + +pub fn flushModule( + spork8: *Spork8, + arena: Allocator, + tid: Zcu.PerThread.Id, + prog_node: std.Progress.Node, +) link.File.FlushError!void { + // The goal is to never use this because it's only needed if we need to + // write to InternPool, but flushModule is too late to be writing to the + // InternPool. + _ = tid; + const comp = spork8.base.comp; + const diags = &comp.link_diags; + + const sub_prog_node = prog_node.start("Spork8 Flush", 0); + defer sub_prog_node.end(); + + _ = arena; + + return diags.fail("TODO implement flushModule for spork8", .{}); +} diff --git a/src/target.zig b/src/target.zig index 03686d7687..75c446e82d 100644 --- a/src/target.zig +++ b/src/target.zig @@ -133,6 +133,7 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { // LLVM does not support these object formats: .c, .plan9, + .spork8, => return false, .coff, @@ -200,6 +201,7 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { .kalimba, .or1k, .propeller, + .spork8, => false, }; } @@ -323,6 +325,7 @@ pub fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool, have_llvm: bool else => {}, } switch (target.cpu.arch) { + .spork8 => return false, .spirv, .spirv32, .spirv64 => return false, // Remove this once https://github.com/ziglang/zig/issues/23714 is fixed .amdgcn => return false, @@ -336,12 +339,13 @@ pub fn canBuildLibCompilerRt(target: std.Target, use_llvm: bool, have_llvm: bool } pub fn canBuildLibUbsanRt(target: std.Target) bool { - switch (target.cpu.arch) { - .spirv, .spirv32, .spirv64 => return false, + return switch (target.cpu.arch) { + .spork8 => false, + .spirv, .spirv32, .spirv64 => false, // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed - .nvptx, .nvptx64 => return false, - else => return true, - } + .nvptx, .nvptx64 => false, + else => true, + }; } pub fn hasRedZone(target: std.Target) bool { @@ -804,6 +808,7 @@ pub fn zigBackend(target: std.Target, use_llvm: bool) std.builtin.CompilerBacken .riscv64 => .stage2_riscv64, .sparc64 => .stage2_sparc64, .spirv64 => .stage2_spirv64, + .spork8 => .stage2_spork8, else => .other, }; }