diff --git a/lib/std/event/fs.zig b/lib/std/event/fs.zig index 0bbc710df..5d55805e3 100644 --- a/lib/std/event/fs.zig +++ b/lib/std/event/fs.zig @@ -735,24 +735,26 @@ pub fn Watch(comptime V: type) type { allocator: *Allocator, const OsData = switch (builtin.os) { - .macosx, .freebsd, .netbsd, .dragonfly => struct { - file_table: FileTable, - table_lock: event.Lock, - - const FileTable = std.StringHashMap(*Put); - const Put = struct { - putter_frame: @Frame(kqPutEvents), - cancelled: bool = false, - value: V, - }; - }, - + // TODO https://github.com/ziglang/zig/issues/3778 + .macosx, .freebsd, .netbsd, .dragonfly => KqOsData, .linux => LinuxOsData, .windows => WindowsOsData, else => @compileError("Unsupported OS"), }; + const KqOsData = struct { + file_table: FileTable, + table_lock: event.Lock, + + const FileTable = std.StringHashMap(*Put); + const Put = struct { + putter_frame: @Frame(kqPutEvents), + cancelled: bool = false, + value: V, + }; + }; + const WindowsOsData = struct { table_lock: event.Lock, dir_table: DirTable, diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig index c8da54032..259cfd602 100644 --- a/src-self-hosted/compilation.zig +++ b/src-self-hosted/compilation.zig @@ -133,7 +133,7 @@ pub const Compilation = struct { zig_std_dir: []const u8, /// lazily created when we need it - tmp_dir: event.Future(BuildError![]u8), + tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(), version_major: u32 = 0, version_minor: u32 = 0, @@ -158,7 +158,7 @@ pub const Compilation = struct { /// functions that have their own objects that we need to link /// it uses an optional pointer so that tombstone removals are possible - fn_link_set: event.Locked(FnLinkSet), + fn_link_set: event.Locked(FnLinkSet) = event.Locked(FnLinkSet).init(FnLinkSet.init()), pub const FnLinkSet = std.TailQueue(?*Value.Fn); @@ -227,9 +227,9 @@ pub const Compilation = struct { /// need to wait on this group before deinitializing deinit_group: event.Group(void), - // destroy_frame: @Frame(createAsync), - // main_loop_frame: @Frame(Compilation.mainLoop), - main_loop_future: event.Future(void), + destroy_frame: *@Frame(createAsync), + main_loop_frame: *@Frame(Compilation.mainLoop), + main_loop_future: event.Future(void) = event.Future(void).init(), have_err_ret_tracing: bool = false, @@ -245,6 +245,8 @@ pub const Compilation = struct { fs_watch: *fs.Watch(*Scope.Root), + cancelled: bool = false, + 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); const PtrTypeTable = std.HashMap(*const Type.Pointer.Key, *Type.Pointer, Type.Pointer.Key.hash, Type.Pointer.Key.eql); @@ -348,7 +350,9 @@ pub const Compilation = struct { zig_lib_dir: []const u8, ) !*Compilation { var optional_comp: ?*Compilation = null; - var frame = async createAsync( + var frame = try zig_compiler.allocator.create(@Frame(createAsync)); + errdefer zig_compiler.allocator.destroy(frame); + frame.* = async createAsync( &optional_comp, zig_compiler, name, @@ -385,15 +389,12 @@ 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(), - // .destroy_frame = @frame(), - // .main_loop_frame = undefined, - .main_loop_future = event.Future(void).init(), + .destroy_frame = @frame(), + .main_loop_frame = undefined, .name = undefined, .llvm_triple = undefined, .is_static = is_static, - .fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()), .link_libs_list = undefined, .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)), @@ -505,7 +506,10 @@ pub const Compilation = struct { try comp.initTypes(); defer comp.primitive_type_table.deinit(); - // comp.main_loop_frame = async comp.mainLoop(); + comp.main_loop_frame = try allocator.create(@Frame(mainLoop)); + defer allocator.destroy(comp.main_loop_frame); + + 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. @@ -718,8 +722,11 @@ pub const Compilation = struct { } pub fn destroy(self: *Compilation) void { - // await self.main_loop_frame; - // resume self.destroy_frame; + const allocator = self.gpa(); + self.cancelled = true; + await self.main_loop_frame; + resume self.destroy_frame; + allocator.destroy(self.destroy_frame); } fn start(self: *Compilation) void { @@ -732,7 +739,7 @@ pub const Compilation = struct { var build_result = self.initialCompile(); - while (true) { + while (!self.cancelled) { const link_result = if (build_result) blk: { break :blk self.maybeLink(); } else |err| err; @@ -1130,11 +1137,10 @@ pub const Compilation = struct { return link_lib; } - /// cancels itself so no need to await or cancel the promise. async fn startFindingNativeLibC(self: *Compilation) void { - std.event.Loop.instance.?.yield(); + event.Loop.startCpuBoundOperation(); // we don't care if it fails, we're just trying to kick off the future resolution - _ = (self.zig_compiler.getNativeLibC()) catch return; + _ = self.zig_compiler.getNativeLibC() catch return; } /// General Purpose Allocator. Must free when done. @@ -1215,7 +1221,10 @@ pub const Compilation = struct { node: *ast.Node, expected_type: *Type, ) !*Value { - const analyzed_code = try comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type); + var frame = try comp.gpa().create(@Frame(genAndAnalyzeCode)); + defer comp.gpa().destroy(frame); + frame.* = async comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type); + const analyzed_code = try await frame; defer analyzed_code.destroy(comp.gpa()); return analyzed_code.getCompTimeResult(comp); @@ -1315,12 +1324,15 @@ fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void { try fn_type.non_key.Normal.variable_list.append(var_scope); } - const analyzed_code = try comp.genAndAnalyzeCode( + var frame = try comp.gpa().create(@Frame(Compilation.genAndAnalyzeCode)); + defer comp.gpa().destroy(frame); + frame.* = async comp.genAndAnalyzeCode( tree_scope, fn_val.child_scope, body_node, fn_type.key.data.Normal.return_type, ); + const analyzed_code = try await frame; errdefer analyzed_code.destroy(comp.gpa()); assert(fn_val.block_scope != null); diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index 4cab9a4ce..8d1c32cef 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -658,7 +658,7 @@ pub const Inst = struct { const amt = try align_inst.getAsConstAlign(ira); break :blk Type.Pointer.Align{ .Override = amt }; } else blk: { - break :blk Type.Pointer.Align{ .Abi = {} }; + break :blk .Abi; }; const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{ .child_type = child_type, @@ -1078,6 +1078,14 @@ pub const Builder = struct { self.current_basic_block = basic_block; } + pub fn genNodeRecursive(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst { + const alloc = irb.comp.gpa(); + var frame = try alloc.create(@Frame(genNode)); + defer alloc.destroy(frame); + frame.* = async irb.genNode(node, scope, lval); + return await frame; + } + pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst { switch (node.id) { .Root => unreachable, @@ -1157,7 +1165,7 @@ pub const Builder = struct { }, .GroupedExpression => { const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node); - return irb.genNode(grouped_expr.expr, scope, lval); + return irb.genNodeRecursive(grouped_expr.expr, scope, lval); }, .BuiltinCall => return error.Unimplemented, .ErrorSetDecl => return error.Unimplemented, @@ -1187,14 +1195,13 @@ pub const Builder = struct { } fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst { - async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst { - const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None); + const fn_ref = try irb.genNodeRecursive(suffix_op.lhs.node, 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 irb.genNode(arg_node_ptr.*, scope, .None); + args[i] = try irb.genNodeRecursive(arg_node_ptr.*, scope, .None); } //bool is_async = node->data.fn_call_expr.is_async; @@ -1239,7 +1246,7 @@ pub const Builder = struct { //} else { // align_value = nullptr; //} - const child_type = try irb.genNode(prefix_op.rhs, scope, .None); + const child_type = try irb.genNodeRecursive(prefix_op.rhs, scope, .None); //uint32_t bit_offset_start = 0; //if (node->data.pointer_type.bit_offset_start != nullptr) { @@ -1438,7 +1445,7 @@ pub const Builder = struct { child_scope = &defer_child_scope.base; continue; } - const statement_value = try irb.genNode(statement_node, child_scope, .None); + const statement_value = try irb.genNodeRecursive(statement_node, child_scope, .None); is_continuation_unreachable = statement_value.isNoReturn(); if (is_continuation_unreachable) { @@ -1534,7 +1541,7 @@ pub const Builder = struct { const outer_scope = irb.begin_scope.?; const return_value = if (control_flow_expr.rhs) |rhs| blk: { - break :blk try irb.genNode(rhs, scope, .None); + break :blk try irb.genNodeRecursive(rhs, scope, .None); } else blk: { break :blk try irb.buildConstVoid(scope, src_span, true); }; @@ -1713,7 +1720,7 @@ pub const Builder = struct { }; if (generate) { const defer_expr_scope = defer_scope.defer_expr_scope; - const instruction = try irb.genNode( + const instruction = try irb.genNodeRecursive( defer_expr_scope.expr_node, &defer_expr_scope.base, .None, diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig index 3d121ecf6..71cec00eb 100644 --- a/src-self-hosted/libc_installation.zig +++ b/src-self-hosted/libc_installation.zig @@ -400,7 +400,7 @@ fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool const argv = [_][]const u8{ cc_exe, arg1 }; // TODO This simulates evented I/O for the child process exec - std.event.Loop.instance.?.yield(); + event.Loop.startCpuBoundOperation(); 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; diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index f5ccb5a0d..54835f9a0 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -623,16 +623,15 @@ fn constructLinkerArgsWasm(ctx: *Context) void { } fn addFnObjects(ctx: *Context) !void { - // at this point it's guaranteed nobody else has this lock, so we circumvent it - // and avoid having to be an async function - const fn_link_set = &ctx.comp.fn_link_set.private_data; + const held = ctx.comp.fn_link_set.acquire(); + defer held.release(); - var it = fn_link_set.first; + var it = held.value.first; while (it) |node| { const fn_val = node.data orelse { // handle the tombstone. See Value.Fn.destroy. it = node.next; - fn_link_set.remove(node); + held.value.remove(node); ctx.comp.gpa().destroy(node); continue; }; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 934c7ab77..81b3055a5 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -127,7 +127,7 @@ pub fn main() !void { try stderr.print("unknown command: {}\n\n", args[1]); try stderr.write(usage); process.argsFree(allocator, args); - defer process.exit(1); + process.exit(1); } const usage_build_generic = @@ -467,7 +467,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void { var count: usize = 0; - while (true) { // TODO(Vexu) + while (!comp.cancelled) { const build_event = comp.events.get(); count += 1; @@ -545,7 +545,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil "Try running `zig libc` to see an example for the native target.\n", libc_paths_file, @errorName(err), - ) catch process.exit(1); + ) catch {}; process.exit(1); }; } @@ -568,7 +568,7 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void { defer zig_compiler.deinit(); const libc = zig_compiler.getNativeLibC() catch |err| { - stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1); + stderr.print("unable to find libc: {}\n", @errorName(err)) catch {}; process.exit(1); }; libc.render(stdout) catch process.exit(1); @@ -706,7 +706,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro while (try it.next()) |entry| { if (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); + @panic("TODO https://github.com/ziglang/zig/issues/3777"); + // try group.call(fmtPath, fmt, full_path, check_mode); } } return group.wait(); diff --git a/src-self-hosted/util.zig b/src-self-hosted/util.zig index 4cd54cdc2..070ba9ba8 100644 --- a/src-self-hosted/util.zig +++ b/src-self-hosted/util.zig @@ -167,7 +167,7 @@ pub fn getDarwinArchString(self: Target) [:0]const u8 { .powerpc64 => return "ppc64", .powerpc64le => return "ppc64le", // @tagName should be able to return sentinel terminated slice - else => @panic("TODO"), //return @tagName(arch), + else => @panic("TODO https://github.com/ziglang/zig/issues/3779"), //return @tagName(arch), } } diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index b4dc757af..accd70d9c 100644 --- a/src-self-hosted/value.zig +++ b/src-self-hosted/value.zig @@ -350,7 +350,7 @@ pub const Value = struct { .mut = mut, .vol = Type.Pointer.Vol.Non, .size = size, - .alignment = Type.Pointer.Align.Abi, + .alignment = .Abi, }); var ptr_type_consumed = false; errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);