authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-27 13:38:49-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-27 13:38:49-05:00
log83c664eaa080669cff83f7c30046376f3399eafb
tree06cccc09052be4459e924d04a867ff34a889d87c
parent63300a21ddf4cfe209a39796c6d7ea7773e14fd6
parent4d8a8e65df79ddd5edf52f961552036ccfca6e8e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3780 from Vexu/stage2-async-review

Update use of async functions in self hosted compiler

13 files changed, 346 insertions(+), 368 deletions(-)

lib/std/event/fs.zig+15-13
...@@ -735,24 +735,26 @@ pub fn Watch(comptime V: type) type {...@@ -735,24 +735,26 @@ pub fn Watch(comptime V: type) type {
735 allocator: *Allocator,735 allocator: *Allocator,
736736
737 const OsData = switch (builtin.os) {737 const OsData = switch (builtin.os) {
738 .macosx, .freebsd, .netbsd, .dragonfly => struct {738 // TODO https://github.com/ziglang/zig/issues/3778
739 file_table: FileTable,739 .macosx, .freebsd, .netbsd, .dragonfly => KqOsData,
740 table_lock: event.Lock,
741
742 const FileTable = std.StringHashMap(*Put);
743 const Put = struct {
744 putter_frame: @Frame(kqPutEvents),
745 cancelled: bool = false,
746 value: V,
747 };
748 },
749
750 .linux => LinuxOsData,740 .linux => LinuxOsData,
751 .windows => WindowsOsData,741 .windows => WindowsOsData,
752742
753 else => @compileError("Unsupported OS"),743 else => @compileError("Unsupported OS"),
754 };744 };
755745
746 const KqOsData = struct {
747 file_table: FileTable,
748 table_lock: event.Lock,
749
750 const FileTable = std.StringHashMap(*Put);
751 const Put = struct {
752 putter_frame: @Frame(kqPutEvents),
753 cancelled: bool = false,
754 value: V,
755 };
756 };
757
756 const WindowsOsData = struct {758 const WindowsOsData = struct {
757 table_lock: event.Lock,759 table_lock: event.Lock,
758 dir_table: DirTable,760 dir_table: DirTable,
...@@ -1291,7 +1293,7 @@ pub fn Watch(comptime V: type) type {...@@ -1291,7 +1293,7 @@ pub fn Watch(comptime V: type) type {
1291 os.linux.EINVAL => unreachable,1293 os.linux.EINVAL => unreachable,
1292 os.linux.EFAULT => unreachable,1294 os.linux.EFAULT => unreachable,
1293 os.linux.EAGAIN => {1295 os.linux.EAGAIN => {
1294 global_event_loop.linuxWaitFd(self.os_data.inotify_fd, os.linux.EPOLLET | os.linux.EPOLLIN);1296 global_event_loop.linuxWaitFd(self.os_data.inotify_fd, os.linux.EPOLLET | os.linux.EPOLLIN | os.EPOLLONESHOT);
1295 },1297 },
1296 else => unreachable,1298 else => unreachable,
1297 }1299 }
src-self-hosted/codegen.zig+15-15
...@@ -25,10 +25,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -25,10 +25,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
2525
26 const context = llvm_handle.node.data;26 const context = llvm_handle.node.data;
2727
28 const module = llvm.ModuleCreateWithNameInContext(comp.name.ptr(), context) orelse return error.OutOfMemory;28 const module = llvm.ModuleCreateWithNameInContext(comp.name.toSliceConst(), context) orelse return error.OutOfMemory;
29 defer llvm.DisposeModule(module);29 defer llvm.DisposeModule(module);
3030
31 llvm.SetTarget(module, comp.llvm_triple.ptr());31 llvm.SetTarget(module, comp.llvm_triple.toSliceConst());
32 llvm.SetDataLayout(module, comp.target_layout_str);32 llvm.SetDataLayout(module, comp.target_layout_str);
3333
34 if (util.getObjectFormat(comp.target) == .coff) {34 if (util.getObjectFormat(comp.target) == .coff) {
...@@ -48,23 +48,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -48,23 +48,23 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
48 const producer = try std.Buffer.allocPrint(48 const producer = try std.Buffer.allocPrint(
49 &code.arena.allocator,49 &code.arena.allocator,
50 "zig {}.{}.{}",50 "zig {}.{}.{}",
51 u32(c.ZIG_VERSION_MAJOR),51 @as(u32, c.ZIG_VERSION_MAJOR),
52 u32(c.ZIG_VERSION_MINOR),52 @as(u32, c.ZIG_VERSION_MINOR),
53 u32(c.ZIG_VERSION_PATCH),53 @as(u32, c.ZIG_VERSION_PATCH),
54 );54 );
55 const flags = "";55 const flags = "";
56 const runtime_version = 0;56 const runtime_version = 0;
57 const compile_unit_file = llvm.CreateFile(57 const compile_unit_file = llvm.CreateFile(
58 dibuilder,58 dibuilder,
59 comp.name.ptr(),59 comp.name.toSliceConst(),
60 comp.root_package.root_src_dir.ptr(),60 comp.root_package.root_src_dir.toSliceConst(),
61 ) orelse return error.OutOfMemory;61 ) orelse return error.OutOfMemory;
62 const is_optimized = comp.build_mode != .Debug;62 const is_optimized = comp.build_mode != .Debug;
63 const compile_unit = llvm.CreateCompileUnit(63 const compile_unit = llvm.CreateCompileUnit(
64 dibuilder,64 dibuilder,
65 DW.LANG_C99,65 DW.LANG_C99,
66 compile_unit_file,66 compile_unit_file,
67 producer.ptr(),67 producer.toSliceConst(),
68 is_optimized,68 is_optimized,
69 flags,69 flags,
70 runtime_version,70 runtime_version,
...@@ -99,7 +99,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -99,7 +99,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
9999
100 // verify the llvm module when safety is on100 // verify the llvm module when safety is on
101 if (std.debug.runtime_safety) {101 if (std.debug.runtime_safety) {
102 var error_ptr: ?[*]u8 = null;102 var error_ptr: ?[*:0]u8 = null;
103 _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);103 _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
104 }104 }
105105
...@@ -108,12 +108,12 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -108,12 +108,12 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
108 const is_small = comp.build_mode == .ReleaseSmall;108 const is_small = comp.build_mode == .ReleaseSmall;
109 const is_debug = comp.build_mode == .Debug;109 const is_debug = comp.build_mode == .Debug;
110110
111 var err_msg: [*]u8 = undefined;111 var err_msg: [*:0]u8 = undefined;
112 // TODO integrate this with evented I/O112 // TODO integrate this with evented I/O
113 if (llvm.TargetMachineEmitToFile(113 if (llvm.TargetMachineEmitToFile(
114 comp.target_machine,114 comp.target_machine,
115 module,115 module,
116 output_path.ptr(),116 output_path.toSliceConst(),
117 llvm.EmitBinary,117 llvm.EmitBinary,
118 &err_msg,118 &err_msg,
119 is_debug,119 is_debug,
...@@ -154,7 +154,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -154,7 +154,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
154 const llvm_fn_type = try fn_val.base.typ.getLlvmType(ofile.arena, ofile.context);154 const llvm_fn_type = try fn_val.base.typ.getLlvmType(ofile.arena, ofile.context);
155 const llvm_fn = llvm.AddFunction(155 const llvm_fn = llvm.AddFunction(
156 ofile.module,156 ofile.module,
157 fn_val.symbol_name.ptr(),157 fn_val.symbol_name.toSliceConst(),
158 llvm_fn_type,158 llvm_fn_type,
159 ) orelse return error.OutOfMemory;159 ) orelse return error.OutOfMemory;
160160
...@@ -379,7 +379,7 @@ fn renderLoadUntyped(...@@ -379,7 +379,7 @@ fn renderLoadUntyped(
379 ptr: *llvm.Value,379 ptr: *llvm.Value,
380 alignment: Type.Pointer.Align,380 alignment: Type.Pointer.Align,
381 vol: Type.Pointer.Vol,381 vol: Type.Pointer.Vol,
382 name: [*]const u8,382 name: [*:0]const u8,
383) !*llvm.Value {383) !*llvm.Value {
384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385 switch (vol) {385 switch (vol) {
...@@ -390,7 +390,7 @@ fn renderLoadUntyped(...@@ -390,7 +390,7 @@ fn renderLoadUntyped(
390 return result;390 return result;
391}391}
392392
393fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {393fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*:0]const u8) !*llvm.Value {
394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);394 return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
395}395}
396396
...@@ -438,7 +438,7 @@ pub fn renderAlloca(...@@ -438,7 +438,7 @@ pub fn renderAlloca(
438) !*llvm.Value {438) !*llvm.Value {
439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);439 const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);440 const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;441 const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, @ptrCast([*:0]const u8, name_with_null.ptr)) orelse return error.OutOfMemory;
442 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm_var_type));442 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm_var_type));
443 return result;443 return result;
444}444}
src-self-hosted/compilation.zig+130-149
...@@ -93,7 +93,7 @@ pub const ZigCompiler = struct {...@@ -93,7 +93,7 @@ pub const ZigCompiler = struct {
93 return LlvmHandle{ .node = node };93 return LlvmHandle{ .node = node };
94 }94 }
9595
96 pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {96 pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
97 if (self.native_libc.start()) |ptr| return ptr;97 if (self.native_libc.start()) |ptr| return ptr;
98 try self.native_libc.data.findNative(self.allocator);98 try self.native_libc.data.findNative(self.allocator);
99 self.native_libc.resolve();99 self.native_libc.resolve();
...@@ -133,62 +133,62 @@ pub const Compilation = struct {...@@ -133,62 +133,62 @@ pub const Compilation = struct {
133 zig_std_dir: []const u8,133 zig_std_dir: []const u8,
134134
135 /// lazily created when we need it135 /// lazily created when we need it
136 tmp_dir: event.Future(BuildError![]u8),136 tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),
137137
138 version_major: u32,138 version_major: u32 = 0,
139 version_minor: u32,139 version_minor: u32 = 0,
140 version_patch: u32,140 version_patch: u32 = 0,
141141
142 linker_script: ?[]const u8,142 linker_script: ?[]const u8 = null,
143 out_h_path: ?[]const u8,143 out_h_path: ?[]const u8 = null,
144144
145 is_test: bool,145 is_test: bool = false,
146 each_lib_rpath: bool,146 each_lib_rpath: bool = false,
147 strip: bool,147 strip: bool = false,
148 is_static: bool,148 is_static: bool,
149 linker_rdynamic: bool,149 linker_rdynamic: bool = false,
150150
151 clang_argv: []const []const u8,151 clang_argv: []const []const u8 = [_][]const u8{},
152 lib_dirs: []const []const u8,152 lib_dirs: []const []const u8 = [_][]const u8{},
153 rpath_list: []const []const u8,153 rpath_list: []const []const u8 = [_][]const u8{},
154 assembly_files: []const []const u8,154 assembly_files: []const []const u8 = [_][]const u8{},
155155
156 /// paths that are explicitly provided by the user to link against156 /// paths that are explicitly provided by the user to link against
157 link_objects: []const []const u8,157 link_objects: []const []const u8 = [_][]const u8{},
158158
159 /// functions that have their own objects that we need to link159 /// functions that have their own objects that we need to link
160 /// it uses an optional pointer so that tombstone removals are possible160 /// it uses an optional pointer so that tombstone removals are possible
161 fn_link_set: event.Locked(FnLinkSet),161 fn_link_set: event.Locked(FnLinkSet) = event.Locked(FnLinkSet).init(FnLinkSet.init()),
162162
163 pub const FnLinkSet = std.TailQueue(?*Value.Fn);163 pub const FnLinkSet = std.TailQueue(?*Value.Fn);
164164
165 windows_subsystem_windows: bool,165 windows_subsystem_windows: bool = false,
166 windows_subsystem_console: bool,166 windows_subsystem_console: bool = false,
167167
168 link_libs_list: ArrayList(*LinkLib),168 link_libs_list: ArrayList(*LinkLib),
169 libc_link_lib: ?*LinkLib,169 libc_link_lib: ?*LinkLib = null,
170170
171 err_color: errmsg.Color,171 err_color: errmsg.Color = .Auto,
172172
173 verbose_tokenize: bool,173 verbose_tokenize: bool = false,
174 verbose_ast_tree: bool,174 verbose_ast_tree: bool = false,
175 verbose_ast_fmt: bool,175 verbose_ast_fmt: bool = false,
176 verbose_cimport: bool,176 verbose_cimport: bool = false,
177 verbose_ir: bool,177 verbose_ir: bool = false,
178 verbose_llvm_ir: bool,178 verbose_llvm_ir: bool = false,
179 verbose_link: bool,179 verbose_link: bool = false,
180180
181 darwin_frameworks: []const []const u8,181 darwin_frameworks: []const []const u8 = [_][]const u8{},
182 darwin_version_min: DarwinVersionMin,182 darwin_version_min: DarwinVersionMin = .None,
183183
184 test_filters: []const []const u8,184 test_filters: []const []const u8 = [_][]const u8{},
185 test_name_prefix: ?[]const u8,185 test_name_prefix: ?[]const u8 = null,
186186
187 emit_file_type: Emit,187 emit_file_type: Emit = .Binary,
188188
189 kind: Kind,189 kind: Kind,
190190
191 link_out_file: ?[]const u8,191 link_out_file: ?[]const u8 = null,
192 events: *event.Channel(Event),192 events: *event.Channel(Event),
193193
194 exported_symbol_names: event.Locked(Decl.Table),194 exported_symbol_names: event.Locked(Decl.Table),
...@@ -213,7 +213,7 @@ pub const Compilation = struct {...@@ -213,7 +213,7 @@ pub const Compilation = struct {
213213
214 target_machine: *llvm.TargetMachine,214 target_machine: *llvm.TargetMachine,
215 target_data_ref: *llvm.TargetData,215 target_data_ref: *llvm.TargetData,
216 target_layout_str: [*]u8,216 target_layout_str: [*:0]u8,
217 target_ptr_bits: u32,217 target_ptr_bits: u32,
218218
219 /// for allocating things which have the same lifetime as this Compilation219 /// for allocating things which have the same lifetime as this Compilation
...@@ -222,16 +222,16 @@ pub const Compilation = struct {...@@ -222,16 +222,16 @@ pub const Compilation = struct {
222 root_package: *Package,222 root_package: *Package,
223 std_package: *Package,223 std_package: *Package,
224224
225 override_libc: ?*LibCInstallation,225 override_libc: ?*LibCInstallation = null,
226226
227 /// need to wait on this group before deinitializing227 /// need to wait on this group before deinitializing
228 deinit_group: event.Group(void),228 deinit_group: event.Group(void),
229229
230 // destroy_frame: @Frame(createAsync),230 destroy_frame: *@Frame(createAsync),
231 // main_loop_frame: @Frame(Compilation.mainLoop),231 main_loop_frame: *@Frame(Compilation.mainLoop),
232 main_loop_future: event.Future(void),232 main_loop_future: event.Future(void) = event.Future(void).init(),
233233
234 have_err_ret_tracing: bool,234 have_err_ret_tracing: bool = false,
235235
236 /// not locked because it is read-only236 /// not locked because it is read-only
237 primitive_type_table: TypeTable,237 primitive_type_table: TypeTable,
...@@ -243,7 +243,9 @@ pub const Compilation = struct {...@@ -243,7 +243,9 @@ pub const Compilation = struct {
243243
244 c_int_types: [CInt.list.len]*Type.Int,244 c_int_types: [CInt.list.len]*Type.Int,
245245
246 // fs_watch: *fs.Watch(*Scope.Root),246 fs_watch: *fs.Watch(*Scope.Root),
247
248 cancelled: bool = false,
247249
248 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);250 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);
249 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);251 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);
...@@ -348,7 +350,9 @@ pub const Compilation = struct {...@@ -348,7 +350,9 @@ pub const Compilation = struct {
348 zig_lib_dir: []const u8,350 zig_lib_dir: []const u8,
349 ) !*Compilation {351 ) !*Compilation {
350 var optional_comp: ?*Compilation = null;352 var optional_comp: ?*Compilation = null;
351 var frame = async createAsync(353 var frame = try zig_compiler.allocator.create(@Frame(createAsync));
354 errdefer zig_compiler.allocator.destroy(frame);
355 frame.* = async createAsync(
352 &optional_comp,356 &optional_comp,
353 zig_compiler,357 zig_compiler,
354 name,358 name,
...@@ -359,7 +363,11 @@ pub const Compilation = struct {...@@ -359,7 +363,11 @@ pub const Compilation = struct {
359 is_static,363 is_static,
360 zig_lib_dir,364 zig_lib_dir,
361 );365 );
362 return optional_comp orelse if (await frame) |_| unreachable else |err| err;366 // TODO causes segfault
367 // return optional_comp orelse if (await frame) |_| unreachable else |err| err;
368 if (optional_comp) |comp| {
369 return comp;
370 } else if (await frame) |_| unreachable else |err| return err;
363 }371 }
364372
365 async fn createAsync(373 async fn createAsync(
...@@ -385,50 +393,14 @@ pub const Compilation = struct {...@@ -385,50 +393,14 @@ pub const Compilation = struct {
385 .build_mode = build_mode,393 .build_mode = build_mode,
386 .zig_lib_dir = zig_lib_dir,394 .zig_lib_dir = zig_lib_dir,
387 .zig_std_dir = undefined,395 .zig_std_dir = undefined,
388 .tmp_dir = event.Future(BuildError![]u8).init(),396 .destroy_frame = @frame(),
389 // .destroy_frame = @frame(),397 .main_loop_frame = undefined,
390 // .main_loop_frame = undefined,
391 .main_loop_future = event.Future(void).init(),
392398
393 .name = undefined,399 .name = undefined,
394 .llvm_triple = undefined,400 .llvm_triple = undefined,
395
396 .version_major = 0,
397 .version_minor = 0,
398 .version_patch = 0,
399
400 .verbose_tokenize = false,
401 .verbose_ast_tree = false,
402 .verbose_ast_fmt = false,
403 .verbose_cimport = false,
404 .verbose_ir = false,
405 .verbose_llvm_ir = false,
406 .verbose_link = false,
407
408 .linker_script = null,
409 .out_h_path = null,
410 .is_test = false,
411 .each_lib_rpath = false,
412 .strip = false,
413 .is_static = is_static,401 .is_static = is_static,
414 .linker_rdynamic = false,
415 .clang_argv = [_][]const u8{},
416 .lib_dirs = [_][]const u8{},
417 .rpath_list = [_][]const u8{},
418 .assembly_files = [_][]const u8{},
419 .link_objects = [_][]const u8{},
420 .fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()),
421 .windows_subsystem_windows = false,
422 .windows_subsystem_console = false,
423 .link_libs_list = undefined,402 .link_libs_list = undefined,
424 .libc_link_lib = null,403
425 .err_color = errmsg.Color.Auto,
426 .darwin_frameworks = [_][]const u8{},
427 .darwin_version_min = DarwinVersionMin.None,
428 .test_filters = [_][]const u8{},
429 .test_name_prefix = null,
430 .emit_file_type = Emit.Binary,
431 .link_out_file = null,
432 .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),404 .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),
433 .prelink_group = event.Group(BuildError!void).init(allocator),405 .prelink_group = event.Group(BuildError!void).init(allocator),
434 .deinit_group = event.Group(void).init(allocator),406 .deinit_group = event.Group(void).init(allocator),
...@@ -458,11 +430,9 @@ pub const Compilation = struct {...@@ -458,11 +430,9 @@ pub const Compilation = struct {
458 .root_package = undefined,430 .root_package = undefined,
459 .std_package = undefined,431 .std_package = undefined,
460432
461 .override_libc = null,
462 .have_err_ret_tracing = false,
463 .primitive_type_table = undefined,433 .primitive_type_table = undefined,
464434
465 // .fs_watch = undefined,435 .fs_watch = undefined,
466 };436 };
467 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());437 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());
468 comp.primitive_type_table = TypeTable.init(comp.arena());438 comp.primitive_type_table = TypeTable.init(comp.arena());
...@@ -534,13 +504,16 @@ pub const Compilation = struct {...@@ -534,13 +504,16 @@ pub const Compilation = struct {
534 comp.root_package = try Package.create(comp.arena(), ".", "");504 comp.root_package = try Package.create(comp.arena(), ".", "");
535 }505 }
536506
537 // comp.fs_watch = try fs.Watch(*Scope.Root).create(16);507 comp.fs_watch = try fs.Watch(*Scope.Root).init(allocator, 16);
538 // defer comp.fs_watch.destroy();508 defer comp.fs_watch.deinit();
539509
540 try comp.initTypes();510 try comp.initTypes();
541 defer comp.primitive_type_table.deinit();511 defer comp.primitive_type_table.deinit();
542512
543 // comp.main_loop_frame = async comp.mainLoop();513 comp.main_loop_frame = try allocator.create(@Frame(mainLoop));
514 defer allocator.destroy(comp.main_loop_frame);
515
516 comp.main_loop_frame.* = async comp.mainLoop();
544 // Set this to indicate that initialization completed successfully.517 // Set this to indicate that initialization completed successfully.
545 // from here on out we must not return an error.518 // from here on out we must not return an error.
546 // This must occur before the first suspend/await.519 // This must occur before the first suspend/await.
...@@ -559,7 +532,7 @@ pub const Compilation = struct {...@@ -559,7 +532,7 @@ pub const Compilation = struct {
559 }532 }
560533
561 /// it does ref the result because it could be an arbitrary integer size534 /// it does ref the result because it could be an arbitrary integer size
562 pub async fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {535 pub fn getPrimitiveType(comp: *Compilation, name: []const u8) !?*Type {
563 if (name.len >= 2) {536 if (name.len >= 2) {
564 switch (name[0]) {537 switch (name[0]) {
565 'i', 'u' => blk: {538 'i', 'u' => blk: {
...@@ -753,8 +726,11 @@ pub const Compilation = struct {...@@ -753,8 +726,11 @@ pub const Compilation = struct {
753 }726 }
754727
755 pub fn destroy(self: *Compilation) void {728 pub fn destroy(self: *Compilation) void {
756 // await self.main_loop_frame;729 const allocator = self.gpa();
757 // resume self.destroy_frame;730 self.cancelled = true;
731 await self.main_loop_frame;
732 resume self.destroy_frame;
733 allocator.destroy(self.destroy_frame);
758 }734 }
759735
760 fn start(self: *Compilation) void {736 fn start(self: *Compilation) void {
...@@ -767,7 +743,7 @@ pub const Compilation = struct {...@@ -767,7 +743,7 @@ pub const Compilation = struct {
767743
768 var build_result = self.initialCompile();744 var build_result = self.initialCompile();
769745
770 while (true) {746 while (!self.cancelled) {
771 const link_result = if (build_result) blk: {747 const link_result = if (build_result) blk: {
772 break :blk self.maybeLink();748 break :blk self.maybeLink();
773 } else |err| err;749 } else |err| err;
...@@ -795,47 +771,47 @@ pub const Compilation = struct {...@@ -795,47 +771,47 @@ pub const Compilation = struct {
795 self.events.put(Event{ .Error = err });771 self.events.put(Event{ .Error = err });
796 }772 }
797773
798 // // First, get an item from the watch channel, waiting on the channel.774 // First, get an item from the watch channel, waiting on the channel.
799 // var group = event.Group(BuildError!void).init(self.gpa());775 var group = event.Group(BuildError!void).init(self.gpa());
800 // {776 {
801 // const ev = (self.fs_watch.channel.get()) catch |err| {777 const ev = (self.fs_watch.channel.get()) catch |err| {
802 // build_result = err;778 build_result = err;
803 // continue;779 continue;
804 // };780 };
805 // const root_scope = ev.data;781 const root_scope = ev.data;
806 // group.call(rebuildFile, self, root_scope) catch |err| {782 group.call(rebuildFile, self, root_scope) catch |err| {
807 // build_result = err;783 build_result = err;
808 // continue;784 continue;
809 // };785 };
810 // }786 }
811 // // Next, get all the items from the channel that are buffered up.787 // Next, get all the items from the channel that are buffered up.
812 // while (self.fs_watch.channel.getOrNull()) |ev_or_err| {788 while (self.fs_watch.channel.getOrNull()) |ev_or_err| {
813 // if (ev_or_err) |ev| {789 if (ev_or_err) |ev| {
814 // const root_scope = ev.data;790 const root_scope = ev.data;
815 // group.call(rebuildFile, self, root_scope) catch |err| {791 group.call(rebuildFile, self, root_scope) catch |err| {
816 // build_result = err;792 build_result = err;
817 // continue;793 continue;
818 // };794 };
819 // } else |err| {795 } else |err| {
820 // build_result = err;796 build_result = err;
821 // continue;797 continue;
822 // }798 }
823 // }799 }
824 // build_result = group.wait();800 build_result = group.wait();
825 }801 }
826 }802 }
827803
828 async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {804 async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) BuildError!void {
829 const tree_scope = blk: {805 const tree_scope = blk: {
830 const source_code = "";806 const source_code = fs.readFile(
831 // const source_code = fs.readFile(807 self.gpa(),
832 // root_scope.realpath,808 root_scope.realpath,
833 // max_src_size,809 max_src_size,
834 // ) catch |err| {810 ) catch |err| {
835 // try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));811 try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
836 // return;812 return;
837 // };813 };
838 // errdefer self.gpa().free(source_code);814 errdefer self.gpa().free(source_code);
839815
840 const tree = try std.zig.parse(self.gpa(), source_code);816 const tree = try std.zig.parse(self.gpa(), source_code);
841 errdefer {817 errdefer {
...@@ -873,7 +849,7 @@ pub const Compilation = struct {...@@ -873,7 +849,7 @@ pub const Compilation = struct {
873 try decl_group.wait();849 try decl_group.wait();
874 }850 }
875851
876 async fn rebuildChangedDecls(852 fn rebuildChangedDecls(
877 self: *Compilation,853 self: *Compilation,
878 group: *event.Group(BuildError!void),854 group: *event.Group(BuildError!void),
879 locked_table: *Decl.Table,855 locked_table: *Decl.Table,
...@@ -962,7 +938,7 @@ pub const Compilation = struct {...@@ -962,7 +938,7 @@ pub const Compilation = struct {
962 }938 }
963 }939 }
964940
965 async fn initialCompile(self: *Compilation) !void {941 fn initialCompile(self: *Compilation) !void {
966 if (self.root_src_path) |root_src_path| {942 if (self.root_src_path) |root_src_path| {
967 const root_scope = blk: {943 const root_scope = blk: {
968 // TODO async/await std.fs.realpath944 // TODO async/await std.fs.realpath
...@@ -981,7 +957,7 @@ pub const Compilation = struct {...@@ -981,7 +957,7 @@ pub const Compilation = struct {
981 }957 }
982 }958 }
983959
984 async fn maybeLink(self: *Compilation) !void {960 fn maybeLink(self: *Compilation) !void {
985 (self.prelink_group.wait()) catch |err| switch (err) {961 (self.prelink_group.wait()) catch |err| switch (err) {
986 error.SemanticAnalysisFailed => {},962 error.SemanticAnalysisFailed => {},
987 else => return err,963 else => return err,
...@@ -1165,11 +1141,10 @@ pub const Compilation = struct {...@@ -1165,11 +1141,10 @@ pub const Compilation = struct {
1165 return link_lib;1141 return link_lib;
1166 }1142 }
11671143
1168 /// cancels itself so no need to await or cancel the promise.
1169 async fn startFindingNativeLibC(self: *Compilation) void {1144 async fn startFindingNativeLibC(self: *Compilation) void {
1170 std.event.Loop.instance.?.yield();1145 event.Loop.startCpuBoundOperation();
1171 // we don't care if it fails, we're just trying to kick off the future resolution1146 // we don't care if it fails, we're just trying to kick off the future resolution
1172 _ = (self.zig_compiler.getNativeLibC()) catch return;1147 _ = self.zig_compiler.getNativeLibC() catch return;
1173 }1148 }
11741149
1175 /// General Purpose Allocator. Must free when done.1150 /// General Purpose Allocator. Must free when done.
...@@ -1184,7 +1159,7 @@ pub const Compilation = struct {...@@ -1184,7 +1159,7 @@ pub const Compilation = struct {
11841159
1185 /// If the temporary directory for this compilation has not been created, it creates it.1160 /// If the temporary directory for this compilation has not been created, it creates it.
1186 /// Then it creates a random file name in that dir and returns it.1161 /// Then it creates a random file name in that dir and returns it.
1187 pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {1162 pub fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
1188 const tmp_dir = try self.getTmpDir();1163 const tmp_dir = try self.getTmpDir();
1189 const file_prefix = self.getRandomFileName();1164 const file_prefix = self.getRandomFileName();
11901165
...@@ -1200,14 +1175,14 @@ pub const Compilation = struct {...@@ -1200,14 +1175,14 @@ pub const Compilation = struct {
1200 /// If the temporary directory for this Compilation has not been created, creates it.1175 /// If the temporary directory for this Compilation has not been created, creates it.
1201 /// Then returns it. The directory is unique to this Compilation and cleaned up when1176 /// Then returns it. The directory is unique to this Compilation and cleaned up when
1202 /// the Compilation deinitializes.1177 /// the Compilation deinitializes.
1203 async fn getTmpDir(self: *Compilation) ![]const u8 {1178 fn getTmpDir(self: *Compilation) ![]const u8 {
1204 if (self.tmp_dir.start()) |ptr| return ptr.*;1179 if (self.tmp_dir.start()) |ptr| return ptr.*;
1205 self.tmp_dir.data = self.getTmpDirImpl();1180 self.tmp_dir.data = self.getTmpDirImpl();
1206 self.tmp_dir.resolve();1181 self.tmp_dir.resolve();
1207 return self.tmp_dir.data;1182 return self.tmp_dir.data;
1208 }1183 }
12091184
1210 async fn getTmpDirImpl(self: *Compilation) ![]u8 {1185 fn getTmpDirImpl(self: *Compilation) ![]u8 {
1211 const comp_dir_name = self.getRandomFileName();1186 const comp_dir_name = self.getRandomFileName();
1212 const zig_dir_path = try getZigDir(self.gpa());1187 const zig_dir_path = try getZigDir(self.gpa());
1213 defer self.gpa().free(zig_dir_path);1188 defer self.gpa().free(zig_dir_path);
...@@ -1217,7 +1192,7 @@ pub const Compilation = struct {...@@ -1217,7 +1192,7 @@ pub const Compilation = struct {
1217 return tmp_dir;1192 return tmp_dir;
1218 }1193 }
12191194
1220 async fn getRandomFileName(self: *Compilation) [12]u8 {1195 fn getRandomFileName(self: *Compilation) [12]u8 {
1221 // here we replace the standard +/ with -_ so that it can be used in a file name1196 // here we replace the standard +/ with -_ so that it can be used in a file name
1222 const b64_fs_encoder = std.base64.Base64Encoder.init(1197 const b64_fs_encoder = std.base64.Base64Encoder.init(
1223 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",1198 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
...@@ -1243,20 +1218,23 @@ pub const Compilation = struct {...@@ -1243,20 +1218,23 @@ pub const Compilation = struct {
1243 }1218 }
12441219
1245 /// Returns a value which has been ref()'d once1220 /// Returns a value which has been ref()'d once
1246 async fn analyzeConstValue(1221 fn analyzeConstValue(
1247 comp: *Compilation,1222 comp: *Compilation,
1248 tree_scope: *Scope.AstTree,1223 tree_scope: *Scope.AstTree,
1249 scope: *Scope,1224 scope: *Scope,
1250 node: *ast.Node,1225 node: *ast.Node,
1251 expected_type: *Type,1226 expected_type: *Type,
1252 ) !*Value {1227 ) !*Value {
1253 const analyzed_code = try comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type);1228 var frame = try comp.gpa().create(@Frame(genAndAnalyzeCode));
1229 defer comp.gpa().destroy(frame);
1230 frame.* = async comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type);
1231 const analyzed_code = try await frame;
1254 defer analyzed_code.destroy(comp.gpa());1232 defer analyzed_code.destroy(comp.gpa());
12551233
1256 return analyzed_code.getCompTimeResult(comp);1234 return analyzed_code.getCompTimeResult(comp);
1257 }1235 }
12581236
1259 async fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {1237 fn analyzeTypeExpr(comp: *Compilation, tree_scope: *Scope.AstTree, scope: *Scope, node: *ast.Node) !*Type {
1260 const meta_type = &Type.MetaType.get(comp).base;1238 const meta_type = &Type.MetaType.get(comp).base;
1261 defer meta_type.base.deref(comp);1239 defer meta_type.base.deref(comp);
12621240
...@@ -1287,7 +1265,7 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib...@@ -1287,7 +1265,7 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
1287}1265}
12881266
1289/// The function that actually does the generation.1267/// The function that actually does the generation.
1290async fn generateDecl(comp: *Compilation, decl: *Decl) !void {1268fn generateDecl(comp: *Compilation, decl: *Decl) !void {
1291 switch (decl.id) {1269 switch (decl.id) {
1292 .Var => @panic("TODO"),1270 .Var => @panic("TODO"),
1293 .Fn => {1271 .Fn => {
...@@ -1298,7 +1276,7 @@ async fn generateDecl(comp: *Compilation, decl: *Decl) !void {...@@ -1298,7 +1276,7 @@ async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
1298 }1276 }
1299}1277}
13001278
1301async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {1279fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1302 const tree_scope = fn_decl.base.tree_scope;1280 const tree_scope = fn_decl.base.tree_scope;
13031281
1304 const body_node = fn_decl.fn_proto.body_node orelse return generateDeclFnProto(comp, fn_decl);1282 const body_node = fn_decl.fn_proto.body_node orelse return generateDeclFnProto(comp, fn_decl);
...@@ -1315,7 +1293,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {...@@ -1315,7 +1293,7 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
13151293
1316 // The Decl.Fn owns the initial 1 reference count1294 // The Decl.Fn owns the initial 1 reference count
1317 const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);1295 const fn_val = try Value.Fn.create(comp, fn_type, fndef_scope, symbol_name);
1318 fn_decl.value = Decl.Fn.Val{ .Fn = fn_val };1296 fn_decl.value = .{ .Fn = fn_val };
1319 symbol_name_consumed = true;1297 symbol_name_consumed = true;
13201298
1321 // Define local parameter variables1299 // Define local parameter variables
...@@ -1350,12 +1328,15 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {...@@ -1350,12 +1328,15 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1350 try fn_type.non_key.Normal.variable_list.append(var_scope);1328 try fn_type.non_key.Normal.variable_list.append(var_scope);
1351 }1329 }
13521330
1353 const analyzed_code = try comp.genAndAnalyzeCode(1331 var frame = try comp.gpa().create(@Frame(Compilation.genAndAnalyzeCode));
1332 defer comp.gpa().destroy(frame);
1333 frame.* = async comp.genAndAnalyzeCode(
1354 tree_scope,1334 tree_scope,
1355 fn_val.child_scope,1335 fn_val.child_scope,
1356 body_node,1336 body_node,
1357 fn_type.key.data.Normal.return_type,1337 fn_type.key.data.Normal.return_type,
1358 );1338 );
1339 const analyzed_code = try await frame;
1359 errdefer analyzed_code.destroy(comp.gpa());1340 errdefer analyzed_code.destroy(comp.gpa());
13601341
1361 assert(fn_val.block_scope != null);1342 assert(fn_val.block_scope != null);
...@@ -1382,7 +1363,7 @@ fn getZigDir(allocator: *mem.Allocator) ![]u8 {...@@ -1382,7 +1363,7 @@ fn getZigDir(allocator: *mem.Allocator) ![]u8 {
1382 return std.fs.getAppDataDir(allocator, "zig");1363 return std.fs.getAppDataDir(allocator, "zig");
1383}1364}
13841365
1385async fn analyzeFnType(1366fn analyzeFnType(
1386 comp: *Compilation,1367 comp: *Compilation,
1387 tree_scope: *Scope.AstTree,1368 tree_scope: *Scope.AstTree,
1388 scope: *Scope,1369 scope: *Scope,
...@@ -1444,7 +1425,7 @@ async fn analyzeFnType(...@@ -1444,7 +1425,7 @@ async fn analyzeFnType(
1444 return fn_type;1425 return fn_type;
1445}1426}
14461427
1447async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {1428fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1448 const fn_type = try analyzeFnType(1429 const fn_type = try analyzeFnType(
1449 comp,1430 comp,
1450 fn_decl.base.tree_scope,1431 fn_decl.base.tree_scope,
...@@ -1459,6 +1440,6 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {...@@ -1459,6 +1440,6 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
14591440
1460 // The Decl.Fn owns the initial 1 reference count1441 // The Decl.Fn owns the initial 1 reference count
1461 const fn_proto_val = try Value.FnProto.create(comp, fn_type, symbol_name);1442 const fn_proto_val = try Value.FnProto.create(comp, fn_type, symbol_name);
1462 fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };1443 fn_decl.value = .{ .FnProto = fn_proto_val };
1463 symbol_name_consumed = true;1444 symbol_name_consumed = true;
1464}1445}
src-self-hosted/decl.zig+3-6
...@@ -69,15 +69,12 @@ pub const Decl = struct {...@@ -69,15 +69,12 @@ pub const Decl = struct {
6969
70 pub const Fn = struct {70 pub const Fn = struct {
71 base: Decl,71 base: Decl,
72 value: Val,72 value: union(enum) {
73 fn_proto: *ast.Node.FnProto,
74
75 // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
76 pub const Val = union(enum) {
77 Unresolved,73 Unresolved,
78 Fn: *Value.Fn,74 Fn: *Value.Fn,
79 FnProto: *Value.FnProto,75 FnProto: *Value.FnProto,
80 };76 },
77 fn_proto: *ast.Node.FnProto,
8178
82 pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 {79 pub fn externLibName(self: Fn, tree: *ast.Tree) ?[]const u8 {
83 return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {80 return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
src-self-hosted/ir.zig+38-30
...@@ -110,7 +110,7 @@ pub const Inst = struct {...@@ -110,7 +110,7 @@ pub const Inst = struct {
110 unreachable;110 unreachable;
111 }111 }
112112
113 pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {113 pub fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
114 switch (base.id) {114 switch (base.id) {
115 .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),115 .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
116 .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),116 .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
...@@ -422,7 +422,7 @@ pub const Inst = struct {...@@ -422,7 +422,7 @@ pub const Inst = struct {
422 return false;422 return false;
423 }423 }
424424
425 pub async fn analyze(self: *const Ref, ira: *Analyze) !*Inst {425 pub fn analyze(self: *const Ref, ira: *Analyze) !*Inst {
426 const target = try self.params.target.getAsParam();426 const target = try self.params.target.getAsParam();
427427
428 if (ira.getCompTimeValOrNullUndefOk(target)) |val| {428 if (ira.getCompTimeValOrNullUndefOk(target)) |val| {
...@@ -472,7 +472,7 @@ pub const Inst = struct {...@@ -472,7 +472,7 @@ pub const Inst = struct {
472 return false;472 return false;
473 }473 }
474474
475 pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {475 pub fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
476 (ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) {476 (ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) {
477 error.OutOfMemory => return error.OutOfMemory,477 error.OutOfMemory => return error.OutOfMemory,
478 else => return error.SemanticAnalysisFailed,478 else => return error.SemanticAnalysisFailed,
...@@ -516,7 +516,7 @@ pub const Inst = struct {...@@ -516,7 +516,7 @@ pub const Inst = struct {
516 return false;516 return false;
517 }517 }
518518
519 pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {519 pub fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
520 switch (self.params.var_scope.data) {520 switch (self.params.var_scope.data) {
521 .Const => @panic("TODO"),521 .Const => @panic("TODO"),
522 .Param => |param| {522 .Param => |param| {
...@@ -563,7 +563,7 @@ pub const Inst = struct {...@@ -563,7 +563,7 @@ pub const Inst = struct {
563 return false;563 return false;
564 }564 }
565565
566 pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {566 pub fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
567 const target = try self.params.target.getAsParam();567 const target = try self.params.target.getAsParam();
568 const target_type = target.getKnownType();568 const target_type = target.getKnownType();
569 if (target_type.id != .Pointer) {569 if (target_type.id != .Pointer) {
...@@ -645,7 +645,7 @@ pub const Inst = struct {...@@ -645,7 +645,7 @@ pub const Inst = struct {
645 return false;645 return false;
646 }646 }
647647
648 pub async fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {648 pub fn analyze(self: *const PtrType, ira: *Analyze) !*Inst {
649 const child_type = try self.params.child_type.getAsConstType(ira);649 const child_type = try self.params.child_type.getAsConstType(ira);
650 // if (child_type->id == TypeTableEntryIdUnreachable) {650 // if (child_type->id == TypeTableEntryIdUnreachable) {
651 // ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));651 // ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed"));
...@@ -658,7 +658,7 @@ pub const Inst = struct {...@@ -658,7 +658,7 @@ pub const Inst = struct {
658 const amt = try align_inst.getAsConstAlign(ira);658 const amt = try align_inst.getAsConstAlign(ira);
659 break :blk Type.Pointer.Align{ .Override = amt };659 break :blk Type.Pointer.Align{ .Override = amt };
660 } else blk: {660 } else blk: {
661 break :blk Type.Pointer.Align{ .Abi = {} };661 break :blk .Abi;
662 };662 };
663 const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{663 const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
664 .child_type = child_type,664 .child_type = child_type,
...@@ -927,7 +927,7 @@ pub const Variable = struct {...@@ -927,7 +927,7 @@ pub const Variable = struct {
927927
928pub const BasicBlock = struct {928pub const BasicBlock = struct {
929 ref_count: usize,929 ref_count: usize,
930 name_hint: [*]const u8, // must be a C string literal930 name_hint: [*:0]const u8,
931 debug_id: usize,931 debug_id: usize,
932 scope: *Scope,932 scope: *Scope,
933 instruction_list: std.ArrayList(*Inst),933 instruction_list: std.ArrayList(*Inst),
...@@ -1051,7 +1051,7 @@ pub const Builder = struct {...@@ -1051,7 +1051,7 @@ pub const Builder = struct {
1051 }1051 }
10521052
1053 /// No need to clean up resources thanks to the arena allocator.1053 /// No need to clean up resources thanks to the arena allocator.
1054 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*]const u8) !*BasicBlock {1054 pub fn createBasicBlock(self: *Builder, scope: *Scope, name_hint: [*:0]const u8) !*BasicBlock {
1055 const basic_block = try self.arena().create(BasicBlock);1055 const basic_block = try self.arena().create(BasicBlock);
1056 basic_block.* = BasicBlock{1056 basic_block.* = BasicBlock{
1057 .ref_count = 0,1057 .ref_count = 0,
...@@ -1078,6 +1078,14 @@ pub const Builder = struct {...@@ -1078,6 +1078,14 @@ pub const Builder = struct {
1078 self.current_basic_block = basic_block;1078 self.current_basic_block = basic_block;
1079 }1079 }
10801080
1081 pub fn genNodeRecursive(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
1082 const alloc = irb.comp.gpa();
1083 var frame = try alloc.create(@Frame(genNode));
1084 defer alloc.destroy(frame);
1085 frame.* = async irb.genNode(node, scope, lval);
1086 return await frame;
1087 }
1088
1081 pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {1089 pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
1082 switch (node.id) {1090 switch (node.id) {
1083 .Root => unreachable,1091 .Root => unreachable,
...@@ -1157,7 +1165,7 @@ pub const Builder = struct {...@@ -1157,7 +1165,7 @@ pub const Builder = struct {
1157 },1165 },
1158 .GroupedExpression => {1166 .GroupedExpression => {
1159 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);1167 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);
1160 return irb.genNode(grouped_expr.expr, scope, lval);1168 return irb.genNodeRecursive(grouped_expr.expr, scope, lval);
1161 },1169 },
1162 .BuiltinCall => return error.Unimplemented,1170 .BuiltinCall => return error.Unimplemented,
1163 .ErrorSetDecl => return error.Unimplemented,1171 .ErrorSetDecl => return error.Unimplemented,
...@@ -1186,14 +1194,14 @@ pub const Builder = struct {...@@ -1186,14 +1194,14 @@ pub const Builder = struct {
1186 }1194 }
1187 }1195 }
11881196
1189 async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {1197 fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
1190 const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None);1198 const fn_ref = try irb.genNodeRecursive(suffix_op.lhs.node, scope, .None);
11911199
1192 const args = try irb.arena().alloc(*Inst, call.params.len);1200 const args = try irb.arena().alloc(*Inst, call.params.len);
1193 var it = call.params.iterator(0);1201 var it = call.params.iterator(0);
1194 var i: usize = 0;1202 var i: usize = 0;
1195 while (it.next()) |arg_node_ptr| : (i += 1) {1203 while (it.next()) |arg_node_ptr| : (i += 1) {
1196 args[i] = try irb.genNode(arg_node_ptr.*, scope, .None);1204 args[i] = try irb.genNodeRecursive(arg_node_ptr.*, scope, .None);
1197 }1205 }
11981206
1199 //bool is_async = node->data.fn_call_expr.is_async;1207 //bool is_async = node->data.fn_call_expr.is_async;
...@@ -1214,7 +1222,7 @@ pub const Builder = struct {...@@ -1214,7 +1222,7 @@ pub const Builder = struct {
1214 //return ir_lval_wrap(irb, scope, fn_call, lval);1222 //return ir_lval_wrap(irb, scope, fn_call, lval);
1215 }1223 }
12161224
1217 async fn genPtrType(1225 fn genPtrType(
1218 irb: *Builder,1226 irb: *Builder,
1219 prefix_op: *ast.Node.PrefixOp,1227 prefix_op: *ast.Node.PrefixOp,
1220 ptr_info: ast.Node.PrefixOp.PtrInfo,1228 ptr_info: ast.Node.PrefixOp.PtrInfo,
...@@ -1238,7 +1246,7 @@ pub const Builder = struct {...@@ -1238,7 +1246,7 @@ pub const Builder = struct {
1238 //} else {1246 //} else {
1239 // align_value = nullptr;1247 // align_value = nullptr;
1240 //}1248 //}
1241 const child_type = try irb.genNode(prefix_op.rhs, scope, .None);1249 const child_type = try irb.genNodeRecursive(prefix_op.rhs, scope, .None);
12421250
1243 //uint32_t bit_offset_start = 0;1251 //uint32_t bit_offset_start = 0;
1244 //if (node->data.pointer_type.bit_offset_start != nullptr) {1252 //if (node->data.pointer_type.bit_offset_start != nullptr) {
...@@ -1307,9 +1315,9 @@ pub const Builder = struct {...@@ -1307,9 +1315,9 @@ pub const Builder = struct {
1307 var rest: []const u8 = undefined;1315 var rest: []const u8 = undefined;
1308 if (int_token.len >= 3 and int_token[0] == '0') {1316 if (int_token.len >= 3 and int_token[0] == '0') {
1309 base = switch (int_token[1]) {1317 base = switch (int_token[1]) {
1310 'b' => u8(2),1318 'b' => 2,
1311 'o' => u8(8),1319 'o' => 8,
1312 'x' => u8(16),1320 'x' => 16,
1313 else => unreachable,1321 else => unreachable,
1314 };1322 };
1315 rest = int_token[2..];1323 rest = int_token[2..];
...@@ -1339,7 +1347,7 @@ pub const Builder = struct {...@@ -1339,7 +1347,7 @@ pub const Builder = struct {
1339 return inst;1347 return inst;
1340 }1348 }
13411349
1342 pub async fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {1350 pub fn genStrLit(irb: *Builder, str_lit: *ast.Node.StringLiteral, scope: *Scope) !*Inst {
1343 const str_token = irb.code.tree_scope.tree.tokenSlice(str_lit.token);1351 const str_token = irb.code.tree_scope.tree.tokenSlice(str_lit.token);
1344 const src_span = Span.token(str_lit.token);1352 const src_span = Span.token(str_lit.token);
13451353
...@@ -1389,7 +1397,7 @@ pub const Builder = struct {...@@ -1389,7 +1397,7 @@ pub const Builder = struct {
1389 }1397 }
1390 }1398 }
13911399
1392 pub async fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {1400 pub fn genBlock(irb: *Builder, block: *ast.Node.Block, parent_scope: *Scope) !*Inst {
1393 const block_scope = try Scope.Block.create(irb.comp, parent_scope);1401 const block_scope = try Scope.Block.create(irb.comp, parent_scope);
13941402
1395 const outer_block_scope = &block_scope.base;1403 const outer_block_scope = &block_scope.base;
...@@ -1437,7 +1445,7 @@ pub const Builder = struct {...@@ -1437,7 +1445,7 @@ pub const Builder = struct {
1437 child_scope = &defer_child_scope.base;1445 child_scope = &defer_child_scope.base;
1438 continue;1446 continue;
1439 }1447 }
1440 const statement_value = try irb.genNode(statement_node, child_scope, .None);1448 const statement_value = try irb.genNodeRecursive(statement_node, child_scope, .None);
14411449
1442 is_continuation_unreachable = statement_value.isNoReturn();1450 is_continuation_unreachable = statement_value.isNoReturn();
1443 if (is_continuation_unreachable) {1451 if (is_continuation_unreachable) {
...@@ -1499,7 +1507,7 @@ pub const Builder = struct {...@@ -1499,7 +1507,7 @@ pub const Builder = struct {
1499 return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);1507 return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
1500 }1508 }
15011509
1502 pub async fn genControlFlowExpr(1510 pub fn genControlFlowExpr(
1503 irb: *Builder,1511 irb: *Builder,
1504 control_flow_expr: *ast.Node.ControlFlowExpression,1512 control_flow_expr: *ast.Node.ControlFlowExpression,
1505 scope: *Scope,1513 scope: *Scope,
...@@ -1533,7 +1541,7 @@ pub const Builder = struct {...@@ -1533,7 +1541,7 @@ pub const Builder = struct {
15331541
1534 const outer_scope = irb.begin_scope.?;1542 const outer_scope = irb.begin_scope.?;
1535 const return_value = if (control_flow_expr.rhs) |rhs| blk: {1543 const return_value = if (control_flow_expr.rhs) |rhs| blk: {
1536 break :blk try irb.genNode(rhs, scope, .None);1544 break :blk try irb.genNodeRecursive(rhs, scope, .None);
1537 } else blk: {1545 } else blk: {
1538 break :blk try irb.buildConstVoid(scope, src_span, true);1546 break :blk try irb.buildConstVoid(scope, src_span, true);
1539 };1547 };
...@@ -1596,7 +1604,7 @@ pub const Builder = struct {...@@ -1596,7 +1604,7 @@ pub const Builder = struct {
1596 }1604 }
1597 }1605 }
15981606
1599 pub async fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {1607 pub fn genIdentifier(irb: *Builder, identifier: *ast.Node.Identifier, scope: *Scope, lval: LVal) !*Inst {
1600 const src_span = Span.token(identifier.token);1608 const src_span = Span.token(identifier.token);
1601 const name = irb.code.tree_scope.tree.tokenSlice(identifier.token);1609 const name = irb.code.tree_scope.tree.tokenSlice(identifier.token);
16021610
...@@ -1694,7 +1702,7 @@ pub const Builder = struct {...@@ -1694,7 +1702,7 @@ pub const Builder = struct {
1694 return result;1702 return result;
1695 }1703 }
16961704
1697 async fn genDefersForBlock(1705 fn genDefersForBlock(
1698 irb: *Builder,1706 irb: *Builder,
1699 inner_scope: *Scope,1707 inner_scope: *Scope,
1700 outer_scope: *Scope,1708 outer_scope: *Scope,
...@@ -1712,7 +1720,7 @@ pub const Builder = struct {...@@ -1712,7 +1720,7 @@ pub const Builder = struct {
1712 };1720 };
1713 if (generate) {1721 if (generate) {
1714 const defer_expr_scope = defer_scope.defer_expr_scope;1722 const defer_expr_scope = defer_scope.defer_expr_scope;
1715 const instruction = try irb.genNode(1723 const instruction = try irb.genNodeRecursive(
1716 defer_expr_scope.expr_node,1724 defer_expr_scope.expr_node,
1717 &defer_expr_scope.base,1725 &defer_expr_scope.base,
1718 .None,1726 .None,
...@@ -1797,7 +1805,7 @@ pub const Builder = struct {...@@ -1797,7 +1805,7 @@ pub const Builder = struct {
1797 // Look at the params and ref() other instructions1805 // Look at the params and ref() other instructions
1798 comptime var i = 0;1806 comptime var i = 0;
1799 inline while (i < @memberCount(I.Params)) : (i += 1) {1807 inline while (i < @memberCount(I.Params)) : (i += 1) {
1800 const FieldType = comptime @typeOf(@field(I.Params(undefined), @memberName(I.Params, i)));1808 const FieldType = comptime @typeOf(@field(@as(I.Params, undefined), @memberName(I.Params, i)));
1801 switch (FieldType) {1809 switch (FieldType) {
1802 *Inst => @field(inst.params, @memberName(I.Params, i)).ref(self),1810 *Inst => @field(inst.params, @memberName(I.Params, i)).ref(self),
1803 *BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self),1811 *BasicBlock => @field(inst.params, @memberName(I.Params, i)).ref(self),
...@@ -1909,7 +1917,7 @@ pub const Builder = struct {...@@ -1909,7 +1917,7 @@ pub const Builder = struct {
1909 VarScope: *Scope.Var,1917 VarScope: *Scope.Var,
1910 };1918 };
19111919
1912 async fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {1920 fn findIdent(irb: *Builder, scope: *Scope, name: []const u8) Ident {
1913 var s = scope;1921 var s = scope;
1914 while (true) {1922 while (true) {
1915 switch (s.id) {1923 switch (s.id) {
...@@ -2519,7 +2527,7 @@ const Analyze = struct {...@@ -2519,7 +2527,7 @@ const Analyze = struct {
2519 }2527 }
2520};2528};
25212529
2522pub async fn gen(2530pub fn gen(
2523 comp: *Compilation,2531 comp: *Compilation,
2524 body_node: *ast.Node,2532 body_node: *ast.Node,
2525 tree_scope: *Scope.AstTree,2533 tree_scope: *Scope.AstTree,
...@@ -2541,7 +2549,7 @@ pub async fn gen(...@@ -2541,7 +2549,7 @@ pub async fn gen(
2541 return irb.finish();2549 return irb.finish();
2542}2550}
25432551
2544pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {2552pub fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type) !*Code {
2545 const old_entry_bb = old_code.basic_block_list.at(0);2553 const old_entry_bb = old_code.basic_block_list.at(0);
25462554
2547 var ira = try Analyze.init(comp, old_code.tree_scope, expected_type);2555 var ira = try Analyze.init(comp, old_code.tree_scope, expected_type);
src-self-hosted/libc_installation.zig+3-3
...@@ -143,7 +143,7 @@ pub const LibCInstallation = struct {...@@ -143,7 +143,7 @@ pub const LibCInstallation = struct {
143 }143 }
144144
145 /// Finds the default, native libc.145 /// Finds the default, native libc.
146 pub async fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {146 pub fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
147 self.initEmpty();147 self.initEmpty();
148 var group = event.Group(FindError!void).init(allocator);148 var group = event.Group(FindError!void).init(allocator);
149 errdefer group.wait() catch {};149 errdefer group.wait() catch {};
...@@ -393,14 +393,14 @@ pub const LibCInstallation = struct {...@@ -393,14 +393,14 @@ pub const LibCInstallation = struct {
393};393};
394394
395/// caller owns returned memory395/// caller owns returned memory
396async fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {396fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
397 const cc_exe = std.os.getenv("CC") orelse "cc";397 const cc_exe = std.os.getenv("CC") orelse "cc";
398 const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file);398 const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file);
399 defer allocator.free(arg1);399 defer allocator.free(arg1);
400 const argv = [_][]const u8{ cc_exe, arg1 };400 const argv = [_][]const u8{ cc_exe, arg1 };
401401
402 // TODO This simulates evented I/O for the child process exec402 // TODO This simulates evented I/O for the child process exec
403 std.event.Loop.instance.?.yield();403 event.Loop.startCpuBoundOperation();
404 const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);404 const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
405 const exec_result = if (std.debug.runtime_safety) blk: {405 const exec_result = if (std.debug.runtime_safety) blk: {
406 break :blk errorable_result catch unreachable;406 break :blk errorable_result catch unreachable;
src-self-hosted/link.zig+33-35
...@@ -11,7 +11,7 @@ const util = @import("util.zig");...@@ -11,7 +11,7 @@ const util = @import("util.zig");
11const Context = struct {11const Context = struct {
12 comp: *Compilation,12 comp: *Compilation,
13 arena: std.heap.ArenaAllocator,13 arena: std.heap.ArenaAllocator,
14 args: std.ArrayList([*]const u8),14 args: std.ArrayList([*:0]const u8),
15 link_in_crt: bool,15 link_in_crt: bool,
1616
17 link_err: error{OutOfMemory}!void,17 link_err: error{OutOfMemory}!void,
...@@ -21,7 +21,7 @@ const Context = struct {...@@ -21,7 +21,7 @@ const Context = struct {
21 out_file_path: std.Buffer,21 out_file_path: std.Buffer,
22};22};
2323
24pub async fn link(comp: *Compilation) !void {24pub fn link(comp: *Compilation) !void {
25 var ctx = Context{25 var ctx = Context{
26 .comp = comp,26 .comp = comp,
27 .arena = std.heap.ArenaAllocator.init(comp.gpa()),27 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
...@@ -33,7 +33,7 @@ pub async fn link(comp: *Compilation) !void {...@@ -33,7 +33,7 @@ pub async fn link(comp: *Compilation) !void {
33 .out_file_path = undefined,33 .out_file_path = undefined,
34 };34 };
35 defer ctx.arena.deinit();35 defer ctx.arena.deinit();
36 ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);36 ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
37 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);37 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
3838
39 if (comp.link_out_file) |out_file| {39 if (comp.link_out_file) |out_file| {
...@@ -58,7 +58,8 @@ pub async fn link(comp: *Compilation) !void {...@@ -58,7 +58,8 @@ pub async fn link(comp: *Compilation) !void {
58 try ctx.args.append("lld");58 try ctx.args.append("lld");
5959
60 if (comp.haveLibC()) {60 if (comp.haveLibC()) {
61 ctx.libc = ctx.comp.override_libc orelse blk: {61 // TODO https://github.com/ziglang/zig/issues/3190
62 var libc = ctx.comp.override_libc orelse blk: {
62 switch (comp.target) {63 switch (comp.target) {
63 Target.Native => {64 Target.Native => {
64 break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;65 break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
...@@ -66,6 +67,7 @@ pub async fn link(comp: *Compilation) !void {...@@ -66,6 +67,7 @@ pub async fn link(comp: *Compilation) !void {
66 else => return error.LibCRequiredButNotProvidedOrFound,67 else => return error.LibCRequiredButNotProvidedOrFound,
67 }68 }
68 };69 };
70 ctx.libc = libc;
69 }71 }
7072
71 try constructLinkerArgs(&ctx);73 try constructLinkerArgs(&ctx);
...@@ -171,7 +173,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -171,7 +173,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
171 //}173 //}
172174
173 try ctx.args.append("-o");175 try ctx.args.append("-o");
174 try ctx.args.append(ctx.out_file_path.ptr());176 try ctx.args.append(ctx.out_file_path.toSliceConst());
175177
176 if (ctx.link_in_crt) {178 if (ctx.link_in_crt) {
177 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";179 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
...@@ -214,10 +216,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -214,10 +216,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
214216
215 if (ctx.comp.haveLibC()) {217 if (ctx.comp.haveLibC()) {
216 try ctx.args.append("-L");218 try ctx.args.append("-L");
217 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);219 // TODO addNullByte should probably return [:0]u8
220 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr));
218221
219 try ctx.args.append("-L");222 try ctx.args.append("-L");
220 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);223 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr));
221224
222 if (!ctx.comp.is_static) {225 if (!ctx.comp.is_static) {
223 const dl = blk: {226 const dl = blk: {
...@@ -226,7 +229,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -226,7 +229,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
226 return error.LibCMissingDynamicLinker;229 return error.LibCMissingDynamicLinker;
227 };230 };
228 try ctx.args.append("-dynamic-linker");231 try ctx.args.append("-dynamic-linker");
229 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);232 try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
230 }233 }
231 }234 }
232235
...@@ -238,7 +241,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -238,7 +241,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
238 // .o files241 // .o files
239 for (ctx.comp.link_objects) |link_object| {242 for (ctx.comp.link_objects) |link_object| {
240 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);243 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
241 try ctx.args.append(link_obj_with_null.ptr);244 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
242 }245 }
243 try addFnObjects(ctx);246 try addFnObjects(ctx);
244247
...@@ -313,7 +316,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -313,7 +316,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
313fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {316fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
314 const full_path = try std.fs.path.join(&ctx.arena.allocator, [_][]const u8{ dirname, basename });317 const full_path = try std.fs.path.join(&ctx.arena.allocator, [_][]const u8{ dirname, basename });
315 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);318 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
316 try ctx.args.append(full_path_with_null.ptr);319 try ctx.args.append(@ptrCast([*:0]const u8, full_path_with_null.ptr));
317}320}
318321
319fn constructLinkerArgsCoff(ctx: *Context) !void {322fn constructLinkerArgsCoff(ctx: *Context) !void {
...@@ -339,12 +342,12 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -339,12 +342,12 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
339 const is_library = ctx.comp.kind == .Lib;342 const is_library = ctx.comp.kind == .Lib;
340343
341 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());344 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());
342 try ctx.args.append(out_arg.ptr);345 try ctx.args.append(@ptrCast([*:0]const u8, out_arg.ptr));
343346
344 if (ctx.comp.haveLibC()) {347 if (ctx.comp.haveLibC()) {
345 try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr);348 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.msvc_lib_dir.?)).ptr));
346 try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr);349 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.kernel32_lib_dir.?)).ptr));
347 try ctx.args.append((try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr);350 try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", ctx.libc.lib_dir.?)).ptr));
348 }351 }
349352
350 if (ctx.link_in_crt) {353 if (ctx.link_in_crt) {
...@@ -353,17 +356,17 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -353,17 +356,17 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
353356
354 if (ctx.comp.is_static) {357 if (ctx.comp.is_static) {
355 const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);358 const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);
356 try ctx.args.append(cmt_lib_name.ptr);359 try ctx.args.append(@ptrCast([*:0]const u8, cmt_lib_name.ptr));
357 } else {360 } else {
358 const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", d_str);361 const msvcrt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "msvcrt{}.lib\x00", d_str);
359 try ctx.args.append(msvcrt_lib_name.ptr);362 try ctx.args.append(@ptrCast([*:0]const u8, msvcrt_lib_name.ptr));
360 }363 }
361364
362 const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", lib_str, d_str);365 const vcruntime_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}vcruntime{}.lib\x00", lib_str, d_str);
363 try ctx.args.append(vcruntime_lib_name.ptr);366 try ctx.args.append(@ptrCast([*:0]const u8, vcruntime_lib_name.ptr));
364367
365 const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", lib_str, d_str);368 const crt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "{}ucrt{}.lib\x00", lib_str, d_str);
366 try ctx.args.append(crt_lib_name.ptr);369 try ctx.args.append(@ptrCast([*:0]const u8, crt_lib_name.ptr));
367370
368 // Visual C++ 2015 Conformance Changes371 // Visual C++ 2015 Conformance Changes
369 // https://msdn.microsoft.com/en-us/library/bb531344.aspx372 // https://msdn.microsoft.com/en-us/library/bb531344.aspx
...@@ -395,7 +398,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -395,7 +398,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
395398
396 for (ctx.comp.link_objects) |link_object| {399 for (ctx.comp.link_objects) |link_object| {
397 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);400 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
398 try ctx.args.append(link_obj_with_null.ptr);401 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
399 }402 }
400 try addFnObjects(ctx);403 try addFnObjects(ctx);
401404
...@@ -504,11 +507,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -504,11 +507,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
504 //}507 //}
505508
506 try ctx.args.append("-arch");509 try ctx.args.append("-arch");
507 const darwin_arch_str = try std.cstr.addNullByte(510 try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
508 &ctx.arena.allocator,
509 ctx.comp.target.getDarwinArchString(),
510 );
511 try ctx.args.append(darwin_arch_str.ptr);
512511
513 const platform = try DarwinPlatform.get(ctx.comp);512 const platform = try DarwinPlatform.get(ctx.comp);
514 switch (platform.kind) {513 switch (platform.kind) {
...@@ -517,7 +516,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -517,7 +516,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
517 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),516 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
518 }517 }
519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);518 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
520 try ctx.args.append(ver_str.ptr);519 try ctx.args.append(@ptrCast([*:0]const u8, ver_str.ptr));
521520
522 if (ctx.comp.kind == .Exe) {521 if (ctx.comp.kind == .Exe) {
523 if (ctx.comp.is_static) {522 if (ctx.comp.is_static) {
...@@ -528,7 +527,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -528,7 +527,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
528 }527 }
529528
530 try ctx.args.append("-o");529 try ctx.args.append("-o");
531 try ctx.args.append(ctx.out_file_path.ptr());530 try ctx.args.append(ctx.out_file_path.toSliceConst());
532531
533 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {532 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
534 // Buf *rpath = g->rpath_list.at(i);533 // Buf *rpath = g->rpath_list.at(i);
...@@ -572,7 +571,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -572,7 +571,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
572571
573 for (ctx.comp.link_objects) |link_object| {572 for (ctx.comp.link_objects) |link_object| {
574 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);573 const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
575 try ctx.args.append(link_obj_with_null.ptr);574 try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
576 }575 }
577 try addFnObjects(ctx);576 try addFnObjects(ctx);
578577
...@@ -593,10 +592,10 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -593,10 +592,10 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
593 } else {592 } else {
594 if (mem.indexOfScalar(u8, lib.name, '/') == null) {593 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
595 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);594 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
596 try ctx.args.append(arg.ptr);595 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
597 } else {596 } else {
598 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);597 const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
599 try ctx.args.append(arg.ptr);598 try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
600 }599 }
601 }600 }
602 }601 }
...@@ -626,20 +625,19 @@ fn constructLinkerArgsWasm(ctx: *Context) void {...@@ -626,20 +625,19 @@ fn constructLinkerArgsWasm(ctx: *Context) void {
626}625}
627626
628fn addFnObjects(ctx: *Context) !void {627fn addFnObjects(ctx: *Context) !void {
629 // at this point it's guaranteed nobody else has this lock, so we circumvent it628 const held = ctx.comp.fn_link_set.acquire();
630 // and avoid having to be an async function629 defer held.release();
631 const fn_link_set = &ctx.comp.fn_link_set.private_data;
632630
633 var it = fn_link_set.first;631 var it = held.value.first;
634 while (it) |node| {632 while (it) |node| {
635 const fn_val = node.data orelse {633 const fn_val = node.data orelse {
636 // handle the tombstone. See Value.Fn.destroy.634 // handle the tombstone. See Value.Fn.destroy.
637 it = node.next;635 it = node.next;
638 fn_link_set.remove(node);636 held.value.remove(node);
639 ctx.comp.gpa().destroy(node);637 ctx.comp.gpa().destroy(node);
640 continue;638 continue;
641 };639 };
642 try ctx.args.append(fn_val.containing_object.ptr());640 try ctx.args.append(fn_val.containing_object.toSliceConst());
643 it = node.next;641 it = node.next;
644 }642 }
645}643}
src-self-hosted/llvm.zig+1-1
...@@ -86,7 +86,7 @@ pub const AddGlobal = LLVMAddGlobal;...@@ -86,7 +86,7 @@ pub const AddGlobal = LLVMAddGlobal;
86extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value;86extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value;
8787
88pub const ConstStringInContext = LLVMConstStringInContext;88pub const ConstStringInContext = LLVMConstStringInContext;
89extern fn LLVMConstStringInContext(C: *Context, Str: [*:0]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;89extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
9090
91pub const ConstInt = LLVMConstInt;91pub const ConstInt = LLVMConstInt;
92extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;92extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
src-self-hosted/main.zig+64-73
...@@ -49,14 +49,15 @@ const usage =...@@ -49,14 +49,15 @@ const usage =
4949
50const Command = struct {50const Command = struct {
51 name: []const u8,51 name: []const u8,
52 exec: fn (*Allocator, []const []const u8) anyerror!void,52 exec: async fn (*Allocator, []const []const u8) anyerror!void,
53};53};
5454
55pub fn main() !void {55pub fn main() !void {
56 // This allocator needs to be thread-safe because we use it for the event.Loop56 // This allocator needs to be thread-safe because we use it for the event.Loop
57 // which multiplexes async functions onto kernel threads.57 // which multiplexes async functions onto kernel threads.
58 // libc allocator is guaranteed to have this property.58 // libc allocator is guaranteed to have this property.
59 const allocator = std.heap.c_allocator;59 // TODO https://github.com/ziglang/zig/issues/3783
60 const allocator = std.heap.page_allocator;
6061
61 stdout = &std.io.getStdOut().outStream().stream;62 stdout = &std.io.getStdOut().outStream().stream;
6263
...@@ -118,14 +119,18 @@ pub fn main() !void {...@@ -118,14 +119,18 @@ pub fn main() !void {
118 },119 },
119 };120 };
120121
121 for (commands) |command| {122 inline for (commands) |command| {
122 if (mem.eql(u8, command.name, args[1])) {123 if (mem.eql(u8, command.name, args[1])) {
123 return command.exec(allocator, args[2..]);124 var frame = try allocator.create(@Frame(command.exec));
125 defer allocator.destroy(frame);
126 frame.* = async command.exec(allocator, args[2..]);
127 return await frame;
124 }128 }
125 }129 }
126130
127 try stderr.print("unknown command: {}\n\n", args[1]);131 try stderr.print("unknown command: {}\n\n", args[1]);
128 try stderr.write(usage);132 try stderr.write(usage);
133 process.argsFree(allocator, args);
129 process.exit(1);134 process.exit(1);
130}135}
131136
...@@ -461,13 +466,12 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -461,13 +466,12 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
461 comp.link_objects = link_objects;466 comp.link_objects = link_objects;
462467
463 comp.start();468 comp.start();
464 const frame = async processBuildEvents(comp, color);469 processBuildEvents(comp, color);
465}470}
466471
467async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {472fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
468 var count: usize = 0;473 var count: usize = 0;
469 while (true) {474 while (!comp.cancelled) {
470 // TODO directly awaiting async should guarantee memory allocation elision
471 const build_event = comp.events.get();475 const build_event = comp.events.get();
472 count += 1;476 count += 1;
473477
...@@ -545,7 +549,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil...@@ -545,7 +549,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil
545 "Try running `zig libc` to see an example for the native target.\n",549 "Try running `zig libc` to see an example for the native target.\n",
546 libc_paths_file,550 libc_paths_file,
547 @errorName(err),551 @errorName(err),
548 ) catch process.exit(1);552 ) catch {};
549 process.exit(1);553 process.exit(1);
550 };554 };
551}555}
...@@ -567,12 +571,8 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {...@@ -567,12 +571,8 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
567 var zig_compiler = try ZigCompiler.init(allocator);571 var zig_compiler = try ZigCompiler.init(allocator);
568 defer zig_compiler.deinit();572 defer zig_compiler.deinit();
569573
570 const frame = async findLibCAsync(&zig_compiler);
571}
572
573async fn findLibCAsync(zig_compiler: *ZigCompiler) void {
574 const libc = zig_compiler.getNativeLibC() catch |err| {574 const libc = zig_compiler.getNativeLibC() catch |err| {
575 stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);575 stderr.print("unable to find libc: {}\n", @errorName(err)) catch {};
576 process.exit(1);576 process.exit(1);
577 };577 };
578 libc.render(stdout) catch process.exit(1);578 libc.render(stdout) catch process.exit(1);
...@@ -644,11 +644,23 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -644,11 +644,23 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
644 process.exit(1);644 process.exit(1);
645 }645 }
646646
647 return asyncFmtMain(647 var fmt = Fmt{
648 allocator,648 .allocator = allocator,
649 &flags,649 .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
650 color,650 .any_error = false,
651 );651 .color = color,
652 };
653
654 const check_mode = flags.present("check");
655
656 var group = event.Group(FmtError!void).init(allocator);
657 for (flags.positionals.toSliceConst()) |file_path| {
658 try group.call(fmtPath, &fmt, file_path, check_mode);
659 }
660 try group.wait();
661 if (fmt.any_error) {
662 process.exit(1);
663 }
652}664}
653665
654const FmtError = error{666const FmtError = error{
...@@ -673,30 +685,6 @@ const FmtError = error{...@@ -673,30 +685,6 @@ const FmtError = error{
673 CurrentWorkingDirectoryUnlinked,685 CurrentWorkingDirectoryUnlinked,
674} || fs.File.OpenError;686} || fs.File.OpenError;
675687
676async fn asyncFmtMain(
677 allocator: *Allocator,
678 flags: *const Args,
679 color: errmsg.Color,
680) FmtError!void {
681 var fmt = Fmt{
682 .allocator = allocator,
683 .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
684 .any_error = false,
685 .color = color,
686 };
687
688 const check_mode = flags.present("check");
689
690 var group = event.Group(FmtError!void).init(allocator);
691 for (flags.positionals.toSliceConst()) |file_path| {
692 try group.call(fmtPath, &fmt, file_path, check_mode);
693 }
694 try group.wait();
695 if (fmt.any_error) {
696 process.exit(1);
697 }
698}
699
700async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {688async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
701 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);689 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
702 defer fmt.allocator.free(file_path);690 defer fmt.allocator.free(file_path);
...@@ -708,33 +696,34 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -708,33 +696,34 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
708 if (try held.value.put(file_path, {})) |_| return;696 if (try held.value.put(file_path, {})) |_| return;
709 }697 }
710698
711 const source_code = "";699 const source_code = event.fs.readFile(
712 // const source_code = event.fs.readFile(700 fmt.allocator,
713 // file_path,701 file_path,
714 // max_src_size,702 max_src_size,
715 // ) catch |err| switch (err) {703 ) catch |err| switch (err) {
716 // error.IsDir, error.AccessDenied => {704 error.IsDir, error.AccessDenied => {
717 // // TODO make event based (and dir.next())705 var dir = try fs.Dir.cwd().openDirList(file_path);
718 // var dir = try fs.Dir.cwd().openDirList(file_path);706 defer dir.close();
719 // defer dir.close();707
720708 var group = event.Group(FmtError!void).init(fmt.allocator);
721 // var group = event.Group(FmtError!void).init(fmt.allocator);709 var it = dir.iterate();
722 // while (try dir.next()) |entry| {710 while (try it.next()) |entry| {
723 // if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {711 if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) {
724 // const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });712 const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
725 // try group.call(fmtPath, fmt, full_path, check_mode);713 @panic("TODO https://github.com/ziglang/zig/issues/3777");
726 // }714 // try group.call(fmtPath, fmt, full_path, check_mode);
727 // }715 }
728 // return group.wait();716 }
729 // },717 return group.wait();
730 // else => {718 },
731 // // TODO lock stderr printing719 else => {
732 // try stderr.print("unable to open '{}': {}\n", file_path, err);720 // TODO lock stderr printing
733 // fmt.any_error = true;721 try stderr.print("unable to open '{}': {}\n", file_path, err);
734 // return;722 fmt.any_error = true;
735 // },723 return;
736 // };724 },
737 // defer fmt.allocator.free(source_code);725 };
726 defer fmt.allocator.free(source_code);
738727
739 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {728 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
740 try stderr.print("error parsing file '{}': {}\n", file_path, err);729 try stderr.print("error parsing file '{}': {}\n", file_path, err);
...@@ -867,10 +856,12 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {...@@ -867,10 +856,12 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
867 .exec = cmdInternalBuildInfo,856 .exec = cmdInternalBuildInfo,
868 }};857 }};
869858
870 for (sub_commands) |sub_command| {859 inline for (sub_commands) |sub_command| {
871 if (mem.eql(u8, sub_command.name, args[0])) {860 if (mem.eql(u8, sub_command.name, args[0])) {
872 try sub_command.exec(allocator, args[1..]);861 var frame = try allocator.create(@Frame(sub_command.exec));
873 return;862 defer allocator.destroy(frame);
863 frame.* = async sub_command.exec(allocator, args[1..]);
864 return await frame;
874 }865 }
875 }866 }
876867
src-self-hosted/test.zig+11-13
...@@ -26,7 +26,8 @@ test "stage2" {...@@ -26,7 +26,8 @@ test "stage2" {
26}26}
2727
28const file1 = "1.zig";28const file1 = "1.zig";
29const allocator = std.heap.c_allocator;29// TODO https://github.com/ziglang/zig/issues/3783
30const allocator = std.heap.page_allocator;
3031
31pub const TestContext = struct {32pub const TestContext = struct {
32 zig_compiler: ZigCompiler,33 zig_compiler: ZigCompiler,
...@@ -94,8 +95,8 @@ pub const TestContext = struct {...@@ -94,8 +95,8 @@ pub const TestContext = struct {
94 &self.zig_compiler,95 &self.zig_compiler,
95 "test",96 "test",
96 file1_path,97 file1_path,
97 Target.Native,98 .Native,
98 Compilation.Kind.Obj,99 .Obj,
99 .Debug,100 .Debug,
100 true, // is_static101 true, // is_static
101 self.zig_lib_dir,102 self.zig_lib_dir,
...@@ -116,7 +117,7 @@ pub const TestContext = struct {...@@ -116,7 +117,7 @@ pub const TestContext = struct {
116 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());117 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
117 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });118 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
118119
119 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{.Native = {}}).exeFileExt());120 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{ .Native = {} }).exeFileExt());
120 if (std.fs.path.dirname(file1_path)) |dirname| {121 if (std.fs.path.dirname(file1_path)) |dirname| {
121 try std.fs.makePath(allocator, dirname);122 try std.fs.makePath(allocator, dirname);
122 }123 }
...@@ -128,8 +129,8 @@ pub const TestContext = struct {...@@ -128,8 +129,8 @@ pub const TestContext = struct {
128 &self.zig_compiler,129 &self.zig_compiler,
129 "test",130 "test",
130 file1_path,131 file1_path,
131 Target.Native,132 .Native,
132 Compilation.Kind.Exe,133 .Exe,
133 .Debug,134 .Debug,
134 false,135 false,
135 self.zig_lib_dir,136 self.zig_lib_dir,
...@@ -148,15 +149,12 @@ pub const TestContext = struct {...@@ -148,15 +149,12 @@ pub const TestContext = struct {
148 exe_file: []const u8,149 exe_file: []const u8,
149 expected_output: []const u8,150 expected_output: []const u8,
150 ) anyerror!void {151 ) anyerror!void {
151 // TODO this should not be necessary
152 const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);
153
154 defer comp.destroy();152 defer comp.destroy();
155 const build_event = comp.events.get();153 const build_event = comp.events.get();
156154
157 switch (build_event) {155 switch (build_event) {
158 .Ok => {156 .Ok => {
159 const argv = [_][]const u8{exe_file_2};157 const argv = [_][]const u8{exe_file};
160 // TODO use event loop158 // TODO use event loop
161 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);159 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
162 switch (child.term) {160 switch (child.term) {
...@@ -173,13 +171,13 @@ pub const TestContext = struct {...@@ -173,13 +171,13 @@ pub const TestContext = struct {
173 return error.OutputMismatch;171 return error.OutputMismatch;
174 }172 }
175 },173 },
176 Compilation.Event.Error => |err| return err,174 .Error => @panic("Cannot return error: https://github.com/ziglang/zig/issues/3190"), // |err| return err,
177 Compilation.Event.Fail => |msgs| {175 .Fail => |msgs| {
178 const stderr = std.io.getStdErr();176 const stderr = std.io.getStdErr();
179 try stderr.write("build incorrectly failed:\n");177 try stderr.write("build incorrectly failed:\n");
180 for (msgs) |msg| {178 for (msgs) |msg| {
181 defer msg.destroy();179 defer msg.destroy();
182 try msg.printToFile(stderr, errmsg.Color.Auto);180 try msg.printToFile(stderr, .Auto);
183 }181 }
184 },182 },
185 }183 }
src-self-hosted/type.zig+14-12
...@@ -53,7 +53,7 @@ pub const Type = struct {...@@ -53,7 +53,7 @@ pub const Type = struct {
53 base: *Type,53 base: *Type,
54 allocator: *Allocator,54 allocator: *Allocator,
55 llvm_context: *llvm.Context,55 llvm_context: *llvm.Context,
56 ) (error{OutOfMemory}!*llvm.Type) {56 ) error{OutOfMemory}!*llvm.Type {
57 switch (base.id) {57 switch (base.id) {
58 .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),58 .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
59 .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),59 .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
...@@ -184,7 +184,7 @@ pub const Type = struct {...@@ -184,7 +184,7 @@ pub const Type = struct {
184184
185 /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.185 /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.
186 /// Otherwise, this one will grab one from the pool and then release it.186 /// Otherwise, this one will grab one from the pool and then release it.
187 pub async fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {187 pub fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {
188 if (base.abi_alignment.start()) |ptr| return ptr.*;188 if (base.abi_alignment.start()) |ptr| return ptr.*;
189189
190 {190 {
...@@ -200,7 +200,7 @@ pub const Type = struct {...@@ -200,7 +200,7 @@ pub const Type = struct {
200 }200 }
201201
202 /// If you have an llvm conext handy, you can use it here.202 /// If you have an llvm conext handy, you can use it here.
203 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {203 pub fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
204 if (base.abi_alignment.start()) |ptr| return ptr.*;204 if (base.abi_alignment.start()) |ptr| return ptr.*;
205205
206 base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);206 base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);
...@@ -209,7 +209,7 @@ pub const Type = struct {...@@ -209,7 +209,7 @@ pub const Type = struct {
209 }209 }
210210
211 /// Lower level function that does the work. See getAbiAlignment.211 /// Lower level function that does the work. See getAbiAlignment.
212 async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {212 fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
213 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);213 const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
214 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));214 return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
215 }215 }
...@@ -367,7 +367,7 @@ pub const Type = struct {...@@ -367,7 +367,7 @@ pub const Type = struct {
367 }367 }
368368
369 /// takes ownership of key.Normal.params on success369 /// takes ownership of key.Normal.params on success
370 pub async fn get(comp: *Compilation, key: Key) !*Fn {370 pub fn get(comp: *Compilation, key: Key) !*Fn {
371 {371 {
372 const held = comp.fn_type_table.acquire();372 const held = comp.fn_type_table.acquire();
373 defer held.release();373 defer held.release();
...@@ -564,7 +564,7 @@ pub const Type = struct {...@@ -564,7 +564,7 @@ pub const Type = struct {
564 return comp.u8_type;564 return comp.u8_type;
565 }565 }
566566
567 pub async fn get(comp: *Compilation, key: Key) !*Int {567 pub fn get(comp: *Compilation, key: Key) !*Int {
568 {568 {
569 const held = comp.int_type_table.acquire();569 const held = comp.int_type_table.acquire();
570 defer held.release();570 defer held.release();
...@@ -606,7 +606,7 @@ pub const Type = struct {...@@ -606,7 +606,7 @@ pub const Type = struct {
606 comp.registerGarbage(Int, &self.garbage_node);606 comp.registerGarbage(Int, &self.garbage_node);
607 }607 }
608608
609 pub async fn gcDestroy(self: *Int, comp: *Compilation) void {609 pub fn gcDestroy(self: *Int, comp: *Compilation) void {
610 {610 {
611 const held = comp.int_type_table.acquire();611 const held = comp.int_type_table.acquire();
612 defer held.release();612 defer held.release();
...@@ -700,7 +700,7 @@ pub const Type = struct {...@@ -700,7 +700,7 @@ pub const Type = struct {
700 comp.registerGarbage(Pointer, &self.garbage_node);700 comp.registerGarbage(Pointer, &self.garbage_node);
701 }701 }
702702
703 pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {703 pub fn gcDestroy(self: *Pointer, comp: *Compilation) void {
704 {704 {
705 const held = comp.ptr_type_table.acquire();705 const held = comp.ptr_type_table.acquire();
706 defer held.release();706 defer held.release();
...@@ -711,14 +711,14 @@ pub const Type = struct {...@@ -711,14 +711,14 @@ pub const Type = struct {
711 comp.gpa().destroy(self);711 comp.gpa().destroy(self);
712 }712 }
713713
714 pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {714 pub fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
715 switch (self.key.alignment) {715 switch (self.key.alignment) {
716 .Abi => return self.key.child_type.getAbiAlignment(comp),716 .Abi => return self.key.child_type.getAbiAlignment(comp),
717 .Override => |alignment| return alignment,717 .Override => |alignment| return alignment,
718 }718 }
719 }719 }
720720
721 pub async fn get(721 pub fn get(
722 comp: *Compilation,722 comp: *Compilation,
723 key: Key,723 key: Key,
724 ) !*Pointer {724 ) !*Pointer {
...@@ -726,8 +726,10 @@ pub const Type = struct {...@@ -726,8 +726,10 @@ pub const Type = struct {
726 switch (key.alignment) {726 switch (key.alignment) {
727 .Abi => {},727 .Abi => {},
728 .Override => |alignment| {728 .Override => |alignment| {
729 // TODO https://github.com/ziglang/zig/issues/3190
730 var align_spill = alignment;
729 const abi_align = try key.child_type.getAbiAlignment(comp);731 const abi_align = try key.child_type.getAbiAlignment(comp);
730 if (abi_align == alignment) {732 if (abi_align == align_spill) {
731 normal_key.alignment = .Abi;733 normal_key.alignment = .Abi;
732 }734 }
733 },735 },
...@@ -828,7 +830,7 @@ pub const Type = struct {...@@ -828,7 +830,7 @@ pub const Type = struct {
828 comp.gpa().destroy(self);830 comp.gpa().destroy(self);
829 }831 }
830832
831 pub async fn get(comp: *Compilation, key: Key) !*Array {833 pub fn get(comp: *Compilation, key: Key) !*Array {
832 key.elem_type.base.ref();834 key.elem_type.base.ref();
833 errdefer key.elem_type.base.deref(comp);835 errdefer key.elem_type.base.deref(comp);
834836
src-self-hosted/util.zig+12-11
...@@ -32,21 +32,21 @@ pub fn getFloatAbi(self: Target) FloatAbi {...@@ -32,21 +32,21 @@ pub fn getFloatAbi(self: Target) FloatAbi {
32 };32 };
33}33}
3434
35pub fn getObjectFormat(self: Target) Target.ObjectFormat {35pub fn getObjectFormat(target: Target) Target.ObjectFormat {
36 return switch (self) {36 switch (target) {
37 .Native => @import("builtin").object_format,37 .Native => return @import("builtin").object_format,
38 .Cross => {38 .Cross => blk: {
39 if (target.isWindows() or target.isUefi()) {39 if (target.isWindows() or target.isUefi()) {
40 break .coff;40 return .coff;
41 } else if (target.isDarwin()) {41 } else if (target.isDarwin()) {
42 break .macho;42 return .macho;
43 }43 }
44 if (target.isWasm()) {44 if (target.isWasm()) {
45 break .wasm;45 return .wasm;
46 }46 }
47 break .elf;47 return .elf;
48 },48 },
49 };49 }
50}50}
5151
52pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {52pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
...@@ -156,7 +156,7 @@ pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {...@@ -156,7 +156,7 @@ pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
156 }156 }
157}157}
158158
159pub fn getDarwinArchString(self: Target) []const u8 {159pub fn getDarwinArchString(self: Target) [:0]const u8 {
160 const arch = self.getArch();160 const arch = self.getArch();
161 switch (arch) {161 switch (arch) {
162 .aarch64 => return "arm64",162 .aarch64 => return "arm64",
...@@ -166,7 +166,8 @@ pub fn getDarwinArchString(self: Target) []const u8 {...@@ -166,7 +166,8 @@ pub fn getDarwinArchString(self: Target) []const u8 {
166 .powerpc => return "ppc",166 .powerpc => return "ppc",
167 .powerpc64 => return "ppc64",167 .powerpc64 => return "ppc64",
168 .powerpc64le => return "ppc64le",168 .powerpc64le => return "ppc64le",
169 else => return @tagName(arch),169 // @tagName should be able to return sentinel terminated slice
170 else => @panic("TODO https://github.com/ziglang/zig/issues/3779"), //return @tagName(arch),
170 }171 }
171}172}
172173
src-self-hosted/value.zig+7-7
...@@ -156,7 +156,7 @@ pub const Value = struct {...@@ -156,7 +156,7 @@ pub const Value = struct {
156 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);156 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
157 const llvm_fn = llvm.AddFunction(157 const llvm_fn = llvm.AddFunction(
158 ofile.module,158 ofile.module,
159 self.symbol_name.ptr(),159 self.symbol_name.toSliceConst(),
160 llvm_fn_type,160 llvm_fn_type,
161 ) orelse return error.OutOfMemory;161 ) orelse return error.OutOfMemory;
162162
...@@ -241,7 +241,7 @@ pub const Value = struct {...@@ -241,7 +241,7 @@ pub const Value = struct {
241 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);241 const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
242 const llvm_fn = llvm.AddFunction(242 const llvm_fn = llvm.AddFunction(
243 ofile.module,243 ofile.module,
244 self.symbol_name.ptr(),244 self.symbol_name.toSliceConst(),
245 llvm_fn_type,245 llvm_fn_type,
246 ) orelse return error.OutOfMemory;246 ) orelse return error.OutOfMemory;
247247
...@@ -334,7 +334,7 @@ pub const Value = struct {...@@ -334,7 +334,7 @@ pub const Value = struct {
334 field_index: usize,334 field_index: usize,
335 };335 };
336336
337 pub async fn createArrayElemPtr(337 pub fn createArrayElemPtr(
338 comp: *Compilation,338 comp: *Compilation,
339 array_val: *Array,339 array_val: *Array,
340 mut: Type.Pointer.Mut,340 mut: Type.Pointer.Mut,
...@@ -350,7 +350,7 @@ pub const Value = struct {...@@ -350,7 +350,7 @@ pub const Value = struct {
350 .mut = mut,350 .mut = mut,
351 .vol = Type.Pointer.Vol.Non,351 .vol = Type.Pointer.Vol.Non,
352 .size = size,352 .size = size,
353 .alignment = Type.Pointer.Align.Abi,353 .alignment = .Abi,
354 });354 });
355 var ptr_type_consumed = false;355 var ptr_type_consumed = false;
356 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);356 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
...@@ -390,13 +390,13 @@ pub const Value = struct {...@@ -390,13 +390,13 @@ pub const Value = struct {
390 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;390 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
391 const ptr_bit_count = ofile.comp.target_ptr_bits;391 const ptr_bit_count = ofile.comp.target_ptr_bits;
392 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;392 const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
393 const indices = [_]*llvm.Value{393 var indices = [_]*llvm.Value{
394 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,394 llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
395 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,395 llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
396 };396 };
397 return llvm.ConstInBoundsGEP(397 return llvm.ConstInBoundsGEP(
398 array_llvm_value,398 array_llvm_value,
399 &indices,399 @ptrCast([*]*llvm.Value, &indices),
400 @intCast(c_uint, indices.len),400 @intCast(c_uint, indices.len),
401 ) orelse return error.OutOfMemory;401 ) orelse return error.OutOfMemory;
402 },402 },
...@@ -423,7 +423,7 @@ pub const Value = struct {...@@ -423,7 +423,7 @@ pub const Value = struct {
423 };423 };
424424
425 /// Takes ownership of buffer425 /// Takes ownership of buffer
426 pub async fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {426 pub fn createOwnedBuffer(comp: *Compilation, buffer: []u8) !*Array {
427 const u8_type = Type.Int.get_u8(comp);427 const u8_type = Type.Int.get_u8(comp);
428 defer u8_type.base.base.deref(comp);428 defer u8_type.base.base.deref(comp);
429429