Commit 6dd4a276de

Vexu <15308111+Vexu@users.noreply.github.com>
2019-11-06 20:29:18
self hosted compiler: update to new std.event
1 parent 110e575
src-self-hosted/codegen.zig
@@ -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,
     };
 
src-self-hosted/compilation.zig
@@ -35,9 +35,9 @@ 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,7 +46,7 @@ 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();
             lazy_init_targets.resolve();
@@ -57,11 +57,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 +70,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 +82,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 (self.native_libc.start()) |ptr| return ptr;
-        try self.native_libc.data.findNative(self.loop);
+        try self.native_libc.data.findNative(self.allocator);
         self.native_libc.resolve();
         return &self.native_libc.data;
     }
@@ -122,7 +122,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,
@@ -228,7 +227,7 @@ pub const Compilation = struct {
     deinit_group: event.Group(void),
 
     // destroy_frame: @Frame(createAsync),
-    main_loop_frame: @Frame(Compilation.mainLoop),
+    // main_loop_frame: @Frame(Compilation.mainLoop),
     main_loop_future: event.Future(void),
 
     have_err_ret_tracing: bool,
@@ -348,7 +347,7 @@ pub const Compilation = struct {
         zig_lib_dir: []const u8,
     ) !*Compilation {
         var optional_comp: ?*Compilation = null;
-        const frame = async createAsync(
+        var frame = async createAsync(
             &optional_comp,
             zig_compiler,
             name,
@@ -359,7 +358,7 @@ pub const Compilation = struct {
             is_static,
             zig_lib_dir,
         );
-        return optional_comp orelse await frame;
+        return optional_comp orelse if (await frame) |_| unreachable else |err| err;
     }
 
     async fn createAsync(
@@ -374,10 +373,9 @@ pub const Compilation = struct {
         zig_lib_dir: []const u8,
     ) !void {
 
-        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,
@@ -387,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_frame = @frame(),
-            .main_loop_frame = 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,
@@ -419,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,
@@ -431,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,
@@ -519,8 +517,8 @@ 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.init([0]Event{});
+        defer comp.events.deinit();
 
         if (root_src_path) |root_src| {
             const dirname = std.fs.path.dirname(root_src) orelse ".";
@@ -533,13 +531,13 @@ pub const Compilation = struct {
             comp.root_package = try Package.create(comp.arena(), ".", "");
         }
 
-        comp.fs_watch = try fs.Watch(*Scope.Root).create(loop, 16);
+        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_frame = 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.
@@ -552,7 +550,7 @@ pub const Compilation = struct {
 
         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 {};
+            std.fs.deleteTree(tmp_dir) catch {};
         } else |_| {};
     }
 
@@ -601,7 +599,7 @@ pub const Compilation = struct {
                     .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),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
             .value = undefined,
         };
@@ -619,7 +617,7 @@ pub const Compilation = struct {
                     .ref_count = std.atomic.Int(usize).init(1),
                 },
                 .id = builtin.TypeId.Void,
-                .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
         };
         assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
@@ -634,7 +632,7 @@ pub const Compilation = struct {
                     .ref_count = std.atomic.Int(usize).init(1),
                 },
                 .id = builtin.TypeId.NoReturn,
-                .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
         };
         assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
@@ -649,7 +647,7 @@ pub const Compilation = struct {
                     .ref_count = std.atomic.Int(usize).init(1),
                 },
                 .id = builtin.TypeId.ComptimeInt,
-                .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
         };
         assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
@@ -664,7 +662,7 @@ pub const Compilation = struct {
                     .ref_count = std.atomic.Int(usize).init(1),
                 },
                 .id = builtin.TypeId.Bool,
-                .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
         };
         assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
@@ -718,7 +716,7 @@ pub const Compilation = struct {
                         .ref_count = std.atomic.Int(usize).init(1),
                     },
                     .id = builtin.TypeId.Int,
