Commit 36849d8a7b

Vexu <15308111+Vexu@users.noreply.github.com>
2019-11-26 09:27:51
fixes and cleanup in self hosted
1 parent 76f2185
src-self-hosted/codegen.zig
@@ -25,10 +25,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
 
     const context = llvm_handle.node.data;
 
-    const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;
+    const module = llvm.ModuleCreateWithNameInContext(comp.name.toSliceConst(), context) orelse return error.OutOfMemory;
     defer llvm.DisposeModule(module);
 
-    llvm.SetTarget(module, comp.llvm_triple.ptr());
+    llvm.SetTarget(module, comp.llvm_triple.toSliceConst());
     llvm.SetDataLayout(module, comp.target_layout_str);
 
     if (util.getObjectFormat(comp.target) == .coff) {
@@ -48,23 +48,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
     const producer = try std.Buffer.allocPrint(
         &code.arena.allocator,
         "zig {}.{}.{}",
-        u32(c.ZIG_VERSION_MAJOR),
-        u32(c.ZIG_VERSION_MINOR),
-        u32(c.ZIG_VERSION_PATCH),
+        @as(u32, c.ZIG_VERSION_MAJOR),
+        @as(u32, c.ZIG_VERSION_MINOR),
+        @as(u32, c.ZIG_VERSION_PATCH),
     );
     const flags = "";
     const runtime_version = 0;
     const compile_unit_file = llvm.CreateFile(
         dibuilder,
-        comp.name.ptr(),
-        comp.root_package.root_src_dir.ptr(),
+        comp.name.toSliceConst(),
+        comp.root_package.root_src_dir.toSliceConst(),
     ) orelse return error.OutOfMemory;
     const is_optimized = comp.build_mode != .Debug;
     const compile_unit = llvm.CreateCompileUnit(
         dibuilder,
         DW.LANG_C99,
         compile_unit_file,
-        producer.ptr(),
+        producer.toSliceConst(),
         is_optimized,
         flags,
         runtime_version,
@@ -99,7 +99,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
 
     // verify the llvm module when safety is on
     if (std.debug.runtime_safety) {
-        var error_ptr: ?[*]u8 = null;
+        var error_ptr: ?[*:0]u8 = null;
         _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
     }
 
@@ -108,12 +108,12 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
     const is_small = comp.build_mode == .ReleaseSmall;
     const is_debug = comp.build_mode == .Debug;
 
-    var err_msg: [*]u8 = undefined;
+    var err_msg: [*:0]u8 = undefined;
     // TODO integrate this with evented I/O
     if (llvm.TargetMachineEmitToFile(
         comp.target_machine,
         module,
-        output_path.ptr(),
+        output_path.toSliceConst(),
         llvm.EmitBinary,
         &err_msg,
         is_debug,
@@ -154,7 +154,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
     const llvm_fn_type = try fn_val.base.typ.getLlvmType(ofile.arena, ofile.context);
     const llvm_fn = llvm.AddFunction(
         ofile.module,
-        fn_val.symbol_name.ptr(),
+        fn_val.symbol_name.toSliceConst(),
         llvm_fn_type,
     ) orelse return error.OutOfMemory;
 
@@ -379,7 +379,7 @@ fn renderLoadUntyped(
     ptr: *llvm.Value,
     alignment: Type.Pointer.Align,
     vol: Type.Pointer.Vol,
-    name: [*]const u8,
+    name: [*:0]const u8,
 ) !*llvm.Value {
     const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
     switch (vol) {
@@ -390,7 +390,7 @@ fn renderLoadUntyped(
     return result;
 }
 
-fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
+fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*:0]const u8) !*llvm.Value {
     return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
 }
 
@@ -438,7 +438,7 @@ pub fn renderAlloca(
 ) !*llvm.Value {
     const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
     const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
-    const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
+    const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, @ptrCast([*:0]const u8, name_with_null.ptr)) orelse return error.OutOfMemory;
     llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm_var_type));
     return result;
 }
src-self-hosted/compilation.zig
@@ -93,7 +93,7 @@ pub const ZigCompiler = struct {
         return LlvmHandle{ .node = node };
     }
 
-    pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
+    pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
         if (self.native_libc.start()) |ptr| return ptr;
         try self.native_libc.data.findNative(self.allocator);
         self.native_libc.resolve();
@@ -135,26 +135,26 @@ pub const Compilation = struct {
     /// lazily created when we need it
     tmp_dir: event.Future(BuildError![]u8),
 
-    version_major: u32,
-    version_minor: u32,
-    version_patch: u32,
+    version_major: u32 = 0,
+    version_minor: u32 = 0,
+    version_patch: u32 = 0,
 
-    linker_script: ?[]const u8,
-    out_h_path: ?[]const u8,
+    linker_script: ?[]const u8 = null,
+    out_h_path: ?[]const u8 = null,
 
-    is_test: bool,
-    each_lib_rpath: bool,
-    strip: bool,
+    is_test: bool = false,
+    each_lib_rpath: bool = false,
+    strip: bool = false,
     is_static: bool,
-    linker_rdynamic: bool,
+    linker_rdynamic: bool = false,
 
-    clang_argv: []const []const u8,
-    lib_dirs: []const []const u8,
-    rpath_list: []const []const u8,
-    assembly_files: []const []const u8,
+    clang_argv: []const []const u8 = [_][]const u8{},
+    lib_dirs: []const []const u8 = [_][]const u8{},
+    rpath_list: []const []const u8 = [_][]const u8{},
+    assembly_files: []const []const u8 = [_][]const u8{},
 
     /// paths that are explicitly provided by the user to link against
-    link_objects: []const []const u8,
+    link_objects: []const []const u8 = [_][]const u8{},
 
     /// functions that have their own objects that we need to link
     /// it uses an optional pointer so that tombstone removals are possible
@@ -162,33 +162,33 @@ pub const Compilation = struct {
 
     pub const FnLinkSet = std.TailQueue(?*Value.Fn);
 
-    windows_subsystem_windows: bool,
-    windows_subsystem_console: bool,
+    windows_subsystem_windows: bool = false,
+    windows_subsystem_console: bool = false,
 
     link_libs_list: ArrayList(*LinkLib),
-    libc_link_lib: ?*LinkLib,
+    libc_link_lib: ?*LinkLib = null,
 
-    err_color: errmsg.Color,
+    err_color: errmsg.Color = .Auto,
 
-    verbose_tokenize: bool,
-    verbose_ast_tree: bool,
-    verbose_ast_fmt: bool,
-    verbose_cimport: bool,
-    verbose_ir: bool,
-    verbose_llvm_ir: bool,
-    verbose_link: bool,
+    verbose_tokenize: bool = false,
+    verbose_ast_tree: bool = false,
+    verbose_ast_fmt: bool = false,
+    verbose_cimport: bool = false,
+    verbose_ir: bool = false,
+    verbose_llvm_ir: bool = false,
+    verbose_link: bool = false,
 
-    darwin_frameworks: []const []const u8,
-    darwin_version_min: DarwinVersionMin,
+    darwin_frameworks: []const []const u8 = [_][]const u8{},
+    darwin_version_min: DarwinVersionMin = .None,
 
-    test_filters: []const []const u8,
-    test_name_prefix: ?[]const u8,
+    test_filters: []const []const u8 = [_][]const u8{},
+    test_name_prefix: ?[]const u8 = null,
 
-    emit_file_type: Emit,
+    emit_file_type: Emit = .Binary,
 
     kind: Kind,
 
-    link_out_file: ?[]const u8,
+    link_out_file: ?[]const u8 = null,
     events: *event.Channel(Event),
 
     exported_symbol_names: event.Locked(Decl.Table),
@@ -213,7 +213,7 @@ pub const Compilation = struct {
 
     target_machine: *llvm.TargetMachine,
     target_data_ref: *llvm.TargetData,
-    target_layout_str: [*]u8,
+    target_layout_str: [*:0]u8,
     target_ptr_bits: u32,
 
     /// for allocating things which have the same lifetime as this Compilation
@@ -222,7 +222,7 @@ pub const Compilation = struct {
     root_package: *Package,
     std_package: *Package,
 
-    override_libc: ?*LibCInstallation,
+    override_libc: ?*LibCInstallation = null,
 
     /// need to wait on this group before deinitializing
     deinit_group: event.Group(void),
@@ -231,7 +231,7 @@ pub const Compilation = struct {
     // main_loop_frame: @Frame(Compilation.mainLoop),
     main_loop_future: event.Future(void),
 
-    have_err_ret_tracing: bool,
+    have_err_ret_tracing: bool = false,
 
     /// not locked because it is read-only
     primitive_type_table: TypeTable,
@@ -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);
@@ -392,43 +392,10 @@ pub const Compilation = struct {
 
             .name = undefined,
             .llvm_triple = undefined,
-
-            .version_major = 0,
-            .version_minor = 0,
-            .version_patch = 0,
-
-            .verbose_tokenize = false,
-            .verbose_ast_tree = false,
-            .verbose_ast_fmt = false,
-            .verbose_cimport = false,
-            .verbose_ir = false,
-            .verbose_llvm_ir = false,
-            .verbose_link = false,
-
-            .linker_script = null,
-            .out_h_path = null,
-            .is_test = false,
-            .each_lib_rpath = false,
-            .strip = false,
             .is_static = is_static,
-            .linker_rdynamic = false,
-            .clang_argv = [_][]const u8{},
-            .lib_dirs = [_][]const u8{},
-            .rpath_list = [_][]const u8{},
-            .assembly_files = [_][]const u8{},
-            .link_objects = [_][]const u8{},
             .fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()),
-            .windows_subsystem_windows = false,
-            .windows_subsystem_console = false,
             .link_libs_list = undefined,
-            .libc_link_lib = null,
-            .err_color = errmsg.Color.Auto,
-            .darwin_frameworks = [_][]const u8{},
-            .darwin_version_min = DarwinVersionMin.None,
-            .test_filters = [_][]const u8{},
-            .test_name_prefix = null,
-            .emit_file_type = Emit.Binary,
-            .link_out_file = null,
+
             .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),
@@ -458,11 +425,9 @@ pub const Compilation = struct {
             .root_package = undefined,
             .std_package = undefined,
 
-            .override_libc = null,
-            .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());
@@ -534,8 +499,8 @@ pub const Compilation = struct {
             comp.root_package = try Package.create(comp.arena(), ".", "");
         }
 
-        // comp.fs_watch = try fs.Watch(*Scope.Root).create(16);
-        // defer comp.fs_watch.destroy();
+        comp.fs_watch = try fs.Watch(*Scope.Root).init(allocator, 16);
+        defer comp.fs_watch.deinit();
 
         try comp.initTypes();
         defer comp.primitive_type_table.deinit();
@@ -559,7 +524,7 @@ pub const Compilation = struct {
     }
 
     /// it does ref the result because it could be an arbitrary integer size
-    pub async fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {
+    pub fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {
         if (name.len >= 2) {
             switch (name[0]) {
                 'i', 'u' => blk: {
@@ -795,47 +760,47 @@ pub const Compilation = struct {
                 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.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();
+            // 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 {
+    async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) BuildError!void {
         const tree_scope = blk: {
-            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 source_code = fs.readFile(
+                self.gpa(),
+                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 {
@@ -873,7 +838,7 @@ pub const Compilation = struct {
         try decl_group.wait();
     }
 
-    async fn rebuildChangedDecls(
+    fn rebuildChangedDecls(
         self: *Compilation,
         group: *event.Group(BuildError!void),
         locked_table: *Decl.Table,
@@ -962,7 +927,7 @@ pub const Compilation = struct {
         }
     }
 
-    async fn initialCompile(self: *Compilation) !void {
+    fn initialCompile(self: *Compilation) !void {
         if (self.root_src_path) |root_src_path| {
             const root_scope = blk: {
                 // TODO async/await std.fs.realpath
@@ -981,7 +946,7 @@ pub const Compilation = struct {
         }
     }
 
-    async fn maybeLink(self: *Compilation) !void {
+    fn maybeLink(self: *Compilation) !void {
         (self.prelink_group.wait()) catch |err| switch (err) {
             error.SemanticAnalysisFailed => {},
             else => return err,
@@ -1184,7 +1149,7 @@ 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 {
+    pub fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
         const tmp_dir = try self.getTmpDir();
         const file_prefix = self.getRandomFileName();
 
@@ -1200,14 +1165,14 @@ pub const Compilation = struct {
     /// If the temporary directory for this Compilation has not been created, creates it.
     /// Then returns it. The directory is unique to this Compilation and cleaned up when
     /// the Compilation deinitializes.
-    async fn getTmpDir(self: *Compilation) ![]const u8 {
+    fn getTmpDir(self: *Compilation) ![]const u8 {
         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 {
+    fn getTmpDirImpl(self: *Compilation) ![]u8 {
         const comp_dir_name = self.getRandomFileName();
         const zig_dir_path = try getZigDir(self.gpa());
         defer self.gpa().free(zig_dir_path);
@@ -1217,7 +1182,7 @@ pub const Compilation = struct {
         return tmp_dir;
     }
 
-    async fn getRandomFileName(self: *Compilation) [12]u8 {
+    fn getRandomFileName(self: *Compilation) [12]u8 {
         // here we replace the standard +/ with -_ so that it can be used in a file name
         const b64_fs_encoder = std.base64.Base64Encoder.init(
             "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
@@ -1243,7 +1208,7 @@ pub const Compilation = struct {
     }
 
     /// Returns a value which has been ref()'d once
-    async fn analyzeConstValue(
+    fn analyzeConstValue(
         comp: *Compilation,
         tree_scope: *Scope.AstTree,
         scope: *Scope,
@@ -1256,7 +1221,7 @@ pub const Compilation = struct {
         return analyzed_code.getCompTimeResult(comp);
     }
 
-    async fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {
+    fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {
         const meta_type = &Type.MetaType.get(comp).base;
         defer meta_type.base.deref(comp);
 
@@ -1287,7 +1252,7 @@ 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 {
+fn generateDecl(comp: *Compilation, decl: *Decl) !void {
     switch (decl.id) {
         .Var => @panic("TODO"),
         .Fn => {
@@ -1298,7 +1263,7 @@ async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
     }
 }
 
-async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
+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 generateDeclFnProto(comp, fn_decl);
@@ -1315,7 +1280,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
 
     // The Decl.Fn owns the initial 1 reference count
     const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
-    fn_decl.value = Decl.Fn.Val{ .Fn = fn_val };
+    fn_decl.value = .{ .Fn = fn_val };
     symbol_name_consumed = true;
 
     // Define local parameter variables
@@ -1382,7 +1347,7 @@ fn getZigDir(allocator: *mem.Allocator) ![]u8 {
     return std.fs.getAppDataDir(allocator, "zig");
 }
 
-async fn analyzeFnType(
+fn analyzeFnType(
     comp: *Compilation,
     tree_scope: *Scope.AstTree,
     scope: *Scope,
@@ -1444,7 +1409,7 @@ async fn analyzeFnType(
     return fn_type;
 }
 
-async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
+fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
     const fn_type = try analyzeFnType(
         comp,
         fn_decl.base.tree_scope,
@@ -1459,6 +1424,6 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
 
     // The Decl.Fn owns the initial 1 reference count
     const fn_proto_val = try Value.FnProto.create(comp, fn_type, symbol_name);
-    fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };
+    fn_decl.value = .{ .FnProto = fn_proto_val };
     symbol_name_consumed = true;
 }
src-self-hosted/decl.zig
@@ -69,15 +69,12 @@ pub const Decl = struct {
 
     pub const Fn = struct {
         base: Decl,
-        value: Val,
-        fn_proto: *ast.Node.FnProto,
-
-        // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
-        pub const Val = union(enum) {
+        value: union(enum) {
             Unresolved,
             Fn: *Value.Fn,
             FnProto: *Value.FnProto,
-        };
+        },
+        fn_proto: *ast.Node.FnProto,
 
         pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 {
             return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
src-self-hosted/ir.zig
@@ -110,7 +110,7 @@ pub const Inst = struct {
         unreachable;
     }
 
-    pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
+    pub fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
         switch (base.id) {
             .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
             .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
@@ -422,7 +422,7 @@ pub const Inst = struct {
             return false;
         }
 
-        pub async fn analyze(self: *const Ref, ira: *Analyze) !*Inst {
+        pub fn analyze(self: *const Ref, ira: *Analyze) !*Inst {
             const target = try self.params.target.getAsParam();
 
             if (ira.getCompTimeValOrNullUndefOk(target)) |val| {
@@ -472,7 +472,7 @@ pub const Inst = struct {
             return false;
         }
 
-        pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
+        pub fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
             (ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) {
                 error.OutOfMemory => return error.OutOfMemory,
                 else => return error.SemanticAnalysisFailed,
@@ -516,7 +516,7 @@ pub const Inst = struct {
             return false;
         }
 
-        pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
+        pub fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
             switch (self.params.var_scope.data) {
                 .Const => @panic("TODO"),
                 .Param => |param| {
@@ -563,7 +563,7 @@ pub const Inst = struct {
             return false;
         }
 
-        pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
+        pub fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
             const target = try self.params.target.getAsParam();
             const target_type = target.getKnownType();
             if (target_type.id != .Pointer) {
@@ -645,7 +645,7 @@ pub const Inst = struct {
             return false;
         }
 
-        pub async fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {
+        pub fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {
             const child_type = try self.params.child_type.getAsConstType(ira);
             // if (child_type->id == TypeTableEntryIdUnreachable) {
             //     ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
@@ -927,7 +927,7 @@ pub const Variable = struct {
 
 pub const BasicBlock = struct {
     ref_count: usize,
-    name_hint: [*]const u8, // must be a C string literal
+    name_hint: [*:0]const u8,
     debug_id: usize,
     scope: *Scope,
     instruction_list: std.ArrayList(*Inst),
@@ -1051,7 +1051,7 @@ pub const Builder = struct {
     }
 
     /// No need to clean up resources thanks to the arena allocator.
-    pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {
+    pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*:0]const u8) !*BasicBlock {
         const basic_block = try self.arena().create(BasicBlock);
         basic_block.* = BasicBlock{
             .ref_count = 0,
@@ -1186,6 +1186,7 @@ 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);
 
@@ -1214,7 +1215,7 @@ pub const Builder = struct {
         //return ir_lval_wrap(irb, scope, fn_call, lval);
     }
 
-    async fn genPtrType(
+    fn genPtrType(
         irb: *Builder,
         prefix_op: *ast.Node.PrefixOp,
         ptr_info: ast.Node.PrefixOp.PtrInfo,
@@ -1307,9 +1308,9 @@ pub const Builder = struct {
         var rest: []const u8 = undefined;
         if (int_token.len >= 3 and int_token[0] == '0') {
             base = switch (int_token[1]) {
-                'b' => u8(2),
-                'o' => u8(8),
-                'x' => u8(16),
+                'b' => 2,
+                'o' => 8,
+                'x' => 16,
                 else => unreachable,
             };
             rest = int_token[2..];
@@ -1339,7 +1340,7 @@ pub const Builder = struct {
         return inst;
     }
 
-    pub async fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {
+    pub fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {
         const str_token = irb.code.tree_scope.tree.tokenSlice(str_lit.token);
         const src_span = Span.token(str_lit.token);
 
@@ -1389,7 +1390,7 @@ pub const Builder = struct {
         }
     }
 
-    pub async fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
+    pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
         const block_scope = try Scope.Block.create(irb.comp, parent_scope);
 
         const outer_block_scope = &block_scope.base;
@@ -1499,7 +1500,7 @@ pub const Builder = struct {
         return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
     }
 
-    pub async fn genControlFlowExpr(
+    pub fn genControlFlowExpr(
         irb: *Builder,
         control_flow_expr: *ast.Node.ControlFlowExpression,
         scope: *Scope,
@@ -1596,7 +1597,7 @@ pub const Builder = struct {
         }
     }
 
-    pub async fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {
+    pub fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {
         const src_span = Span.token(identifier.token);
         const name = irb.code.tree_scope.tree.tokenSlice(identifier.token);
 
@@ -1694,7 +1695,7 @@ pub const Builder = struct {
         return result;
     }
 
-    async fn genDefersForBlock(
+    fn genDefersForBlock(
         irb: *Builder,
         inner_scope: *Scope,
         outer_scope: *Scope,
@@ -1797,7 +1798,7 @@ pub const Builder = struct {
         // Look at the params and ref() other instructions
         comptime var i = 0;
         inline while (i < @memberCount(I.Params)) : (i += 1) {
-            const FieldType = comptime @typeOf(@field(I.Params(undefined), @memberName(I.Params, i)));
+            const FieldType = comptime @typeOf(@field(@as(I.Params, undefined), @memberName(I.Params, i)));
             switch (FieldType) {
                 *Inst => @field(inst.params, @memberName(I.Params, i)).ref(self),
                 *BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self),
@@ -1909,7 +1910,7 @@ pub const Builder = struct {
         VarScope: *Scope.Var,
     };
 
-    async fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {
+    fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {
         var s = scope;
         while (true) {
             switch (s.id) {
@@ -2519,7 +2520,7 @@ const Analyze = struct {
     }
 };
 
-pub async fn gen(
+pub fn gen(
     comp: *Compilation,
     body_node: *ast.Node,
     tree_scope: *Scope.AstTree,
@@ -2541,7 +2542,7 @@ pub async fn gen(
     return irb.finish();
 }
 
-pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {
+pub fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {
     const old_entry_bb = old_code.basic_block_list.at(0);
 
     var ira = try Analyze.init(comp, old_code.tree_scope, expected_type);
src-self-hosted/libc_installation.zig
@@ -143,7 +143,7 @@ pub const LibCInstallation = struct {
     }
 
     /// Finds the default, native libc.
-    pub async fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
+    pub fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
         self.initEmpty();
         var group = event.Group(FindError!void).init(allocator);
         errdefer group.wait() catch {};
@@ -393,7 +393,7 @@ pub const LibCInstallation = struct {
 };
 
 /// caller owns returned memory
-async fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
+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(allocator, "-print-file-name={}", o_file);
     defer allocator.free(arg1);
src-self-hosted/link.zig
@@ -11,7 +11,7 @@ const util = @import("util.zig");
 const Context = struct {
     comp: *Compilation,
     arena: std.heap.ArenaAllocator,
-    args: std.ArrayList([*]const u8),
+    args: std.ArrayList([*:0]const u8),
     link_in_crt: bool,
 
     link_err: error{OutOfMemory}!void,
@@ -21,7 +21,7 @@ const Context = struct {
     out_file_path: std.Buffer,
 };
 
-pub async fn link(comp: *Compilation) !void {
+pub fn link(comp: *Compilation) !void {
     var ctx = Context{
         .comp = comp,
         .arena = std.heap.ArenaAllocator.init(comp.gpa()),
@@ -33,7 +33,7 @@ pub async fn link(comp: *Compilation) !void {
         .out_file_path = undefined,
     };
     defer ctx.arena.deinit();
-    ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);
+    ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
     ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
 
     if (comp.link_out_file) |out_file| {
@@ -171,7 +171,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
     //}
 
     try ctx.args.append("-o");
-    try ctx.args.append(ctx.out_file_path.ptr());
+    try ctx.args.append(ctx.out_file_path.toSliceConst());
 
     if (ctx.link_in_crt) {
         const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
@@ -214,10 +214,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
 
     if (ctx.comp.haveLibC()) {
         try ctx.args.append("-L");
-        try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
+        // TODO addNullByte should probably return [:0]u8
+        try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr));
 
         try ctx.args.append("-L");
-        try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr));
 
         if (!ctx.comp.is_static) {
             const dl = blk: {
@@ -226,7 +227,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
                 return error.LibCMissingDynamicLinker;
             };
             try ctx.args.append("-dynamic-linker");
-            try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
+            try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
         }
     }
 
@@ -238,7 +239,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
     // .o files
     for (ctx.comp.link_objects) |link_object| {
         const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
-        try ctx.args.append(link_obj_with_null.ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
     }
     try addFnObjects(ctx);
 
@@ -313,7 +314,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
 fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
     const full_path = try std.fs.path.join(&ctx.arena.allocator, [_][]const u8{ dirname, basename });
     const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
-    try ctx.args.append(full_path_with_null.ptr);
+    try ctx.args.append(@ptrCast([*:0]const u8, full_path_with_null.ptr));
 }
 
 fn constructLinkerArgsCoff(ctx: *Context) !void {
@@ -339,12 +340,12 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
     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);
+    try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
 
     if (ctx.comp.haveLibC()) {
-        try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr);
-        try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr);
-        try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr));
+        try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr));
+        try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr));
     }
 
     if (ctx.link_in_crt) {
@@ -353,17 +354,17 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
 
         if (ctx.comp.is_static) {
             const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);
-            try ctx.args.append(cmt_lib_name.ptr);
+            try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
         } else {
             const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", d_str);
-            try ctx.args.append(msvcrt_lib_name.ptr);
+            try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
         }
 
         const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", lib_str, d_str);
-        try ctx.args.append(vcruntime_lib_name.ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
 
         const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", lib_str, d_str);
-        try ctx.args.append(crt_lib_name.ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
 
         // Visual C++ 2015 Conformance Changes
         // https://msdn.microsoft.com/en-us/library/bb531344.aspx
@@ -395,7 +396,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
 
     for (ctx.comp.link_objects) |link_object| {
         const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
-        try ctx.args.append(link_obj_with_null.ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
     }
     try addFnObjects(ctx);
 
@@ -504,11 +505,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
     //}
 
     try ctx.args.append("-arch");
-    const darwin_arch_str = try std.cstr.addNullByte(
-        &ctx.arena.allocator,
-        ctx.comp.target.getDarwinArchString(),
-    );
-    try ctx.args.append(darwin_arch_str.ptr);
+    try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
 
     const platform = try DarwinPlatform.get(ctx.comp);
     switch (platform.kind) {
@@ -517,7 +514,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
         .IPhoneOSSimulator => try ctx.args.append("-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);
+    try ctx.args.append(@ptrCast([*:0]const u8, ver_str.ptr));
 
     if (ctx.comp.kind == .Exe) {
         if (ctx.comp.is_static) {
@@ -528,7 +525,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
     }
 
     try ctx.args.append("-o");
-    try ctx.args.append(ctx.out_file_path.ptr());
+    try ctx.args.append(ctx.out_file_path.toSliceConst());
 
     //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
     //    Buf *rpath = g->rpath_list.at(i);
@@ -572,7 +569,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
 
     for (ctx.comp.link_objects) |link_object| {
         const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
-        try ctx.args.append(link_obj_with_null.ptr);
+        try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
     }
     try addFnObjects(ctx);
 
@@ -593,10 +590,10 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
             } else {
                 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
                     const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
-                    try ctx.args.append(arg.ptr);
+                    try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
                 } else {
                     const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
-                    try ctx.args.append(arg.ptr);
+                    try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
                 }
             }
         }
@@ -639,7 +636,7 @@ fn addFnObjects(ctx: *Context) !void {
             ctx.comp.gpa().destroy(node);
             continue;
         };
-        try ctx.args.append(fn_val.containing_object.ptr());
+        try ctx.args.append(fn_val.containing_object.toSliceConst());
         it = node.next;
     }
 }
src-self-hosted/llvm.zig
@@ -86,7 +86,7 @@ pub const AddGlobal = LLVMAddGlobal;
 extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value;
 
 pub const ConstStringInContext = LLVMConstStringInContext;
-extern fn LLVMConstStringInContext(C: *Context, Str: [*:0]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
+extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
 
 pub const ConstInt = LLVMConstInt;
 extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
src-self-hosted/main.zig
@@ -126,7 +126,8 @@ pub fn main() !void {
 
     try stderr.print("unknown command: {}\n\n", args[1]);
     try stderr.write(usage);
-    process.exit(1);
+    process.argsFree(allocator, args);
+    defer process.exit(1);
 }
 
 const usage_build_generic =
@@ -461,13 +462,12 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
     comp.link_objects = link_objects;
 
     comp.start();
-    const frame = async processBuildEvents(comp, color);
+    processBuildEvents(comp, color);
 }
 
-async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
+fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
     var count: usize = 0;
-    while (true) {
-        // TODO directly awaiting async should guarantee memory allocation elision
+    while (true) { // TODO(Vexu)
         const build_event = comp.events.get();
         count += 1;
 
@@ -567,10 +567,6 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
     var zig_compiler = try ZigCompiler.init(allocator);
     defer zig_compiler.deinit();
 
-    const frame = async findLibCAsync(&zig_compiler);
-}
-
-async fn findLibCAsync(zig_compiler: *ZigCompiler) void {
     const libc = zig_compiler.getNativeLibC() catch |err| {
         stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);
         process.exit(1);
@@ -644,11 +640,23 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
         process.exit(1);
     }
 
-    return asyncFmtMain(
-        allocator,
-        &flags,
-        color,
-    );
+    var fmt = Fmt{
+        .allocator = allocator,
+        .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
+        .any_error = false,
+        .color = color,
+    };
+
+    const check_mode = flags.present("check");
+
+    var group = event.Group(FmtError!void).init(allocator);
+    for (flags.positionals.toSliceConst()) |file_path| {
+        try group.call(fmtPath, &fmt, file_path, check_mode);
+    }
+    try group.wait();
+    if (fmt.any_error) {
+        process.exit(1);
+    }
 }
 
 const FmtError = error{
@@ -673,30 +681,6 @@ const FmtError = error{
     CurrentWorkingDirectoryUnlinked,
 } || fs.File.OpenError;
 
-async fn asyncFmtMain(
-    allocator: *Allocator,
-    flags: *const Args,
-    color: errmsg.Color,
-) FmtError!void {
-    var fmt = Fmt{
-        .allocator = allocator,
-        .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
-        .any_error = false,
-        .color = color,
-    };
-
-    const check_mode = flags.present("check");
-
-    var group = event.Group(FmtError!void).init(allocator);
-    for (flags.positionals.toSliceConst()) |file_path| {
-        try group.call(fmtPath, &fmt, file_path, check_mode);
-    }
-    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.allocator, u8, file_path_ref);
     defer fmt.allocator.free(file_path);
@@ -708,33 +692,33 @@ 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 = "";
-    // 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.cwd().openDirList(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 source_code = event.fs.readFile(
+        fmt.allocator,
+        file_path,
+        max_src_size,
+    ) catch |err| switch (err) {
+        error.IsDir, error.AccessDenied => {
+            var dir = try fs.Dir.cwd().openDirList(file_path);
+            defer dir.close();
+
+            var group = event.Group(FmtError!void).init(fmt.allocator);
+            var it = dir.iterate();
+            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);
+                }
+            }
+            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);
src-self-hosted/test.zig
@@ -116,7 +116,7 @@ pub const TestContext = struct {
         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 output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (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);
         }
@@ -148,15 +148,12 @@ pub const TestContext = struct {
         exe_file: []const u8,
         expected_output: []const u8,
     ) 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 = comp.events.get();
 
         switch (build_event) {
             .Ok => {
-                const argv = [_][]const u8{exe_file_2};
+                const argv = [_][]const u8{exe_file};
                 // TODO use event loop
                 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
                 switch (child.term) {
@@ -173,8 +170,8 @@ pub const TestContext = struct {
                     return error.OutputMismatch;
                 }
             },
-            Compilation.Event.Error => |err| return err,
-            Compilation.Event.Fail => |msgs| {
+            .Error => |err| return err,
+            .Fail => |msgs| {
                 const stderr = std.io.getStdErr();
                 try stderr.write("build incorrectly failed:\n");
                 for (msgs) |msg| {
src-self-hosted/type.zig
@@ -53,7 +53,7 @@ pub const Type = struct {
         base: *Type,
         allocator: *Allocator,
         llvm_context: *llvm.Context,
-    ) (error{OutOfMemory}!*llvm.Type) {
+    ) error{OutOfMemory}!*llvm.Type {
         switch (base.id) {
             .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
             .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
@@ -184,7 +184,7 @@ pub const Type = struct {
 
     /// 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 {
+    pub fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {
         if (base.abi_alignment.start()) |ptr| return ptr.*;
 
         {
@@ -200,7 +200,7 @@ 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 {
+    pub fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
         if (base.abi_alignment.start()) |ptr| return ptr.*;
 
         base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);
@@ -209,7 +209,7 @@ pub const Type = struct {
     }
 
     /// Lower level function that does the work. See getAbiAlignment.
-    async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
+    fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
         const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
         return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
     }
@@ -367,7 +367,7 @@ pub const Type = struct {
         }
 
         /// takes ownership of key.Normal.params on success
-        pub async fn get(comp: *Compilation, key: Key) !*Fn {
+        pub fn get(comp: *Compilation, key: Key) !*Fn {
             {
                 const held = comp.fn_type_table.acquire();
                 defer held.release();
@@ -564,7 +564,7 @@ pub const Type = struct {
             return comp.u8_type;
         }
 
-        pub async fn get(comp: *Compilation, key: Key) !*Int {
+        pub fn get(comp: *Compilation, key: Key) !*Int {
             {
                 const held = comp.int_type_table.acquire();
                 defer held.release();
@@ -606,7 +606,7 @@ pub const Type = struct {
             comp.registerGarbage(Int, &self.garbage_node);
         }
 
-        pub async fn gcDestroy(self: *Int, comp: *Compilation) void {
+        pub fn gcDestroy(self: *Int, comp: *Compilation) void {
             {
                 const held = comp.int_type_table.acquire();
                 defer held.release();
@@ -700,7 +700,7 @@ pub const Type = struct {
             comp.registerGarbage(Pointer, &self.garbage_node);
         }
 
-        pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {
+        pub fn gcDestroy(self: *Pointer, comp: *Compilation) void {
             {
                 const held = comp.ptr_type_table.acquire();
                 defer held.release();
@@ -711,14 +711,14 @@ pub const Type = struct {
             comp.gpa().destroy(self);
         }
 
-        pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
+        pub fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
             switch (self.key.alignment) {
                 .Abi => return self.key.child_type.getAbiAlignment(comp),
                 .Override => |alignment| return alignment,
             }
         }
 
-        pub async fn get(
+        pub fn get(
             comp: *Compilation,
             key: Key,
         ) !*Pointer {
@@ -828,7 +828,7 @@ pub const Type = struct {
             comp.gpa().destroy(self);
         }
 
-        pub async fn get(comp: *Compilation, key: Key) !*Array {
+        pub fn get(comp: *Compilation, key: Key) !*Array {
             key.elem_type.base.ref();
             errdefer key.elem_type.base.deref(comp);
 
src-self-hosted/util.zig
@@ -32,21 +32,21 @@ pub fn getFloatAbi(self: Target) FloatAbi {
     };
 }
 
-pub fn getObjectFormat(self: Target) Target.ObjectFormat {
-    return switch (self) {
-        .Native => @import("builtin").object_format,
-        .Cross => {
+pub fn getObjectFormat(target: Target) Target.ObjectFormat {
+    switch (target) {
+        .Native => return @import("builtin").object_format,
+        .Cross => blk: {
             if (target.isWindows() or target.isUefi()) {
-                break .coff;
+                return .coff;
             } else if (target.isDarwin()) {
-                break .macho;
+                return .macho;
             }
             if (target.isWasm()) {
-                break .wasm;
+                return .wasm;
             }
-            break .elf;
+            return .elf;
         },
-    };
+    }
 }
 
 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
@@ -156,7 +156,7 @@ pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
     }
 }
 
-pub fn getDarwinArchString(self: Target) []const u8 {
+pub fn getDarwinArchString(self: Target) [:0]const u8 {
     const arch = self.getArch();
     switch (arch) {
         .aarch64 => return "arm64",
@@ -166,7 +166,8 @@ pub fn getDarwinArchString(self: Target) []const u8 {
         .powerpc => return "ppc",
         .powerpc64 => return "ppc64",
         .powerpc64le => return "ppc64le",
-        else => return @tagName(arch),
+        // @tagName should be able to return sentinel terminated slice
+        else => @panic("TODO"), //return @tagName(arch),
     }
 }
 
src-self-hosted/value.zig
@@ -156,7 +156,7 @@ pub const Value = struct {
             const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
             const llvm_fn = llvm.AddFunction(
                 ofile.module,
-                self.symbol_name.ptr(),
+                self.symbol_name.toSliceConst(),
                 llvm_fn_type,
             ) orelse return error.OutOfMemory;
 
@@ -241,7 +241,7 @@ pub const Value = struct {
             const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
             const llvm_fn = llvm.AddFunction(
                 ofile.module,
-                self.symbol_name.ptr(),
+                self.symbol_name.toSliceConst(),
                 llvm_fn_type,
             ) orelse return error.OutOfMemory;
 
@@ -334,7 +334,7 @@ pub const Value = struct {
             field_index: usize,
         };
 
-        pub async fn createArrayElemPtr(
+        pub fn createArrayElemPtr(
             comp: *Compilation,
             array_val: *Array,
             mut: Type.Pointer.Mut,
@@ -390,13 +390,13 @@ pub const Value = struct {
                     const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
                     const ptr_bit_count = ofile.comp.target_ptr_bits;
                     const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
-                    const indices = [_]*llvm.Value{
+                    var indices = [_]*llvm.Value{
                         llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
                         llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
                     };
                     return llvm.ConstInBoundsGEP(
                         array_llvm_value,
-                        &indices,
+                        @ptrCast([*]*llvm.Value, &indices),
                         @intCast(c_uint, indices.len),
                     ) orelse return error.OutOfMemory;
                 },
@@ -423,7 +423,7 @@ pub const Value = struct {
         };
 
         /// Takes ownership of buffer
-        pub async fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {
+        pub fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {
             const u8_type = Type.Int.get_u8(comp);
             defer u8_type.base.base.deref(comp);