diff --git a/build.zig b/build.zig index cd25001eef07..fc03296158e0 100644 --- a/build.zig +++ b/build.zig @@ -54,6 +54,7 @@ pub fn build(b: *Builder) !void { var test_stage2 = b.addTest("src-self-hosted/test.zig"); test_stage2.setBuildMode(builtin.Mode.Debug); + test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig"); const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"}); @@ -72,9 +73,9 @@ pub fn build(b: *Builder) !void { const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false; const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false; const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false; - if (!skip_self_hosted) { - // TODO re-enable this after https://github.com/ziglang/zig/issues/2377 - //test_step.dependOn(&exe.step); + if (!skip_self_hosted and builtin.os == .linux) { + // TODO evented I/O other OS's + test_step.dependOn(&exe.step); } const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; @@ -98,11 +99,7 @@ pub fn build(b: *Builder) !void { const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); test_stage2_step.dependOn(&test_stage2.step); - - // TODO see https://github.com/ziglang/zig/issues/1364 - if (false) { - test_step.dependOn(test_stage2_step); - } + test_step.dependOn(test_stage2_step); var chosen_modes: [4]builtin.Mode = undefined; var chosen_mode_index: usize = 0; @@ -235,6 +232,9 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { if (fs.path.isAbsolute(lib_arg)) { try result.libs.append(lib_arg); } else { + if (mem.endsWith(u8, lib_arg, ".lib")) { + lib_arg = lib_arg[0 .. lib_arg.len - 4]; + } try result.system_libs.append(lib_arg); } } diff --git a/lib/std/child_process.zig b/lib/std/child_process.zig index 680c378c0d8c..27ba362a18e6 100644 --- a/lib/std/child_process.zig +++ b/lib/std/child_process.zig @@ -259,7 +259,9 @@ pub const ChildProcess = struct { } fn handleWaitResult(self: *ChildProcess, status: u32) void { - self.term = self.cleanupAfterWait(status); + // TODO https://github.com/ziglang/zig/issues/3190 + var term = self.cleanupAfterWait(status); + self.term = term; } fn cleanupStreams(self: *ChildProcess) void { diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig index 2b26a500ddaf..0f6a89259400 100644 --- a/lib/std/event/group.zig +++ b/lib/std/event/group.zig @@ -66,11 +66,10 @@ pub fn Group(comptime ReturnType: type) type { node.* = AllocStack.Node{ .next = undefined, .data = Node{ - .handle = frame, + .handle = @asyncCall(frame, {}, func, args), .bytes = std.mem.asBytes(frame), }, }; - _ = @asyncCall(frame, {}, func, args); self.alloc_stack.push(node); } diff --git a/src-self-hosted/arg.zig b/src-self-hosted/arg.zig index 8b0ea5ea6185..37767e0ea36e 100644 --- a/src-self-hosted/arg.zig +++ b/src-self-hosted/arg.zig @@ -119,9 +119,9 @@ pub const Args = struct { // MergeN creation disallows 0 length flag entry (doesn't make sense) switch (flag_args) { - FlagArg.None => unreachable, - FlagArg.Single => |inner| try prev.append(inner), - FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()), + .None => unreachable, + .Single => |inner| try prev.append(inner), + .Many => |inner| try prev.appendSlice(inner.toSliceConst()), } _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); @@ -158,7 +158,7 @@ pub const Args = struct { pub fn single(self: *Args, name: []const u8) ?[]const u8 { if (self.flags.get(name)) |entry| { switch (entry.value) { - FlagArg.Single => |inner| { + .Single => |inner| { return inner; }, else => @panic("attempted to retrieve flag with wrong type"), @@ -172,7 +172,7 @@ pub const Args = struct { pub fn many(self: *Args, name: []const u8) []const []const u8 { if (self.flags.get(name)) |entry| { switch (entry.value) { - FlagArg.Many => |inner| { + .Many => |inner| { return inner.toSliceConst(); }, else => @panic("attempted to retrieve flag with wrong type"), diff --git a/src-self-hosted/c_int.zig b/src-self-hosted/c_int.zig index 33d2faa5c1ed..00c521a1672d 100644 --- a/src-self-hosted/c_int.zig +++ b/src-self-hosted/c_int.zig @@ -1,3 +1,5 @@ +const Target = @import("std").Target; + pub const CInt = struct { id: Id, zig_name: []const u8, @@ -17,52 +19,152 @@ pub const CInt = struct { pub const list = [_]CInt{ CInt{ - .id = Id.Short, + .id = .Short, .zig_name = "c_short", .c_name = "short", .is_signed = true, }, CInt{ - .id = Id.UShort, + .id = .UShort, .zig_name = "c_ushort", .c_name = "unsigned short", .is_signed = false, }, CInt{ - .id = Id.Int, + .id = .Int, .zig_name = "c_int", .c_name = "int", .is_signed = true, }, CInt{ - .id = Id.UInt, + .id = .UInt, .zig_name = "c_uint", .c_name = "unsigned int", .is_signed = false, }, CInt{ - .id = Id.Long, + .id = .Long, .zig_name = "c_long", .c_name = "long", .is_signed = true, }, CInt{ - .id = Id.ULong, + .id = .ULong, .zig_name = "c_ulong", .c_name = "unsigned long", .is_signed = false, }, CInt{ - .id = Id.LongLong, + .id = .LongLong, .zig_name = "c_longlong", .c_name = "long long", .is_signed = true, }, CInt{ - .id = Id.ULongLong, + .id = .ULongLong, .zig_name = "c_ulonglong", .c_name = "unsigned long long", .is_signed = false, }, }; + + pub fn sizeInBits(cint: CInt, self: Target) u32 { + const arch = self.getArch(); + switch (self.getOs()) { + .freestanding => switch (self.getArch()) { + .msp430 => switch (cint.id) { + .Short, + .UShort, + .Int, + .UInt, + => return 16, + .Long, + .ULong, + => return 32, + .LongLong, + .ULongLong, + => return 64, + }, + else => switch (cint.id) { + .Short, + .UShort, + => return 16, + .Int, + .UInt, + => return 32, + .Long, + .ULong, + => return self.getArchPtrBitWidth(), + .LongLong, + .ULongLong, + => return 64, + }, + }, + + .linux, + .macosx, + .freebsd, + .openbsd, + .zen, + => switch (cint.id) { + .Short, + .UShort, + => return 16, + .Int, + .UInt, + => return 32, + .Long, + .ULong, + => return self.getArchPtrBitWidth(), + .LongLong, + .ULongLong, + => return 64, + }, + + .windows, .uefi => switch (cint.id) { + .Short, + .UShort, + => return 16, + .Int, + .UInt, + => return 32, + .Long, + .ULong, + .LongLong, + .ULongLong, + => return 64, + }, + + .ananas, + .cloudabi, + .dragonfly, + .fuchsia, + .ios, + .kfreebsd, + .lv2, + .netbsd, + .solaris, + .haiku, + .minix, + .rtems, + .nacl, + .cnk, + .aix, + .cuda, + .nvcl, + .amdhsa, + .ps4, + .elfiamcu, + .tvos, + .watchos, + .mesa3d, + .contiki, + .amdpal, + .hermit, + .hurd, + .wasi, + .emscripten, + => @panic("TODO specify the C integer type sizes for this OS"), + } + } }; diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 90f5309faf92..77b1d4fd74f0 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const Compilation = @import("compilation.zig").Compilation; const llvm = @import("llvm.zig"); const c = @import("c.zig"); @@ -7,17 +6,18 @@ const ir = @import("ir.zig"); const Value = @import("value.zig").Value; const Type = @import("type.zig").Type; const Scope = @import("scope.zig").Scope; +const util = @import("util.zig"); const event = std.event; const assert = std.debug.assert; const DW = std.dwarf; const maxInt = std.math.maxInt; -pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void { +pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) Compilation.BuildError!void { fn_val.base.ref(); defer fn_val.base.deref(comp); defer code.destroy(comp.gpa()); - var output_path = try await (async comp.createRandomOutputPath(comp.target.objFileExt()) catch unreachable); + var output_path = try comp.createRandomOutputPath(comp.target.oFileExt()); errdefer output_path.deinit(); const llvm_handle = try comp.zig_compiler.getAnyLlvmContext(); @@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) llvm.SetTarget(module, comp.llvm_triple.ptr()); llvm.SetDataLayout(module, comp.target_layout_str); - if (comp.target.getObjectFormat() == builtin.ObjectFormat.coff) { + if (util.getObjectFormat(comp.target) == .coff) { llvm.AddModuleCodeViewFlag(module); } else { llvm.AddModuleDebugInfoFlag(module); @@ -59,7 +59,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) comp.name.ptr(), comp.root_package.root_src_dir.ptr(), ) orelse return error.OutOfMemory; - const is_optimized = comp.build_mode != builtin.Mode.Debug; + const is_optimized = comp.build_mode != .Debug; const compile_unit = llvm.CreateCompileUnit( dibuilder, DW.LANG_C99, @@ -79,7 +79,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) .builder = builder, .dibuilder = dibuilder, .context = context, - .lock = event.Lock.init(comp.loop), + .lock = event.Lock.init(), .arena = &code.arena.allocator, }; @@ -105,8 +105,8 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types - const is_small = comp.build_mode == builtin.Mode.ReleaseSmall; - const is_debug = comp.build_mode == builtin.Mode.Debug; + const is_small = comp.build_mode == .ReleaseSmall; + const is_debug = comp.build_mode == .Debug; var err_msg: [*]u8 = undefined; // TODO integrate this with evented I/O @@ -234,8 +234,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) // create debug variable declarations for variables and allocate all local variables for (var_list) |var_scope, i| { const var_type = switch (var_scope.data) { - Scope.Var.Data.Const => unreachable, - Scope.Var.Data.Param => |param| param.typ, + .Const => unreachable, + .Param => |param| param.typ, }; // if (!type_has_bits(var->value->type)) { // continue; @@ -266,7 +266,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i)); } else { // gen_type = var->value->type; - var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, Type.Pointer.Align.Abi); + var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, .Abi); } // if (var->decl_node) { // var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), @@ -300,8 +300,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code) ofile, llvm_param, scope_var.data.Param.llvm_value, - Type.Pointer.Align.Abi, - Type.Pointer.Vol.Non, + .Abi, + .Non, ); } @@ -383,8 +383,8 @@ fn renderLoadUntyped( ) !*llvm.Value { const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory; switch (vol) { - Type.Pointer.Vol.Non => {}, - Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1), + .Non => {}, + .Volatile => llvm.SetVolatile(result, 1), } llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr)))); return result; @@ -414,8 +414,8 @@ pub fn renderStoreUntyped( ) !*llvm.Value { const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory; switch (vol) { - Type.Pointer.Vol.Non => {}, - Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1), + .Non => {}, + .Volatile => llvm.SetVolatile(result, 1), } llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value))); return result; @@ -445,7 +445,7 @@ pub fn renderAlloca( pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 { return switch (alignment) { - Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), - Type.Pointer.Align.Override => |a| a, + .Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type), + .Override => |a| a, }; } diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index 1e71a5e561a8..b12a01d6494b 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -5,8 +5,8 @@ const Allocator = mem.Allocator; const Buffer = std.Buffer; const llvm = @import("llvm.zig"); const c = @import("c.zig"); -const builtin = @import("builtin"); -const Target = @import("target.zig").Target; +const builtin = std.builtin; +const Target = std.Target; const warn = std.debug.warn; const Token = std.zig.Token; const ArrayList = std.ArrayList; @@ -30,14 +30,15 @@ const link = @import("link.zig").link; const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const CInt = @import("c_int.zig").CInt; const fs = event.fs; +const util = @import("util.zig"); const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB /// Data that is local to the event loop. pub const ZigCompiler = struct { - loop: *event.Loop, llvm_handle_pool: std.atomic.Stack(*llvm.Context), lld_lock: event.Lock, + allocator: *Allocator, /// TODO pool these so that it doesn't have to lock prng: event.Locked(std.rand.DefaultPrng), @@ -46,9 +47,9 @@ pub const ZigCompiler = struct { var lazy_init_targets = std.lazyInit(void); - pub fn init(loop: *event.Loop) !ZigCompiler { + pub fn init(allocator: *Allocator) !ZigCompiler { lazy_init_targets.get() orelse { - Target.initializeAll(); + util.initializeAllTargets(); lazy_init_targets.resolve(); }; @@ -57,11 +58,11 @@ pub const ZigCompiler = struct { const seed = mem.readIntNative(u64, &seed_bytes); return ZigCompiler{ - .loop = loop, - .lld_lock = event.Lock.init(loop), + .allocator = allocator, + .lld_lock = event.Lock.init(), .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(), - .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), - .native_libc = event.Future(LibCInstallation).init(loop), + .prng = event.Locked(std.rand.DefaultPrng).init(std.rand.DefaultPrng.init(seed)), + .native_libc = event.Future(LibCInstallation).init(), }; } @@ -70,7 +71,7 @@ pub const ZigCompiler = struct { self.lld_lock.deinit(); while (self.llvm_handle_pool.pop()) |node| { llvm.ContextDispose(node.data); - self.loop.allocator.destroy(node); + self.allocator.destroy(node); } } @@ -82,19 +83,19 @@ pub const ZigCompiler = struct { const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory; errdefer llvm.ContextDispose(context_ref); - const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node); + const node = try self.allocator.create(std.atomic.Stack(*llvm.Context).Node); node.* = std.atomic.Stack(*llvm.Context).Node{ .next = undefined, .data = context_ref, }; - errdefer self.loop.allocator.destroy(node); + errdefer self.allocator.destroy(node); return LlvmHandle{ .node = node }; } pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation { - if (await (async self.native_libc.start() catch unreachable)) |ptr| return ptr; - try await (async self.native_libc.data.findNative(self.loop) catch unreachable); + if (self.native_libc.start()) |ptr| return ptr; + try self.native_libc.data.findNative(self.allocator); self.native_libc.resolve(); return &self.native_libc.data; } @@ -122,7 +123,6 @@ pub const LlvmHandle = struct { pub const Compilation = struct { zig_compiler: *ZigCompiler, - loop: *event.Loop, name: Buffer, llvm_triple: Buffer, root_src_path: ?[]const u8, @@ -227,8 +227,8 @@ pub const Compilation = struct { /// need to wait on this group before deinitializing deinit_group: event.Group(void), - destroy_handle: promise, - main_loop_handle: promise, + // destroy_frame: @Frame(createAsync), + // main_loop_frame: @Frame(Compilation.mainLoop), main_loop_future: event.Future(void), have_err_ret_tracing: bool, @@ -243,7 +243,7 @@ pub const Compilation = struct { c_int_types: [CInt.list.len]*Type.Int, - fs_watch: *fs.Watch(*Scope.Root), + // fs_watch: *fs.Watch(*Scope.Root), const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql); const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql); @@ -348,7 +348,7 @@ pub const Compilation = struct { zig_lib_dir: []const u8, ) !*Compilation { var optional_comp: ?*Compilation = null; - const handle = try async createAsync( + var frame = async createAsync( &optional_comp, zig_compiler, name, @@ -359,10 +359,7 @@ pub const Compilation = struct { is_static, zig_lib_dir, ); - return optional_comp orelse if (getAwaitResult( - zig_compiler.loop.allocator, - handle, - )) |_| unreachable else |err| err; + return optional_comp orelse if (await frame) |_| unreachable else |err| err; } async fn createAsync( @@ -376,15 +373,9 @@ pub const Compilation = struct { is_static: bool, zig_lib_dir: []const u8, ) !void { - // workaround for https://github.com/ziglang/zig/issues/1194 - suspend { - resume @handle(); - } - - const loop = zig_compiler.loop; + const allocator = zig_compiler.allocator; var comp = Compilation{ - .loop = loop, - .arena_allocator = std.heap.ArenaAllocator.init(loop.allocator), + .arena_allocator = std.heap.ArenaAllocator.init(allocator), .zig_compiler = zig_compiler, .events = undefined, .root_src_path = root_src_path, @@ -394,10 +385,10 @@ pub const Compilation = struct { .build_mode = build_mode, .zig_lib_dir = zig_lib_dir, .zig_std_dir = undefined, - .tmp_dir = event.Future(BuildError![]u8).init(loop), - .destroy_handle = @handle(), - .main_loop_handle = undefined, - .main_loop_future = event.Future(void).init(loop), + .tmp_dir = event.Future(BuildError![]u8).init(), + // .destroy_frame = @frame(), + // .main_loop_frame = undefined, + .main_loop_future = event.Future(void).init(), .name = undefined, .llvm_triple = undefined, @@ -426,7 +417,7 @@ pub const Compilation = struct { .rpath_list = [_][]const u8{}, .assembly_files = [_][]const u8{}, .link_objects = [_][]const u8{}, - .fn_link_set = event.Locked(FnLinkSet).init(loop, FnLinkSet.init()), + .fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()), .windows_subsystem_windows = false, .windows_subsystem_console = false, .link_libs_list = undefined, @@ -438,14 +429,14 @@ pub const Compilation = struct { .test_name_prefix = null, .emit_file_type = Emit.Binary, .link_out_file = null, - .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)), - .prelink_group = event.Group(BuildError!void).init(loop), - .deinit_group = event.Group(void).init(loop), - .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)), - .int_type_table = event.Locked(IntTypeTable).init(loop, IntTypeTable.init(loop.allocator)), - .array_type_table = event.Locked(ArrayTypeTable).init(loop, ArrayTypeTable.init(loop.allocator)), - .ptr_type_table = event.Locked(PtrTypeTable).init(loop, PtrTypeTable.init(loop.allocator)), - .fn_type_table = event.Locked(FnTypeTable).init(loop, FnTypeTable.init(loop.allocator)), + .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)), + .prelink_group = event.Group(BuildError!void).init(allocator), + .deinit_group = event.Group(void).init(allocator), + .compile_errors = event.Locked(CompileErrList).init(CompileErrList.init(allocator)), + .int_type_table = event.Locked(IntTypeTable).init(IntTypeTable.init(allocator)), + .array_type_table = event.Locked(ArrayTypeTable).init(ArrayTypeTable.init(allocator)), + .ptr_type_table = event.Locked(PtrTypeTable).init(PtrTypeTable.init(allocator)), + .fn_type_table = event.Locked(FnTypeTable).init(FnTypeTable.init(allocator)), .c_int_types = undefined, .meta_type = undefined, @@ -471,7 +462,7 @@ pub const Compilation = struct { .have_err_ret_tracing = false, .primitive_type_table = undefined, - .fs_watch = undefined, + // .fs_watch = undefined, }; comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena()); comp.primitive_type_table = TypeTable.init(comp.arena()); @@ -485,12 +476,12 @@ pub const Compilation = struct { } comp.name = try Buffer.init(comp.arena(), name); - comp.llvm_triple = try target.getTriple(comp.arena()); - comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple); + comp.llvm_triple = try util.getTriple(comp.arena(), target); + comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple); comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" }); const opt_level = switch (build_mode) { - builtin.Mode.Debug => llvm.CodeGenLevelNone, + .Debug => llvm.CodeGenLevelNone, else => llvm.CodeGenLevelAggressive, }; @@ -516,7 +507,7 @@ pub const Compilation = struct { opt_level, reloc_mode, llvm.CodeModelDefault, - false // TODO: add -ffunction-sections option + false, // TODO: add -ffunction-sections option ) orelse return error.OutOfMemory; defer llvm.DisposeTargetMachine(comp.target_machine); @@ -526,8 +517,11 @@ pub const Compilation = struct { comp.target_layout_str = llvm.CopyStringRepOfTargetData(comp.target_data_ref) orelse return error.OutOfMemory; defer llvm.DisposeMessage(comp.target_layout_str); - comp.events = try event.Channel(Event).create(comp.loop, 0); - defer comp.events.destroy(); + comp.events = try allocator.create(event.Channel(Event)); + defer allocator.destroy(comp.events); + + comp.events.init([0]Event{}); + defer comp.events.deinit(); if (root_src_path) |root_src| { const dirname = std.fs.path.dirname(root_src) orelse "."; @@ -540,13 +534,13 @@ pub const Compilation = struct { comp.root_package = try Package.create(comp.arena(), ".", ""); } - comp.fs_watch = try fs.Watch(*Scope.Root).create(loop, 16); - defer comp.fs_watch.destroy(); + // comp.fs_watch = try fs.Watch(*Scope.Root).create(16); + // defer comp.fs_watch.destroy(); try comp.initTypes(); defer comp.primitive_type_table.deinit(); - comp.main_loop_handle = async comp.mainLoop() catch unreachable; + // comp.main_loop_frame = async comp.mainLoop(); // Set this to indicate that initialization completed successfully. // from here on out we must not return an error. // This must occur before the first suspend/await. @@ -555,12 +549,13 @@ pub const Compilation = struct { suspend; // From here on is cleanup. - await (async comp.deinit_group.wait() catch unreachable); + comp.deinit_group.wait(); - if (comp.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| { - // TODO evented I/O? - std.fs.deleteTree(comp.arena(), tmp_dir) catch {}; - } else |_| {}; + if (comp.tmp_dir.getOrNull()) |tmp_dir_result| + if (tmp_dir_result.*) |tmp_dir| { + // TODO evented I/O? + std.fs.deleteTree(tmp_dir) catch {}; + } else |_| {}; } /// it does ref the result because it could be an arbitrary integer size @@ -578,10 +573,10 @@ pub const Compilation = struct { error.Overflow => return error.Overflow, error.InvalidCharacter => unreachable, // we just checked the characters above }; - const int_type = try await (async Type.Int.get(comp, Type.Int.Key{ + const int_type = try Type.Int.get(comp, Type.Int.Key{ .bit_count = bit_count, .is_signed = is_signed, - }) catch unreachable); + }); errdefer int_type.base.base.deref(); return &int_type.base; }, @@ -603,12 +598,12 @@ pub const Compilation = struct { .base = Type{ .name = "type", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = undefined, .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice }, - .id = builtin.TypeId.Type, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .Type, + .abi_alignment = Type.AbiAlignment.init(), }, .value = undefined, }; @@ -621,12 +616,12 @@ pub const Compilation = struct { .base = Type{ .name = "void", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.Void, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .Void, + .abi_alignment = Type.AbiAlignment.init(), }, }; assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null); @@ -636,12 +631,12 @@ pub const Compilation = struct { .base = Type{ .name = "noreturn", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.NoReturn, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .NoReturn, + .abi_alignment = Type.AbiAlignment.init(), }, }; assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null); @@ -651,12 +646,12 @@ pub const Compilation = struct { .base = Type{ .name = "comptime_int", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.ComptimeInt, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .ComptimeInt, + .abi_alignment = Type.AbiAlignment.init(), }, }; assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null); @@ -666,12 +661,12 @@ pub const Compilation = struct { .base = Type{ .name = "bool", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.Bool, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .Bool, + .abi_alignment = Type.AbiAlignment.init(), }, }; assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null); @@ -679,7 +674,7 @@ pub const Compilation = struct { comp.void_value = try comp.arena().create(Value.Void); comp.void_value.* = Value.Void{ .base = Value{ - .id = Value.Id.Void, + .id = .Void, .typ = &Type.Void.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -688,7 +683,7 @@ pub const Compilation = struct { comp.true_value = try comp.arena().create(Value.Bool); comp.true_value.* = Value.Bool{ .base = Value{ - .id = Value.Id.Bool, + .id = .Bool, .typ = &Type.Bool.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -698,7 +693,7 @@ pub const Compilation = struct { comp.false_value = try comp.arena().create(Value.Bool); comp.false_value.* = Value.Bool{ .base = Value{ - .id = Value.Id.Bool, + .id = .Bool, .typ = &Type.Bool.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -708,7 +703,7 @@ pub const Compilation = struct { comp.noreturn_value = try comp.arena().create(Value.NoReturn); comp.noreturn_value.* = Value.NoReturn{ .base = Value{ - .id = Value.Id.NoReturn, + .id = .NoReturn, .typ = &Type.NoReturn.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -720,16 +715,16 @@ pub const Compilation = struct { .base = Type{ .name = cint.zig_name, .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.Int, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .Int, + .abi_alignment = Type.AbiAlignment.init(), }, .key = Type.Int.Key{ .is_signed = cint.is_signed, - .bit_count = comp.target.cIntTypeSizeInBits(cint.id), + .bit_count = cint.sizeInBits(comp.target), }, .garbage_node = undefined, }; @@ -741,12 +736,12 @@ pub const Compilation = struct { .base = Type{ .name = "u8", .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &Type.MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, - .id = builtin.TypeId.Int, - .abi_alignment = Type.AbiAlignment.init(comp.loop), + .id = .Int, + .abi_alignment = Type.AbiAlignment.init(), }, .key = Type.Int.Key{ .is_signed = false, @@ -758,8 +753,8 @@ pub const Compilation = struct { } pub fn destroy(self: *Compilation) void { - cancel self.main_loop_handle; - resume self.destroy_handle; + // await self.main_loop_frame; + // resume self.destroy_frame; } fn start(self: *Compilation) void { @@ -768,13 +763,13 @@ pub const Compilation = struct { async fn mainLoop(self: *Compilation) void { // wait until start() is called - _ = await (async self.main_loop_future.get() catch unreachable); + _ = self.main_loop_future.get(); - var build_result = await (async self.initialCompile() catch unreachable); + var build_result = self.initialCompile(); while (true) { const link_result = if (build_result) blk: { - break :blk await (async self.maybeLink() catch unreachable); + break :blk self.maybeLink(); } else |err| err; // this makes a handy error return trace and stack trace in debug mode if (std.debug.runtime_safety) { @@ -782,65 +777,65 @@ pub const Compilation = struct { } const compile_errors = blk: { - const held = await (async self.compile_errors.acquire() catch unreachable); + const held = self.compile_errors.acquire(); defer held.release(); break :blk held.value.toOwnedSlice(); }; if (link_result) |_| { if (compile_errors.len == 0) { - await (async self.events.put(Event.Ok) catch unreachable); + self.events.put(Event.Ok); } else { - await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable); + self.events.put(Event{ .Fail = compile_errors }); } } else |err| { // if there's an error then the compile errors have dangling references self.gpa().free(compile_errors); - await (async self.events.put(Event{ .Error = err }) catch unreachable); + self.events.put(Event{ .Error = err }); } - // First, get an item from the watch channel, waiting on the channel. - var group = event.Group(BuildError!void).init(self.loop); - { - const ev = (await (async self.fs_watch.channel.get() catch unreachable)) catch |err| { - build_result = err; - continue; - }; - const root_scope = ev.data; - group.call(rebuildFile, self, root_scope) catch |err| { - build_result = err; - continue; - }; - } - // Next, get all the items from the channel that are buffered up. - while (await (async self.fs_watch.channel.getOrNull() catch unreachable)) |ev_or_err| { - if (ev_or_err) |ev| { - const root_scope = ev.data; - group.call(rebuildFile, self, root_scope) catch |err| { - build_result = err; - continue; - }; - } else |err| { - build_result = err; - continue; - } - } - build_result = await (async group.wait() catch unreachable); + // // First, get an item from the watch channel, waiting on the channel. + // var group = event.Group(BuildError!void).init(self.gpa()); + // { + // const ev = (self.fs_watch.channel.get()) catch |err| { + // build_result = err; + // continue; + // }; + // const root_scope = ev.data; + // group.call(rebuildFile, self, root_scope) catch |err| { + // build_result = err; + // continue; + // }; + // } + // // Next, get all the items from the channel that are buffered up. + // while (self.fs_watch.channel.getOrNull()) |ev_or_err| { + // if (ev_or_err) |ev| { + // const root_scope = ev.data; + // group.call(rebuildFile, self, root_scope) catch |err| { + // build_result = err; + // continue; + // }; + // } else |err| { + // build_result = err; + // continue; + // } + // } + // build_result = group.wait(); } } async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void { const tree_scope = blk: { - const source_code = (await (async fs.readFile( - self.loop, - root_scope.realpath, - max_src_size, - ) catch unreachable)) catch |err| { - try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err)); - return; - }; - errdefer self.gpa().free(source_code); + const source_code = ""; + // const source_code = fs.readFile( + // root_scope.realpath, + // max_src_size, + // ) catch |err| { + // try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err)); + // return; + // }; + // errdefer self.gpa().free(source_code); const tree = try std.zig.parse(self.gpa(), source_code); errdefer { @@ -856,19 +851,18 @@ pub const Compilation = struct { const msg = try Msg.createFromParseErrorAndScope(self, tree_scope, parse_error); errdefer msg.destroy(); - try await (async self.addCompileErrorAsync(msg) catch unreachable); + try self.addCompileErrorAsync(msg); } if (tree_scope.tree.errors.len != 0) { return; } - const locked_table = await (async root_scope.decls.table.acquireWrite() catch unreachable); + const locked_table = root_scope.decls.table.acquireWrite(); defer locked_table.release(); - var decl_group = event.Group(BuildError!void).init(self.loop); - defer decl_group.deinit(); + var decl_group = event.Group(BuildError!void).init(self.gpa()); - try await try async self.rebuildChangedDecls( + try self.rebuildChangedDecls( &decl_group, locked_table.value, root_scope.decls, @@ -876,7 +870,7 @@ pub const Compilation = struct { tree_scope, ); - try await (async decl_group.wait() catch unreachable); + try decl_group.wait(); } async fn rebuildChangedDecls( @@ -894,15 +888,15 @@ pub const Compilation = struct { while (ast_it.next()) |decl_ptr| { const decl = decl_ptr.*; switch (decl.id) { - ast.Node.Id.Comptime => { + .Comptime => { const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl); // TODO connect existing comptime decls to updated source files try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node); }, - ast.Node.Id.VarDecl => @panic("TODO"), - ast.Node.Id.FnProto => { + .VarDecl => @panic("TODO"), + .FnProto => { const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl); const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else { @@ -942,11 +936,11 @@ pub const Compilation = struct { .id = Decl.Id.Fn, .name = name, .visib = parseVisibToken(tree_scope.tree, fn_proto.visib_token), - .resolution = event.Future(BuildError!void).init(self.loop), + .resolution = event.Future(BuildError!void).init(), .parent_scope = &decl_scope.base, .tree_scope = tree_scope, }, - .value = Decl.Fn.Val{ .Unresolved = {} }, + .value = .Unresolved, .fn_proto = fn_proto, }; tree_scope.base.ref(); @@ -955,7 +949,7 @@ pub const Compilation = struct { try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table); } }, - ast.Node.Id.TestDecl => @panic("TODO"), + .TestDecl => @panic("TODO"), else => unreachable, } } @@ -982,26 +976,26 @@ pub const Compilation = struct { }; defer root_scope.base.deref(self); - assert((try await try async self.fs_watch.addFile(root_scope.realpath, root_scope)) == null); - try await try async self.rebuildFile(root_scope); + // assert((try self.fs_watch.addFile(root_scope.realpath, root_scope)) == null); + try self.rebuildFile(root_scope); } } async fn maybeLink(self: *Compilation) !void { - (await (async self.prelink_group.wait() catch unreachable)) catch |err| switch (err) { + (self.prelink_group.wait()) catch |err| switch (err) { error.SemanticAnalysisFailed => {}, else => return err, }; const any_prelink_errors = blk: { - const compile_errors = await (async self.compile_errors.acquire() catch unreachable); + const compile_errors = self.compile_errors.acquire(); defer compile_errors.release(); break :blk compile_errors.value.len != 0; }; if (!any_prelink_errors) { - try await (async link(self) catch unreachable); + try link(self); } } @@ -1013,12 +1007,12 @@ pub const Compilation = struct { node: *ast.Node, expected_type: ?*Type, ) !*ir.Code { - const unanalyzed_code = try await (async ir.gen( + const unanalyzed_code = try ir.gen( comp, node, tree_scope, scope, - ) catch unreachable); + ); defer unanalyzed_code.destroy(comp.gpa()); if (comp.verbose_ir) { @@ -1026,11 +1020,11 @@ pub const Compilation = struct { unanalyzed_code.dump(); } - const analyzed_code = try await (async ir.analyze( + const analyzed_code = try ir.analyze( comp, unanalyzed_code, expected_type, - ) catch unreachable); + ); errdefer analyzed_code.destroy(comp.gpa()); if (comp.verbose_ir) { @@ -1046,17 +1040,17 @@ pub const Compilation = struct { tree_scope: *Scope.AstTree, scope: *Scope, comptime_node: *ast.Node.Comptime, - ) !void { + ) BuildError!void { const void_type = Type.Void.get(comp); defer void_type.base.base.deref(comp); - const analyzed_code = (await (async genAndAnalyzeCode( + const analyzed_code = genAndAnalyzeCode( comp, tree_scope, scope, comptime_node.expr, &void_type.base, - ) catch unreachable)) catch |err| switch (err) { + ) catch |err| switch (err) { // This poison value should not cause the errdefers to run. It simply means // that comp.compile_errors is populated. error.SemanticAnalysisFailed => return {}, @@ -1069,7 +1063,7 @@ pub const Compilation = struct { self: *Compilation, decl: *Decl, locked_table: *Decl.Table, - ) !void { + ) BuildError!void { const is_export = decl.isExported(decl.tree_scope.tree); if (is_export) { @@ -1109,17 +1103,17 @@ pub const Compilation = struct { async fn addCompileErrorAsync( self: *Compilation, msg: *Msg, - ) !void { + ) BuildError!void { errdefer msg.destroy(); - const compile_errors = await (async self.compile_errors.acquire() catch unreachable); + const compile_errors = self.compile_errors.acquire(); defer compile_errors.release(); try compile_errors.value.append(msg); } - async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void { - const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable); + async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) BuildError!void { + const exported_symbol_names = self.exported_symbol_names.acquire(); defer exported_symbol_names.release(); if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| { @@ -1173,14 +1167,14 @@ pub const Compilation = struct { /// cancels itself so no need to await or cancel the promise. async fn startFindingNativeLibC(self: *Compilation) void { - await (async self.loop.yield() catch unreachable); + std.event.Loop.instance.?.yield(); // we don't care if it fails, we're just trying to kick off the future resolution - _ = (await (async self.zig_compiler.getNativeLibC() catch unreachable)) catch return; + _ = (self.zig_compiler.getNativeLibC()) catch return; } /// General Purpose Allocator. Must free when done. fn gpa(self: Compilation) *mem.Allocator { - return self.loop.allocator; + return self.zig_compiler.allocator; } /// Arena Allocator. Automatically freed when the Compilation is destroyed. @@ -1191,8 +1185,8 @@ pub const Compilation = struct { /// If the temporary directory for this compilation has not been created, it creates it. /// Then it creates a random file name in that dir and returns it. pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer { - const tmp_dir = try await (async self.getTmpDir() catch unreachable); - const file_prefix = await (async self.getRandomFileName() catch unreachable); + const tmp_dir = try self.getTmpDir(); + const file_prefix = self.getRandomFileName(); const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix); defer self.gpa().free(file_name); @@ -1207,14 +1201,14 @@ pub const Compilation = struct { /// Then returns it. The directory is unique to this Compilation and cleaned up when /// the Compilation deinitializes. async fn getTmpDir(self: *Compilation) ![]const u8 { - if (await (async self.tmp_dir.start() catch unreachable)) |ptr| return ptr.*; - self.tmp_dir.data = await (async self.getTmpDirImpl() catch unreachable); + if (self.tmp_dir.start()) |ptr| return ptr.*; + self.tmp_dir.data = self.getTmpDirImpl(); self.tmp_dir.resolve(); return self.tmp_dir.data; } async fn getTmpDirImpl(self: *Compilation) ![]u8 { - const comp_dir_name = await (async self.getRandomFileName() catch unreachable); + const comp_dir_name = self.getRandomFileName(); const zig_dir_path = try getZigDir(self.gpa()); defer self.gpa().free(zig_dir_path); @@ -1233,7 +1227,7 @@ pub const Compilation = struct { var rand_bytes: [9]u8 = undefined; { - const held = await (async self.zig_compiler.prng.acquire() catch unreachable); + const held = self.zig_compiler.prng.acquire(); defer held.release(); held.value.random.bytes(rand_bytes[0..]); @@ -1256,7 +1250,7 @@ pub const Compilation = struct { node: *ast.Node, expected_type: *Type, ) !*Value { - const analyzed_code = try await (async comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type) catch unreachable); + const analyzed_code = try comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type); defer analyzed_code.destroy(comp.gpa()); return analyzed_code.getCompTimeResult(comp); @@ -1266,17 +1260,17 @@ pub const Compilation = struct { const meta_type = &Type.MetaType.get(comp).base; defer meta_type.base.deref(comp); - const result_val = try await (async comp.analyzeConstValue(tree_scope, scope, node, meta_type) catch unreachable); + const result_val = try comp.analyzeConstValue(tree_scope, scope, node, meta_type); errdefer result_val.base.deref(comp); return result_val.cast(Type).?; } /// This declaration has been blessed as going into the final code generation. - pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void { - if (await (async decl.resolution.start() catch unreachable)) |ptr| return ptr.*; + pub async fn resolveDecl(comp: *Compilation, decl: *Decl) BuildError!void { + if (decl.resolution.start()) |ptr| return ptr.*; - decl.resolution.data = try await (async generateDecl(comp, decl) catch unreachable); + decl.resolution.data = try generateDecl(comp, decl); decl.resolution.resolve(); return decl.resolution.data; } @@ -1295,24 +1289,24 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib /// The function that actually does the generation. async fn generateDecl(comp: *Compilation, decl: *Decl) !void { switch (decl.id) { - Decl.Id.Var => @panic("TODO"), - Decl.Id.Fn => { + .Var => @panic("TODO"), + .Fn => { const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl); - return await (async generateDeclFn(comp, fn_decl) catch unreachable); + return generateDeclFn(comp, fn_decl); }, - Decl.Id.CompTime => @panic("TODO"), + .CompTime => @panic("TODO"), } } async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void { const tree_scope = fn_decl.base.tree_scope; - const body_node = fn_decl.fn_proto.body_node orelse return await (async generateDeclFnProto(comp, fn_decl) catch unreachable); + const body_node = fn_decl.fn_proto.body_node orelse return generateDeclFnProto(comp, fn_decl); const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope); defer fndef_scope.base.deref(comp); - const fn_type = try await (async analyzeFnType(comp, tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto) catch unreachable); + const fn_type = try analyzeFnType(comp, tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto); defer fn_type.base.base.deref(comp); var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name); @@ -1356,12 +1350,12 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void { try fn_type.non_key.Normal.variable_list.append(var_scope); } - const analyzed_code = try await (async comp.genAndAnalyzeCode( + const analyzed_code = try comp.genAndAnalyzeCode( tree_scope, fn_val.child_scope, body_node, fn_type.key.data.Normal.return_type, - ) catch unreachable); + ); errdefer analyzed_code.destroy(comp.gpa()); assert(fn_val.block_scope != null); @@ -1372,13 +1366,13 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void { try comp.prelink_group.call(addFnToLinkSet, comp, fn_val); } -async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) void { +async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) Compilation.BuildError!void { fn_val.base.ref(); defer fn_val.base.deref(comp); fn_val.link_set_node.data = fn_val; - const held = await (async comp.fn_link_set.acquire() catch unreachable); + const held = comp.fn_link_set.acquire(); defer held.release(); held.value.append(fn_val.link_set_node); @@ -1395,10 +1389,10 @@ async fn analyzeFnType( fn_proto: *ast.Node.FnProto, ) !*Type.Fn { const return_type_node = switch (fn_proto.return_type) { - ast.Node.FnProto.ReturnType.Explicit => |n| n, - ast.Node.FnProto.ReturnType.InferErrorSet => |n| n, + .Explicit => |n| n, + .InferErrorSet => |n| n, }; - const return_type = try await (async comp.analyzeTypeExpr(tree_scope, scope, return_type_node) catch unreachable); + const return_type = try comp.analyzeTypeExpr(tree_scope, scope, return_type_node); return_type.base.deref(comp); var params = ArrayList(Type.Fn.Param).init(comp.gpa()); @@ -1414,7 +1408,7 @@ async fn analyzeFnType( var it = fn_proto.params.iterator(0); while (it.next()) |param_node_ptr| { const param_node = param_node_ptr.*.cast(ast.Node.ParamDecl).?; - const param_type = try await (async comp.analyzeTypeExpr(tree_scope, scope, param_node.type_node) catch unreachable); + const param_type = try comp.analyzeTypeExpr(tree_scope, scope, param_node.type_node); errdefer param_type.base.deref(comp); try params.append(Type.Fn.Param{ .typ = param_type, @@ -1430,7 +1424,7 @@ async fn analyzeFnType( .return_type = return_type, .params = params.toOwnedSlice(), .is_var_args = false, // TODO - .cc = Type.Fn.CallingConvention.Auto, // TODO + .cc = .Unspecified, // TODO }, }, }; @@ -1443,7 +1437,7 @@ async fn analyzeFnType( comp.gpa().free(key.data.Normal.params); }; - const fn_type = try await (async Type.Fn.get(comp, key) catch unreachable); + const fn_type = try Type.Fn.get(comp, key); key_consumed = true; errdefer fn_type.base.base.deref(comp); @@ -1451,12 +1445,12 @@ async fn analyzeFnType( } async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void { - const fn_type = try await (async analyzeFnType( + const fn_type = try analyzeFnType( comp, fn_decl.base.tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto, - ) catch unreachable); + ); defer fn_type.base.base.deref(comp); var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name); @@ -1468,14 +1462,3 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void { fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val }; symbol_name_consumed = true; } - -// TODO these are hacks which should probably be solved by the language -fn getAwaitResult(allocator: *Allocator, handle: var) @typeInfo(@typeOf(handle)).Promise.child.? { - var result: ?@typeInfo(@typeOf(handle)).Promise.child.? = null; - cancel (async getAwaitResultAsync(handle, &result) catch unreachable); - return result.?; -} - -async fn getAwaitResultAsync(handle: var, out: *?@typeInfo(@typeOf(handle)).Promise.child.?) void { - out.* = await handle; -} diff --git a/src-self-hosted/decl.zig b/src-self-hosted/decl.zig index 1af06dea3988..21a99729f582 100644 --- a/src-self-hosted/decl.zig +++ b/src-self-hosted/decl.zig @@ -29,7 +29,7 @@ pub const Decl = struct { pub fn isExported(base: *const Decl, tree: *ast.Tree) bool { switch (base.id) { - Id.Fn => { + .Fn => { const fn_decl = @fieldParentPtr(Fn, "base", base); return fn_decl.isExported(tree); }, @@ -39,7 +39,7 @@ pub const Decl = struct { pub fn getSpan(base: *const Decl) errmsg.Span { switch (base.id) { - Id.Fn => { + .Fn => { const fn_decl = @fieldParentPtr(Fn, "base", base); const fn_proto = fn_decl.fn_proto; const start = fn_proto.fn_token; @@ -74,7 +74,7 @@ pub const Decl = struct { // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous pub const Val = union(enum) { - Unresolved: void, + Unresolved, Fn: *Value.Fn, FnProto: *Value.FnProto, }; @@ -83,7 +83,7 @@ pub const Decl = struct { return if (self.fn_proto.extern_export_inline_token) |tok_index| x: { const token = tree.tokens.at(tok_index); break :x switch (token.id) { - Token.Id.Extern => tree.tokenSlicePtr(token), + .Extern => tree.tokenSlicePtr(token), else => null, }; } else null; @@ -92,7 +92,7 @@ pub const Decl = struct { pub fn isExported(self: Fn, tree: *ast.Tree) bool { if (self.fn_proto.extern_export_inline_token) |tok_index| { const token = tree.tokens.at(tok_index); - return token.id == Token.Id.Keyword_export; + return token.id == .Keyword_export; } else { return false; } diff --git a/src-self-hosted/errmsg.zig b/src-self-hosted/errmsg.zig index eef5817d5815..9782fdda1c23 100644 --- a/src-self-hosted/errmsg.zig +++ b/src-self-hosted/errmsg.zig @@ -62,17 +62,17 @@ pub const Msg = struct { pub fn destroy(self: *Msg) void { switch (self.data) { - Data.Cli => |cli| { + .Cli => |cli| { cli.allocator.free(self.text); cli.allocator.free(self.realpath); cli.allocator.destroy(self); }, - Data.PathAndTree => |path_and_tree| { + .PathAndTree => |path_and_tree| { path_and_tree.allocator.free(self.text); path_and_tree.allocator.free(self.realpath); path_and_tree.allocator.destroy(self); }, - Data.ScopeAndComp => |scope_and_comp| { + .ScopeAndComp => |scope_and_comp| { scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation); scope_and_comp.compilation.gpa().free(self.text); scope_and_comp.compilation.gpa().free(self.realpath); @@ -83,11 +83,11 @@ pub const Msg = struct { fn getAllocator(self: *const Msg) *mem.Allocator { switch (self.data) { - Data.Cli => |cli| return cli.allocator, - Data.PathAndTree => |path_and_tree| { + .Cli => |cli| return cli.allocator, + .PathAndTree => |path_and_tree| { return path_and_tree.allocator; }, - Data.ScopeAndComp => |scope_and_comp| { + .ScopeAndComp => |scope_and_comp| { return scope_and_comp.compilation.gpa(); }, } @@ -95,11 +95,11 @@ pub const Msg = struct { pub fn getTree(self: *const Msg) *ast.Tree { switch (self.data) { - Data.Cli => unreachable, - Data.PathAndTree => |path_and_tree| { + .Cli => unreachable, + .PathAndTree => |path_and_tree| { return path_and_tree.tree; }, - Data.ScopeAndComp => |scope_and_comp| { + .ScopeAndComp => |scope_and_comp| { return scope_and_comp.tree_scope.tree; }, } @@ -107,9 +107,9 @@ pub const Msg = struct { pub fn getSpan(self: *const Msg) Span { return switch (self.data) { - Data.Cli => unreachable, - Data.PathAndTree => |path_and_tree| path_and_tree.span, - Data.ScopeAndComp => |scope_and_comp| scope_and_comp.span, + .Cli => unreachable, + .PathAndTree => |path_and_tree| path_and_tree.span, + .ScopeAndComp => |scope_and_comp| scope_and_comp.span, }; } @@ -230,7 +230,7 @@ pub const Msg = struct { pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void { switch (msg.data) { - Data.Cli => { + .Cli => { try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text); return; }, @@ -279,9 +279,9 @@ pub const Msg = struct { pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void { const color_on = switch (color) { - Color.Auto => file.isTty(), - Color.On => true, - Color.Off => false, + .Auto => file.isTty(), + .On => true, + .Off => false, }; var stream = &file.outStream().stream; return msg.printToStream(stream, color_on); diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index df4d436b5007..0017edd96caa 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const Compilation = @import("compilation.zig").Compilation; const Scope = @import("scope.zig").Scope; const ast = std.zig.ast; @@ -33,13 +32,13 @@ pub const IrVal = union(enum) { pub fn dump(self: IrVal) void { switch (self) { - IrVal.Unknown => std.debug.warn("Unknown"), - IrVal.KnownType => |typ| { + .Unknown => std.debug.warn("Unknown"), + .KnownType => |typ| { std.debug.warn("KnownType("); typ.dump(); std.debug.warn(")"); }, - IrVal.KnownValue => |value| { + .KnownValue => |value| { std.debug.warn("KnownValue("); value.dump(); std.debug.warn(")"); @@ -113,37 +112,37 @@ pub const Inst = struct { pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst { switch (base.id) { - Id.Return => return @fieldParentPtr(Return, "base", base).analyze(ira), - Id.Const => return @fieldParentPtr(Const, "base", base).analyze(ira), - Id.Call => return @fieldParentPtr(Call, "base", base).analyze(ira), - Id.DeclRef => return await (async @fieldParentPtr(DeclRef, "base", base).analyze(ira) catch unreachable), - Id.Ref => return await (async @fieldParentPtr(Ref, "base", base).analyze(ira) catch unreachable), - Id.DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira), - Id.CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira), - Id.Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira), - Id.Br => return @fieldParentPtr(Br, "base", base).analyze(ira), - Id.AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira), - Id.PtrType => return await (async @fieldParentPtr(PtrType, "base", base).analyze(ira) catch unreachable), - Id.VarPtr => return await (async @fieldParentPtr(VarPtr, "base", base).analyze(ira) catch unreachable), - Id.LoadPtr => return await (async @fieldParentPtr(LoadPtr, "base", base).analyze(ira) catch unreachable), + .Return => return @fieldParentPtr(Return, "base", base).analyze(ira), + .Const => return @fieldParentPtr(Const, "base", base).analyze(ira), + .Call => return @fieldParentPtr(Call, "base", base).analyze(ira), + .DeclRef => return @fieldParentPtr(DeclRef, "base", base).analyze(ira), + .Ref => return @fieldParentPtr(Ref, "base", base).analyze(ira), + .DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira), + .CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira), + .Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira), + .Br => return @fieldParentPtr(Br, "base", base).analyze(ira), + .AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira), + .PtrType => return @fieldParentPtr(PtrType, "base", base).analyze(ira), + .VarPtr => return @fieldParentPtr(VarPtr, "base", base).analyze(ira), + .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).analyze(ira), } } pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) { switch (base.id) { - Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), - Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), - Id.Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val), - Id.VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val), - Id.LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val), - Id.DeclRef => unreachable, - Id.PtrType => unreachable, - Id.Ref => @panic("TODO"), - Id.DeclVar => @panic("TODO"), - Id.CheckVoidStmt => @panic("TODO"), - Id.Phi => @panic("TODO"), - Id.Br => @panic("TODO"), - Id.AddImplicitReturnType => @panic("TODO"), + .Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val), + .Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val), + .Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val), + .VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val), + .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val), + .DeclRef => unreachable, + .PtrType => unreachable, + .Ref => @panic("TODO"), + .DeclVar => @panic("TODO"), + .CheckVoidStmt => @panic("TODO"), + .Phi => @panic("TODO"), + .Br => @panic("TODO"), + .AddImplicitReturnType => @panic("TODO"), } } @@ -165,7 +164,7 @@ pub const Inst = struct { param.ref_count -= 1; const child = param.child orelse return error.SemanticAnalysisFailed; switch (child.val) { - IrVal.Unknown => return error.SemanticAnalysisFailed, + .Unknown => return error.SemanticAnalysisFailed, else => return child, } } @@ -213,9 +212,9 @@ pub const Inst = struct { /// asserts that the type is known fn getKnownType(self: *Inst) *Type { switch (self.val) { - IrVal.KnownType => |typ| return typ, - IrVal.KnownValue => |value| return value.typ, - IrVal.Unknown => unreachable, + .KnownType => |typ| return typ, + .KnownValue => |value| return value.typ, + .Unknown => unreachable, } } @@ -225,14 +224,14 @@ pub const Inst = struct { pub fn isNoReturn(base: *const Inst) bool { switch (base.val) { - IrVal.Unknown => return false, - IrVal.KnownValue => |x| return x.typ.id == Type.Id.NoReturn, - IrVal.KnownType => |typ| return typ.id == Type.Id.NoReturn, + .Unknown => return false, + .KnownValue => |x| return x.typ.id == .NoReturn, + .KnownType => |typ| return typ.id == .NoReturn, } } pub fn isCompTime(base: *const Inst) bool { - return base.val == IrVal.KnownValue; + return base.val == .KnownValue; } pub fn linkToParent(self: *Inst, parent: *Inst) void { @@ -441,13 +440,13 @@ pub const Inst = struct { .volatility = self.params.volatility, }); const elem_type = target.getKnownType(); - const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ + const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ .child_type = elem_type, .mut = self.params.mut, .vol = self.params.volatility, - .size = Type.Pointer.Size.One, - .alignment = Type.Pointer.Align.Abi, - }) catch unreachable); + .size = .One, + .alignment = .Abi, + }); // TODO: potentially set the hint that this is a stack pointer. But it might not be - this // could be a ref of a global, for example new_inst.val = IrVal{ .KnownType = &ptr_type.base }; @@ -474,25 +473,25 @@ pub const Inst = struct { } pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst { - (await (async ira.irb.comp.resolveDecl(self.params.decl) catch unreachable)) catch |err| switch (err) { + (ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, else => return error.SemanticAnalysisFailed, }; switch (self.params.decl.id) { - Decl.Id.CompTime => unreachable, - Decl.Id.Var => return error.Unimplemented, - Decl.Id.Fn => { + .CompTime => unreachable, + .Var => return error.Unimplemented, + .Fn => { const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl); const decl_val = switch (fn_decl.value) { - Decl.Fn.Val.Unresolved => unreachable, - Decl.Fn.Val.Fn => |fn_val| &fn_val.base, - Decl.Fn.Val.FnProto => |fn_proto| &fn_proto.base, + .Unresolved => unreachable, + .Fn => |fn_val| &fn_val.base, + .FnProto => |fn_proto| &fn_proto.base, }; switch (self.params.lval) { - LVal.None => { + .None => { return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val); }, - LVal.Ptr => return error.Unimplemented, + .Ptr => return error.Unimplemented, } }, } @@ -519,21 +518,21 @@ pub const Inst = struct { pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst { switch (self.params.var_scope.data) { - Scope.Var.Data.Const => @panic("TODO"), - Scope.Var.Data.Param => |param| { + .Const => @panic("TODO"), + .Param => |param| { const new_inst = try ira.irb.build( Inst.VarPtr, self.base.scope, self.base.span, Inst.VarPtr.Params{ .var_scope = self.params.var_scope }, ); - const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ + const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ .child_type = param.typ, - .mut = Type.Pointer.Mut.Const, - .vol = Type.Pointer.Vol.Non, - .size = Type.Pointer.Size.One, - .alignment = Type.Pointer.Align.Abi, - }) catch unreachable); + .mut = .Const, + .vol = .Non, + .size = .One, + .alignment = .Abi, + }); new_inst.val = IrVal{ .KnownType = &ptr_type.base }; return new_inst; }, @@ -542,8 +541,8 @@ pub const Inst = struct { pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value { switch (self.params.var_scope.data) { - Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass - Scope.Var.Data.Param => |param| return param.llvm_value, + .Const => unreachable, // turned into Inst.Const in analyze pass + .Param => |param| return param.llvm_value, } } }; @@ -567,7 +566,7 @@ pub const Inst = struct { pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst { const target = try self.params.target.getAsParam(); const target_type = target.getKnownType(); - if (target_type.id != Type.Id.Pointer) { + if (target_type.id != .Pointer) { try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name); return error.SemanticAnalysisFailed; } @@ -661,13 +660,13 @@ pub const Inst = struct { } else blk: { break :blk Type.Pointer.Align{ .Abi = {} }; }; - const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ + const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ .child_type = child_type, .mut = self.params.mut, .vol = self.params.vol, .size = self.params.size, .alignment = alignment, - }) catch unreachable); + }); ptr_type.base.base.deref(ira.irb.comp); return ira.irb.buildConstValue(self.base.scope, self.base.span, &ptr_type.base.base); @@ -715,7 +714,7 @@ pub const Inst = struct { pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst { const target = try self.params.target.getAsParam(); - if (target.getKnownType().id != Type.Id.Void) { + if (target.getKnownType().id != .Void) { try ira.addCompileError(self.base.span, "expression value is ignored"); return error.SemanticAnalysisFailed; } @@ -838,7 +837,7 @@ pub const Inst = struct { const target = try self.params.target.getAsParam(); const target_type = target.getKnownType(); switch (target_type.id) { - Type.Id.ErrorUnion => { + .ErrorUnion => { return error.Unimplemented; // if (instr_is_comptime(value)) { // ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad); @@ -868,7 +867,7 @@ pub const Inst = struct { // ir_build_test_err_from(&ira->new_irb, &instruction->base, value); // return ira->codegen->builtin_types.entry_bool; }, - Type.Id.ErrorSet => { + .ErrorSet => { return ira.irb.buildConstBool(self.base.scope, self.base.span, true); }, else => { @@ -1081,120 +1080,120 @@ pub const Builder = struct { pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst { switch (node.id) { - ast.Node.Id.Root => unreachable, - ast.Node.Id.Use => unreachable, - ast.Node.Id.TestDecl => unreachable, - ast.Node.Id.VarDecl => return error.Unimplemented, - ast.Node.Id.Defer => return error.Unimplemented, - ast.Node.Id.InfixOp => return error.Unimplemented, - ast.Node.Id.PrefixOp => { + .Root => unreachable, + .Use => unreachable, + .TestDecl => unreachable, + .VarDecl => return error.Unimplemented, + .Defer => return error.Unimplemented, + .InfixOp => return error.Unimplemented, + .PrefixOp => { const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node); switch (prefix_op.op) { - ast.Node.PrefixOp.Op.AddressOf => return error.Unimplemented, - ast.Node.PrefixOp.Op.ArrayType => |n| return error.Unimplemented, - ast.Node.PrefixOp.Op.Await => return error.Unimplemented, - ast.Node.PrefixOp.Op.BitNot => return error.Unimplemented, - ast.Node.PrefixOp.Op.BoolNot => return error.Unimplemented, - ast.Node.PrefixOp.Op.Cancel => return error.Unimplemented, - ast.Node.PrefixOp.Op.OptionalType => return error.Unimplemented, - ast.Node.PrefixOp.Op.Negation => return error.Unimplemented, - ast.Node.PrefixOp.Op.NegationWrap => return error.Unimplemented, - ast.Node.PrefixOp.Op.Resume => return error.Unimplemented, - ast.Node.PrefixOp.Op.PtrType => |ptr_info| { - const inst = try await (async irb.genPtrType(prefix_op, ptr_info, scope) catch unreachable); + .AddressOf => return error.Unimplemented, + .ArrayType => |n| return error.Unimplemented, + .Await => return error.Unimplemented, + .BitNot => return error.Unimplemented, + .BoolNot => return error.Unimplemented, + .Cancel => return error.Unimplemented, + .OptionalType => return error.Unimplemented, + .Negation => return error.Unimplemented, + .NegationWrap => return error.Unimplemented, + .Resume => return error.Unimplemented, + .PtrType => |ptr_info| { + const inst = try irb.genPtrType(prefix_op, ptr_info, scope); return irb.lvalWrap(scope, inst, lval); }, - ast.Node.PrefixOp.Op.SliceType => |ptr_info| return error.Unimplemented, - ast.Node.PrefixOp.Op.Try => return error.Unimplemented, + .SliceType => |ptr_info| return error.Unimplemented, + .Try => return error.Unimplemented, } }, - ast.Node.Id.SuffixOp => { + .SuffixOp => { const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node); switch (suffix_op.op) { - @TagType(ast.Node.SuffixOp.Op).Call => |*call| { - const inst = try await (async irb.genCall(suffix_op, call, scope) catch unreachable); + .Call => |*call| { + const inst = try irb.genCall(suffix_op, call, scope); return irb.lvalWrap(scope, inst, lval); }, - @TagType(ast.Node.SuffixOp.Op).ArrayAccess => |n| return error.Unimplemented, - @TagType(ast.Node.SuffixOp.Op).Slice => |slice| return error.Unimplemented, - @TagType(ast.Node.SuffixOp.Op).ArrayInitializer => |init_list| return error.Unimplemented, - @TagType(ast.Node.SuffixOp.Op).StructInitializer => |init_list| return error.Unimplemented, - @TagType(ast.Node.SuffixOp.Op).Deref => return error.Unimplemented, - @TagType(ast.Node.SuffixOp.Op).UnwrapOptional => return error.Unimplemented, + .ArrayAccess => |n| return error.Unimplemented, + .Slice => |slice| return error.Unimplemented, + .ArrayInitializer => |init_list| return error.Unimplemented, + .StructInitializer => |init_list| return error.Unimplemented, + .Deref => return error.Unimplemented, + .UnwrapOptional => return error.Unimplemented, } }, - ast.Node.Id.Switch => return error.Unimplemented, - ast.Node.Id.While => return error.Unimplemented, - ast.Node.Id.For => return error.Unimplemented, - ast.Node.Id.If => return error.Unimplemented, - ast.Node.Id.ControlFlowExpression => { + .Switch => return error.Unimplemented, + .While => return error.Unimplemented, + .For => return error.Unimplemented, + .If => return error.Unimplemented, + .ControlFlowExpression => { const control_flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", node); - return await (async irb.genControlFlowExpr(control_flow_expr, scope, lval) catch unreachable); + return irb.genControlFlowExpr(control_flow_expr, scope, lval); }, - ast.Node.Id.Suspend => return error.Unimplemented, - ast.Node.Id.VarType => return error.Unimplemented, - ast.Node.Id.ErrorType => return error.Unimplemented, - ast.Node.Id.FnProto => return error.Unimplemented, - ast.Node.Id.PromiseType => return error.Unimplemented, - ast.Node.Id.IntegerLiteral => { + .Suspend => return error.Unimplemented, + .VarType => return error.Unimplemented, + .ErrorType => return error.Unimplemented, + .FnProto => return error.Unimplemented, + .AnyFrameType => return error.Unimplemented, + .IntegerLiteral => { const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node); return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval); }, - ast.Node.Id.FloatLiteral => return error.Unimplemented, - ast.Node.Id.StringLiteral => { + .FloatLiteral => return error.Unimplemented, + .StringLiteral => { const str_lit = @fieldParentPtr(ast.Node.StringLiteral, "base", node); - const inst = try await (async irb.genStrLit(str_lit, scope) catch unreachable); + const inst = try irb.genStrLit(str_lit, scope); return irb.lvalWrap(scope, inst, lval); }, - ast.Node.Id.MultilineStringLiteral => return error.Unimplemented, - ast.Node.Id.CharLiteral => return error.Unimplemented, - ast.Node.Id.BoolLiteral => return error.Unimplemented, - ast.Node.Id.NullLiteral => return error.Unimplemented, - ast.Node.Id.UndefinedLiteral => return error.Unimplemented, - ast.Node.Id.Unreachable => return error.Unimplemented, - ast.Node.Id.Identifier => { + .MultilineStringLiteral => return error.Unimplemented, + .CharLiteral => return error.Unimplemented, + .BoolLiteral => return error.Unimplemented, + .NullLiteral => return error.Unimplemented, + .UndefinedLiteral => return error.Unimplemented, + .Unreachable => return error.Unimplemented, + .Identifier => { const identifier = @fieldParentPtr(ast.Node.Identifier, "base", node); - return await (async irb.genIdentifier(identifier, scope, lval) catch unreachable); + return irb.genIdentifier(identifier, scope, lval); }, - ast.Node.Id.GroupedExpression => { + .GroupedExpression => { const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node); - return await (async irb.genNode(grouped_expr.expr, scope, lval) catch unreachable); + return irb.genNode(grouped_expr.expr, scope, lval); }, - ast.Node.Id.BuiltinCall => return error.Unimplemented, - ast.Node.Id.ErrorSetDecl => return error.Unimplemented, - ast.Node.Id.ContainerDecl => return error.Unimplemented, - ast.Node.Id.Asm => return error.Unimplemented, - ast.Node.Id.Comptime => return error.Unimplemented, - ast.Node.Id.Block => { + .BuiltinCall => return error.Unimplemented, + .ErrorSetDecl => return error.Unimplemented, + .ContainerDecl => return error.Unimplemented, + .Asm => return error.Unimplemented, + .Comptime => return error.Unimplemented, + .Block => { const block = @fieldParentPtr(ast.Node.Block, "base", node); - const inst = try await (async irb.genBlock(block, scope) catch unreachable); + const inst = try irb.genBlock(block, scope); return irb.lvalWrap(scope, inst, lval); }, - ast.Node.Id.DocComment => return error.Unimplemented, - ast.Node.Id.SwitchCase => return error.Unimplemented, - ast.Node.Id.SwitchElse => return error.Unimplemented, - ast.Node.Id.Else => return error.Unimplemented, - ast.Node.Id.Payload => return error.Unimplemented, - ast.Node.Id.PointerPayload => return error.Unimplemented, - ast.Node.Id.PointerIndexPayload => return error.Unimplemented, - ast.Node.Id.ContainerField => return error.Unimplemented, - ast.Node.Id.ErrorTag => return error.Unimplemented, - ast.Node.Id.AsmInput => return error.Unimplemented, - ast.Node.Id.AsmOutput => return error.Unimplemented, - ast.Node.Id.ParamDecl => return error.Unimplemented, - ast.Node.Id.FieldInitializer => return error.Unimplemented, - ast.Node.Id.EnumLiteral => return error.Unimplemented, + .DocComment => return error.Unimplemented, + .SwitchCase => return error.Unimplemented, + .SwitchElse => return error.Unimplemented, + .Else => return error.Unimplemented, + .Payload => return error.Unimplemented, + .PointerPayload => return error.Unimplemented, + .PointerIndexPayload => return error.Unimplemented, + .ContainerField => return error.Unimplemented, + .ErrorTag => return error.Unimplemented, + .AsmInput => return error.Unimplemented, + .AsmOutput => return error.Unimplemented, + .ParamDecl => return error.Unimplemented, + .FieldInitializer => return error.Unimplemented, + .EnumLiteral => return error.Unimplemented, } } async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst { - const fn_ref = try await (async irb.genNode(suffix_op.lhs, scope, LVal.None) catch unreachable); + const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None); const args = try irb.arena().alloc(*Inst, call.params.len); var it = call.params.iterator(0); var i: usize = 0; while (it.next()) |arg_node_ptr| : (i += 1) { - args[i] = try await (async irb.genNode(arg_node_ptr.*, scope, LVal.None) catch unreachable); + args[i] = try irb.genNode(arg_node_ptr.*, scope, .None); } //bool is_async = node->data.fn_call_expr.is_async; @@ -1239,7 +1238,7 @@ pub const Builder = struct { //} else { // align_value = nullptr; //} - const child_type = try await (async irb.genNode(prefix_op.rhs, scope, LVal.None) catch unreachable); + const child_type = try irb.genNode(prefix_op.rhs, scope, .None); //uint32_t bit_offset_start = 0; //if (node->data.pointer_type.bit_offset_start != nullptr) { @@ -1273,9 +1272,9 @@ pub const Builder = struct { return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{ .child_type = child_type, - .mut = Type.Pointer.Mut.Mut, - .vol = Type.Pointer.Vol.Non, - .size = Type.Pointer.Size.Many, + .mut = .Mut, + .vol = .Non, + .size = .Many, .alignment = null, }); } @@ -1287,15 +1286,15 @@ pub const Builder = struct { var scope = target_scope; while (true) { switch (scope.id) { - Scope.Id.CompTime => return true, - Scope.Id.FnDef => return false, - Scope.Id.Decls => unreachable, - Scope.Id.Root => unreachable, - Scope.Id.AstTree => unreachable, - Scope.Id.Block, - Scope.Id.Defer, - Scope.Id.DeferExpr, - Scope.Id.Var, + .CompTime => return true, + .FnDef => return false, + .Decls => unreachable, + .Root => unreachable, + .AstTree => unreachable, + .Block, + .Defer, + .DeferExpr, + .Var, => scope = scope.parent.?, } } @@ -1366,23 +1365,23 @@ pub const Builder = struct { buf[buf.len - 1] = 0; // next make an array value - const array_val = try await (async Value.Array.createOwnedBuffer(irb.comp, buf) catch unreachable); + const array_val = try Value.Array.createOwnedBuffer(irb.comp, buf); buf_cleaned = true; defer array_val.base.deref(irb.comp); // then make a pointer value pointing at the first element - const ptr_val = try await (async Value.Ptr.createArrayElemPtr( + const ptr_val = try Value.Ptr.createArrayElemPtr( irb.comp, array_val, - Type.Pointer.Mut.Const, - Type.Pointer.Size.Many, + .Const, + .Many, 0, - ) catch unreachable); + ); defer ptr_val.base.deref(irb.comp); return irb.buildConstValue(scope, src_span, &ptr_val.base); } else { - const array_val = try await (async Value.Array.createOwnedBuffer(irb.comp, buf) catch unreachable); + const array_val = try Value.Array.createOwnedBuffer(irb.comp, buf); buf_cleaned = true; defer array_val.base.deref(irb.comp); @@ -1438,7 +1437,7 @@ pub const Builder = struct { child_scope = &defer_child_scope.base; continue; } - const statement_value = try await (async irb.genNode(statement_node, child_scope, LVal.None) catch unreachable); + const statement_value = try irb.genNode(statement_node, child_scope, .None); is_continuation_unreachable = statement_value.isNoReturn(); if (is_continuation_unreachable) { @@ -1481,7 +1480,7 @@ pub const Builder = struct { try block_scope.incoming_values.append( try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true), ); - _ = try await (async irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); + _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit); _ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{ .dest_block = block_scope.end_block, @@ -1496,7 +1495,7 @@ pub const Builder = struct { }); } - _ = try await (async irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); + _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit); return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true); } @@ -1507,9 +1506,9 @@ pub const Builder = struct { lval: LVal, ) !*Inst { switch (control_flow_expr.kind) { - ast.Node.ControlFlowExpression.Kind.Break => |arg| return error.Unimplemented, - ast.Node.ControlFlowExpression.Kind.Continue => |arg| return error.Unimplemented, - ast.Node.ControlFlowExpression.Kind.Return => { + .Break => |arg| return error.Unimplemented, + .Continue => |arg| return error.Unimplemented, + .Return => { const src_span = Span.token(control_flow_expr.ltoken); if (scope.findFnDef() == null) { try irb.comp.addCompileError( @@ -1534,7 +1533,7 @@ pub const Builder = struct { const outer_scope = irb.begin_scope.?; const return_value = if (control_flow_expr.rhs) |rhs| blk: { - break :blk try await (async irb.genNode(rhs, scope, LVal.None) catch unreachable); + break :blk try irb.genNode(rhs, scope, .None); } else blk: { break :blk try irb.buildConstVoid(scope, src_span, true); }; @@ -1545,7 +1544,7 @@ pub const Builder = struct { const err_block = try irb.createBasicBlock(scope, c"ErrRetErr"); const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk"); if (!have_err_defers) { - _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); + _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit); } const is_err = try irb.build( @@ -1568,7 +1567,7 @@ pub const Builder = struct { try irb.setCursorAtEndAndAppendBlock(err_block); if (have_err_defers) { - _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ErrorExit) catch unreachable); + _ = try irb.genDefersForBlock(scope, outer_scope, .ErrorExit); } if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) { _ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{}); @@ -1580,7 +1579,7 @@ pub const Builder = struct { try irb.setCursorAtEndAndAppendBlock(ok_block); if (have_err_defers) { - _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); + _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit); } _ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{ .dest_block = ret_stmt_block, @@ -1590,7 +1589,7 @@ pub const Builder = struct { try irb.setCursorAtEndAndAppendBlock(ret_stmt_block); return irb.genAsyncReturn(scope, src_span, return_value, false); } else { - _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); + _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit); return irb.genAsyncReturn(scope, src_span, return_value, false); } }, @@ -1610,14 +1609,14 @@ pub const Builder = struct { // return &const_instruction->base; //} - if (await (async irb.comp.getPrimitiveType(name) catch unreachable)) |result| { + if (irb.comp.getPrimitiveType(name)) |result| { if (result) |primitive_type| { defer primitive_type.base.deref(irb.comp); switch (lval) { // if (lval == LValPtr) { // return ir_build_ref(irb, scope, node, value, false, false); - LVal.Ptr => return error.Unimplemented, - LVal.None => return irb.buildConstValue(scope, src_span, &primitive_type.base), + .Ptr => return error.Unimplemented, + .None => return irb.buildConstValue(scope, src_span, &primitive_type.base), } } } else |err| switch (err) { @@ -1628,23 +1627,23 @@ pub const Builder = struct { error.OutOfMemory => return error.OutOfMemory, } - switch (await (async irb.findIdent(scope, name) catch unreachable)) { - Ident.Decl => |decl| { + switch (irb.findIdent(scope, name)) { + .Decl => |decl| { return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{ .decl = decl, .lval = lval, }); }, - Ident.VarScope => |var_scope| { + .VarScope => |var_scope| { const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope }); switch (lval) { - LVal.Ptr => return var_ptr, - LVal.None => { + .Ptr => return var_ptr, + .None => { return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr }); }, } }, - Ident.NotFound => {}, + .NotFound => {}, } //if (node->owner->any_imports_failed) { @@ -1671,25 +1670,25 @@ pub const Builder = struct { var scope = inner_scope; while (scope != outer_scope) { switch (scope.id) { - Scope.Id.Defer => { + .Defer => { const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope); switch (defer_scope.kind) { - Scope.Defer.Kind.ScopeExit => result.scope_exit += 1, - Scope.Defer.Kind.ErrorExit => result.error_exit += 1, + .ScopeExit => result.scope_exit += 1, + .ErrorExit => result.error_exit += 1, } scope = scope.parent orelse break; }, - Scope.Id.FnDef => break, + .FnDef => break, - Scope.Id.CompTime, - Scope.Id.Block, - Scope.Id.Decls, - Scope.Id.Root, - Scope.Id.Var, + .CompTime, + .Block, + .Decls, + .Root, + .Var, => scope = scope.parent orelse break, - Scope.Id.DeferExpr => unreachable, - Scope.Id.AstTree => unreachable, + .DeferExpr => unreachable, + .AstTree => unreachable, } } return result; @@ -1705,19 +1704,19 @@ pub const Builder = struct { var is_noreturn = false; while (true) { switch (scope.id) { - Scope.Id.Defer => { + .Defer => { const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope); const generate = switch (defer_scope.kind) { - Scope.Defer.Kind.ScopeExit => true, - Scope.Defer.Kind.ErrorExit => gen_kind == Scope.Defer.Kind.ErrorExit, + .ScopeExit => true, + .ErrorExit => gen_kind == .ErrorExit, }; if (generate) { const defer_expr_scope = defer_scope.defer_expr_scope; - const instruction = try await (async irb.genNode( + const instruction = try irb.genNode( defer_expr_scope.expr_node, &defer_expr_scope.base, - LVal.None, - ) catch unreachable); + .None, + ); if (instruction.isNoReturn()) { is_noreturn = true; } else { @@ -1730,32 +1729,32 @@ pub const Builder = struct { } } }, - Scope.Id.FnDef, - Scope.Id.Decls, - Scope.Id.Root, + .FnDef, + .Decls, + .Root, => return is_noreturn, - Scope.Id.CompTime, - Scope.Id.Block, - Scope.Id.Var, + .CompTime, + .Block, + .Var, => scope = scope.parent orelse return is_noreturn, - Scope.Id.DeferExpr => unreachable, - Scope.Id.AstTree => unreachable, + .DeferExpr => unreachable, + .AstTree => unreachable, } } } pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst { switch (lval) { - LVal.None => return instruction, - LVal.Ptr => { + .None => return instruction, + .Ptr => { // We needed a pointer to a value, but we got a value. So we create // an instruction which just makes a const pointer of it. return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{ .target = instruction, - .mut = Type.Pointer.Mut.Const, - .volatility = Type.Pointer.Vol.Non, + .mut = .Const, + .volatility = .Non, }); }, } @@ -1781,9 +1780,9 @@ pub const Builder = struct { .scope = scope, .debug_id = self.next_debug_id, .val = switch (I.ir_val_init) { - IrVal.Init.Unknown => IrVal.Unknown, - IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base }, - IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base }, + .Unknown => IrVal.Unknown, + .NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base }, + .Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base }, }, .ref_count = 0, .span = span, @@ -1902,7 +1901,6 @@ pub const Builder = struct { ); } return error.Unimplemented; - } const Ident = union(enum) { @@ -1915,16 +1913,16 @@ pub const Builder = struct { var s = scope; while (true) { switch (s.id) { - Scope.Id.Root => return Ident.NotFound, - Scope.Id.Decls => { + .Root => return .NotFound, + .Decls => { const decls = @fieldParentPtr(Scope.Decls, "base", s); - const locked_table = await (async decls.table.acquireRead() catch unreachable); + const locked_table = decls.table.acquireRead(); defer locked_table.release(); if (locked_table.value.get(name)) |entry| { return Ident{ .Decl = entry.value }; } }, - Scope.Id.Var => { + .Var => { const var_scope = @fieldParentPtr(Scope.Var, "base", s); if (mem.eql(u8, var_scope.name, name)) { return Ident{ .VarScope = var_scope }; @@ -2047,7 +2045,7 @@ const Analyze = struct { fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst { const dest_type = optional_dest_type orelse return target; const from_type = target.getKnownType(); - if (from_type == dest_type or from_type.id == Type.Id.NoReturn) return target; + if (from_type == dest_type or from_type.id == .NoReturn) return target; return self.analyzeCast(target, target, dest_type); } @@ -2311,7 +2309,7 @@ const Analyze = struct { //} // cast from comptime-known integer to another integer where the value fits - if (target.isCompTime() and (from_type.id == Type.Id.Int or from_type.id == Type.Id.ComptimeInt)) cast: { + if (target.isCompTime() and (from_type.id == .Int or from_type.id == .ComptimeInt)) cast: { const target_val = target.val.KnownValue; const from_int = &target_val.cast(Value.Int).?.big_int; const fits = fits: { @@ -2534,7 +2532,7 @@ pub async fn gen( entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin. try irb.setCursorAtEndAndAppendBlock(entry_block); - const result = try await (async irb.genNode(body_node, scope, LVal.None) catch unreachable); + const result = try irb.genNode(body_node, scope, .None); if (!result.isNoReturn()) { // no need for save_err_ret_addr because this cannot return error _ = try irb.genAsyncReturn(scope, Span.token(body_node.lastToken()), result, true); @@ -2564,7 +2562,7 @@ pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) continue; } - const return_inst = try await (async old_instruction.analyze(&ira) catch unreachable); + const return_inst = try old_instruction.analyze(&ira); assert(return_inst.val != IrVal.Unknown); // at least the type should be known at this point return_inst.linkToParent(old_instruction); // Note: if we ever modify the above to handle error.CompileError by continuing analysis, diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index e6236c567a4a..42e7de5d0839 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -1,9 +1,11 @@ const std = @import("std"); const builtin = @import("builtin"); const event = std.event; -const Target = @import("target.zig").Target; +const util = @import("util.zig"); +const Target = std.Target; const c = @import("c.zig"); const fs = std.fs; +const Allocator = std.mem.Allocator; /// See the render function implementation for documentation of the fields. pub const LibCInstallation = struct { @@ -29,7 +31,7 @@ pub const LibCInstallation = struct { pub fn parse( self: *LibCInstallation, - allocator: *std.mem.Allocator, + allocator: *Allocator, libc_file: []const u8, stderr: *std.io.OutStream(fs.File.WriteError), ) !void { @@ -71,7 +73,7 @@ pub const LibCInstallation = struct { if (std.mem.eql(u8, name, key)) { found_keys[i].found = true; switch (@typeInfo(@typeOf(@field(self, key)))) { - builtin.TypeId.Optional => { + .Optional => { if (value.len == 0) { @field(self, key) = null; } else { @@ -136,15 +138,15 @@ pub const LibCInstallation = struct { self.static_lib_dir orelse "", self.msvc_lib_dir orelse "", self.kernel32_lib_dir orelse "", - self.dynamic_linker_path orelse Target(Target.Native).getDynamicLinkerPath(), + self.dynamic_linker_path orelse util.getDynamicLinkerPath(Target{ .Native = {} }), ); } /// Finds the default, native libc. - pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void { + pub async fn findNative(self: *LibCInstallation, allocator: *Allocator) !void { self.initEmpty(); - var group = event.Group(FindError!void).init(loop); - errdefer group.deinit(); + var group = event.Group(FindError!void).init(allocator); + errdefer group.wait() catch {}; var windows_sdk: ?*c.ZigWindowsSDK = null; errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk)); @@ -156,11 +158,11 @@ pub const LibCInstallation = struct { windows_sdk = sdk; if (sdk.msvc_lib_dir_ptr != 0) { - self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); + self.msvc_lib_dir = try std.mem.dupe(allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]); } - try group.call(findNativeKernel32LibDir, self, loop, sdk); - try group.call(findNativeIncludeDirWindows, self, loop, sdk); - try group.call(findNativeLibDirWindows, self, loop, sdk); + try group.call(findNativeKernel32LibDir, allocator, self, sdk); + try group.call(findNativeIncludeDirWindows, self, allocator, sdk); + try group.call(findNativeLibDirWindows, self, allocator, sdk); }, c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory, c.ZigFindWindowsSdkError.NotFound => return error.NotFound, @@ -168,20 +170,20 @@ pub const LibCInstallation = struct { } }, .linux => { - try group.call(findNativeIncludeDirLinux, self, loop); - try group.call(findNativeLibDirLinux, self, loop); - try group.call(findNativeStaticLibDir, self, loop); - try group.call(findNativeDynamicLinker, self, loop); + try group.call(findNativeIncludeDirLinux, self, allocator); + try group.call(findNativeLibDirLinux, self, allocator); + try group.call(findNativeStaticLibDir, self, allocator); + try group.call(findNativeDynamicLinker, self, allocator); }, .macosx, .freebsd, .netbsd => { - self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); + self.include_dir = try std.mem.dupe(allocator, u8, "/usr/include"); }, else => @compileError("unimplemented: find libc for this OS"), } - return await (async group.wait() catch unreachable); + return group.wait(); } - async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void { + async fn findNativeIncludeDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void { const cc_exe = std.os.getenv("CC") orelse "cc"; const argv = [_][]const u8{ cc_exe, @@ -191,7 +193,7 @@ pub const LibCInstallation = struct { "/dev/null", }; // TODO make this use event loop - const errorable_result = std.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024); + const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024); const exec_result = if (std.debug.runtime_safety) blk: { break :blk errorable_result catch unreachable; } else blk: { @@ -201,12 +203,12 @@ pub const LibCInstallation = struct { }; }; defer { - loop.allocator.free(exec_result.stdout); - loop.allocator.free(exec_result.stderr); + allocator.free(exec_result.stdout); + allocator.free(exec_result.stderr); } switch (exec_result.term) { - std.ChildProcess.Term.Exited => |code| { + .Exited => |code| { if (code != 0) return error.CCompilerExitCode; }, else => { @@ -215,7 +217,7 @@ pub const LibCInstallation = struct { } var it = std.mem.tokenize(exec_result.stderr, "\n\r"); - var search_paths = std.ArrayList([]const u8).init(loop.allocator); + var search_paths = std.ArrayList([]const u8).init(allocator); defer search_paths.deinit(); while (it.next()) |line| { if (line.len != 0 and line[0] == ' ') { @@ -231,11 +233,11 @@ pub const LibCInstallation = struct { while (path_i < search_paths.len) : (path_i += 1) { const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); - const stdlib_path = try fs.path.join(loop.allocator, [_][]const u8{ search_path, "stdlib.h" }); - defer loop.allocator.free(stdlib_path); + const stdlib_path = try fs.path.join(allocator, [_][]const u8{ search_path, "stdlib.h" }); + defer allocator.free(stdlib_path); if (try fileExists(stdlib_path)) { - self.include_dir = try std.mem.dupe(loop.allocator, u8, search_path); + self.include_dir = try std.mem.dupe(allocator, u8, search_path); return; } } @@ -243,11 +245,11 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - async fn findNativeIncludeDirWindows(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) !void { + async fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) !void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(loop.allocator, 0); + var result_buf = try std.Buffer.initSize(allocator, 0); defer result_buf.deinit(); for (searches) |search| { @@ -256,10 +258,10 @@ pub const LibCInstallation = struct { try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version); const stdlib_path = try fs.path.join( - loop.allocator, + allocator, [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" }, ); - defer loop.allocator.free(stdlib_path); + defer allocator.free(stdlib_path); if (try fileExists(stdlib_path)) { self.include_dir = result_buf.toOwnedSlice(); @@ -270,11 +272,11 @@ pub const LibCInstallation = struct { return error.LibCStdLibHeaderNotFound; } - async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) FindError!void { + async fn findNativeLibDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(loop.allocator, 0); + var result_buf = try std.Buffer.initSize(allocator, 0); defer result_buf.deinit(); for (searches) |search| { @@ -282,16 +284,16 @@ pub const LibCInstallation = struct { const stream = &std.io.BufferOutStream.init(&result_buf).stream; try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version); switch (builtin.arch) { - builtin.Arch.i386 => try stream.write("x86"), - builtin.Arch.x86_64 => try stream.write("x64"), - builtin.Arch.aarch64 => try stream.write("arm"), + .i386 => try stream.write("x86"), + .x86_64 => try stream.write("x64"), + .aarch64 => try stream.write("arm"), else => return error.UnsupportedArchitecture, } const ucrt_lib_path = try fs.path.join( - loop.allocator, + allocator, [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" }, ); - defer loop.allocator.free(ucrt_lib_path); + defer allocator.free(ucrt_lib_path); if (try fileExists(ucrt_lib_path)) { self.lib_dir = result_buf.toOwnedSlice(); return; @@ -300,15 +302,15 @@ pub const LibCInstallation = struct { return error.LibCRuntimeNotFound; } - async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void { - self.lib_dir = try await (async ccPrintFileName(loop, "crt1.o", true) catch unreachable); + async fn findNativeLibDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void { + self.lib_dir = try ccPrintFileName(allocator, "crt1.o", true); } - async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void { - self.static_lib_dir = try await (async ccPrintFileName(loop, "crtbegin.o", true) catch unreachable); + async fn findNativeStaticLibDir(self: *LibCInstallation, allocator: *Allocator) FindError!void { + self.static_lib_dir = try ccPrintFileName(allocator, "crtbegin.o", true); } - async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void { + async fn findNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator) FindError!void { var dyn_tests = [_]DynTest{ DynTest{ .name = "ld-linux-x86-64.so.2", @@ -319,12 +321,12 @@ pub const LibCInstallation = struct { .result = null, }, }; - var group = event.Group(FindError!void).init(loop); - errdefer group.deinit(); + var group = event.Group(FindError!void).init(allocator); + errdefer group.wait() catch {}; for (dyn_tests) |*dyn_test| { - try group.call(testNativeDynamicLinker, self, loop, dyn_test); + try group.call(testNativeDynamicLinker, self, allocator, dyn_test); } - try await (async group.wait() catch unreachable); + try group.wait(); for (dyn_tests) |*dyn_test| { if (dyn_test.result) |result| { self.dynamic_linker_path = result; @@ -338,8 +340,8 @@ pub const LibCInstallation = struct { result: ?[]const u8, }; - async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void { - if (await (async ccPrintFileName(loop, dyn_test.name, false) catch unreachable)) |result| { + async fn testNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator, dyn_test: *DynTest) FindError!void { + if (ccPrintFileName(allocator, dyn_test.name, false)) |result| { dyn_test.result = result; return; } else |err| switch (err) { @@ -348,11 +350,11 @@ pub const LibCInstallation = struct { } } - async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) FindError!void { + async fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void { var search_buf: [2]Search = undefined; const searches = fillSearch(&search_buf, sdk); - var result_buf = try std.Buffer.initSize(loop.allocator, 0); + var result_buf = try std.Buffer.initSize(allocator, 0); defer result_buf.deinit(); for (searches) |search| { @@ -360,16 +362,16 @@ pub const LibCInstallation = struct { const stream = &std.io.BufferOutStream.init(&result_buf).stream; try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version); switch (builtin.arch) { - builtin.Arch.i386 => try stream.write("x86\\"), - builtin.Arch.x86_64 => try stream.write("x64\\"), - builtin.Arch.aarch64 => try stream.write("arm\\"), + .i386 => try stream.write("x86\\"), + .x86_64 => try stream.write("x64\\"), + .aarch64 => try stream.write("arm\\"), else => return error.UnsupportedArchitecture, } const kernel32_path = try fs.path.join( - loop.allocator, + allocator, [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" }, ); - defer loop.allocator.free(kernel32_path); + defer allocator.free(kernel32_path); if (try fileExists(kernel32_path)) { self.kernel32_lib_dir = result_buf.toOwnedSlice(); return; @@ -380,7 +382,7 @@ pub const LibCInstallation = struct { fn initEmpty(self: *LibCInstallation) void { self.* = LibCInstallation{ - .include_dir = ([*]const u8)(undefined)[0..0], + .include_dir = @as([*]const u8, undefined)[0..0], .lib_dir = null, .static_lib_dir = null, .msvc_lib_dir = null, @@ -391,15 +393,15 @@ pub const LibCInstallation = struct { }; /// caller owns returned memory -async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bool) ![]u8 { +async fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 { const cc_exe = std.os.getenv("CC") orelse "cc"; - const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file); - defer loop.allocator.free(arg1); + const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file); + defer allocator.free(arg1); const argv = [_][]const u8{ cc_exe, arg1 }; // TODO This simulates evented I/O for the child process exec - await (async loop.yield() catch unreachable); - const errorable_result = std.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024); + std.event.Loop.instance.?.yield(); + const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024); const exec_result = if (std.debug.runtime_safety) blk: { break :blk errorable_result catch unreachable; } else blk: { @@ -409,8 +411,8 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo }; }; defer { - loop.allocator.free(exec_result.stdout); - loop.allocator.free(exec_result.stderr); + allocator.free(exec_result.stdout); + allocator.free(exec_result.stderr); } switch (exec_result.term) { .Exited => |code| { @@ -425,9 +427,9 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound; if (want_dirname) { - return std.mem.dupe(loop.allocator, u8, dirname); + return std.mem.dupe(allocator, u8, dirname); } else { - return std.mem.dupe(loop.allocator, u8, line); + return std.mem.dupe(allocator, u8, line); } } diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 1f5f07eff02b..845d96b193ce 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -1,12 +1,12 @@ const std = @import("std"); const mem = std.mem; const c = @import("c.zig"); -const builtin = @import("builtin"); -const ObjectFormat = builtin.ObjectFormat; const Compilation = @import("compilation.zig").Compilation; -const Target = @import("target.zig").Target; +const Target = std.Target; +const ObjectFormat = Target.ObjectFormat; const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const assert = std.debug.assert; +const util = @import("util.zig"); const Context = struct { comp: *Compilation, @@ -26,7 +26,7 @@ pub async fn link(comp: *Compilation) !void { .comp = comp, .arena = std.heap.ArenaAllocator.init(comp.gpa()), .args = undefined, - .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe, + .link_in_crt = comp.haveLibC() and comp.kind == .Exe, .link_err = {}, .link_msg = undefined, .libc = undefined, @@ -41,14 +41,14 @@ pub async fn link(comp: *Compilation) !void { } else { ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); switch (comp.kind) { - Compilation.Kind.Exe => { + .Exe => { try ctx.out_file_path.append(comp.target.exeFileExt()); }, - Compilation.Kind.Lib => { - try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static)); + .Lib => { + try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix()); }, - Compilation.Kind.Obj => { - try ctx.out_file_path.append(comp.target.objFileExt()); + .Obj => { + try ctx.out_file_path.append(comp.target.oFileExt()); }, } } @@ -61,7 +61,7 @@ pub async fn link(comp: *Compilation) !void { ctx.libc = ctx.comp.override_libc orelse blk: { switch (comp.target) { Target.Native => { - break :blk (await (async comp.zig_compiler.getNativeLibC() catch unreachable)) catch return error.LibCRequiredButNotProvidedOrFound; + break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound; }, else => return error.LibCRequiredButNotProvidedOrFound, } @@ -78,12 +78,12 @@ pub async fn link(comp: *Compilation) !void { std.debug.warn("\n"); } - const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat()); + const extern_ofmt = toExternObjectFormatType(util.getObjectFormat(comp.target)); const args_slice = ctx.args.toSlice(); { // LLD is not thread-safe, so we grab a global lock. - const held = await (async comp.zig_compiler.lld_lock.acquire() catch unreachable); + const held = comp.zig_compiler.lld_lock.acquire(); defer held.release(); // Not evented I/O. LLD does its own multithreading internally. @@ -121,21 +121,21 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void { fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType { return switch (ofmt) { - ObjectFormat.unknown => c.ZigLLVM_UnknownObjectFormat, - ObjectFormat.coff => c.ZigLLVM_COFF, - ObjectFormat.elf => c.ZigLLVM_ELF, - ObjectFormat.macho => c.ZigLLVM_MachO, - ObjectFormat.wasm => c.ZigLLVM_Wasm, + .unknown => c.ZigLLVM_UnknownObjectFormat, + .coff => c.ZigLLVM_COFF, + .elf => c.ZigLLVM_ELF, + .macho => c.ZigLLVM_MachO, + .wasm => c.ZigLLVM_Wasm, }; } fn constructLinkerArgs(ctx: *Context) !void { - switch (ctx.comp.target.getObjectFormat()) { - ObjectFormat.unknown => unreachable, - ObjectFormat.coff => return constructLinkerArgsCoff(ctx), - ObjectFormat.elf => return constructLinkerArgsElf(ctx), - ObjectFormat.macho => return constructLinkerArgsMachO(ctx), - ObjectFormat.wasm => return constructLinkerArgsWasm(ctx), + switch (util.getObjectFormat(ctx.comp.target)) { + .unknown => unreachable, + .coff => return constructLinkerArgsCoff(ctx), + .elf => return constructLinkerArgsElf(ctx), + .macho => return constructLinkerArgsMachO(ctx), + .wasm => return constructLinkerArgsWasm(ctx), } } @@ -154,7 +154,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void { //bool shared = !g->is_static && is_lib; //Buf *soname = nullptr; if (ctx.comp.is_static) { - if (ctx.comp.target.isArmOrThumb()) { + if (util.isArmOrThumb(ctx.comp.target)) { try ctx.args.append(c"-Bstatic"); } else { try ctx.args.append(c"-static"); @@ -222,7 +222,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void { if (!ctx.comp.is_static) { const dl = blk: { if (ctx.libc.dynamic_linker_path) |dl| break :blk dl; - if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl; + if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl; return error.LibCMissingDynamicLinker; }; try ctx.args.append(c"-dynamic-linker"); @@ -324,9 +324,9 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { } switch (ctx.comp.target.getArch()) { - builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"), - builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"), - builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"), + .i386 => try ctx.args.append(c"-MACHINE:X86"), + .x86_64 => try ctx.args.append(c"-MACHINE:X64"), + .aarch64 => try ctx.args.append(c"-MACHINE:ARM"), else => return error.UnsupportedLinkArchitecture, } @@ -336,7 +336,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { try ctx.args.append(c"/SUBSYSTEM:console"); } - const is_library = ctx.comp.kind == Compilation.Kind.Lib; + const is_library = ctx.comp.kind == .Lib; const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst()); try ctx.args.append(out_arg.ptr); @@ -349,7 +349,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { if (ctx.link_in_crt) { const lib_str = if (ctx.comp.is_static) "lib" else ""; - const d_str = if (ctx.comp.build_mode == builtin.Mode.Debug) "d" else ""; + const d_str = if (ctx.comp.build_mode == .Debug) "d" else ""; if (ctx.comp.is_static) { const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str); @@ -400,7 +400,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { try addFnObjects(ctx); switch (ctx.comp.kind) { - Compilation.Kind.Exe, Compilation.Kind.Lib => { + .Exe, .Lib => { if (!ctx.comp.haveLibC()) { @panic("TODO"); //Buf *builtin_o_path = build_o(g, "builtin"); @@ -412,7 +412,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { //Buf *compiler_rt_o_path = build_compiler_rt(g); //lj->args.append(buf_ptr(compiler_rt_o_path)); }, - Compilation.Kind.Obj => {}, + .Obj => {}, } //Buf *def_contents = buf_alloc(); @@ -469,7 +469,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append(c"-export_dynamic"); } - const is_lib = ctx.comp.kind == Compilation.Kind.Lib; + const is_lib = ctx.comp.kind == .Lib; const shared = !ctx.comp.is_static and is_lib; if (ctx.comp.is_static) { try ctx.args.append(c"-static"); @@ -512,14 +512,14 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { const platform = try DarwinPlatform.get(ctx.comp); switch (platform.kind) { - DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"), - DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"), - DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"), + .MacOS => try ctx.args.append(c"-macosx_version_min"), + .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"), + .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"), } const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro); try ctx.args.append(ver_str.ptr); - if (ctx.comp.kind == Compilation.Kind.Exe) { + if (ctx.comp.kind == .Exe) { if (ctx.comp.is_static) { try ctx.args.append(c"-no_pie"); } else { @@ -542,7 +542,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append(c"-lcrt0.o"); } else { switch (platform.kind) { - DarwinPlatform.Kind.MacOS => { + .MacOS => { if (platform.versionLessThan(10, 5)) { try ctx.args.append(c"-lcrt1.o"); } else if (platform.versionLessThan(10, 6)) { @@ -551,8 +551,8 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append(c"-lcrt1.10.6.o"); } }, - DarwinPlatform.Kind.IPhoneOS => { - if (ctx.comp.target.getArch() == builtin.Arch.aarch64) { + .IPhoneOS => { + if (ctx.comp.target.getArch() == .aarch64) { // iOS does not need any crt1 files for arm64 } else if (platform.versionLessThan(3, 1)) { try ctx.args.append(c"-lcrt1.o"); @@ -560,7 +560,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append(c"-lcrt1.3.1.o"); } }, - DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed + .IPhoneOSSimulator => {}, // no crt1.o needed } } @@ -605,7 +605,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { try ctx.args.append(c"dynamic_lookup"); } - if (platform.kind == DarwinPlatform.Kind.MacOS) { + if (platform.kind == .MacOS) { if (platform.versionLessThan(10, 5)) { try ctx.args.append(c"-lgcc_s.10.4"); } else if (platform.versionLessThan(10, 6)) { @@ -659,17 +659,17 @@ const DarwinPlatform = struct { fn get(comp: *Compilation) !DarwinPlatform { var result: DarwinPlatform = undefined; const ver_str = switch (comp.darwin_version_min) { - Compilation.DarwinVersionMin.MacOS => |ver| blk: { - result.kind = Kind.MacOS; + .MacOS => |ver| blk: { + result.kind = .MacOS; break :blk ver; }, - Compilation.DarwinVersionMin.Ios => |ver| blk: { - result.kind = Kind.IPhoneOS; + .Ios => |ver| blk: { + result.kind = .IPhoneOS; break :blk ver; }, - Compilation.DarwinVersionMin.None => blk: { + .None => blk: { assert(comp.target.getOs() == .macosx); - result.kind = Kind.MacOS; + result.kind = .MacOS; break :blk "10.14"; }, }; @@ -686,11 +686,11 @@ const DarwinPlatform = struct { return error.InvalidDarwinVersionString; } - if (result.kind == Kind.IPhoneOS) { + if (result.kind == .IPhoneOS) { switch (comp.target.getArch()) { - builtin.Arch.i386, - builtin.Arch.x86_64, - => result.kind = Kind.IPhoneOSSimulator, + .i386, + .x86_64, + => result.kind = .IPhoneOSSimulator, else => {}, } } diff --git a/src-self-hosted/llvm.zig b/src-self-hosted/llvm.zig index 40d414e5f7e2..c8eba2cd2d93 100644 --- a/src-self-hosted/llvm.zig +++ b/src-self-hosted/llvm.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const c = @import("c.zig"); const assert = @import("std").debug.assert; @@ -268,7 +267,7 @@ pub const FnInline = extern enum { }; fn removeNullability(comptime T: type) type { - comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C); + comptime assert(@typeInfo(T).Pointer.size == .C); return *T.Child; } diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 71f978118613..501c8679f6f4 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -18,7 +18,7 @@ const Args = arg.Args; const Flag = arg.Flag; const ZigCompiler = @import("compilation.zig").ZigCompiler; const Compilation = @import("compilation.zig").Compilation; -const Target = @import("target.zig").Target; +const Target = std.Target; const errmsg = @import("errmsg.zig"); const LibCInstallation = @import("libc_installation.zig").LibCInstallation; @@ -26,6 +26,8 @@ var stderr_file: fs.File = undefined; var stderr: *io.OutStream(fs.File.WriteError) = undefined; var stdout: *io.OutStream(fs.File.WriteError) = undefined; +pub const io_mode = .evented; + pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB const usage = @@ -258,47 +260,47 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co process.exit(0); } - const build_mode = blk: { + const build_mode: std.builtin.Mode = blk: { if (flags.single("mode")) |mode_flag| { if (mem.eql(u8, mode_flag, "debug")) { - break :blk builtin.Mode.Debug; + break :blk .Debug; } else if (mem.eql(u8, mode_flag, "release-fast")) { - break :blk builtin.Mode.ReleaseFast; + break :blk .ReleaseFast; } else if (mem.eql(u8, mode_flag, "release-safe")) { - break :blk builtin.Mode.ReleaseSafe; + break :blk .ReleaseSafe; } else if (mem.eql(u8, mode_flag, "release-small")) { - break :blk builtin.Mode.ReleaseSmall; + break :blk .ReleaseSmall; } else unreachable; } else { - break :blk builtin.Mode.Debug; + break :blk .Debug; } }; - const color = blk: { + const color: errmsg.Color = blk: { if (flags.single("color")) |color_flag| { if (mem.eql(u8, color_flag, "auto")) { - break :blk errmsg.Color.Auto; + break :blk .Auto; } else if (mem.eql(u8, color_flag, "on")) { - break :blk errmsg.Color.On; + break :blk .On; } else if (mem.eql(u8, color_flag, "off")) { - break :blk errmsg.Color.Off; + break :blk .Off; } else unreachable; } else { - break :blk errmsg.Color.Auto; + break :blk .Auto; } }; - const emit_type = blk: { + const emit_type: Compilation.Emit = blk: { if (flags.single("emit")) |emit_flag| { if (mem.eql(u8, emit_flag, "asm")) { - break :blk Compilation.Emit.Assembly; + break :blk .Assembly; } else if (mem.eql(u8, emit_flag, "bin")) { - break :blk Compilation.Emit.Binary; + break :blk .Binary; } else if (mem.eql(u8, emit_flag, "llvm-ir")) { - break :blk Compilation.Emit.LlvmIr; + break :blk .LlvmIr; } else unreachable; } else { - break :blk Compilation.Emit.Binary; + break :blk .Binary; } }; @@ -383,11 +385,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co var override_libc: LibCInstallation = undefined; - var loop: event.Loop = undefined; - try loop.initMultiThreaded(allocator); - defer loop.deinit(); - - var zig_compiler = try ZigCompiler.init(&loop); + var zig_compiler = try ZigCompiler.init(allocator); defer zig_compiler.deinit(); var comp = try Compilation.create( @@ -403,7 +401,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co defer comp.destroy(); if (flags.single("libc")) |libc_path| { - parseLibcPaths(loop.allocator, &override_libc, libc_path); + parseLibcPaths(allocator, &override_libc, libc_path); comp.override_libc = &override_libc; } @@ -463,25 +461,24 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co comp.link_objects = link_objects; comp.start(); - // TODO const process_build_events_handle = try async processBuildEvents(comp, color); - loop.run(); + const frame = async processBuildEvents(comp, color); } async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void { var count: usize = 0; while (true) { // TODO directly awaiting async should guarantee memory allocation elision - const build_event = await (async comp.events.get() catch unreachable); + const build_event = comp.events.get(); count += 1; switch (build_event) { - Compilation.Event.Ok => { + .Ok => { stderr.print("Build {} succeeded\n", count) catch process.exit(1); }, - Compilation.Event.Error => |err| { + .Error => |err| { stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1); }, - Compilation.Event.Fail => |msgs| { + .Fail => |msgs| { stderr.print("Build {} compile errors:\n", count) catch process.exit(1); for (msgs) |msg| { defer msg.destroy(); @@ -536,7 +533,7 @@ const Fmt = struct { seen: event.Locked(SeenMap), any_error: bool, color: errmsg.Color, - loop: *event.Loop, + allocator: *Allocator, const SeenMap = std.StringHashMap(void); }; @@ -567,20 +564,14 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void { }, } - var loop: event.Loop = undefined; - try loop.initMultiThreaded(allocator); - defer loop.deinit(); - - var zig_compiler = try ZigCompiler.init(&loop); + var zig_compiler = try ZigCompiler.init(allocator); defer zig_compiler.deinit(); - // TODO const handle = try async findLibCAsync(&zig_compiler); - - loop.run(); + const frame = async findLibCAsync(&zig_compiler); } async fn findLibCAsync(zig_compiler: *ZigCompiler) void { - const libc = (await (async zig_compiler.getNativeLibC() catch unreachable)) catch |err| { + const libc = zig_compiler.getNativeLibC() catch |err| { stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1); process.exit(1); }; @@ -596,17 +587,17 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { process.exit(0); } - const color = blk: { + const color: errmsg.Color = blk: { if (flags.single("color")) |color_flag| { if (mem.eql(u8, color_flag, "auto")) { - break :blk errmsg.Color.Auto; + break :blk .Auto; } else if (mem.eql(u8, color_flag, "on")) { - break :blk errmsg.Color.On; + break :blk .On; } else if (mem.eql(u8, color_flag, "off")) { - break :blk errmsg.Color.Off; + break :blk .Off; } else unreachable; } else { - break :blk errmsg.Color.Auto; + break :blk .Auto; } }; @@ -640,7 +631,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { } if (flags.present("check")) { const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); - const code = if (anything_changed) u8(1) else u8(0); + const code: u8 = if (anything_changed) 1 else 0; process.exit(code); } @@ -653,28 +644,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { process.exit(1); } - var loop: event.Loop = undefined; - try loop.initMultiThreaded(allocator); - defer loop.deinit(); - - var result: FmtError!void = undefined; - // TODO const main_handle = try async asyncFmtMainChecked( - // TODO &result, - // TODO &loop, - // TODO &flags, - // TODO color, - // TODO ); - loop.run(); - return result; -} - -async fn asyncFmtMainChecked( - result: *(FmtError!void), - loop: *event.Loop, - flags: *const Args, - color: errmsg.Color, -) void { - result.* = await (async asyncFmtMain(loop, flags, color) catch unreachable); + return asyncFmtMain( + allocator, + &flags, + color, + ); } const FmtError = error{ @@ -700,72 +674,69 @@ const FmtError = error{ } || fs.File.OpenError; async fn asyncFmtMain( - loop: *event.Loop, + allocator: *Allocator, flags: *const Args, color: errmsg.Color, ) FmtError!void { - suspend { - resume @handle(); - } var fmt = Fmt{ - .seen = event.Locked(Fmt.SeenMap).init(loop, Fmt.SeenMap.init(loop.allocator)), + .allocator = allocator, + .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)), .any_error = false, .color = color, - .loop = loop, }; const check_mode = flags.present("check"); - var group = event.Group(FmtError!void).init(loop); + var group = event.Group(FmtError!void).init(allocator); for (flags.positionals.toSliceConst()) |file_path| { try group.call(fmtPath, &fmt, file_path, check_mode); } - try await (async group.wait() catch unreachable); + try group.wait(); if (fmt.any_error) { process.exit(1); } } async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void { - const file_path = try std.mem.dupe(fmt.loop.allocator, u8, file_path_ref); - defer fmt.loop.allocator.free(file_path); + const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref); + defer fmt.allocator.free(file_path); { - const held = await (async fmt.seen.acquire() catch unreachable); + const held = fmt.seen.acquire(); defer held.release(); if (try held.value.put(file_path, {})) |_| return; } - const source_code = (await try async event.fs.readFile( - fmt.loop, - file_path, - max_src_size, - )) catch |err| switch (err) { - error.IsDir, error.AccessDenied => { - // TODO make event based (and dir.next()) - var dir = try fs.Dir.open(file_path); - defer dir.close(); - - var group = event.Group(FmtError!void).init(fmt.loop); - while (try dir.next()) |entry| { - if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { - const full_path = try fs.path.join(fmt.loop.allocator, [_][]const u8{ file_path, entry.name }); - try group.call(fmtPath, fmt, full_path, check_mode); - } - } - return await (async group.wait() catch unreachable); - }, - else => { - // TODO lock stderr printing - try stderr.print("unable to open '{}': {}\n", file_path, err); - fmt.any_error = true; - return; - }, - }; - defer fmt.loop.allocator.free(source_code); - - const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| { + const source_code = ""; + // const source_code = event.fs.readFile( + // file_path, + // max_src_size, + // ) catch |err| switch (err) { + // error.IsDir, error.AccessDenied => { + // // TODO make event based (and dir.next()) + // var dir = try fs.Dir.open(file_path); + // defer dir.close(); + + // var group = event.Group(FmtError!void).init(fmt.allocator); + // while (try dir.next()) |entry| { + // if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) { + // const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name }); + // try group.call(fmtPath, fmt, full_path, check_mode); + // } + // } + // return group.wait(); + // }, + // else => { + // // TODO lock stderr printing + // try stderr.print("unable to open '{}': {}\n", file_path, err); + // fmt.any_error = true; + // return; + // }, + // }; + // defer fmt.allocator.free(source_code); + + const tree = std.zig.parse(fmt.allocator, source_code) catch |err| { try stderr.print("error parsing file '{}': {}\n", file_path, err); fmt.any_error = true; return; @@ -774,8 +745,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro var error_it = tree.errors.iterator(0); while (error_it.next()) |parse_error| { - const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, tree, file_path); - defer fmt.loop.allocator.destroy(msg); + const msg = try errmsg.Msg.createFromParseError(fmt.allocator, parse_error, tree, file_path); + defer fmt.allocator.destroy(msg); try msg.printToFile(stderr_file, fmt.color); } @@ -785,17 +756,17 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro } if (check_mode) { - const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, tree); + const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree); if (anything_changed) { try stderr.print("{}\n", file_path); fmt.any_error = true; } } else { // TODO make this evented - const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path); + const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); defer baf.destroy(); - const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), tree); + const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree); if (anything_changed) { try stderr.print("{}\n", file_path); try baf.finish(); @@ -822,8 +793,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void { try stdout.write("Operating Systems:\n"); { comptime var i: usize = 0; - inline while (i < @memberCount(builtin.Os)) : (i += 1) { - comptime const os_tag = @memberName(builtin.Os, i); + inline while (i < @memberCount(Target.Os)) : (i += 1) { + comptime const os_tag = @memberName(Target.Os, i); // NOTE: Cannot use empty string, see #918. comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n"; @@ -835,8 +806,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void { try stdout.write("C ABIs:\n"); { comptime var i: usize = 0; - inline while (i < @memberCount(builtin.Abi)) : (i += 1) { - comptime const abi_tag = @memberName(builtin.Abi, i); + inline while (i < @memberCount(Target.Abi)) : (i += 1) { + comptime const abi_tag = @memberName(Target.Abi, i); // NOTE: Cannot use empty string, see #918. comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n"; @@ -911,21 +882,17 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void { try stdout.print( \\ZIG_CMAKE_BINARY_DIR {} \\ZIG_CXX_COMPILER {} - \\ZIG_LLVM_CONFIG_EXE {} \\ZIG_LLD_INCLUDE_PATH {} \\ZIG_LLD_LIBRARIES {} - \\ZIG_STD_FILES {} - \\ZIG_C_HEADER_FILES {} + \\ZIG_LLVM_CONFIG_EXE {} \\ZIG_DIA_GUIDS_LIB {} \\ , std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR), std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER), - std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE), std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH), std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES), - std.mem.toSliceConst(u8, c.ZIG_STD_FILES), - std.mem.toSliceConst(u8, c.ZIG_C_HEADER_FILES), + std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE), std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB), ); } diff --git a/src-self-hosted/scope.zig b/src-self-hosted/scope.zig index 4ff3e303a2da..c294bf8b7c6b 100644 --- a/src-self-hosted/scope.zig +++ b/src-self-hosted/scope.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const Allocator = mem.Allocator; const Decl = @import("decl.zig").Decl; const Compilation = @import("compilation.zig").Compilation; @@ -28,15 +27,15 @@ pub const Scope = struct { if (base.ref_count.decr() == 1) { if (base.parent) |parent| parent.deref(comp); switch (base.id) { - Id.Root => @fieldParentPtr(Root, "base", base).destroy(comp), - Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(comp), - Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp), - Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp), - Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp), - Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp), - Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp), - Id.Var => @fieldParentPtr(Var, "base", base).destroy(comp), - Id.AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp), + .Root => @fieldParentPtr(Root, "base", base).destroy(comp), + .Decls => @fieldParentPtr(Decls, "base", base).destroy(comp), + .Block => @fieldParentPtr(Block, "base", base).destroy(comp), + .FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp), + .CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp), + .Defer => @fieldParentPtr(Defer, "base", base).destroy(comp), + .DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp), + .Var => @fieldParentPtr(Var, "base", base).destroy(comp), + .AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp), } } } @@ -46,7 +45,7 @@ pub const Scope = struct { while (scope.parent) |parent| { scope = parent; } - assert(scope.id == Id.Root); + assert(scope.id == .Root); return @fieldParentPtr(Root, "base", scope); } @@ -54,17 +53,17 @@ pub const Scope = struct { var scope = base; while (true) { switch (scope.id) { - Id.FnDef => return @fieldParentPtr(FnDef, "base", scope), - Id.Root, Id.Decls => return null, - - Id.Block, - Id.Defer, - Id.DeferExpr, - Id.CompTime, - Id.Var, + .FnDef => return @fieldParentPtr(FnDef, "base", scope), + .Root, .Decls => return null, + + .Block, + .Defer, + .DeferExpr, + .CompTime, + .Var, => scope = scope.parent.?, - Id.AstTree => unreachable, + .AstTree => unreachable, } } } @@ -73,20 +72,20 @@ pub const Scope = struct { var scope = base; while (true) { switch (scope.id) { - Id.DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope), + .DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope), - Id.FnDef, - Id.Decls, + .FnDef, + .Decls, => return null, - Id.Block, - Id.Defer, - Id.CompTime, - Id.Root, - Id.Var, + .Block, + .Defer, + .CompTime, + .Root, + .Var, => scope = scope.parent orelse return null, - Id.AstTree => unreachable, + .AstTree => unreachable, } } } @@ -123,7 +122,7 @@ pub const Scope = struct { const self = try comp.gpa().create(Root); self.* = Root{ .base = Scope{ - .id = Id.Root, + .id = .Root, .parent = null, .ref_count = std.atomic.Int(usize).init(1), }, @@ -155,7 +154,7 @@ pub const Scope = struct { .base = undefined, .tree = tree, }; - self.base.init(Id.AstTree, &root_scope.base); + self.base.init(.AstTree, &root_scope.base); return self; } @@ -184,9 +183,9 @@ pub const Scope = struct { const self = try comp.gpa().create(Decls); self.* = Decls{ .base = undefined, - .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())), + .table = event.RwLocked(Decl.Table).init(Decl.Table.init(comp.gpa())), }; - self.base.init(Id.Decls, parent); + self.base.init(.Decls, parent); return self; } @@ -219,15 +218,15 @@ pub const Scope = struct { fn get(self: Safety, comp: *Compilation) bool { return switch (self) { - Safety.Auto => switch (comp.build_mode) { - builtin.Mode.Debug, - builtin.Mode.ReleaseSafe, + .Auto => switch (comp.build_mode) { + .Debug, + .ReleaseSafe, => true, - builtin.Mode.ReleaseFast, - builtin.Mode.ReleaseSmall, + .ReleaseFast, + .ReleaseSmall, => false, }, - @TagType(Safety).Manual => |man| man.enabled, + .Manual => |man| man.enabled, }; } }; @@ -243,7 +242,7 @@ pub const Scope = struct { .is_comptime = undefined, .safety = Safety.Auto, }; - self.base.init(Id.Block, parent); + self.base.init(.Block, parent); return self; } @@ -266,7 +265,7 @@ pub const Scope = struct { .base = undefined, .fn_val = null, }; - self.base.init(Id.FnDef, parent); + self.base.init(.FnDef, parent); return self; } @@ -282,7 +281,7 @@ pub const Scope = struct { pub fn create(comp: *Compilation, parent: *Scope) !*CompTime { const self = try comp.gpa().create(CompTime); self.* = CompTime{ .base = undefined }; - self.base.init(Id.CompTime, parent); + self.base.init(.CompTime, parent); return self; } @@ -314,7 +313,7 @@ pub const Scope = struct { .defer_expr_scope = defer_expr_scope, .kind = kind, }; - self.base.init(Id.Defer, parent); + self.base.init(.Defer, parent); defer_expr_scope.base.ref(); return self; } @@ -338,7 +337,7 @@ pub const Scope = struct { .expr_node = expr_node, .reported_err = false, }; - self.base.init(Id.DeferExpr, parent); + self.base.init(.DeferExpr, parent); return self; } @@ -404,14 +403,14 @@ pub const Scope = struct { .src_node = src_node, .data = undefined, }; - self.base.init(Id.Var, parent); + self.base.init(.Var, parent); return self; } pub fn destroy(self: *Var, comp: *Compilation) void { switch (self.data) { - Data.Param => {}, - Data.Const => |value| value.deref(comp), + .Param => {}, + .Const => |value| value.deref(comp), } comp.gpa().destroy(self); } diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 37945bf02952..e214ba6ea944 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -1,7 +1,6 @@ // This is Zig code that is used by both stage1 and stage2. // The prototypes in src/userland.h must match these definitions. -const builtin = @import("builtin"); const std = @import("std"); const io = std.io; const mem = std.mem; @@ -354,9 +353,9 @@ fn printErrMsgToFile( color: errmsg.Color, ) !void { const color_on = switch (color) { - errmsg.Color.Auto => file.isTty(), - errmsg.Color.On => true, - errmsg.Color.Off => false, + .Auto => file.isTty(), + .On => true, + .Off => false, }; const lok_token = parse_error.loc(); const span = errmsg.Span{ @@ -421,8 +420,8 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); return stage2_DepNextResult{ .type_id = switch (token.id) { - .target => stage2_DepNextResult.TypeId.target, - .prereq => stage2_DepNextResult.TypeId.prereq, + .target => .target, + .prereq => .prereq, }, .textz = textz.toSlice().ptr, }; diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig deleted file mode 100644 index c62e5af9dd39..000000000000 --- a/src-self-hosted/target.zig +++ /dev/null @@ -1,440 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const llvm = @import("llvm.zig"); -const CInt = @import("c_int.zig").CInt; - -// TODO delete this file and use std.Target - -pub const FloatAbi = enum { - Hard, - Soft, - SoftFp, -}; - -pub const Target = union(enum) { - Native, - Cross: Cross, - - pub const Cross = struct { - arch: builtin.Arch, - os: builtin.Os, - abi: builtin.Abi, - object_format: builtin.ObjectFormat, - }; - - pub fn objFileExt(self: Target) []const u8 { - return switch (self.getObjectFormat()) { - builtin.ObjectFormat.coff => ".obj", - else => ".o", - }; - } - - pub fn exeFileExt(self: Target) []const u8 { - return switch (self.getOs()) { - builtin.Os.windows => ".exe", - else => "", - }; - } - - pub fn libFileExt(self: Target, is_static: bool) []const u8 { - return switch (self.getOs()) { - builtin.Os.windows => if (is_static) ".lib" else ".dll", - else => if (is_static) ".a" else ".so", - }; - } - - pub fn getOs(self: Target) builtin.Os { - return switch (self) { - Target.Native => builtin.os, - @TagType(Target).Cross => |t| t.os, - }; - } - - pub fn getArch(self: Target) builtin.Arch { - switch (self) { - Target.Native => return builtin.arch, - @TagType(Target).Cross => |t| return t.arch, - } - } - - pub fn getAbi(self: Target) builtin.Abi { - return switch (self) { - Target.Native => builtin.abi, - @TagType(Target).Cross => |t| t.abi, - }; - } - - pub fn getObjectFormat(self: Target) builtin.ObjectFormat { - return switch (self) { - Target.Native => builtin.object_format, - @TagType(Target).Cross => |t| t.object_format, - }; - } - - pub fn isWasm(self: Target) bool { - return switch (self.getArch()) { - builtin.Arch.wasm32, builtin.Arch.wasm64 => true, - else => false, - }; - } - - pub fn isDarwin(self: Target) bool { - return switch (self.getOs()) { - builtin.Os.ios, builtin.Os.macosx => true, - else => false, - }; - } - - pub fn isWindows(self: Target) bool { - return switch (self.getOs()) { - builtin.Os.windows => true, - else => false, - }; - } - - /// TODO expose the arch and subarch separately - pub fn isArmOrThumb(self: Target) bool { - return switch (self.getArch()) { - builtin.Arch.arm, - builtin.Arch.armeb, - builtin.Arch.aarch64, - builtin.Arch.aarch64_be, - builtin.Arch.thumb, - builtin.Arch.thumbeb, - => true, - else => false, - }; - } - - pub fn initializeAll() void { - llvm.InitializeAllTargets(); - llvm.InitializeAllTargetInfos(); - llvm.InitializeAllTargetMCs(); - llvm.InitializeAllAsmPrinters(); - llvm.InitializeAllAsmParsers(); - } - - pub fn getTriple(self: Target, allocator: *std.mem.Allocator) !std.Buffer { - var result = try std.Buffer.initSize(allocator, 0); - errdefer result.deinit(); - - // LLVM WebAssembly output support requires the target to be activated at - // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly. - // - // LLVM determines the output format based on the abi suffix, - // defaulting to an object based on the architecture. The default format in - // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to - // explicitly set this ourself in order for it to work. - // - // This is fixed in LLVM 7 and you will be able to get wasm output by - // using the target triple `wasm32-unknown-unknown-unknown`. - const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi()); - - var out = &std.io.BufferOutStream.init(&result).stream; - try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name); - - return result; - } - - pub fn is64bit(self: Target) bool { - return self.getArchPtrBitWidth() == 64; - } - - pub fn getArchPtrBitWidth(self: Target) u32 { - switch (self.getArch()) { - builtin.Arch.avr, - builtin.Arch.msp430, - => return 16, - - builtin.Arch.arc, - builtin.Arch.arm, - builtin.Arch.armeb, - builtin.Arch.hexagon, - builtin.Arch.le32, - builtin.Arch.mips, - builtin.Arch.mipsel, - builtin.Arch.powerpc, - builtin.Arch.r600, - builtin.Arch.riscv32, - builtin.Arch.sparc, - builtin.Arch.sparcel, - builtin.Arch.tce, - builtin.Arch.tcele, - builtin.Arch.thumb, - builtin.Arch.thumbeb, - builtin.Arch.i386, - builtin.Arch.xcore, - builtin.Arch.nvptx, - builtin.Arch.amdil, - builtin.Arch.hsail, - builtin.Arch.spir, - builtin.Arch.kalimba, - builtin.Arch.shave, - builtin.Arch.lanai, - builtin.Arch.wasm32, - builtin.Arch.renderscript32, - => return 32, - - builtin.Arch.aarch64, - builtin.Arch.aarch64_be, - builtin.Arch.mips64, - builtin.Arch.mips64el, - builtin.Arch.powerpc64, - builtin.Arch.powerpc64le, - builtin.Arch.riscv64, - builtin.Arch.x86_64, - builtin.Arch.nvptx64, - builtin.Arch.le64, - builtin.Arch.amdil64, - builtin.Arch.hsail64, - builtin.Arch.spir64, - builtin.Arch.wasm64, - builtin.Arch.renderscript64, - builtin.Arch.amdgcn, - builtin.Arch.bpfel, - builtin.Arch.bpfeb, - builtin.Arch.sparcv9, - builtin.Arch.s390x, - => return 64, - } - } - - pub fn getFloatAbi(self: Target) FloatAbi { - return switch (self.getAbi()) { - builtin.Abi.gnueabihf, - builtin.Abi.eabihf, - builtin.Abi.musleabihf, - => FloatAbi.Hard, - else => FloatAbi.Soft, - }; - } - - pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { - const env = self.getAbi(); - const arch = self.getArch(); - const os = self.getOs(); - switch (os) { - builtin.Os.freebsd => { - return "/libexec/ld-elf.so.1"; - }, - builtin.Os.linux => { - switch (env) { - builtin.Abi.android => { - if (self.is64bit()) { - return "/system/bin/linker64"; - } else { - return "/system/bin/linker"; - } - }, - builtin.Abi.gnux32 => { - if (arch == builtin.Arch.x86_64) { - return "/libx32/ld-linux-x32.so.2"; - } - }, - builtin.Abi.musl, - builtin.Abi.musleabi, - builtin.Abi.musleabihf, - => { - if (arch == builtin.Arch.x86_64) { - return "/lib/ld-musl-x86_64.so.1"; - } - }, - else => {}, - } - switch (arch) { - builtin.Arch.i386, - builtin.Arch.sparc, - builtin.Arch.sparcel, - => return "/lib/ld-linux.so.2", - - builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1", - - builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1", - - builtin.Arch.arm, - builtin.Arch.thumb, - => return switch (self.getFloatAbi()) { - FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - builtin.Arch.armeb, - builtin.Arch.thumbeb, - => return switch (self.getFloatAbi()) { - FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3", - else => return "/lib/ld-linux.so.3", - }, - - builtin.Arch.mips, - builtin.Arch.mipsel, - builtin.Arch.mips64, - builtin.Arch.mips64el, - => return null, - - builtin.Arch.powerpc => return "/lib/ld.so.1", - builtin.Arch.powerpc64 => return "/lib64/ld64.so.2", - builtin.Arch.powerpc64le => return "/lib64/ld64.so.2", - builtin.Arch.s390x => return "/lib64/ld64.so.1", - builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2", - builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2", - - builtin.Arch.arc, - builtin.Arch.avr, - builtin.Arch.bpfel, - builtin.Arch.bpfeb, - builtin.Arch.hexagon, - builtin.Arch.msp430, - builtin.Arch.r600, - builtin.Arch.amdgcn, - builtin.Arch.riscv32, - builtin.Arch.riscv64, - builtin.Arch.tce, - builtin.Arch.tcele, - builtin.Arch.xcore, - builtin.Arch.nvptx, - builtin.Arch.nvptx64, - builtin.Arch.le32, - builtin.Arch.le64, - builtin.Arch.amdil, - builtin.Arch.amdil64, - builtin.Arch.hsail, - builtin.Arch.hsail64, - builtin.Arch.spir, - builtin.Arch.spir64, - builtin.Arch.kalimba, - builtin.Arch.shave, - builtin.Arch.lanai, - builtin.Arch.wasm32, - builtin.Arch.wasm64, - builtin.Arch.renderscript32, - builtin.Arch.renderscript64, - => return null, - } - }, - else => return null, - } - } - - pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { - var result: *llvm.Target = undefined; - var err_msg: [*]u8 = undefined; - if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) { - std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg); - return error.UnsupportedTarget; - } - return result; - } - - pub fn cIntTypeSizeInBits(self: Target, id: CInt.Id) u32 { - const arch = self.getArch(); - switch (self.getOs()) { - builtin.Os.freestanding => switch (self.getArch()) { - builtin.Arch.msp430 => switch (id) { - CInt.Id.Short, - CInt.Id.UShort, - CInt.Id.Int, - CInt.Id.UInt, - => return 16, - CInt.Id.Long, - CInt.Id.ULong, - => return 32, - CInt.Id.LongLong, - CInt.Id.ULongLong, - => return 64, - }, - else => switch (id) { - CInt.Id.Short, - CInt.Id.UShort, - => return 16, - CInt.Id.Int, - CInt.Id.UInt, - => return 32, - CInt.Id.Long, - CInt.Id.ULong, - => return self.getArchPtrBitWidth(), - CInt.Id.LongLong, - CInt.Id.ULongLong, - => return 64, - }, - }, - - builtin.Os.linux, - builtin.Os.macosx, - builtin.Os.freebsd, - builtin.Os.openbsd, - builtin.Os.zen, - => switch (id) { - CInt.Id.Short, - CInt.Id.UShort, - => return 16, - CInt.Id.Int, - CInt.Id.UInt, - => return 32, - CInt.Id.Long, - CInt.Id.ULong, - => return self.getArchPtrBitWidth(), - CInt.Id.LongLong, - CInt.Id.ULongLong, - => return 64, - }, - - builtin.Os.windows, builtin.Os.uefi => switch (id) { - CInt.Id.Short, - CInt.Id.UShort, - => return 16, - CInt.Id.Int, - CInt.Id.UInt, - => return 32, - CInt.Id.Long, - CInt.Id.ULong, - CInt.Id.LongLong, - CInt.Id.ULongLong, - => return 64, - }, - - builtin.Os.ananas, - builtin.Os.cloudabi, - builtin.Os.dragonfly, - builtin.Os.fuchsia, - builtin.Os.ios, - builtin.Os.kfreebsd, - builtin.Os.lv2, - builtin.Os.netbsd, - builtin.Os.solaris, - builtin.Os.haiku, - builtin.Os.minix, - builtin.Os.rtems, - builtin.Os.nacl, - builtin.Os.cnk, - builtin.Os.aix, - builtin.Os.cuda, - builtin.Os.nvcl, - builtin.Os.amdhsa, - builtin.Os.ps4, - builtin.Os.elfiamcu, - builtin.Os.tvos, - builtin.Os.watchos, - builtin.Os.mesa3d, - builtin.Os.contiki, - builtin.Os.amdpal, - builtin.Os.hermit, - builtin.Os.hurd, - builtin.Os.wasi, - => @panic("TODO specify the C integer type sizes for this OS"), - } - } - - pub fn getDarwinArchString(self: Target) []const u8 { - const arch = self.getArch(); - switch (arch) { - builtin.Arch.aarch64 => return "arm64", - builtin.Arch.thumb, - builtin.Arch.arm, - => return "arm", - builtin.Arch.powerpc => return "ppc", - builtin.Arch.powerpc64 => return "ppc64", - builtin.Arch.powerpc64le => return "ppc64le", - else => return @tagName(arch), - } - } -}; diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig index 496a7e05042d..85b9d6b912f5 100644 --- a/src-self-hosted/test.zig +++ b/src-self-hosted/test.zig @@ -1,7 +1,6 @@ const std = @import("std"); const mem = std.mem; -const builtin = @import("builtin"); -const Target = @import("target.zig").Target; +const Target = std.Target; const Compilation = @import("compilation.zig").Compilation; const introspect = @import("introspect.zig"); const testing = std.testing; @@ -11,11 +10,17 @@ const ZigCompiler = @import("compilation.zig").ZigCompiler; var ctx: TestContext = undefined; test "stage2" { + // TODO provide a way to run tests in evented I/O mode + if (!std.io.is_async) return error.SkipZigTest; + + // TODO https://github.com/ziglang/zig/issues/1364 + // TODO https://github.com/ziglang/zig/issues/3117 + if (true) return error.SkipZigTest; + try ctx.init(); defer ctx.deinit(); - try @import("../test/stage2/compile_errors.zig").addCases(&ctx); - try @import("../test/stage2/compare_output.zig").addCases(&ctx); + try @import("stage2_tests").addCases(&ctx); try ctx.run(); } @@ -24,7 +29,6 @@ const file1 = "1.zig"; const allocator = std.heap.c_allocator; pub const TestContext = struct { - loop: std.event.Loop, zig_compiler: ZigCompiler, zig_lib_dir: []u8, file_index: std.atomic.Int(usize), @@ -36,21 +40,17 @@ pub const TestContext = struct { fn init(self: *TestContext) !void { self.* = TestContext{ .any_err = {}, - .loop = undefined, .zig_compiler = undefined, .zig_lib_dir = undefined, .group = undefined, .file_index = std.atomic.Int(usize).init(0), }; - try self.loop.initSingleThreaded(allocator); - errdefer self.loop.deinit(); - - self.zig_compiler = try ZigCompiler.init(&self.loop); + self.zig_compiler = try ZigCompiler.init(allocator); errdefer self.zig_compiler.deinit(); - self.group = std.event.Group(anyerror!void).init(&self.loop); - errdefer self.group.deinit(); + self.group = std.event.Group(anyerror!void).init(allocator); + errdefer self.group.wait() catch {}; self.zig_lib_dir = try introspect.resolveZigLibDir(allocator); errdefer allocator.free(self.zig_lib_dir); @@ -63,20 +63,14 @@ pub const TestContext = struct { std.fs.deleteTree(tmp_dir_name) catch {}; allocator.free(self.zig_lib_dir); self.zig_compiler.deinit(); - self.loop.deinit(); } fn run(self: *TestContext) !void { - const handle = try self.loop.call(waitForGroup, self); - defer cancel handle; - self.loop.run(); + std.event.Loop.startCpuBoundOperation(); + self.any_err = self.group.wait(); return self.any_err; } - async fn waitForGroup(self: *TestContext) void { - self.any_err = await (async self.group.wait() catch unreachable); - } - fn testCompileError( self: *TestContext, source: []const u8, @@ -87,7 +81,7 @@ pub const TestContext = struct { ) !void { var file_index_buf: [20]u8 = undefined; const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); - const file1_path = try std.fs.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 }); + const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 }); if (std.fs.path.dirname(file1_path)) |dirname| { try std.fs.makePath(allocator, dirname); @@ -102,7 +96,7 @@ pub const TestContext = struct { file1_path, Target.Native, Compilation.Kind.Obj, - builtin.Mode.Debug, + .Debug, true, // is_static self.zig_lib_dir, ); @@ -120,9 +114,9 @@ pub const TestContext = struct { ) !void { var file_index_buf: [20]u8 = undefined; const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr()); - const file1_path = try std.fs.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 }); + const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 }); - const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt()); + const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{.Native = {}}).exeFileExt()); if (std.fs.path.dirname(file1_path)) |dirname| { try std.fs.makePath(allocator, dirname); } @@ -136,7 +130,7 @@ pub const TestContext = struct { file1_path, Target.Native, Compilation.Kind.Exe, - builtin.Mode.Debug, + .Debug, false, self.zig_lib_dir, ); @@ -153,16 +147,16 @@ pub const TestContext = struct { comp: *Compilation, exe_file: []const u8, expected_output: []const u8, - ) !void { + ) anyerror!void { // TODO this should not be necessary const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file); defer comp.destroy(); - const build_event = await (async comp.events.get() catch unreachable); + const build_event = comp.events.get(); switch (build_event) { - Compilation.Event.Ok => { - const argv = []const []const u8{exe_file_2}; + .Ok => { + const argv = [_][]const u8{exe_file_2}; // TODO use event loop const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024); switch (child.term) { @@ -198,18 +192,18 @@ pub const TestContext = struct { line: usize, column: usize, text: []const u8, - ) !void { + ) anyerror!void { defer comp.destroy(); - const build_event = await (async comp.events.get() catch unreachable); + const build_event = comp.events.get(); switch (build_event) { - Compilation.Event.Ok => { + .Ok => { @panic("build incorrectly succeeded"); }, - Compilation.Event.Error => |err| { + .Error => |err| { @panic("build incorrectly failed"); }, - Compilation.Event.Fail => |msgs| { + .Fail => |msgs| { testing.expect(msgs.len != 0); for (msgs) |msg| { if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) { diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index e91997711649..32753ed9967d 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -2,7 +2,6 @@ // and stage2. Currently the only way it is used is with `zig translate-c-2`. const std = @import("std"); -const builtin = @import("builtin"); const assert = std.debug.assert; const ast = std.zig.ast; const Token = std.zig.Token; @@ -13,8 +12,7 @@ pub const Mode = enum { translate, }; -// TODO merge with Type.Fn.CallingConvention -const CallingConvention = builtin.TypeInfo.CallingConvention; +const CallingConvention = std.builtin.TypeInfo.CallingConvention; pub const ClangErrMsg = Stage2ErrorMsg; diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig index 5a8dc47ef9ad..3bf39d908587 100644 --- a/src-self-hosted/type.zig +++ b/src-self-hosted/type.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const builtin = @import("builtin"); +const builtin = std.builtin; const Scope = @import("scope.zig").Scope; const Compilation = @import("compilation.zig").Compilation; const Value = @import("value.zig").Value; @@ -20,31 +20,32 @@ pub const Type = struct { pub fn destroy(base: *Type, comp: *Compilation) void { switch (base.id) { - Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp), - Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), - Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp), - Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp), - Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), - Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), - Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp), - Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp), - Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp), - Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp), - Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp), - Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp), - Id.EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp), - Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp), - Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp), - Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp), - Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp), - Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp), - Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp), - Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp), - Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp), - Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), - Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), - Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp), - Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp), + .Struct => @fieldParentPtr(Struct, "base", base).destroy(comp), + .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), + .Type => @fieldParentPtr(MetaType, "base", base).destroy(comp), + .Void => @fieldParentPtr(Void, "base", base).destroy(comp), + .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), + .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), + .Int => @fieldParentPtr(Int, "base", base).destroy(comp), + .Float => @fieldParentPtr(Float, "base", base).destroy(comp), + .Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp), + .Array => @fieldParentPtr(Array, "base", base).destroy(comp), + .ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp), + .ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp), + .EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp), + .Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp), + .Null => @fieldParentPtr(Null, "base", base).destroy(comp), + .Optional => @fieldParentPtr(Optional, "base", base).destroy(comp), + .ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp), + .ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp), + .Enum => @fieldParentPtr(Enum, "base", base).destroy(comp), + .Union => @fieldParentPtr(Union, "base", base).destroy(comp), + .BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp), + .ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp), + .Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp), + .Frame => @fieldParentPtr(Frame, "base", base).destroy(comp), + .AnyFrame => @fieldParentPtr(AnyFrame, "base", base).destroy(comp), + .Vector => @fieldParentPtr(Vector, "base", base).destroy(comp), } } @@ -54,105 +55,108 @@ pub const Type = struct { llvm_context: *llvm.Context, ) (error{OutOfMemory}!*llvm.Type) { switch (base.id) { - Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), - Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), - Id.Type => unreachable, - Id.Void => unreachable, - Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context), - Id.NoReturn => unreachable, - Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context), - Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context), - Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context), - Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context), - Id.ComptimeFloat => unreachable, - Id.ComptimeInt => unreachable, - Id.EnumLiteral => unreachable, - Id.Undefined => unreachable, - Id.Null => unreachable, - Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context), - Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context), - Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context), - Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context), - Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context), - Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context), - Id.ArgTuple => unreachable, - Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), - Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context), - Id.Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context), + .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context), + .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context), + .Type => unreachable, + .Void => unreachable, + .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context), + .NoReturn => unreachable, + .Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context), + .Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context), + .Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context), + .Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context), + .ComptimeFloat => unreachable, + .ComptimeInt => unreachable, + .EnumLiteral => unreachable, + .Undefined => unreachable, + .Null => unreachable, + .Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context), + .ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context), + .ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context), + .Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context), + .Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context), + .BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context), + .ArgTuple => unreachable, + .Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context), + .Frame => return @fieldParentPtr(Frame, "base", base).getLlvmType(allocator, llvm_context), + .AnyFrame => return @fieldParentPtr(AnyFrame, "base", base).getLlvmType(allocator, llvm_context), + .Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context), } } pub fn handleIsPtr(base: *Type) bool { switch (base.id) { - Id.Type, - Id.ComptimeFloat, - Id.ComptimeInt, - Id.EnumLiteral, - Id.Undefined, - Id.Null, - Id.BoundFn, - Id.ArgTuple, - Id.Opaque, + .Type, + .ComptimeFloat, + .ComptimeInt, + .EnumLiteral, + .Undefined, + .Null, + .BoundFn, + .ArgTuple, + .Opaque, => unreachable, - Id.NoReturn, - Id.Void, - Id.Bool, - Id.Int, - Id.Float, - Id.Pointer, - Id.ErrorSet, - Id.Enum, - Id.Fn, - Id.Promise, - Id.Vector, + .NoReturn, + .Void, + .Bool, + .Int, + .Float, + .Pointer, + .ErrorSet, + .Enum, + .Fn, + .Frame, + .AnyFrame, + .Vector, => return false, - Id.Struct => @panic("TODO"), - Id.Array => @panic("TODO"), - Id.Optional => @panic("TODO"), - Id.ErrorUnion => @panic("TODO"), - Id.Union => @panic("TODO"), + .Struct => @panic("TODO"), + .Array => @panic("TODO"), + .Optional => @panic("TODO"), + .ErrorUnion => @panic("TODO"), + .Union => @panic("TODO"), } } pub fn hasBits(base: *Type) bool { switch (base.id) { - Id.Type, - Id.ComptimeFloat, - Id.ComptimeInt, - Id.EnumLiteral, - Id.Undefined, - Id.Null, - Id.BoundFn, - Id.ArgTuple, - Id.Opaque, + .Type, + .ComptimeFloat, + .ComptimeInt, + .EnumLiteral, + .Undefined, + .Null, + .BoundFn, + .ArgTuple, + .Opaque, => unreachable, - Id.Void, - Id.NoReturn, + .Void, + .NoReturn, => return false, - Id.Bool, - Id.Int, - Id.Float, - Id.Fn, - Id.Promise, - Id.Vector, + .Bool, + .Int, + .Float, + .Fn, + .Frame, + .AnyFrame, + .Vector, => return true, - Id.Pointer => { + .Pointer => { const ptr_type = @fieldParentPtr(Pointer, "base", base); return ptr_type.key.child_type.hasBits(); }, - Id.ErrorSet => @panic("TODO"), - Id.Enum => @panic("TODO"), - Id.Struct => @panic("TODO"), - Id.Array => @panic("TODO"), - Id.Optional => @panic("TODO"), - Id.ErrorUnion => @panic("TODO"), - Id.Union => @panic("TODO"), + .ErrorSet => @panic("TODO"), + .Enum => @panic("TODO"), + .Struct => @panic("TODO"), + .Array => @panic("TODO"), + .Optional => @panic("TODO"), + .ErrorUnion => @panic("TODO"), + .Union => @panic("TODO"), } } @@ -168,20 +172,20 @@ pub const Type = struct { fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void { base.* = Type{ .base = Value{ - .id = Value.Id.Type, + .id = .Type, .typ = &MetaType.get(comp).base, .ref_count = std.atomic.Int(usize).init(1), }, .id = id, .name = name, - .abi_alignment = AbiAlignment.init(comp.loop), + .abi_alignment = AbiAlignment.init(), }; } /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead. /// Otherwise, this one will grab one from the pool and then release it. pub async fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 { - if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*; + if (base.abi_alignment.start()) |ptr| return ptr.*; { const held = try comp.zig_compiler.getAnyLlvmContext(); @@ -189,7 +193,7 @@ pub const Type = struct { const llvm_context = held.node.data; - base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable); + base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context); } base.abi_alignment.resolve(); return base.abi_alignment.data; @@ -197,9 +201,9 @@ pub const Type = struct { /// If you have an llvm conext handy, you can use it here. pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 { - if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*; + if (base.abi_alignment.start()) |ptr| return ptr.*; - base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable); + base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context); base.abi_alignment.resolve(); return base.abi_alignment.data; } @@ -261,30 +265,18 @@ pub const Type = struct { pub const Generic = struct { param_count: usize, - cc: CC, - - pub const CC = union(CallingConvention) { - Auto, - C, - Cold, - Naked, - Stdcall, - Async: *Type, // allocator type - }; + cc: CallingConvention, }; pub fn hash(self: *const Key) u32 { var result: u32 = 0; result +%= hashAny(self.alignment, 0); switch (self.data) { - Kind.Generic => |generic| { + .Generic => |generic| { result +%= hashAny(generic.param_count, 1); - switch (generic.cc) { - CallingConvention.Async => |allocator_type| result +%= hashAny(allocator_type, 2), - else => result +%= hashAny(CallingConvention(generic.cc), 3), - } + result +%= hashAny(generic.cc, 3); }, - Kind.Normal => |normal| { + .Normal => |normal| { result +%= hashAny(normal.return_type, 4); result +%= hashAny(normal.is_var_args, 5); result +%= hashAny(normal.cc, 6); @@ -302,21 +294,14 @@ pub const Type = struct { if (self.alignment) |self_align| { if (self_align != other.alignment.?) return false; } - if (@TagType(Data)(self.data) != @TagType(Data)(other.data)) return false; + if (@as(@TagType(Data), self.data) != @as(@TagType(Data), other.data)) return false; switch (self.data) { - Kind.Generic => |*self_generic| { + .Generic => |*self_generic| { const other_generic = &other.data.Generic; if (self_generic.param_count != other_generic.param_count) return false; - if (CallingConvention(self_generic.cc) != CallingConvention(other_generic.cc)) return false; - switch (self_generic.cc) { - CallingConvention.Async => |self_allocator_type| { - const other_allocator_type = other_generic.cc.Async; - if (self_allocator_type != other_allocator_type) return false; - }, - else => {}, - } + if (self_generic.cc != other_generic.cc) return false; }, - Kind.Normal => |*self_normal| { + .Normal => |*self_normal| { const other_normal = &other.data.Normal; if (self_normal.cc != other_normal.cc) return false; if (self_normal.is_var_args != other_normal.is_var_args) return false; @@ -333,13 +318,8 @@ pub const Type = struct { pub fn deref(key: Key, comp: *Compilation) void { switch (key.data) { - Kind.Generic => |generic| { - switch (generic.cc) { - CallingConvention.Async => |allocator_type| allocator_type.base.deref(comp), - else => {}, - } - }, - Kind.Normal => |normal| { + .Generic => {}, + .Normal => |normal| { normal.return_type.base.deref(comp); for (normal.params) |param| { param.typ.base.deref(comp); @@ -350,13 +330,8 @@ pub const Type = struct { pub fn ref(key: Key) void { switch (key.data) { - Kind.Generic => |generic| { - switch (generic.cc) { - CallingConvention.Async => |allocator_type| allocator_type.base.ref(), - else => {}, - } - }, - Kind.Normal => |normal| { + .Generic => {}, + .Normal => |normal| { normal.return_type.base.ref(); for (normal.params) |param| { param.typ.base.ref(); @@ -366,14 +341,7 @@ pub const Type = struct { } }; - pub const CallingConvention = enum { - Auto, - C, - Cold, - Naked, - Stdcall, - Async, - }; + const CallingConvention = builtin.TypeInfo.CallingConvention; pub const Param = struct { is_noalias: bool, @@ -382,26 +350,26 @@ pub const Type = struct { fn ccFnTypeStr(cc: CallingConvention) []const u8 { return switch (cc) { - CallingConvention.Auto => "", - CallingConvention.C => "extern ", - CallingConvention.Cold => "coldcc ", - CallingConvention.Naked => "nakedcc ", - CallingConvention.Stdcall => "stdcallcc ", - CallingConvention.Async => unreachable, + .Unspecified => "", + .C => "extern ", + .Cold => "coldcc ", + .Naked => "nakedcc ", + .Stdcall => "stdcallcc ", + .Async => "async ", }; } pub fn paramCount(self: *Fn) usize { return switch (self.key.data) { - Kind.Generic => |generic| generic.param_count, - Kind.Normal => |normal| normal.params.len, + .Generic => |generic| generic.param_count, + .Normal => |normal| normal.params.len, }; } /// takes ownership of key.Normal.params on success pub async fn get(comp: *Compilation, key: Key) !*Fn { { - const held = await (async comp.fn_type_table.acquire() catch unreachable); + const held = comp.fn_type_table.acquire(); defer held.release(); if (held.value.get(&key)) |entry| { @@ -428,18 +396,10 @@ pub const Type = struct { const name_stream = &std.io.BufferOutStream.init(&name_buf).stream; switch (key.data) { - Kind.Generic => |generic| { + .Generic => |generic| { self.non_key = NonKey{ .Generic = {} }; - switch (generic.cc) { - CallingConvention.Async => |async_allocator_type| { - try name_stream.print("async<{}> ", async_allocator_type.name); - }, - else => { - const cc_str = ccFnTypeStr(generic.cc); - try name_stream.write(cc_str); - }, - } - try name_stream.write("fn("); + const cc_str = ccFnTypeStr(generic.cc); + try name_stream.print("{}fn(", cc_str); var param_i: usize = 0; while (param_i < generic.param_count) : (param_i += 1) { const arg = if (param_i == 0) "var" else ", var"; @@ -447,11 +407,11 @@ pub const Type = struct { } try name_stream.write(")"); if (key.alignment) |alignment| { - try name_stream.print(" align<{}>", alignment); + try name_stream.print(" align({})", alignment); } try name_stream.write(" var"); }, - Kind.Normal => |normal| { + .Normal => |normal| { self.non_key = NonKey{ .Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) }, }; @@ -468,16 +428,16 @@ pub const Type = struct { } try name_stream.write(")"); if (key.alignment) |alignment| { - try name_stream.print(" align<{}>", alignment); + try name_stream.print(" align({})", alignment); } try name_stream.print(" {}", normal.return_type.name); }, } - self.base.init(comp, Id.Fn, name_buf.toOwnedSlice()); + self.base.init(comp, .Fn, name_buf.toOwnedSlice()); { - const held = await (async comp.fn_type_table.acquire() catch unreachable); + const held = comp.fn_type_table.acquire(); defer held.release(); _ = try held.value.put(&self.key, self); @@ -488,8 +448,8 @@ pub const Type = struct { pub fn destroy(self: *Fn, comp: *Compilation) void { self.key.deref(comp); switch (self.key.data) { - Kind.Generic => {}, - Kind.Normal => { + .Generic => {}, + .Normal => { self.non_key.Normal.variable_list.deinit(); }, } @@ -499,7 +459,7 @@ pub const Type = struct { pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type { const normal = &self.key.data.Normal; const llvm_return_type = switch (normal.return_type.id) { - Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, + .Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory, else => try normal.return_type.getLlvmType(allocator, llvm_context), }; const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len); @@ -606,7 +566,7 @@ pub const Type = struct { pub async fn get(comp: *Compilation, key: Key) !*Int { { - const held = await (async comp.int_type_table.acquire() catch unreachable); + const held = comp.int_type_table.acquire(); defer held.release(); if (held.value.get(&key)) |entry| { @@ -627,10 +587,10 @@ pub const Type = struct { const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count); errdefer comp.gpa().free(name); - self.base.init(comp, Id.Int, name); + self.base.init(comp, .Int, name); { - const held = await (async comp.int_type_table.acquire() catch unreachable); + const held = comp.int_type_table.acquire(); defer held.release(); _ = try held.value.put(&self.key, self); @@ -648,7 +608,7 @@ pub const Type = struct { pub async fn gcDestroy(self: *Int, comp: *Compilation) void { { - const held = await (async comp.int_type_table.acquire() catch unreachable); + const held = comp.int_type_table.acquire(); defer held.release(); _ = held.value.remove(&self.key).?; @@ -689,8 +649,8 @@ pub const Type = struct { pub fn hash(self: *const Key) u32 { var result: u32 = 0; result +%= switch (self.alignment) { - Align.Abi => 0xf201c090, - Align.Override => |x| hashAny(x, 0), + .Abi => 0xf201c090, + .Override => |x| hashAny(x, 0), }; result +%= hashAny(self.child_type, 1); result +%= hashAny(self.mut, 2); @@ -704,13 +664,13 @@ pub const Type = struct { self.mut != other.mut or self.vol != other.vol or self.size != other.size or - @TagType(Align)(self.alignment) != @TagType(Align)(other.alignment)) + @as(@TagType(Align), self.alignment) != @as(@TagType(Align), other.alignment)) { return false; } switch (self.alignment) { - Align.Abi => return true, - Align.Override => |x| return x == other.alignment.Override, + .Abi => return true, + .Override => |x| return x == other.alignment.Override, } } }; @@ -742,7 +702,7 @@ pub const Type = struct { pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void { { - const held = await (async comp.ptr_type_table.acquire() catch unreachable); + const held = comp.ptr_type_table.acquire(); defer held.release(); _ = held.value.remove(&self.key).?; @@ -753,8 +713,8 @@ pub const Type = struct { pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 { switch (self.key.alignment) { - Align.Abi => return await (async self.key.child_type.getAbiAlignment(comp) catch unreachable), - Align.Override => |alignment| return alignment, + .Abi => return self.key.child_type.getAbiAlignment(comp), + .Override => |alignment| return alignment, } } @@ -764,16 +724,16 @@ pub const Type = struct { ) !*Pointer { var normal_key = key; switch (key.alignment) { - Align.Abi => {}, - Align.Override => |alignment| { - const abi_align = try await (async key.child_type.getAbiAlignment(comp) catch unreachable); + .Abi => {}, + .Override => |alignment| { + const abi_align = try key.child_type.getAbiAlignment(comp); if (abi_align == alignment) { - normal_key.alignment = Align.Abi; + normal_key.alignment = .Abi; } }, } { - const held = await (async comp.ptr_type_table.acquire() catch unreachable); + const held = comp.ptr_type_table.acquire(); defer held.release(); if (held.value.get(&normal_key)) |entry| { @@ -791,21 +751,21 @@ pub const Type = struct { errdefer comp.gpa().destroy(self); const size_str = switch (self.key.size) { - Size.One => "*", - Size.Many => "[*]", - Size.Slice => "[]", - Size.C => "[*c]", + .One => "*", + .Many => "[*]", + .Slice => "[]", + .C => "[*c]", }; const mut_str = switch (self.key.mut) { - Mut.Const => "const ", - Mut.Mut => "", + .Const => "const ", + .Mut => "", }; const vol_str = switch (self.key.vol) { - Vol.Volatile => "volatile ", - Vol.Non => "", + .Volatile => "volatile ", + .Non => "", }; const name = switch (self.key.alignment) { - Align.Abi => try std.fmt.allocPrint( + .Abi => try std.fmt.allocPrint( comp.gpa(), "{}{}{}{}", size_str, @@ -813,7 +773,7 @@ pub const Type = struct { vol_str, self.key.child_type.name, ), - Align.Override => |alignment| try std.fmt.allocPrint( + .Override => |alignment| try std.fmt.allocPrint( comp.gpa(), "{}align<{}> {}{}{}", size_str, @@ -825,10 +785,10 @@ pub const Type = struct { }; errdefer comp.gpa().free(name); - self.base.init(comp, Id.Pointer, name); + self.base.init(comp, .Pointer, name); { - const held = await (async comp.ptr_type_table.acquire() catch unreachable); + const held = comp.ptr_type_table.acquire(); defer held.release(); _ = try held.value.put(&self.key, self); @@ -873,7 +833,7 @@ pub const Type = struct { errdefer key.elem_type.base.deref(comp); { - const held = await (async comp.array_type_table.acquire() catch unreachable); + const held = comp.array_type_table.acquire(); defer held.release(); if (held.value.get(&key)) |entry| { @@ -893,10 +853,10 @@ pub const Type = struct { const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name); errdefer comp.gpa().free(name); - self.base.init(comp, Id.Array, name); + self.base.init(comp, .Array, name); { - const held = await (async comp.array_type_table.acquire() catch unreachable); + const held = comp.array_type_table.acquire(); defer held.release(); _ = try held.value.put(&self.key, self); @@ -1066,14 +1026,26 @@ pub const Type = struct { } }; - pub const Promise = struct { + pub const Frame = struct { + base: Type, + + pub fn destroy(self: *Frame, comp: *Compilation) void { + comp.gpa().destroy(self); + } + + pub fn getLlvmType(self: *Frame, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { + @panic("TODO"); + } + }; + + pub const AnyFrame = struct { base: Type, - pub fn destroy(self: *Promise, comp: *Compilation) void { + pub fn destroy(self: *AnyFrame, comp: *Compilation) void { comp.gpa().destroy(self); } - pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { + pub fn getLlvmType(self: *AnyFrame, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type { @panic("TODO"); } }; @@ -1081,34 +1053,34 @@ pub const Type = struct { fn hashAny(x: var, comptime seed: u64) u32 { switch (@typeInfo(@typeOf(x))) { - builtin.TypeId.Int => |info| { + .Int => |info| { comptime var rng = comptime std.rand.DefaultPrng.init(seed); const unsigned_x = @bitCast(@IntType(false, info.bits), x); if (info.bits <= 32) { - return u32(unsigned_x) *% comptime rng.random.scalar(u32); + return @as(u32, unsigned_x) *% comptime rng.random.scalar(u32); } else { return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x))); } }, - builtin.TypeId.Pointer => |info| { + .Pointer => |info| { switch (info.size) { - builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed), - builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"), - builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"), - builtin.TypeInfo.Pointer.Size.C => unreachable, + .One => return hashAny(@ptrToInt(x), seed), + .Many => @compileError("implement hash function"), + .Slice => @compileError("implement hash function"), + .C => unreachable, } }, - builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed), - builtin.TypeId.Bool => { + .Enum => return hashAny(@enumToInt(x), seed), + .Bool => { comptime var rng = comptime std.rand.DefaultPrng.init(seed); const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) }; return vals[@boolToInt(x)]; }, - builtin.TypeId.Optional => { + .Optional => { if (x) |non_opt| { return hashAny(non_opt, seed); } else { - return hashAny(u32(1), seed); + return hashAny(@as(u32, 1), seed); } }, else => @compileError("implement hash function for " ++ @typeName(@typeOf(x))), diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig new file mode 100644 index 000000000000..c1e2393d0f6d --- /dev/null +++ b/src-self-hosted/util.zig @@ -0,0 +1,211 @@ +const std = @import("std"); +const Target = std.Target; +const llvm = @import("llvm.zig"); + +pub const FloatAbi = enum { + Hard, + Soft, + SoftFp, +}; + +/// TODO expose the arch and subarch separately +pub fn isArmOrThumb(self: Target) bool { + return switch (self.getArch()) { + .arm, + .armeb, + .aarch64, + .aarch64_be, + .thumb, + .thumbeb, + => true, + else => false, + }; +} + +pub fn getFloatAbi(self: Target) FloatAbi { + return switch (self.getAbi()) { + .gnueabihf, + .eabihf, + .musleabihf, + => .Hard, + else => .Soft, + }; +} + +pub fn getObjectFormat(self: Target) Target.ObjectFormat { + return switch (self) { + .Native => @import("builtin").object_format, + .Cross => { + if (target.isWindows() or target.isUefi()) { + break .coff; + } else if (target.isDarwin()) { + break .macho; + } + if (target.isWasm()) { + break .wasm; + } + break .elf; + }, + }; +} + +pub fn getDynamicLinkerPath(self: Target) ?[]const u8 { + const env = self.getAbi(); + const arch = self.getArch(); + const os = self.getOs(); + switch (os) { + .freebsd => { + return "/libexec/ld-elf.so.1"; + }, + .linux => { + switch (env) { + .android => { + if (self.getArchPtrBitWidth() == 64) { + return "/system/bin/linker64"; + } else { + return "/system/bin/linker"; + } + }, + .gnux32 => { + if (arch == .x86_64) { + return "/libx32/ld-linux-x32.so.2"; + } + }, + .musl, + .musleabi, + .musleabihf, + => { + if (arch == .x86_64) { + return "/lib/ld-musl-x86_64.so.1"; + } + }, + else => {}, + } + switch (arch) { + .i386, + .sparc, + .sparcel, + => return "/lib/ld-linux.so.2", + + .aarch64 => return "/lib/ld-linux-aarch64.so.1", + + .aarch64_be => return "/lib/ld-linux-aarch64_be.so.1", + + .arm, + .thumb, + => return switch (getFloatAbi(self)) { + .Hard => return "/lib/ld-linux-armhf.so.3", + else => return "/lib/ld-linux.so.3", + }, + + .armeb, + .thumbeb, + => return switch (getFloatAbi(self)) { + .Hard => return "/lib/ld-linux-armhf.so.3", + else => return "/lib/ld-linux.so.3", + }, + + .mips, + .mipsel, + .mips64, + .mips64el, + => return null, + + .powerpc => return "/lib/ld.so.1", + .powerpc64 => return "/lib64/ld64.so.2", + .powerpc64le => return "/lib64/ld64.so.2", + .s390x => return "/lib64/ld64.so.1", + .sparcv9 => return "/lib64/ld-linux.so.2", + .x86_64 => return "/lib64/ld-linux-x86-64.so.2", + + .arc, + .avr, + .bpfel, + .bpfeb, + .hexagon, + .msp430, + .r600, + .amdgcn, + .riscv32, + .riscv64, + .tce, + .tcele, + .xcore, + .nvptx, + .nvptx64, + .le32, + .le64, + .amdil, + .amdil64, + .hsail, + .hsail64, + .spir, + .spir64, + .kalimba, + .shave, + .lanai, + .wasm32, + .wasm64, + .renderscript32, + .renderscript64, + .aarch64_32, + => return null, + } + }, + else => return null, + } +} + +pub fn getDarwinArchString(self: Target) []const u8 { + const arch = self.getArch(); + switch (arch) { + .aarch64 => return "arm64", + .thumb, + .arm, + => return "arm", + .powerpc => return "ppc", + .powerpc64 => return "ppc64", + .powerpc64le => return "ppc64le", + else => return @tagName(arch), + } +} + +pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { + var result: *llvm.Target = undefined; + var err_msg: [*]u8 = undefined; + if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) { + std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg); + return error.UnsupportedTarget; + } + return result; +} + +pub fn initializeAllTargets() void { + llvm.InitializeAllTargets(); + llvm.InitializeAllTargetInfos(); + llvm.InitializeAllTargetMCs(); + llvm.InitializeAllAsmPrinters(); + llvm.InitializeAllAsmParsers(); +} + +pub fn getTriple(allocator: *std.mem.Allocator, self: std.Target) !std.Buffer { + var result = try std.Buffer.initSize(allocator, 0); + errdefer result.deinit(); + + // LLVM WebAssembly output support requires the target to be activated at + // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly. + // + // LLVM determines the output format based on the abi suffix, + // defaulting to an object based on the architecture. The default format in + // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to + // explicitly set this ourself in order for it to work. + // + // This is fixed in LLVM 7 and you will be able to get wasm output by + // using the target triple `wasm32-unknown-unknown-unknown`. + const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi()); + + var out = &std.io.BufferOutStream.init(&result).stream; + try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name); + + return result; +} diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index 6908307c560a..5d579a5ef776 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const Scope = @import("scope.zig").Scope; const Compilation = @import("compilation.zig").Compilation; const ObjectFile = @import("codegen.zig").ObjectFile; @@ -24,15 +23,15 @@ pub const Value = struct { if (base.ref_count.decr() == 1) { base.typ.base.deref(comp); switch (base.id) { - Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp), - Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), - Id.FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp), - Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp), - Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), - Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), - Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp), - Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp), - Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp), + .Type => @fieldParentPtr(Type, "base", base).destroy(comp), + .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp), + .FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp), + .Void => @fieldParentPtr(Void, "base", base).destroy(comp), + .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp), + .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp), + .Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp), + .Int => @fieldParentPtr(Int, "base", base).destroy(comp), + .Array => @fieldParentPtr(Array, "base", base).destroy(comp), } } } @@ -59,15 +58,15 @@ pub const Value = struct { pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) { switch (base.id) { - Id.Type => unreachable, - Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), - Id.FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile), - Id.Void => return null, - Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile), - Id.NoReturn => unreachable, - Id.Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile), - Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile), - Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile), + .Type => unreachable, + .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile), + .FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile), + .Void => return null, + .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile), + .NoReturn => unreachable, + .Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile), + .Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile), + .Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile), } } @@ -83,15 +82,15 @@ pub const Value = struct { pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) { switch (base.id) { - Id.Type => unreachable, - Id.Fn => unreachable, - Id.FnProto => unreachable, - Id.Void => unreachable, - Id.Bool => unreachable, - Id.NoReturn => unreachable, - Id.Ptr => unreachable, - Id.Array => unreachable, - Id.Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base, + .Type => unreachable, + .Fn => unreachable, + .FnProto => unreachable, + .Void => unreachable, + .Bool => unreachable, + .NoReturn => unreachable, + .Ptr => unreachable, + .Array => unreachable, + .Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base, } } @@ -138,7 +137,7 @@ pub const Value = struct { const self = try comp.gpa().create(FnProto); self.* = FnProto{ .base = Value{ - .id = Value.Id.FnProto, + .id = .FnProto, .typ = &fn_type.base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -202,7 +201,7 @@ pub const Value = struct { const self = try comp.gpa().create(Fn); self.* = Fn{ .base = Value{ - .id = Value.Id.Fn, + .id = .Fn, .typ = &fn_type.base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -346,20 +345,20 @@ pub const Value = struct { errdefer array_val.base.deref(comp); const elem_type = array_val.base.typ.cast(Type.Array).?.key.elem_type; - const ptr_type = try await (async Type.Pointer.get(comp, Type.Pointer.Key{ + const ptr_type = try Type.Pointer.get(comp, Type.Pointer.Key{ .child_type = elem_type, .mut = mut, .vol = Type.Pointer.Vol.Non, .size = size, .alignment = Type.Pointer.Align.Abi, - }) catch unreachable); + }); var ptr_type_consumed = false; errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp); const self = try comp.gpa().create(Value.Ptr); self.* = Value.Ptr{ .base = Value{ - .id = Value.Id.Ptr, + .id = .Ptr, .typ = &ptr_type.base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -385,8 +384,8 @@ pub const Value = struct { const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context); // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr switch (self.special) { - Special.Scalar => |scalar| @panic("TODO"), - Special.BaseArray => |base_array| { + .Scalar => |scalar| @panic("TODO"), + .BaseArray => |base_array| { // TODO put this in one .o file only, and after that, generate extern references to it const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?; const ptr_bit_count = ofile.comp.target_ptr_bits; @@ -401,9 +400,9 @@ pub const Value = struct { @intCast(c_uint, indices.len), ) orelse return error.OutOfMemory; }, - Special.BaseStruct => |base_struct| @panic("TODO"), - Special.HardCodedAddr => |addr| @panic("TODO"), - Special.Discard => unreachable, + .BaseStruct => |base_struct| @panic("TODO"), + .HardCodedAddr => |addr| @panic("TODO"), + .Discard => unreachable, } } }; @@ -428,16 +427,16 @@ pub const Value = struct { const u8_type = Type.Int.get_u8(comp); defer u8_type.base.base.deref(comp); - const array_type = try await (async Type.Array.get(comp, Type.Array.Key{ + const array_type = try Type.Array.get(comp, Type.Array.Key{ .elem_type = &u8_type.base, .len = buffer.len, - }) catch unreachable); + }); errdefer array_type.base.base.deref(comp); const self = try comp.gpa().create(Value.Array); self.* = Value.Array{ .base = Value{ - .id = Value.Id.Array, + .id = .Array, .typ = &array_type.base, .ref_count = std.atomic.Int(usize).init(1), }, @@ -450,22 +449,22 @@ pub const Value = struct { pub fn destroy(self: *Array, comp: *Compilation) void { switch (self.special) { - Special.Undefined => {}, - Special.OwnedBuffer => |buf| { + .Undefined => {}, + .OwnedBuffer => |buf| { comp.gpa().free(buf); }, - Special.Explicit => {}, + .Explicit => {}, } comp.gpa().destroy(self); } pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value { switch (self.special) { - Special.Undefined => { + .Undefined => { const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context); return llvm.GetUndef(llvm_type); }, - Special.OwnedBuffer => |buf| { + .OwnedBuffer => |buf| { const dont_null_terminate = 1; const llvm_str_init = llvm.ConstStringInContext( ofile.context, @@ -482,7 +481,7 @@ pub const Value = struct { llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type)); return global; }, - Special.Explicit => @panic("TODO"), + .Explicit => @panic("TODO"), } //{ @@ -517,7 +516,7 @@ pub const Value = struct { const self = try comp.gpa().create(Value.Int); self.* = Value.Int{ .base = Value{ - .id = Value.Id.Int, + .id = .Int, .typ = typ, .ref_count = std.atomic.Int(usize).init(1), }, @@ -536,7 +535,7 @@ pub const Value = struct { pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value { switch (self.base.typ.id) { - Type.Id.Int => { + .Int => { const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context); if (self.big_int.len() == 0) { return llvm.ConstNull(type_ref); @@ -554,7 +553,7 @@ pub const Value = struct { }; return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val); }, - Type.Id.ComptimeInt => unreachable, + .ComptimeInt => unreachable, else => unreachable, } } @@ -566,7 +565,7 @@ pub const Value = struct { const new = try comp.gpa().create(Value.Int); new.* = Value.Int{ .base = Value{ - .id = Value.Id.Int, + .id = .Int, .typ = old.base.typ, .ref_count = std.atomic.Int(usize).init(1), }, diff --git a/src/zig_llvm.h b/src/zig_llvm.h index a3043b7e2568..ebc3c1a00dd2 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -465,7 +465,7 @@ ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char * ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, enum ZigLLVM_OSType os_type); -bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch, +bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch, const char *output_lib_path, const bool kill_at); ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type, diff --git a/test/stage2/test.zig b/test/stage2/test.zig new file mode 100644 index 000000000000..f4768cd39ad0 --- /dev/null +++ b/test/stage2/test.zig @@ -0,0 +1,6 @@ +const TestContext = @import("../../src-self-hosted/test.zig").TestContext; + +pub fn addCases(ctx: *TestContext) !void { + try @import("compile_errors.zig").addCases(ctx); + try @import("compare_output.zig").addCases(ctx); +}