-                    .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                    .abi_alignment = Type.AbiAlignment.init(),
                 },
                 .key = Type.Int.Key{
                     .is_signed = cint.is_signed,
@@ -739,7 +737,7 @@ pub const Compilation = struct {
                     .ref_count = std.atomic.Int(usize).init(1),
                 },
                 .id = builtin.TypeId.Int,
-                .abi_alignment = Type.AbiAlignment.init(comp.loop),
+                .abi_alignment = Type.AbiAlignment.init(),
             },
             .key = Type.Int.Key{
                 .is_signed = false,
@@ -751,8 +749,8 @@ pub const Compilation = struct {
     }
 
     pub fn destroy(self: *Compilation) void {
-        await self.main_loop_frame;
-        resume self.destroy_frame;
+        // await self.main_loop_frame;
+        // resume self.destroy_frame;
     }
 
     fn start(self: *Compilation) void {
@@ -794,7 +792,7 @@ pub const Compilation = struct {
             }
 
             // First, get an item from the watch channel, waiting on the channel.
-            var group = event.Group(BuildError!void).init(self.loop);
+            var group = event.Group(BuildError!void).init(self.gpa());
             {
                 const ev = (self.fs_watch.channel.get()) catch |err| {
                     build_result = err;
@@ -826,7 +824,6 @@ pub const Compilation = struct {
     async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {
         const tree_scope = blk: {
             const source_code = fs.readFile(
-                self.loop,
                 root_scope.realpath,
                 max_src_size,
             ) catch |err| {
@@ -858,10 +855,10 @@ pub const Compilation = struct {
         const locked_table = root_scope.decls.table.acquireWrite();
         defer locked_table.release();
 
-        var decl_group = event.Group(BuildError!void).init(self.loop);
+        var decl_group = event.Group(BuildError!void).init(self.gpa());
         defer decl_group.deinit();
 
-        try await try async self.rebuildChangedDecls(
+        try self.rebuildChangedDecls(
             &decl_group,
             locked_table.value,
             root_scope.decls,
@@ -935,7 +932,7 @@ 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,
                             },
@@ -975,8 +972,8 @@ 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);
         }
     }
 
@@ -1039,7 +1036,7 @@ 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);
 
@@ -1062,7 +1059,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) {
@@ -1166,14 +1163,14 @@ pub const Compilation = struct {
 
     /// cancels itself so no need to await or cancel the promise.
     async fn startFindingNativeLibC(self: *Compilation) void {
-        self.loop.yield();
+        std.event.Loop.instance.?.yield();
         // we don't care if it fails, we're just trying to kick off the future resolution
         _ = (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.
src-self-hosted/libc_installation.zig
@@ -4,6 +4,7 @@ const event = std.event;
 const Target = @import("target.zig").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 +30,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 {
@@ -141,10 +142,10 @@ pub const LibCInstallation = struct {
     }
 
     /// 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.deinit();
         var windows_sdk: ?*c.ZigWindowsSDK = null;
         errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk));
 
@@ -156,11 +157,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, self, sdk);
+                        try group.call(findNativeIncludeDirWindows, self, sdk);
+                        try group.call(findNativeLibDirWindows, self, sdk);
                     },
                     c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory,
                     c.ZigFindWindowsSdkError.NotFound => return error.NotFound,
@@ -168,20 +169,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 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 +192,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,8 +202,8 @@ 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) {
@@ -215,7 +216,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 +232,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 +244,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 +257,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 +271,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| {
@@ -288,10 +289,10 @@ pub const LibCInstallation = struct {
                 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 +301,15 @@ pub const LibCInstallation = struct {
         return error.LibCRuntimeNotFound;
     }
 
-    async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void {
-        self.lib_dir = try ccPrintFileName(loop, "crt1.o", true);
+    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 ccPrintFileName(loop, "crtbegin.o", true);
+    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,10 +320,10 @@ pub const LibCInstallation = struct {
                 .result = null,
             },
         };
-        var group = event.Group(FindError!void).init(loop);
+        var group = event.Group(FindError!void).init(allocator);
         errdefer group.deinit();
         for (dyn_tests) |*dyn_test| {
-            try group.call(testNativeDynamicLinker, self, loop, dyn_test);
+            try group.call(testNativeDynamicLinker, self, allocator, dyn_test);
         }
         try group.wait();
         for (dyn_tests) |*dyn_test| {
@@ -338,8 +339,8 @@ pub const LibCInstallation = struct {
         result: ?[]const u8,
     };
 
-    async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void {
-        if (ccPrintFileName(loop, dyn_test.name, false)) |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 +349,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| {
@@ -366,10 +367,10 @@ pub const LibCInstallation = struct {
                 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;
@@ -391,15 +392,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
-    loop.yield();
-    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 +410,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 +426,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);
     }
 }
 
src-self-hosted/main.zig
@@ -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 =
@@ -386,11 +388,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(
@@ -406,7 +404,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;
     }
 
@@ -466,8 +464,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
     comp.link_objects = link_objects;
 
     comp.start();
-    const frame = try async processBuildEvents(comp, color);
-    loop.run();
+    const frame = async processBuildEvents(comp, color);
 }
 
 async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
@@ -539,7 +536,7 @@ const Fmt = struct {
     seen: event.Locked(SeenMap),
     any_error: bool,
     color: errmsg.Color,
-    loop: *event.Loop,
+    allocator: *Allocator,
 
     const SeenMap = std.StringHashMap(void);
 };
@@ -570,16 +567,10 @@ 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();
 
     const frame = async findLibCAsync(&zig_compiler);
-
-    loop.run();
 }
 
 async fn findLibCAsync(zig_compiler: *ZigCompiler) void {
@@ -656,15 +647,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();
-
     return asyncFmtMain(
+        allocator,
         &flags,
         color,
     );
-    // loop.run();
 }
 
 const FmtError = error{
@@ -690,20 +677,20 @@ const FmtError = error{
 } || fs.File.OpenError;
 
 async fn asyncFmtMain(
-    loop: *event.Loop,
+    allocator: *Allocator,
     flags: *const Args,
     color: errmsg.Color,
 ) FmtError!void {
     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);
     }
@@ -714,8 +701,8 @@ async fn asyncFmtMain(
 }
 
 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 = fmt.seen.acquire();
@@ -724,20 +711,19 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
         if (try held.value.put(file_path, {})) |_| return;
     }
 
-    const source_code = (await try async event.fs.readFile(
-        fmt.loop,
+    const source_code =  event.fs.readFile(
         file_path,
         max_src_size,
-    )) catch |err| switch (err) {
+    ) 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);
+            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.loop.allocator, [_][]const u8{ file_path, entry.name });
+                    const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
                     try group.call(fmtPath, fmt, full_path, check_mode);
                 }
             }
@@ -750,9 +736,9 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
             return;
         },
     };
-    defer fmt.loop.allocator.free(source_code);
+    defer fmt.allocator.free(source_code);
 
-    const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {
+    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;
@@ -761,8 +747,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);
     }
@@ -772,17 +758,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();
src-self-hosted/scope.zig
@@ -184,7 +184,7 @@ 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);
             return self;
src-self-hosted/test.zig
@@ -24,7 +24,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,20 +35,16 @@ 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();
         errdefer self.zig_compiler.deinit();
 
-        self.group = std.event.Group(anyerror!void).init(&self.loop);
+        self.group = std.event.Group(anyerror!void).init(allocator);
         errdefer self.group.deinit();
 
         self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
@@ -63,13 +58,11 @@ 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 await handle;
-        self.loop.run();
+        const handle = try std.event.Loop.instance.?.call(waitForGroup, self);
+        await handle;
         return self.any_err;
     }
 
src-self-hosted/type.zig
@@ -178,7 +178,7 @@ pub const Type = struct {
             },
             .id = id,
             .name = name,
-            .abi_alignment = AbiAlignment.init(comp.loop),
+            .abi_alignment = AbiAlignment.init(),
         };
     }