authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-24 14:40:16-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-24 14:40:16-05:00
log2b1faa1f20ce22c07d7767e8af3bc64614b0ca0e
treec0bc74564724f5aed82506e7fb991f6e99a746c0
parent29d7b5a80c9faf640c3db0de14cd229e90b2d8c3
parent0cbf00a3ec3f6640556e39efaa6e936b0b42630b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3748 from Vexu/modernize-stage2

Updates and cleanup in self hosted compiler

24 files changed, 1336 insertions(+), 1546 deletions(-)

build.zig+8-8
......@@ -54,6 +54,7 @@ pub fn build(b: *Builder) !void {
5454
5555 var test_stage2 = b.addTest("src-self-hosted/test.zig");
5656 test_stage2.setBuildMode(builtin.Mode.Debug);
57 test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig");
5758
5859 const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"});
5960
......@@ -72,9 +73,9 @@ pub fn build(b: *Builder) !void {
7273 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
7374 const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;
7475 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;
75 if (!skip_self_hosted) {
76 // TODO re-enable this after https://github.com/ziglang/zig/issues/2377
77 //test_step.dependOn(&exe.step);
76 if (!skip_self_hosted and builtin.os == .linux) {
77 // TODO evented I/O other OS's
78 test_step.dependOn(&exe.step);
7879 }
7980
8081 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;
......@@ -98,11 +99,7 @@ pub fn build(b: *Builder) !void {
9899
99100 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
100101 test_stage2_step.dependOn(&test_stage2.step);
101
102 // TODO see https://github.com/ziglang/zig/issues/1364
103 if (false) {
104 test_step.dependOn(test_stage2_step);
105 }
102 test_step.dependOn(test_stage2_step);
106103
107104 var chosen_modes: [4]builtin.Mode = undefined;
108105 var chosen_mode_index: usize = 0;
......@@ -235,6 +232,9 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
235232 if (fs.path.isAbsolute(lib_arg)) {
236233 try result.libs.append(lib_arg);
237234 } else {
235 if (mem.endsWith(u8, lib_arg, ".lib")) {
236 lib_arg = lib_arg[0 .. lib_arg.len - 4];
237 }
238238 try result.system_libs.append(lib_arg);
239239 }
240240 }
lib/std/child_process.zig+3-1
......@@ -259,7 +259,9 @@ pub const ChildProcess = struct {
259259 }
260260
261261 fn handleWaitResult(self: *ChildProcess, status: u32) void {
262 self.term = self.cleanupAfterWait(status);
262 // TODO https://github.com/ziglang/zig/issues/3190
263 var term = self.cleanupAfterWait(status);
264 self.term = term;
263265 }
264266
265267 fn cleanupStreams(self: *ChildProcess) void {
lib/std/event/group.zig+1-2
......@@ -66,11 +66,10 @@ pub fn Group(comptime ReturnType: type) type {
6666 node.* = AllocStack.Node{
6767 .next = undefined,
6868 .data = Node{
69 .handle = frame,
69 .handle = @asyncCall(frame, {}, func, args),
7070 .bytes = std.mem.asBytes(frame),
7171 },
7272 };
73 _ = @asyncCall(frame, {}, func, args);
7473 self.alloc_stack.push(node);
7574 }
7675
src-self-hosted/arg.zig+5-5
......@@ -119,9 +119,9 @@ pub const Args = struct {
119119
120120 // MergeN creation disallows 0 length flag entry (doesn't make sense)
121121 switch (flag_args) {
122 FlagArg.None => unreachable,
123 FlagArg.Single => |inner| try prev.append(inner),
124 FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
122 .None => unreachable,
123 .Single => |inner| try prev.append(inner),
124 .Many => |inner| try prev.appendSlice(inner.toSliceConst()),
125125 }
126126
127127 _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
......@@ -158,7 +158,7 @@ pub const Args = struct {
158158 pub fn single(self: *Args, name: []const u8) ?[]const u8 {
159159 if (self.flags.get(name)) |entry| {
160160 switch (entry.value) {
161 FlagArg.Single => |inner| {
161 .Single => |inner| {
162162 return inner;
163163 },
164164 else => @panic("attempted to retrieve flag with wrong type"),
......@@ -172,7 +172,7 @@ pub const Args = struct {
172172 pub fn many(self: *Args, name: []const u8) []const []const u8 {
173173 if (self.flags.get(name)) |entry| {
174174 switch (entry.value) {
175 FlagArg.Many => |inner| {
175 .Many => |inner| {
176176 return inner.toSliceConst();
177177 },
178178 else => @panic("attempted to retrieve flag with wrong type"),
src-self-hosted/c_int.zig+110-8
......@@ -1,3 +1,5 @@
1const Target = @import("std").Target;
2
13pub const CInt = struct {
24 id: Id,
35 zig_name: []const u8,
......@@ -17,52 +19,152 @@ pub const CInt = struct {
1719
1820 pub const list = [_]CInt{
1921 CInt{
20 .id = Id.Short,
22 .id = .Short,
2123 .zig_name = "c_short",
2224 .c_name = "short",
2325 .is_signed = true,
2426 },
2527 CInt{
26 .id = Id.UShort,
28 .id = .UShort,
2729 .zig_name = "c_ushort",
2830 .c_name = "unsigned short",
2931 .is_signed = false,
3032 },
3133 CInt{
32 .id = Id.Int,
34 .id = .Int,
3335 .zig_name = "c_int",
3436 .c_name = "int",
3537 .is_signed = true,
3638 },
3739 CInt{
38 .id = Id.UInt,
40 .id = .UInt,
3941 .zig_name = "c_uint",
4042 .c_name = "unsigned int",
4143 .is_signed = false,
4244 },
4345 CInt{
44 .id = Id.Long,
46 .id = .Long,
4547 .zig_name = "c_long",
4648 .c_name = "long",
4749 .is_signed = true,
4850 },
4951 CInt{
50 .id = Id.ULong,
52 .id = .ULong,
5153 .zig_name = "c_ulong",
5254 .c_name = "unsigned long",
5355 .is_signed = false,
5456 },
5557 CInt{
56 .id = Id.LongLong,
58 .id = .LongLong,
5759 .zig_name = "c_longlong",
5860 .c_name = "long long",
5961 .is_signed = true,
6062 },
6163 CInt{
62 .id = Id.ULongLong,
64 .id = .ULongLong,
6365 .zig_name = "c_ulonglong",
6466 .c_name = "unsigned long long",
6567 .is_signed = false,
6668 },
6769 };
70
71 pub fn sizeInBits(cint: CInt, self: Target) u32 {
72 const arch = self.getArch();
73 switch (self.getOs()) {
74 .freestanding => switch (self.getArch()) {
75 .msp430 => switch (cint.id) {
76 .Short,
77 .UShort,
78 .Int,
79 .UInt,
80 => return 16,
81 .Long,
82 .ULong,
83 => return 32,
84 .LongLong,
85 .ULongLong,
86 => return 64,
87 },
88 else => switch (cint.id) {
89 .Short,
90 .UShort,
91 => return 16,
92 .Int,
93 .UInt,
94 => return 32,
95 .Long,
96 .ULong,
97 => return self.getArchPtrBitWidth(),
98 .LongLong,
99 .ULongLong,
100 => return 64,
101 },
102 },
103
104 .linux,
105 .macosx,
106 .freebsd,
107 .openbsd,
108 .zen,
109 => switch (cint.id) {
110 .Short,
111 .UShort,
112 => return 16,
113 .Int,
114 .UInt,
115 => return 32,
116 .Long,
117 .ULong,
118 => return self.getArchPtrBitWidth(),
119 .LongLong,
120 .ULongLong,
121 => return 64,
122 },
123
124 .windows, .uefi => switch (cint.id) {
125 .Short,
126 .UShort,
127 => return 16,
128 .Int,
129 .UInt,
130 => return 32,
131 .Long,
132 .ULong,
133 .LongLong,
134 .ULongLong,
135 => return 64,
136 },
137
138 .ananas,
139 .cloudabi,
140 .dragonfly,
141 .fuchsia,
142 .ios,
143 .kfreebsd,
144 .lv2,
145 .netbsd,
146 .solaris,
147 .haiku,
148 .minix,
149 .rtems,
150 .nacl,
151 .cnk,
152 .aix,
153 .cuda,
154 .nvcl,
155 .amdhsa,
156 .ps4,
157 .elfiamcu,
158 .tvos,
159 .watchos,
160 .mesa3d,
161 .contiki,
162 .amdpal,
163 .hermit,
164 .hurd,
165 .wasi,
166 .emscripten,
167 => @panic("TODO specify the C integer type sizes for this OS"),
168 }
169 }
68170};
src-self-hosted/codegen.zig+19-19
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const Compilation = @import("compilation.zig").Compilation;
43const llvm = @import("llvm.zig");
54const c = @import("c.zig");
......@@ -7,17 +6,18 @@ const ir = @import("ir.zig");
76const Value = @import("value.zig").Value;
87const Type = @import("type.zig").Type;
98const Scope = @import("scope.zig").Scope;
9const util = @import("util.zig");
1010const event = std.event;
1111const assert = std.debug.assert;
1212const DW = std.dwarf;
1313const maxInt = std.math.maxInt;
1414
15pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) !void {
15pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) Compilation.BuildError!void {
1616 fn_val.base.ref();
1717 defer fn_val.base.deref(comp);
1818 defer code.destroy(comp.gpa());
1919
20 var output_path = try await (async comp.createRandomOutputPath(comp.target.objFileExt()) catch unreachable);
20 var output_path = try comp.createRandomOutputPath(comp.target.oFileExt());
2121 errdefer output_path.deinit();
2222
2323 const llvm_handle = try comp.zig_compiler.getAnyLlvmContext();
......@@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
3131 llvm.SetTarget(module, comp.llvm_triple.ptr());
3232 llvm.SetDataLayout(module, comp.target_layout_str);
3333
34 if (comp.target.getObjectFormat() == builtin.ObjectFormat.coff) {
34 if (util.getObjectFormat(comp.target) == .coff) {
3535 llvm.AddModuleCodeViewFlag(module);
3636 } else {
3737 llvm.AddModuleDebugInfoFlag(module);
......@@ -59,7 +59,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
5959 comp.name.ptr(),
6060 comp.root_package.root_src_dir.ptr(),
6161 ) orelse return error.OutOfMemory;
62 const is_optimized = comp.build_mode != builtin.Mode.Debug;
62 const is_optimized = comp.build_mode != .Debug;
6363 const compile_unit = llvm.CreateCompileUnit(
6464 dibuilder,
6565 DW.LANG_C99,
......@@ -79,7 +79,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
7979 .builder = builder,
8080 .dibuilder = dibuilder,
8181 .context = context,
82 .lock = event.Lock.init(comp.loop),
82 .lock = event.Lock.init(),
8383 .arena = &code.arena.allocator,
8484 };
8585
......@@ -105,8 +105,8 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
105105
106106 assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types
107107
108 const is_small = comp.build_mode == builtin.Mode.ReleaseSmall;
109 const is_debug = comp.build_mode == builtin.Mode.Debug;
108 const is_small = comp.build_mode == .ReleaseSmall;
109 const is_debug = comp.build_mode == .Debug;
110110
111111 var err_msg: [*]u8 = undefined;
112112 // TODO integrate this with evented I/O
......@@ -234,8 +234,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
234234 // create debug variable declarations for variables and allocate all local variables
235235 for (var_list) |var_scope, i| {
236236 const var_type = switch (var_scope.data) {
237 Scope.Var.Data.Const => unreachable,
238 Scope.Var.Data.Param => |param| param.typ,
237 .Const => unreachable,
238 .Param => |param| param.typ,
239239 };
240240 // if (!type_has_bits(var->value->type)) {
241241 // continue;
......@@ -266,7 +266,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
266266 var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i));
267267 } else {
268268 // gen_type = var->value->type;
269 var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, Type.Pointer.Align.Abi);
269 var_scope.data.Param.llvm_value = try renderAlloca(ofile, var_type, var_scope.name, .Abi);
270270 }
271271 // if (var->decl_node) {
272272 // var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
......@@ -300,8 +300,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
300300 ofile,
301301 llvm_param,
302302 scope_var.data.Param.llvm_value,
303 Type.Pointer.Align.Abi,
304 Type.Pointer.Vol.Non,
303 .Abi,
304 .Non,
305305 );
306306 }
307307
......@@ -383,8 +383,8 @@ fn renderLoadUntyped(
383383) !*llvm.Value {
384384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385385 switch (vol) {
386 Type.Pointer.Vol.Non => {},
387 Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1),
386 .Non => {},
387 .Volatile => llvm.SetVolatile(result, 1),
388388 }
389389 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr))));
390390 return result;
......@@ -414,8 +414,8 @@ pub fn renderStoreUntyped(
414414) !*llvm.Value {
415415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416416 switch (vol) {
417 Type.Pointer.Vol.Non => {},
418 Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1),
417 .Non => {},
418 .Volatile => llvm.SetVolatile(result, 1),
419419 }
420420 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value)));
421421 return result;
......@@ -445,7 +445,7 @@ pub fn renderAlloca(
445445
446446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
447447 return switch (alignment) {
448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 Type.Pointer.Align.Override => |a| a,
448 .Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 .Override => |a| a,
450450 };
451451}
src-self-hosted/compilation.zig+187-204
......@@ -5,8 +5,8 @@ const Allocator = mem.Allocator;
55const Buffer = std.Buffer;
66const llvm = @import("llvm.zig");
77const c = @import("c.zig");
8const builtin = @import("builtin");
9const Target = @import("target.zig").Target;
8const builtin = std.builtin;
9const Target = std.Target;
1010const warn = std.debug.warn;
1111const Token = std.zig.Token;
1212const ArrayList = std.ArrayList;
......@@ -30,14 +30,15 @@ const link = @import("link.zig").link;
3030const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
3131const CInt = @import("c_int.zig").CInt;
3232const fs = event.fs;
33const util = @import("util.zig");
3334
3435const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
3536
3637/// Data that is local to the event loop.
3738pub const ZigCompiler = struct {
38 loop: *event.Loop,
3939 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
4040 lld_lock: event.Lock,
41 allocator: *Allocator,
4142
4243 /// TODO pool these so that it doesn't have to lock
4344 prng: event.Locked(std.rand.DefaultPrng),
......@@ -46,9 +47,9 @@ pub const ZigCompiler = struct {
4647
4748 var lazy_init_targets = std.lazyInit(void);
4849
49 pub fn init(loop: *event.Loop) !ZigCompiler {
50 pub fn init(allocator: *Allocator) !ZigCompiler {
5051 lazy_init_targets.get() orelse {
51 Target.initializeAll();
52 util.initializeAllTargets();
5253 lazy_init_targets.resolve();
5354 };
5455
......@@ -57,11 +58,11 @@ pub const ZigCompiler = struct {
5758 const seed = mem.readIntNative(u64, &seed_bytes);
5859
5960 return ZigCompiler{
60 .loop = loop,
61 .lld_lock = event.Lock.init(loop),
61 .allocator = allocator,
62 .lld_lock = event.Lock.init(),
6263 .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
63 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
64 .native_libc = event.Future(LibCInstallation).init(loop),
64 .prng = event.Locked(std.rand.DefaultPrng).init(std.rand.DefaultPrng.init(seed)),
65 .native_libc = event.Future(LibCInstallation).init(),
6566 };
6667 }
6768
......@@ -70,7 +71,7 @@ pub const ZigCompiler = struct {
7071 self.lld_lock.deinit();
7172 while (self.llvm_handle_pool.pop()) |node| {
7273 llvm.ContextDispose(node.data);
73 self.loop.allocator.destroy(node);
74 self.allocator.destroy(node);
7475 }
7576 }
7677
......@@ -82,19 +83,19 @@ pub const ZigCompiler = struct {
8283 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
8384 errdefer llvm.ContextDispose(context_ref);
8485
85 const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
86 const node = try self.allocator.create(std.atomic.Stack(*llvm.Context).Node);
8687 node.* = std.atomic.Stack(*llvm.Context).Node{
8788 .next = undefined,
8889 .data = context_ref,
8990 };
90 errdefer self.loop.allocator.destroy(node);
91 errdefer self.allocator.destroy(node);
9192
9293 return LlvmHandle{ .node = node };
9394 }
9495
9596 pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
96 if (await (async self.native_libc.start() catch unreachable)) |ptr| return ptr;
97 try await (async self.native_libc.data.findNative(self.loop) catch unreachable);
97 if (self.native_libc.start()) |ptr| return ptr;
98 try self.native_libc.data.findNative(self.allocator);
9899 self.native_libc.resolve();
99100 return &self.native_libc.data;
100101 }
......@@ -122,7 +123,6 @@ pub const LlvmHandle = struct {
122123
123124pub const Compilation = struct {
124125 zig_compiler: *ZigCompiler,
125 loop: *event.Loop,
126126 name: Buffer,
127127 llvm_triple: Buffer,
128128 root_src_path: ?[]const u8,
......@@ -227,8 +227,8 @@ pub const Compilation = struct {
227227 /// need to wait on this group before deinitializing
228228 deinit_group: event.Group(void),
229229
230 destroy_handle: promise,
231 main_loop_handle: promise,
230 // destroy_frame: @Frame(createAsync),
231 // main_loop_frame: @Frame(Compilation.mainLoop),
232232 main_loop_future: event.Future(void),
233233
234234 have_err_ret_tracing: bool,
......@@ -243,7 +243,7 @@ pub const Compilation = struct {
243243
244244 c_int_types: [CInt.list.len]*Type.Int,
245245
246 fs_watch: *fs.Watch(*Scope.Root),
246 // fs_watch: *fs.Watch(*Scope.Root),
247247
248248 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);
249249 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);
......@@ -348,7 +348,7 @@ pub const Compilation = struct {
348348 zig_lib_dir: []const u8,
349349 ) !*Compilation {
350350 var optional_comp: ?*Compilation = null;
351 const handle = try async<zig_compiler.loop.allocator> createAsync(
351 var frame = async createAsync(
352352 &optional_comp,
353353 zig_compiler,
354354 name,
......@@ -359,10 +359,7 @@ pub const Compilation = struct {
359359 is_static,
360360 zig_lib_dir,
361361 );
362 return optional_comp orelse if (getAwaitResult(
363 zig_compiler.loop.allocator,
364 handle,
365 )) |_| unreachable else |err| err;
362 return optional_comp orelse if (await frame) |_| unreachable else |err| err;
366363 }
367364
368365 async fn createAsync(
......@@ -376,15 +373,9 @@ pub const Compilation = struct {
376373 is_static: bool,
377374 zig_lib_dir: []const u8,
378375 ) !void {
379 // workaround for https://github.com/ziglang/zig/issues/1194
380 suspend {
381 resume @handle();
382 }
383
384 const loop = zig_compiler.loop;
376 const allocator = zig_compiler.allocator;
385377 var comp = Compilation{
386 .loop = loop,
387 .arena_allocator = std.heap.ArenaAllocator.init(loop.allocator),
378 .arena_allocator = std.heap.ArenaAllocator.init(allocator),
388379 .zig_compiler = zig_compiler,
389380 .events = undefined,
390381 .root_src_path = root_src_path,
......@@ -394,10 +385,10 @@ pub const Compilation = struct {
394385 .build_mode = build_mode,
395386 .zig_lib_dir = zig_lib_dir,
396387 .zig_std_dir = undefined,
397 .tmp_dir = event.Future(BuildError![]u8).init(loop),
398 .destroy_handle = @handle(),
399 .main_loop_handle = undefined,
400 .main_loop_future = event.Future(void).init(loop),
388 .tmp_dir = event.Future(BuildError![]u8).init(),
389 // .destroy_frame = @frame(),
390 // .main_loop_frame = undefined,
391 .main_loop_future = event.Future(void).init(),
401392
402393 .name = undefined,
403394 .llvm_triple = undefined,
......@@ -426,7 +417,7 @@ pub const Compilation = struct {
426417 .rpath_list = [_][]const u8{},
427418 .assembly_files = [_][]const u8{},
428419 .link_objects = [_][]const u8{},
429 .fn_link_set = event.Locked(FnLinkSet).init(loop, FnLinkSet.init()),
420 .fn_link_set = event.Locked(FnLinkSet).init(FnLinkSet.init()),
430421 .windows_subsystem_windows = false,
431422 .windows_subsystem_console = false,
432423 .link_libs_list = undefined,
......@@ -438,14 +429,14 @@ pub const Compilation = struct {
438429 .test_name_prefix = null,
439430 .emit_file_type = Emit.Binary,
440431 .link_out_file = null,
441 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
442 .prelink_group = event.Group(BuildError!void).init(loop),
443 .deinit_group = event.Group(void).init(loop),
444 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
445 .int_type_table = event.Locked(IntTypeTable).init(loop, IntTypeTable.init(loop.allocator)),
446 .array_type_table = event.Locked(ArrayTypeTable).init(loop, ArrayTypeTable.init(loop.allocator)),
447 .ptr_type_table = event.Locked(PtrTypeTable).init(loop, PtrTypeTable.init(loop.allocator)),
448 .fn_type_table = event.Locked(FnTypeTable).init(loop, FnTypeTable.init(loop.allocator)),
432 .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),
433 .prelink_group = event.Group(BuildError!void).init(allocator),
434 .deinit_group = event.Group(void).init(allocator),
435 .compile_errors = event.Locked(CompileErrList).init(CompileErrList.init(allocator)),
436 .int_type_table = event.Locked(IntTypeTable).init(IntTypeTable.init(allocator)),
437 .array_type_table = event.Locked(ArrayTypeTable).init(ArrayTypeTable.init(allocator)),
438 .ptr_type_table = event.Locked(PtrTypeTable).init(PtrTypeTable.init(allocator)),
439 .fn_type_table = event.Locked(FnTypeTable).init(FnTypeTable.init(allocator)),
449440 .c_int_types = undefined,
450441
451442 .meta_type = undefined,
......@@ -471,7 +462,7 @@ pub const Compilation = struct {
471462 .have_err_ret_tracing = false,
472463 .primitive_type_table = undefined,
473464
474 .fs_watch = undefined,
465 // .fs_watch = undefined,
475466 };
476467 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());
477468 comp.primitive_type_table = TypeTable.init(comp.arena());
......@@ -485,12 +476,12 @@ pub const Compilation = struct {
485476 }
486477
487478 comp.name = try Buffer.init(comp.arena(), name);
488 comp.llvm_triple = try target.getTriple(comp.arena());
489 comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);
479 comp.llvm_triple = try util.getTriple(comp.arena(), target);
480 comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);
490481 comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" });
491482
492483 const opt_level = switch (build_mode) {
493 builtin.Mode.Debug => llvm.CodeGenLevelNone,
484 .Debug => llvm.CodeGenLevelNone,
494485 else => llvm.CodeGenLevelAggressive,
495486 };
496487
......@@ -516,7 +507,7 @@ pub const Compilation = struct {
516507 opt_level,
517508 reloc_mode,
518509 llvm.CodeModelDefault,
519 false // TODO: add -ffunction-sections option
510 false, // TODO: add -ffunction-sections option
520511 ) orelse return error.OutOfMemory;
521512 defer llvm.DisposeTargetMachine(comp.target_machine);
522513
......@@ -526,8 +517,11 @@ pub const Compilation = struct {
526517 comp.target_layout_str = llvm.CopyStringRepOfTargetData(comp.target_data_ref) orelse return error.OutOfMemory;
527518 defer llvm.DisposeMessage(comp.target_layout_str);
528519
529 comp.events = try event.Channel(Event).create(comp.loop, 0);
530 defer comp.events.destroy();
520 comp.events = try allocator.create(event.Channel(Event));
521 defer allocator.destroy(comp.events);
522
523 comp.events.init([0]Event{});
524 defer comp.events.deinit();
531525
532526 if (root_src_path) |root_src| {
533527 const dirname = std.fs.path.dirname(root_src) orelse ".";
......@@ -540,13 +534,13 @@ pub const Compilation = struct {
540534 comp.root_package = try Package.create(comp.arena(), ".", "");
541535 }
542536
543 comp.fs_watch = try fs.Watch(*Scope.Root).create(loop, 16);
544 defer comp.fs_watch.destroy();
537 // comp.fs_watch = try fs.Watch(*Scope.Root).create(16);
538 // defer comp.fs_watch.destroy();
545539
546540 try comp.initTypes();
547541 defer comp.primitive_type_table.deinit();
548542
549 comp.main_loop_handle = async comp.mainLoop() catch unreachable;
543 // comp.main_loop_frame = async comp.mainLoop();
550544 // Set this to indicate that initialization completed successfully.
551545 // from here on out we must not return an error.
552546 // This must occur before the first suspend/await.
......@@ -555,12 +549,13 @@ pub const Compilation = struct {
555549 suspend;
556550 // From here on is cleanup.
557551
558 await (async comp.deinit_group.wait() catch unreachable);
552 comp.deinit_group.wait();
559553
560 if (comp.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
561 // TODO evented I/O?
562 std.fs.deleteTree(comp.arena(), tmp_dir) catch {};
563 } else |_| {};
554 if (comp.tmp_dir.getOrNull()) |tmp_dir_result|
555 if (tmp_dir_result.*) |tmp_dir| {
556 // TODO evented I/O?
557 std.fs.deleteTree(tmp_dir) catch {};
558 } else |_| {};
564559 }
565560
566561 /// it does ref the result because it could be an arbitrary integer size
......@@ -578,10 +573,10 @@ pub const Compilation = struct {
578573 error.Overflow => return error.Overflow,
579574 error.InvalidCharacter => unreachable, // we just checked the characters above
580575 };
581 const int_type = try await (async Type.Int.get(comp, Type.Int.Key{
576 const int_type = try Type.Int.get(comp, Type.Int.Key{
582577 .bit_count = bit_count,
583578 .is_signed = is_signed,
584 }) catch unreachable);
579 });
585580 errdefer int_type.base.base.deref();
586581 return &int_type.base;
587582 },
......@@ -603,12 +598,12 @@ pub const Compilation = struct {
603598 .base = Type{
604599 .name = "type",
605600 .base = Value{
606 .id = Value.Id.Type,
601 .id = .Type,
607602 .typ = undefined,
608603 .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
609604 },
610 .id = builtin.TypeId.Type,
611 .abi_alignment = Type.AbiAlignment.init(comp.loop),
605 .id = .Type,
606 .abi_alignment = Type.AbiAlignment.init(),
612607 },
613608 .value = undefined,
614609 };
......@@ -621,12 +616,12 @@ pub const Compilation = struct {
621616 .base = Type{
622617 .name = "void",
623618 .base = Value{
624 .id = Value.Id.Type,
619 .id = .Type,
625620 .typ = &Type.MetaType.get(comp).base,
626621 .ref_count = std.atomic.Int(usize).init(1),
627622 },
628 .id = builtin.TypeId.Void,
629 .abi_alignment = Type.AbiAlignment.init(comp.loop),
623 .id = .Void,
624 .abi_alignment = Type.AbiAlignment.init(),
630625 },
631626 };
632627 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);
......@@ -636,12 +631,12 @@ pub const Compilation = struct {
636631 .base = Type{
637632 .name = "noreturn",
638633 .base = Value{
639 .id = Value.Id.Type,
634 .id = .Type,
640635 .typ = &Type.MetaType.get(comp).base,
641636 .ref_count = std.atomic.Int(usize).init(1),
642637 },
643 .id = builtin.TypeId.NoReturn,
644 .abi_alignment = Type.AbiAlignment.init(comp.loop),
638 .id = .NoReturn,
639 .abi_alignment = Type.AbiAlignment.init(),
645640 },
646641 };
647642 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);
......@@ -651,12 +646,12 @@ pub const Compilation = struct {
651646 .base = Type{
652647 .name = "comptime_int",
653648 .base = Value{
654 .id = Value.Id.Type,
649 .id = .Type,
655650 .typ = &Type.MetaType.get(comp).base,
656651 .ref_count = std.atomic.Int(usize).init(1),
657652 },
658 .id = builtin.TypeId.ComptimeInt,
659 .abi_alignment = Type.AbiAlignment.init(comp.loop),
653 .id = .ComptimeInt,
654 .abi_alignment = Type.AbiAlignment.init(),
660655 },
661656 };
662657 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);
......@@ -666,12 +661,12 @@ pub const Compilation = struct {
666661 .base = Type{
667662 .name = "bool",
668663 .base = Value{
669 .id = Value.Id.Type,
664 .id = .Type,
670665 .typ = &Type.MetaType.get(comp).base,
671666 .ref_count = std.atomic.Int(usize).init(1),
672667 },
673 .id = builtin.TypeId.Bool,
674 .abi_alignment = Type.AbiAlignment.init(comp.loop),
668 .id = .Bool,
669 .abi_alignment = Type.AbiAlignment.init(),
675670 },
676671 };
677672 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);
......@@ -679,7 +674,7 @@ pub const Compilation = struct {
679674 comp.void_value = try comp.arena().create(Value.Void);
680675 comp.void_value.* = Value.Void{
681676 .base = Value{
682 .id = Value.Id.Void,
677 .id = .Void,
683678 .typ = &Type.Void.get(comp).base,
684679 .ref_count = std.atomic.Int(usize).init(1),
685680 },
......@@ -688,7 +683,7 @@ pub const Compilation = struct {
688683 comp.true_value = try comp.arena().create(Value.Bool);
689684 comp.true_value.* = Value.Bool{
690685 .base = Value{
691 .id = Value.Id.Bool,
686 .id = .Bool,
692687 .typ = &Type.Bool.get(comp).base,
693688 .ref_count = std.atomic.Int(usize).init(1),
694689 },
......@@ -698,7 +693,7 @@ pub const Compilation = struct {
698693 comp.false_value = try comp.arena().create(Value.Bool);
699694 comp.false_value.* = Value.Bool{
700695 .base = Value{
701 .id = Value.Id.Bool,
696 .id = .Bool,
702697 .typ = &Type.Bool.get(comp).base,
703698 .ref_count = std.atomic.Int(usize).init(1),
704699 },
......@@ -708,7 +703,7 @@ pub const Compilation = struct {
708703 comp.noreturn_value = try comp.arena().create(Value.NoReturn);
709704 comp.noreturn_value.* = Value.NoReturn{
710705 .base = Value{
711 .id = Value.Id.NoReturn,
706 .id = .NoReturn,
712707 .typ = &Type.NoReturn.get(comp).base,
713708 .ref_count = std.atomic.Int(usize).init(1),
714709 },
......@@ -720,16 +715,16 @@ pub const Compilation = struct {
720715 .base = Type{
721716 .name = cint.zig_name,
722717 .base = Value{
723 .id = Value.Id.Type,
718 .id = .Type,
724719 .typ = &Type.MetaType.get(comp).base,
725720 .ref_count = std.atomic.Int(usize).init(1),
726721 },
727 .id = builtin.TypeId.Int,
728 .abi_alignment = Type.AbiAlignment.init(comp.loop),
722 .id = .Int,
723 .abi_alignment = Type.AbiAlignment.init(),
729724 },
730725 .key = Type.Int.Key{
731726 .is_signed = cint.is_signed,
732 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),
727 .bit_count = cint.sizeInBits(comp.target),
733728 },
734729 .garbage_node = undefined,
735730 };
......@@ -741,12 +736,12 @@ pub const Compilation = struct {
741736 .base = Type{
742737 .name = "u8",
743738 .base = Value{
744 .id = Value.Id.Type,
739 .id = .Type,
745740 .typ = &Type.MetaType.get(comp).base,
746741 .ref_count = std.atomic.Int(usize).init(1),
747742 },
748 .id = builtin.TypeId.Int,
749 .abi_alignment = Type.AbiAlignment.init(comp.loop),
743 .id = .Int,
744 .abi_alignment = Type.AbiAlignment.init(),
750745 },
751746 .key = Type.Int.Key{
752747 .is_signed = false,
......@@ -758,8 +753,8 @@ pub const Compilation = struct {
758753 }
759754
760755 pub fn destroy(self: *Compilation) void {
761 cancel self.main_loop_handle;
762 resume self.destroy_handle;
756 // await self.main_loop_frame;
757 // resume self.destroy_frame;
763758 }
764759
765760 fn start(self: *Compilation) void {
......@@ -768,13 +763,13 @@ pub const Compilation = struct {
768763
769764 async fn mainLoop(self: *Compilation) void {
770765 // wait until start() is called
771 _ = await (async self.main_loop_future.get() catch unreachable);
766 _ = self.main_loop_future.get();
772767
773 var build_result = await (async self.initialCompile() catch unreachable);
768 var build_result = self.initialCompile();
774769
775770 while (true) {
776771 const link_result = if (build_result) blk: {
777 break :blk await (async self.maybeLink() catch unreachable);
772 break :blk self.maybeLink();
778773 } else |err| err;
779774 // this makes a handy error return trace and stack trace in debug mode
780775 if (std.debug.runtime_safety) {
......@@ -782,65 +777,65 @@ pub const Compilation = struct {
782777 }
783778
784779 const compile_errors = blk: {
785 const held = await (async self.compile_errors.acquire() catch unreachable);
780 const held = self.compile_errors.acquire();
786781 defer held.release();
787782 break :blk held.value.toOwnedSlice();
788783 };
789784
790785 if (link_result) |_| {
791786 if (compile_errors.len == 0) {
792 await (async self.events.put(Event.Ok) catch unreachable);
787 self.events.put(Event.Ok);
793788 } else {
794 await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
789 self.events.put(Event{ .Fail = compile_errors });
795790 }
796791 } else |err| {
797792 // if there's an error then the compile errors have dangling references
798793 self.gpa().free(compile_errors);
799794
800 await (async self.events.put(Event{ .Error = err }) catch unreachable);
795 self.events.put(Event{ .Error = err });
801796 }
802797
803 // First, get an item from the watch channel, waiting on the channel.
804 var group = event.Group(BuildError!void).init(self.loop);
805 {
806 const ev = (await (async self.fs_watch.channel.get() catch unreachable)) catch |err| {
807 build_result = err;
808 continue;
809 };
810 const root_scope = ev.data;
811 group.call(rebuildFile, self, root_scope) catch |err| {
812 build_result = err;
813 continue;
814 };
815 }
816 // Next, get all the items from the channel that are buffered up.
817 while (await (async self.fs_watch.channel.getOrNull() catch unreachable)) |ev_or_err| {
818 if (ev_or_err) |ev| {
819 const root_scope = ev.data;
820 group.call(rebuildFile, self, root_scope) catch |err| {
821 build_result = err;
822 continue;
823 };
824 } else |err| {
825 build_result = err;
826 continue;
827 }
828 }
829 build_result = await (async group.wait() catch unreachable);
798 // // First, get an item from the watch channel, waiting on the channel.
799 // var group = event.Group(BuildError!void).init(self.gpa());
800 // {
801 // const ev = (self.fs_watch.channel.get()) catch |err| {
802 // build_result = err;
803 // continue;
804 // };
805 // const root_scope = ev.data;
806 // group.call(rebuildFile, self, root_scope) catch |err| {
807 // build_result = err;
808 // continue;
809 // };
810 // }
811 // // Next, get all the items from the channel that are buffered up.
812 // while (self.fs_watch.channel.getOrNull()) |ev_or_err| {
813 // if (ev_or_err) |ev| {
814 // const root_scope = ev.data;
815 // group.call(rebuildFile, self, root_scope) catch |err| {
816 // build_result = err;
817 // continue;
818 // };
819 // } else |err| {
820 // build_result = err;
821 // continue;
822 // }
823 // }
824 // build_result = group.wait();
830825 }
831826 }
832827
833828 async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {
834829 const tree_scope = blk: {
835 const source_code = (await (async fs.readFile(
836 self.loop,
837 root_scope.realpath,
838 max_src_size,
839 ) catch unreachable)) catch |err| {
840 try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
841 return;
842 };
843 errdefer self.gpa().free(source_code);
830 const source_code = "";
831 // const source_code = fs.readFile(
832 // root_scope.realpath,
833 // max_src_size,
834 // ) catch |err| {
835 // try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
836 // return;
837 // };
838 // errdefer self.gpa().free(source_code);
844839
845840 const tree = try std.zig.parse(self.gpa(), source_code);
846841 errdefer {
......@@ -856,19 +851,18 @@ pub const Compilation = struct {
856851 const msg = try Msg.createFromParseErrorAndScope(self, tree_scope, parse_error);
857852 errdefer msg.destroy();
858853
859 try await (async self.addCompileErrorAsync(msg) catch unreachable);
854 try self.addCompileErrorAsync(msg);
860855 }
861856 if (tree_scope.tree.errors.len != 0) {
862857 return;
863858 }
864859
865 const locked_table = await (async root_scope.decls.table.acquireWrite() catch unreachable);
860 const locked_table = root_scope.decls.table.acquireWrite();
866861 defer locked_table.release();
867862
868 var decl_group = event.Group(BuildError!void).init(self.loop);
869 defer decl_group.deinit();
863 var decl_group = event.Group(BuildError!void).init(self.gpa());
870864
871 try await try async self.rebuildChangedDecls(
865 try self.rebuildChangedDecls(
872866 &decl_group,
873867 locked_table.value,
874868 root_scope.decls,
......@@ -876,7 +870,7 @@ pub const Compilation = struct {
876870 tree_scope,
877871 );
878872
879 try await (async decl_group.wait() catch unreachable);
873 try decl_group.wait();
880874 }
881875
882876 async fn rebuildChangedDecls(
......@@ -894,15 +888,15 @@ pub const Compilation = struct {
894888 while (ast_it.next()) |decl_ptr| {
895889 const decl = decl_ptr.*;
896890 switch (decl.id) {
897 ast.Node.Id.Comptime => {
891 .Comptime => {
898892 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl);
899893
900894 // TODO connect existing comptime decls to updated source files
901895
902896 try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node);
903897 },
904 ast.Node.Id.VarDecl => @panic("TODO"),
905 ast.Node.Id.FnProto => {
898 .VarDecl => @panic("TODO"),
899 .FnProto => {
906900 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
907901
908902 const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else {
......@@ -942,11 +936,11 @@ pub const Compilation = struct {
942936 .id = Decl.Id.Fn,
943937 .name = name,
944938 .visib = parseVisibToken(tree_scope.tree, fn_proto.visib_token),
945 .resolution = event.Future(BuildError!void).init(self.loop),
939 .resolution = event.Future(BuildError!void).init(),
946940 .parent_scope = &decl_scope.base,
947941 .tree_scope = tree_scope,
948942 },
949 .value = Decl.Fn.Val{ .Unresolved = {} },
943 .value = .Unresolved,
950944 .fn_proto = fn_proto,
951945 };
952946 tree_scope.base.ref();
......@@ -955,7 +949,7 @@ pub const Compilation = struct {
955949 try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table);
956950 }
957951 },
958 ast.Node.Id.TestDecl => @panic("TODO"),
952 .TestDecl => @panic("TODO"),
959953 else => unreachable,
960954 }
961955 }
......@@ -982,26 +976,26 @@ pub const Compilation = struct {
982976 };
983977 defer root_scope.base.deref(self);
984978
985 assert((try await try async self.fs_watch.addFile(root_scope.realpath, root_scope)) == null);
986 try await try async self.rebuildFile(root_scope);
979 // assert((try self.fs_watch.addFile(root_scope.realpath, root_scope)) == null);
980 try self.rebuildFile(root_scope);
987981 }
988982 }
989983
990984 async fn maybeLink(self: *Compilation) !void {
991 (await (async self.prelink_group.wait() catch unreachable)) catch |err| switch (err) {
985 (self.prelink_group.wait()) catch |err| switch (err) {
992986 error.SemanticAnalysisFailed => {},
993987 else => return err,
994988 };
995989
996990 const any_prelink_errors = blk: {
997 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
991 const compile_errors = self.compile_errors.acquire();
998992 defer compile_errors.release();
999993
1000994 break :blk compile_errors.value.len != 0;
1001995 };
1002996
1003997 if (!any_prelink_errors) {
1004 try await (async link(self) catch unreachable);
998 try link(self);
1005999 }
10061000 }
10071001
......@@ -1013,12 +1007,12 @@ pub const Compilation = struct {
10131007 node: *ast.Node,
10141008 expected_type: ?*Type,
10151009 ) !*ir.Code {
1016 const unanalyzed_code = try await (async ir.gen(
1010 const unanalyzed_code = try ir.gen(
10171011 comp,
10181012 node,
10191013 tree_scope,
10201014 scope,
1021 ) catch unreachable);
1015 );
10221016 defer unanalyzed_code.destroy(comp.gpa());
10231017
10241018 if (comp.verbose_ir) {
......@@ -1026,11 +1020,11 @@ pub const Compilation = struct {
10261020 unanalyzed_code.dump();
10271021 }
10281022
1029 const analyzed_code = try await (async ir.analyze(
1023 const analyzed_code = try ir.analyze(
10301024 comp,
10311025 unanalyzed_code,
10321026 expected_type,
1033 ) catch unreachable);
1027 );
10341028 errdefer analyzed_code.destroy(comp.gpa());
10351029
10361030 if (comp.verbose_ir) {
......@@ -1046,17 +1040,17 @@ pub const Compilation = struct {
10461040 tree_scope: *Scope.AstTree,
10471041 scope: *Scope,
10481042 comptime_node: *ast.Node.Comptime,
1049 ) !void {
1043 ) BuildError!void {
10501044 const void_type = Type.Void.get(comp);
10511045 defer void_type.base.base.deref(comp);
10521046
1053 const analyzed_code = (await (async genAndAnalyzeCode(
1047 const analyzed_code = genAndAnalyzeCode(
10541048 comp,
10551049 tree_scope,
10561050 scope,
10571051 comptime_node.expr,
10581052 &void_type.base,
1059 ) catch unreachable)) catch |err| switch (err) {
1053 ) catch |err| switch (err) {
10601054 // This poison value should not cause the errdefers to run. It simply means
10611055 // that comp.compile_errors is populated.
10621056 error.SemanticAnalysisFailed => return {},
......@@ -1069,7 +1063,7 @@ pub const Compilation = struct {
10691063 self: *Compilation,
10701064 decl: *Decl,
10711065 locked_table: *Decl.Table,
1072 ) !void {
1066 ) BuildError!void {
10731067 const is_export = decl.isExported(decl.tree_scope.tree);
10741068
10751069 if (is_export) {
......@@ -1109,17 +1103,17 @@ pub const Compilation = struct {
11091103 async fn addCompileErrorAsync(
11101104 self: *Compilation,
11111105 msg: *Msg,
1112 ) !void {
1106 ) BuildError!void {
11131107 errdefer msg.destroy();
11141108
1115 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
1109 const compile_errors = self.compile_errors.acquire();
11161110 defer compile_errors.release();
11171111
11181112 try compile_errors.value.append(msg);
11191113 }
11201114
1121 async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void {
1122 const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
1115 async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) BuildError!void {
1116 const exported_symbol_names = self.exported_symbol_names.acquire();
11231117 defer exported_symbol_names.release();
11241118
11251119 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
......@@ -1173,14 +1167,14 @@ pub const Compilation = struct {
11731167
11741168 /// cancels itself so no need to await or cancel the promise.
11751169 async fn startFindingNativeLibC(self: *Compilation) void {
1176 await (async self.loop.yield() catch unreachable);
1170 std.event.Loop.instance.?.yield();
11771171 // we don't care if it fails, we're just trying to kick off the future resolution
1178 _ = (await (async self.zig_compiler.getNativeLibC() catch unreachable)) catch return;
1172 _ = (self.zig_compiler.getNativeLibC()) catch return;
11791173 }
11801174
11811175 /// General Purpose Allocator. Must free when done.
11821176 fn gpa(self: Compilation) *mem.Allocator {
1183 return self.loop.allocator;
1177 return self.zig_compiler.allocator;
11841178 }
11851179
11861180 /// Arena Allocator. Automatically freed when the Compilation is destroyed.
......@@ -1191,8 +1185,8 @@ pub const Compilation = struct {
11911185 /// If the temporary directory for this compilation has not been created, it creates it.
11921186 /// Then it creates a random file name in that dir and returns it.
11931187 pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
1194 const tmp_dir = try await (async self.getTmpDir() catch unreachable);
1195 const file_prefix = await (async self.getRandomFileName() catch unreachable);
1188 const tmp_dir = try self.getTmpDir();
1189 const file_prefix = self.getRandomFileName();
11961190
11971191 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
11981192 defer self.gpa().free(file_name);
......@@ -1207,14 +1201,14 @@ pub const Compilation = struct {
12071201 /// Then returns it. The directory is unique to this Compilation and cleaned up when
12081202 /// the Compilation deinitializes.
12091203 async fn getTmpDir(self: *Compilation) ![]const u8 {
1210 if (await (async self.tmp_dir.start() catch unreachable)) |ptr| return ptr.*;
1211 self.tmp_dir.data = await (async self.getTmpDirImpl() catch unreachable);
1204 if (self.tmp_dir.start()) |ptr| return ptr.*;
1205 self.tmp_dir.data = self.getTmpDirImpl();
12121206 self.tmp_dir.resolve();
12131207 return self.tmp_dir.data;
12141208 }
12151209
12161210 async fn getTmpDirImpl(self: *Compilation) ![]u8 {
1217 const comp_dir_name = await (async self.getRandomFileName() catch unreachable);
1211 const comp_dir_name = self.getRandomFileName();
12181212 const zig_dir_path = try getZigDir(self.gpa());
12191213 defer self.gpa().free(zig_dir_path);
12201214
......@@ -1233,7 +1227,7 @@ pub const Compilation = struct {
12331227 var rand_bytes: [9]u8 = undefined;
12341228
12351229 {
1236 const held = await (async self.zig_compiler.prng.acquire() catch unreachable);
1230 const held = self.zig_compiler.prng.acquire();
12371231 defer held.release();
12381232
12391233 held.value.random.bytes(rand_bytes[0..]);
......@@ -1256,7 +1250,7 @@ pub const Compilation = struct {
12561250 node: *ast.Node,
12571251 expected_type: *Type,
12581252 ) !*Value {
1259 const analyzed_code = try await (async comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type) catch unreachable);
1253 const analyzed_code = try comp.genAndAnalyzeCode(tree_scope, scope, node, expected_type);
12601254 defer analyzed_code.destroy(comp.gpa());
12611255
12621256 return analyzed_code.getCompTimeResult(comp);
......@@ -1266,17 +1260,17 @@ pub const Compilation = struct {
12661260 const meta_type = &Type.MetaType.get(comp).base;
12671261 defer meta_type.base.deref(comp);
12681262
1269 const result_val = try await (async comp.analyzeConstValue(tree_scope, scope, node, meta_type) catch unreachable);
1263 const result_val = try comp.analyzeConstValue(tree_scope, scope, node, meta_type);
12701264 errdefer result_val.base.deref(comp);
12711265
12721266 return result_val.cast(Type).?;
12731267 }
12741268
12751269 /// This declaration has been blessed as going into the final code generation.
1276 pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void {
1277 if (await (async decl.resolution.start() catch unreachable)) |ptr| return ptr.*;
1270 pub async fn resolveDecl(comp: *Compilation, decl: *Decl) BuildError!void {
1271 if (decl.resolution.start()) |ptr| return ptr.*;
12781272
1279 decl.resolution.data = try await (async generateDecl(comp, decl) catch unreachable);
1273 decl.resolution.data = try generateDecl(comp, decl);
12801274 decl.resolution.resolve();
12811275 return decl.resolution.data;
12821276 }
......@@ -1295,24 +1289,24 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
12951289/// The function that actually does the generation.
12961290async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
12971291 switch (decl.id) {
1298 Decl.Id.Var => @panic("TODO"),
1299 Decl.Id.Fn => {
1292 .Var => @panic("TODO"),
1293 .Fn => {
13001294 const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
1301 return await (async generateDeclFn(comp, fn_decl) catch unreachable);
1295 return generateDeclFn(comp, fn_decl);
13021296 },
1303 Decl.Id.CompTime => @panic("TODO"),
1297 .CompTime => @panic("TODO"),
13041298 }
13051299}
13061300
13071301async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
13081302 const tree_scope = fn_decl.base.tree_scope;
13091303
1310 const body_node = fn_decl.fn_proto.body_node orelse return await (async generateDeclFnProto(comp, fn_decl) catch unreachable);
1304 const body_node = fn_decl.fn_proto.body_node orelse return generateDeclFnProto(comp, fn_decl);
13111305
13121306 const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);
13131307 defer fndef_scope.base.deref(comp);
13141308
1315 const fn_type = try await (async analyzeFnType(comp, tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto) catch unreachable);
1309 const fn_type = try analyzeFnType(comp, tree_scope, fn_decl.base.parent_scope, fn_decl.fn_proto);
13161310 defer fn_type.base.base.deref(comp);
13171311
13181312 var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name);
......@@ -1356,12 +1350,12 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
13561350 try fn_type.non_key.Normal.variable_list.append(var_scope);
13571351 }
13581352
1359 const analyzed_code = try await (async comp.genAndAnalyzeCode(
1353 const analyzed_code = try comp.genAndAnalyzeCode(
13601354 tree_scope,
13611355 fn_val.child_scope,
13621356 body_node,
13631357 fn_type.key.data.Normal.return_type,
1364 ) catch unreachable);
1358 );
13651359 errdefer analyzed_code.destroy(comp.gpa());
13661360
13671361 assert(fn_val.block_scope != null);
......@@ -1372,13 +1366,13 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
13721366 try comp.prelink_group.call(addFnToLinkSet, comp, fn_val);
13731367}
13741368
1375async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) void {
1369async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) Compilation.BuildError!void {
13761370 fn_val.base.ref();
13771371 defer fn_val.base.deref(comp);
13781372
13791373 fn_val.link_set_node.data = fn_val;
13801374
1381 const held = await (async comp.fn_link_set.acquire() catch unreachable);
1375 const held = comp.fn_link_set.acquire();
13821376 defer held.release();
13831377
13841378 held.value.append(fn_val.link_set_node);
......@@ -1395,10 +1389,10 @@ async fn analyzeFnType(
13951389 fn_proto: *ast.Node.FnProto,
13961390) !*Type.Fn {
13971391 const return_type_node = switch (fn_proto.return_type) {
1398 ast.Node.FnProto.ReturnType.Explicit => |n| n,
1399 ast.Node.FnProto.ReturnType.InferErrorSet => |n| n,
1392 .Explicit => |n| n,
1393 .InferErrorSet => |n| n,
14001394 };
1401 const return_type = try await (async comp.analyzeTypeExpr(tree_scope, scope, return_type_node) catch unreachable);
1395 const return_type = try comp.analyzeTypeExpr(tree_scope, scope, return_type_node);
14021396 return_type.base.deref(comp);
14031397
14041398 var params = ArrayList(Type.Fn.Param).init(comp.gpa());
......@@ -1414,7 +1408,7 @@ async fn analyzeFnType(
14141408 var it = fn_proto.params.iterator(0);
14151409 while (it.next()) |param_node_ptr| {
14161410 const param_node = param_node_ptr.*.cast(ast.Node.ParamDecl).?;
1417 const param_type = try await (async comp.analyzeTypeExpr(tree_scope, scope, param_node.type_node) catch unreachable);
1411 const param_type = try comp.analyzeTypeExpr(tree_scope, scope, param_node.type_node);
14181412 errdefer param_type.base.deref(comp);
14191413 try params.append(Type.Fn.Param{
14201414 .typ = param_type,
......@@ -1430,7 +1424,7 @@ async fn analyzeFnType(
14301424 .return_type = return_type,
14311425 .params = params.toOwnedSlice(),
14321426 .is_var_args = false, // TODO
1433 .cc = Type.Fn.CallingConvention.Auto, // TODO
1427 .cc = .Unspecified, // TODO
14341428 },
14351429 },
14361430 };
......@@ -1443,7 +1437,7 @@ async fn analyzeFnType(
14431437 comp.gpa().free(key.data.Normal.params);
14441438 };
14451439
1446 const fn_type = try await (async Type.Fn.get(comp, key) catch unreachable);
1440 const fn_type = try Type.Fn.get(comp, key);
14471441 key_consumed = true;
14481442 errdefer fn_type.base.base.deref(comp);
14491443
......@@ -1451,12 +1445,12 @@ async fn analyzeFnType(
14511445}
14521446
14531447async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1454 const fn_type = try await (async analyzeFnType(
1448 const fn_type = try analyzeFnType(
14551449 comp,
14561450 fn_decl.base.tree_scope,
14571451 fn_decl.base.parent_scope,
14581452 fn_decl.fn_proto,
1459 ) catch unreachable);
1453 );
14601454 defer fn_type.base.base.deref(comp);
14611455
14621456 var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name);
......@@ -1468,14 +1462,3 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
14681462 fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };
14691463 symbol_name_consumed = true;
14701464}
1471
1472// TODO these are hacks which should probably be solved by the language
1473fn getAwaitResult(allocator: *Allocator, handle: var) @typeInfo(@typeOf(handle)).Promise.child.? {
1474 var result: ?@typeInfo(@typeOf(handle)).Promise.child.? = null;
1475 cancel (async<allocator> getAwaitResultAsync(handle, &result) catch unreachable);
1476 return result.?;
1477}
1478
1479async fn getAwaitResultAsync(handle: var, out: *?@typeInfo(@typeOf(handle)).Promise.child.?) void {
1480 out.* = await handle;
1481}
src-self-hosted/decl.zig+5-5
......@@ -29,7 +29,7 @@ pub const Decl = struct {
2929
3030 pub fn isExported(base: *const Decl, tree: *ast.Tree) bool {
3131 switch (base.id) {
32 Id.Fn => {
32 .Fn => {
3333 const fn_decl = @fieldParentPtr(Fn, "base", base);
3434 return fn_decl.isExported(tree);
3535 },
......@@ -39,7 +39,7 @@ pub const Decl = struct {
3939
4040 pub fn getSpan(base: *const Decl) errmsg.Span {
4141 switch (base.id) {
42 Id.Fn => {
42 .Fn => {
4343 const fn_decl = @fieldParentPtr(Fn, "base", base);
4444 const fn_proto = fn_decl.fn_proto;
4545 const start = fn_proto.fn_token;
......@@ -74,7 +74,7 @@ pub const Decl = struct {
7474
7575 // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
7676 pub const Val = union(enum) {
77 Unresolved: void,
77 Unresolved,
7878 Fn: *Value.Fn,
7979 FnProto: *Value.FnProto,
8080 };
......@@ -83,7 +83,7 @@ pub const Decl = struct {
8383 return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
8484 const token = tree.tokens.at(tok_index);
8585 break :x switch (token.id) {
86 Token.Id.Extern => tree.tokenSlicePtr(token),
86 .Extern => tree.tokenSlicePtr(token),
8787 else => null,
8888 };
8989 } else null;
......@@ -92,7 +92,7 @@ pub const Decl = struct {
9292 pub fn isExported(self: Fn, tree: *ast.Tree) bool {
9393 if (self.fn_proto.extern_export_inline_token) |tok_index| {
9494 const token = tree.tokens.at(tok_index);
95 return token.id == Token.Id.Keyword_export;
95 return token.id == .Keyword_export;
9696 } else {
9797 return false;
9898 }
src-self-hosted/errmsg.zig+16-16
......@@ -62,17 +62,17 @@ pub const Msg = struct {
6262
6363 pub fn destroy(self: *Msg) void {
6464 switch (self.data) {
65 Data.Cli => |cli| {
65 .Cli => |cli| {
6666 cli.allocator.free(self.text);
6767 cli.allocator.free(self.realpath);
6868 cli.allocator.destroy(self);
6969 },
70 Data.PathAndTree => |path_and_tree| {
70 .PathAndTree => |path_and_tree| {
7171 path_and_tree.allocator.free(self.text);
7272 path_and_tree.allocator.free(self.realpath);
7373 path_and_tree.allocator.destroy(self);
7474 },
75 Data.ScopeAndComp => |scope_and_comp| {
75 .ScopeAndComp => |scope_and_comp| {
7676 scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation);
7777 scope_and_comp.compilation.gpa().free(self.text);
7878 scope_and_comp.compilation.gpa().free(self.realpath);
......@@ -83,11 +83,11 @@ pub const Msg = struct {
8383
8484 fn getAllocator(self: *const Msg) *mem.Allocator {
8585 switch (self.data) {
86 Data.Cli => |cli| return cli.allocator,
87 Data.PathAndTree => |path_and_tree| {
86 .Cli => |cli| return cli.allocator,
87 .PathAndTree => |path_and_tree| {
8888 return path_and_tree.allocator;
8989 },
90 Data.ScopeAndComp => |scope_and_comp| {
90 .ScopeAndComp => |scope_and_comp| {
9191 return scope_and_comp.compilation.gpa();
9292 },
9393 }
......@@ -95,11 +95,11 @@ pub const Msg = struct {
9595
9696 pub fn getTree(self: *const Msg) *ast.Tree {
9797 switch (self.data) {
98 Data.Cli => unreachable,
99 Data.PathAndTree => |path_and_tree| {
98 .Cli => unreachable,
99 .PathAndTree => |path_and_tree| {
100100 return path_and_tree.tree;
101101 },
102 Data.ScopeAndComp => |scope_and_comp| {
102 .ScopeAndComp => |scope_and_comp| {
103103 return scope_and_comp.tree_scope.tree;
104104 },
105105 }
......@@ -107,9 +107,9 @@ pub const Msg = struct {
107107
108108 pub fn getSpan(self: *const Msg) Span {
109109 return switch (self.data) {
110 Data.Cli => unreachable,
111 Data.PathAndTree => |path_and_tree| path_and_tree.span,
112 Data.ScopeAndComp => |scope_and_comp| scope_and_comp.span,
110 .Cli => unreachable,
111 .PathAndTree => |path_and_tree| path_and_tree.span,
112 .ScopeAndComp => |scope_and_comp| scope_and_comp.span,
113113 };
114114 }
115115
......@@ -230,7 +230,7 @@ pub const Msg = struct {
230230
231231 pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void {
232232 switch (msg.data) {
233 Data.Cli => {
233 .Cli => {
234234 try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text);
235235 return;
236236 },
......@@ -279,9 +279,9 @@ pub const Msg = struct {
279279
280280 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
281281 const color_on = switch (color) {
282 Color.Auto => file.isTty(),
283 Color.On => true,
284 Color.Off => false,
282 .Auto => file.isTty(),
283 .On => true,
284 .Off => false,
285285 };
286286 var stream = &file.outStream().stream;
287287 return msg.printToStream(stream, color_on);
src-self-hosted/ir.zig+223-225
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const Compilation = @import("compilation.zig").Compilation;
43const Scope = @import("scope.zig").Scope;
54const ast = std.zig.ast;
......@@ -33,13 +32,13 @@ pub const IrVal = union(enum) {
3332
3433 pub fn dump(self: IrVal) void {
3534 switch (self) {
36 IrVal.Unknown => std.debug.warn("Unknown"),
37 IrVal.KnownType => |typ| {
35 .Unknown => std.debug.warn("Unknown"),
36 .KnownType => |typ| {
3837 std.debug.warn("KnownType(");
3938 typ.dump();
4039 std.debug.warn(")");
4140 },
42 IrVal.KnownValue => |value| {
41 .KnownValue => |value| {
4342 std.debug.warn("KnownValue(");
4443 value.dump();
4544 std.debug.warn(")");
......@@ -113,37 +112,37 @@ pub const Inst = struct {
113112
114113 pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
115114 switch (base.id) {
116 Id.Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
117 Id.Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
118 Id.Call => return @fieldParentPtr(Call, "base", base).analyze(ira),
119 Id.DeclRef => return await (async @fieldParentPtr(DeclRef, "base", base).analyze(ira) catch unreachable),
120 Id.Ref => return await (async @fieldParentPtr(Ref, "base", base).analyze(ira) catch unreachable),
121 Id.DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira),
122 Id.CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira),
123 Id.Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira),
124 Id.Br => return @fieldParentPtr(Br, "base", base).analyze(ira),
125 Id.AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira),
126 Id.PtrType => return await (async @fieldParentPtr(PtrType, "base", base).analyze(ira) catch unreachable),
127 Id.VarPtr => return await (async @fieldParentPtr(VarPtr, "base", base).analyze(ira) catch unreachable),
128 Id.LoadPtr => return await (async @fieldParentPtr(LoadPtr, "base", base).analyze(ira) catch unreachable),
115 .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
116 .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
117 .Call => return @fieldParentPtr(Call, "base", base).analyze(ira),
118 .DeclRef => return @fieldParentPtr(DeclRef, "base", base).analyze(ira),
119 .Ref => return @fieldParentPtr(Ref, "base", base).analyze(ira),
120 .DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira),
121 .CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira),
122 .Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira),
123 .Br => return @fieldParentPtr(Br, "base", base).analyze(ira),
124 .AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira),
125 .PtrType => return @fieldParentPtr(PtrType, "base", base).analyze(ira),
126 .VarPtr => return @fieldParentPtr(VarPtr, "base", base).analyze(ira),
127 .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).analyze(ira),
129128 }
130129 }
131130
132131 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
133132 switch (base.id) {
134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
136 Id.Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val),
137 Id.VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val),
138 Id.LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val),
139 Id.DeclRef => unreachable,
140 Id.PtrType => unreachable,
141 Id.Ref => @panic("TODO"),
142 Id.DeclVar => @panic("TODO"),
143 Id.CheckVoidStmt => @panic("TODO"),
144 Id.Phi => @panic("TODO"),
145 Id.Br => @panic("TODO"),
146 Id.AddImplicitReturnType => @panic("TODO"),
133 .Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
134 .Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
135 .Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val),
136 .VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val),
137 .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val),
138 .DeclRef => unreachable,
139 .PtrType => unreachable,
140 .Ref => @panic("TODO"),
141 .DeclVar => @panic("TODO"),
142 .CheckVoidStmt => @panic("TODO"),
143 .Phi => @panic("TODO"),
144 .Br => @panic("TODO"),
145 .AddImplicitReturnType => @panic("TODO"),
147146 }
148147 }
149148
......@@ -165,7 +164,7 @@ pub const Inst = struct {
165164 param.ref_count -= 1;
166165 const child = param.child orelse return error.SemanticAnalysisFailed;
167166 switch (child.val) {
168 IrVal.Unknown => return error.SemanticAnalysisFailed,
167 .Unknown => return error.SemanticAnalysisFailed,
169168 else => return child,
170169 }
171170 }
......@@ -213,9 +212,9 @@ pub const Inst = struct {
213212 /// asserts that the type is known
214213 fn getKnownType(self: *Inst) *Type {
215214 switch (self.val) {
216 IrVal.KnownType => |typ| return typ,
217 IrVal.KnownValue => |value| return value.typ,
218 IrVal.Unknown => unreachable,
215 .KnownType => |typ| return typ,
216 .KnownValue => |value| return value.typ,
217 .Unknown => unreachable,
219218 }
220219 }
221220
......@@ -225,14 +224,14 @@ pub const Inst = struct {
225224
226225 pub fn isNoReturn(base: *const Inst) bool {
227226 switch (base.val) {
228 IrVal.Unknown => return false,
229 IrVal.KnownValue => |x| return x.typ.id == Type.Id.NoReturn,
230 IrVal.KnownType => |typ| return typ.id == Type.Id.NoReturn,
227 .Unknown => return false,
228 .KnownValue => |x| return x.typ.id == .NoReturn,
229 .KnownType => |typ| return typ.id == .NoReturn,
231230 }
232231 }
233232
234233 pub fn isCompTime(base: *const Inst) bool {
235 return base.val == IrVal.KnownValue;
234 return base.val == .KnownValue;
236235 }
237236
238237 pub fn linkToParent(self: *Inst, parent: *Inst) void {
......@@ -441,13 +440,13 @@ pub const Inst = struct {
441440 .volatility = self.params.volatility,
442441 });
443442 const elem_type = target.getKnownType();
444 const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
443 const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
445444 .child_type = elem_type,
446445 .mut = self.params.mut,
447446 .vol = self.params.volatility,
448 .size = Type.Pointer.Size.One,
449 .alignment = Type.Pointer.Align.Abi,
450 }) catch unreachable);
447 .size = .One,
448 .alignment = .Abi,
449 });
451450 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this
452451 // could be a ref of a global, for example
453452 new_inst.val = IrVal{ .KnownType = &ptr_type.base };
......@@ -474,25 +473,25 @@ pub const Inst = struct {
474473 }
475474
476475 pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {
477 (await (async ira.irb.comp.resolveDecl(self.params.decl) catch unreachable)) catch |err| switch (err) {
476 (ira.irb.comp.resolveDecl(self.params.decl)) catch |err| switch (err) {
478477 error.OutOfMemory => return error.OutOfMemory,
479478 else => return error.SemanticAnalysisFailed,
480479 };
481480 switch (self.params.decl.id) {
482 Decl.Id.CompTime => unreachable,
483 Decl.Id.Var => return error.Unimplemented,
484 Decl.Id.Fn => {
481 .CompTime => unreachable,
482 .Var => return error.Unimplemented,
483 .Fn => {
485484 const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl);
486485 const decl_val = switch (fn_decl.value) {
487 Decl.Fn.Val.Unresolved => unreachable,
488 Decl.Fn.Val.Fn => |fn_val| &fn_val.base,
489 Decl.Fn.Val.FnProto => |fn_proto| &fn_proto.base,
486 .Unresolved => unreachable,
487 .Fn => |fn_val| &fn_val.base,
488 .FnProto => |fn_proto| &fn_proto.base,
490489 };
491490 switch (self.params.lval) {
492 LVal.None => {
491 .None => {
493492 return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val);
494493 },
495 LVal.Ptr => return error.Unimplemented,
494 .Ptr => return error.Unimplemented,
496495 }
497496 },
498497 }
......@@ -519,21 +518,21 @@ pub const Inst = struct {
519518
520519 pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
521520 switch (self.params.var_scope.data) {
522 Scope.Var.Data.Const => @panic("TODO"),
523 Scope.Var.Data.Param => |param| {
521 .Const => @panic("TODO"),
522 .Param => |param| {
524523 const new_inst = try ira.irb.build(
525524 Inst.VarPtr,
526525 self.base.scope,
527526 self.base.span,
528527 Inst.VarPtr.Params{ .var_scope = self.params.var_scope },
529528 );
530 const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
529 const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
531530 .child_type = param.typ,
532 .mut = Type.Pointer.Mut.Const,
533 .vol = Type.Pointer.Vol.Non,
534 .size = Type.Pointer.Size.One,
535 .alignment = Type.Pointer.Align.Abi,
536 }) catch unreachable);
531 .mut = .Const,
532 .vol = .Non,
533 .size = .One,
534 .alignment = .Abi,
535 });
537536 new_inst.val = IrVal{ .KnownType = &ptr_type.base };
538537 return new_inst;
539538 },
......@@ -542,8 +541,8 @@ pub const Inst = struct {
542541
543542 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
544543 switch (self.params.var_scope.data) {
545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
546 Scope.Var.Data.Param => |param| return param.llvm_value,
544 .Const => unreachable, // turned into Inst.Const in analyze pass
545 .Param => |param| return param.llvm_value,
547546 }
548547 }
549548 };
......@@ -567,7 +566,7 @@ pub const Inst = struct {
567566 pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
568567 const target = try self.params.target.getAsParam();
569568 const target_type = target.getKnownType();
570 if (target_type.id != Type.Id.Pointer) {
569 if (target_type.id != .Pointer) {
571570 try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name);
572571 return error.SemanticAnalysisFailed;
573572 }
......@@ -661,13 +660,13 @@ pub const Inst = struct {
661660 } else blk: {
662661 break :blk Type.Pointer.Align{ .Abi = {} };
663662 };
664 const ptr_type = try await (async Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
663 const ptr_type = try Type.Pointer.get(ira.irb.comp, Type.Pointer.Key{
665664 .child_type = child_type,
666665 .mut = self.params.mut,
667666 .vol = self.params.vol,
668667 .size = self.params.size,
669668 .alignment = alignment,
670 }) catch unreachable);
669 });
671670 ptr_type.base.base.deref(ira.irb.comp);
672671
673672 return ira.irb.buildConstValue(self.base.scope, self.base.span, &ptr_type.base.base);
......@@ -715,7 +714,7 @@ pub const Inst = struct {
715714
716715 pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst {
717716 const target = try self.params.target.getAsParam();
718 if (target.getKnownType().id != Type.Id.Void) {
717 if (target.getKnownType().id != .Void) {
719718 try ira.addCompileError(self.base.span, "expression value is ignored");
720719 return error.SemanticAnalysisFailed;
721720 }
......@@ -838,7 +837,7 @@ pub const Inst = struct {
838837 const target = try self.params.target.getAsParam();
839838 const target_type = target.getKnownType();
840839 switch (target_type.id) {
841 Type.Id.ErrorUnion => {
840 .ErrorUnion => {
842841 return error.Unimplemented;
843842 // if (instr_is_comptime(value)) {
844843 // ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
......@@ -868,7 +867,7 @@ pub const Inst = struct {
868867 // ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
869868 // return ira->codegen->builtin_types.entry_bool;
870869 },
871 Type.Id.ErrorSet => {
870 .ErrorSet => {
872871 return ira.irb.buildConstBool(self.base.scope, self.base.span, true);
873872 },
874873 else => {
......@@ -1081,120 +1080,120 @@ pub const Builder = struct {
10811080
10821081 pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
10831082 switch (node.id) {
1084 ast.Node.Id.Root => unreachable,
1085 ast.Node.Id.Use => unreachable,
1086 ast.Node.Id.TestDecl => unreachable,
1087 ast.Node.Id.VarDecl => return error.Unimplemented,
1088 ast.Node.Id.Defer => return error.Unimplemented,
1089 ast.Node.Id.InfixOp => return error.Unimplemented,
1090 ast.Node.Id.PrefixOp => {
1083 .Root => unreachable,
1084 .Use => unreachable,
1085 .TestDecl => unreachable,
1086 .VarDecl => return error.Unimplemented,
1087 .Defer => return error.Unimplemented,
1088 .InfixOp => return error.Unimplemented,
1089 .PrefixOp => {
10911090 const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node);
10921091 switch (prefix_op.op) {
1093 ast.Node.PrefixOp.Op.AddressOf => return error.Unimplemented,
1094 ast.Node.PrefixOp.Op.ArrayType => |n| return error.Unimplemented,
1095 ast.Node.PrefixOp.Op.Await => return error.Unimplemented,
1096 ast.Node.PrefixOp.Op.BitNot => return error.Unimplemented,
1097 ast.Node.PrefixOp.Op.BoolNot => return error.Unimplemented,
1098 ast.Node.PrefixOp.Op.Cancel => return error.Unimplemented,
1099 ast.Node.PrefixOp.Op.OptionalType => return error.Unimplemented,
1100 ast.Node.PrefixOp.Op.Negation => return error.Unimplemented,
1101 ast.Node.PrefixOp.Op.NegationWrap => return error.Unimplemented,
1102 ast.Node.PrefixOp.Op.Resume => return error.Unimplemented,
1103 ast.Node.PrefixOp.Op.PtrType => |ptr_info| {
1104 const inst = try await (async irb.genPtrType(prefix_op, ptr_info, scope) catch unreachable);
1092 .AddressOf => return error.Unimplemented,
1093 .ArrayType => |n| return error.Unimplemented,
1094 .Await => return error.Unimplemented,
1095 .BitNot => return error.Unimplemented,
1096 .BoolNot => return error.Unimplemented,
1097 .Cancel => return error.Unimplemented,
1098 .OptionalType => return error.Unimplemented,
1099 .Negation => return error.Unimplemented,
1100 .NegationWrap => return error.Unimplemented,
1101 .Resume => return error.Unimplemented,
1102 .PtrType => |ptr_info| {
1103 const inst = try irb.genPtrType(prefix_op, ptr_info, scope);
11051104 return irb.lvalWrap(scope, inst, lval);
11061105 },
1107 ast.Node.PrefixOp.Op.SliceType => |ptr_info| return error.Unimplemented,
1108 ast.Node.PrefixOp.Op.Try => return error.Unimplemented,
1106 .SliceType => |ptr_info| return error.Unimplemented,
1107 .Try => return error.Unimplemented,
11091108 }
11101109 },
1111 ast.Node.Id.SuffixOp => {
1110 .SuffixOp => {
11121111 const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node);
11131112 switch (suffix_op.op) {
1114 @TagType(ast.Node.SuffixOp.Op).Call => |*call| {
1115 const inst = try await (async irb.genCall(suffix_op, call, scope) catch unreachable);
1113 .Call => |*call| {
1114 const inst = try irb.genCall(suffix_op, call, scope);
11161115 return irb.lvalWrap(scope, inst, lval);
11171116 },
1118 @TagType(ast.Node.SuffixOp.Op).ArrayAccess => |n| return error.Unimplemented,
1119 @TagType(ast.Node.SuffixOp.Op).Slice => |slice| return error.Unimplemented,
1120 @TagType(ast.Node.SuffixOp.Op).ArrayInitializer => |init_list| return error.Unimplemented,
1121 @TagType(ast.Node.SuffixOp.Op).StructInitializer => |init_list| return error.Unimplemented,
1122 @TagType(ast.Node.SuffixOp.Op).Deref => return error.Unimplemented,
1123 @TagType(ast.Node.SuffixOp.Op).UnwrapOptional => return error.Unimplemented,
1117 .ArrayAccess => |n| return error.Unimplemented,
1118 .Slice => |slice| return error.Unimplemented,
1119 .ArrayInitializer => |init_list| return error.Unimplemented,
1120 .StructInitializer => |init_list| return error.Unimplemented,
1121 .Deref => return error.Unimplemented,
1122 .UnwrapOptional => return error.Unimplemented,
11241123 }
11251124 },
1126 ast.Node.Id.Switch => return error.Unimplemented,
1127 ast.Node.Id.While => return error.Unimplemented,
1128 ast.Node.Id.For => return error.Unimplemented,
1129 ast.Node.Id.If => return error.Unimplemented,
1130 ast.Node.Id.ControlFlowExpression => {
1125 .Switch => return error.Unimplemented,
1126 .While => return error.Unimplemented,
1127 .For => return error.Unimplemented,
1128 .If => return error.Unimplemented,
1129 .ControlFlowExpression => {
11311130 const control_flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", node);
1132 return await (async irb.genControlFlowExpr(control_flow_expr, scope, lval) catch unreachable);
1131 return irb.genControlFlowExpr(control_flow_expr, scope, lval);
11331132 },
1134 ast.Node.Id.Suspend => return error.Unimplemented,
1135 ast.Node.Id.VarType => return error.Unimplemented,
1136 ast.Node.Id.ErrorType => return error.Unimplemented,
1137 ast.Node.Id.FnProto => return error.Unimplemented,
1138 ast.Node.Id.PromiseType => return error.Unimplemented,
1139 ast.Node.Id.IntegerLiteral => {
1133 .Suspend => return error.Unimplemented,
1134 .VarType => return error.Unimplemented,
1135 .ErrorType => return error.Unimplemented,
1136 .FnProto => return error.Unimplemented,
1137 .AnyFrameType => return error.Unimplemented,
1138 .IntegerLiteral => {
11401139 const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node);
11411140 return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval);
11421141 },
1143 ast.Node.Id.FloatLiteral => return error.Unimplemented,
1144 ast.Node.Id.StringLiteral => {
1142 .FloatLiteral => return error.Unimplemented,
1143 .StringLiteral => {
11451144 const str_lit = @fieldParentPtr(ast.Node.StringLiteral, "base", node);
1146 const inst = try await (async irb.genStrLit(str_lit, scope) catch unreachable);
1145 const inst = try irb.genStrLit(str_lit, scope);
11471146 return irb.lvalWrap(scope, inst, lval);
11481147 },
1149 ast.Node.Id.MultilineStringLiteral => return error.Unimplemented,
1150 ast.Node.Id.CharLiteral => return error.Unimplemented,
1151 ast.Node.Id.BoolLiteral => return error.Unimplemented,
1152 ast.Node.Id.NullLiteral => return error.Unimplemented,
1153 ast.Node.Id.UndefinedLiteral => return error.Unimplemented,
1154 ast.Node.Id.Unreachable => return error.Unimplemented,
1155 ast.Node.Id.Identifier => {
1148 .MultilineStringLiteral => return error.Unimplemented,
1149 .CharLiteral => return error.Unimplemented,
1150 .BoolLiteral => return error.Unimplemented,
1151 .NullLiteral => return error.Unimplemented,
1152 .UndefinedLiteral => return error.Unimplemented,
1153 .Unreachable => return error.Unimplemented,
1154 .Identifier => {
11561155 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", node);
1157 return await (async irb.genIdentifier(identifier, scope, lval) catch unreachable);
1156 return irb.genIdentifier(identifier, scope, lval);
11581157 },
1159 ast.Node.Id.GroupedExpression => {
1158 .GroupedExpression => {
11601159 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);
1161 return await (async irb.genNode(grouped_expr.expr, scope, lval) catch unreachable);
1160 return irb.genNode(grouped_expr.expr, scope, lval);
11621161 },
1163 ast.Node.Id.BuiltinCall => return error.Unimplemented,
1164 ast.Node.Id.ErrorSetDecl => return error.Unimplemented,
1165 ast.Node.Id.ContainerDecl => return error.Unimplemented,
1166 ast.Node.Id.Asm => return error.Unimplemented,
1167 ast.Node.Id.Comptime => return error.Unimplemented,
1168 ast.Node.Id.Block => {
1162 .BuiltinCall => return error.Unimplemented,
1163 .ErrorSetDecl => return error.Unimplemented,
1164 .ContainerDecl => return error.Unimplemented,
1165 .Asm => return error.Unimplemented,
1166 .Comptime => return error.Unimplemented,
1167 .Block => {
11691168 const block = @fieldParentPtr(ast.Node.Block, "base", node);
1170 const inst = try await (async irb.genBlock(block, scope) catch unreachable);
1169 const inst = try irb.genBlock(block, scope);
11711170 return irb.lvalWrap(scope, inst, lval);
11721171 },
1173 ast.Node.Id.DocComment => return error.Unimplemented,
1174 ast.Node.Id.SwitchCase => return error.Unimplemented,
1175 ast.Node.Id.SwitchElse => return error.Unimplemented,
1176 ast.Node.Id.Else => return error.Unimplemented,
1177 ast.Node.Id.Payload => return error.Unimplemented,
1178 ast.Node.Id.PointerPayload => return error.Unimplemented,
1179 ast.Node.Id.PointerIndexPayload => return error.Unimplemented,
1180 ast.Node.Id.ContainerField => return error.Unimplemented,
1181 ast.Node.Id.ErrorTag => return error.Unimplemented,
1182 ast.Node.Id.AsmInput => return error.Unimplemented,
1183 ast.Node.Id.AsmOutput => return error.Unimplemented,
1184 ast.Node.Id.ParamDecl => return error.Unimplemented,
1185 ast.Node.Id.FieldInitializer => return error.Unimplemented,
1186 ast.Node.Id.EnumLiteral => return error.Unimplemented,
1172 .DocComment => return error.Unimplemented,
1173 .SwitchCase => return error.Unimplemented,
1174 .SwitchElse => return error.Unimplemented,
1175 .Else => return error.Unimplemented,
1176 .Payload => return error.Unimplemented,
1177 .PointerPayload => return error.Unimplemented,
1178 .PointerIndexPayload => return error.Unimplemented,
1179 .ContainerField => return error.Unimplemented,
1180 .ErrorTag => return error.Unimplemented,
1181 .AsmInput => return error.Unimplemented,
1182 .AsmOutput => return error.Unimplemented,
1183 .ParamDecl => return error.Unimplemented,
1184 .FieldInitializer => return error.Unimplemented,
1185 .EnumLiteral => return error.Unimplemented,
11871186 }
11881187 }
11891188
11901189 async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {
1191 const fn_ref = try await (async irb.genNode(suffix_op.lhs, scope, LVal.None) catch unreachable);
1190 const fn_ref = try irb.genNode(suffix_op.lhs, scope, .None);
11921191
11931192 const args = try irb.arena().alloc(*Inst, call.params.len);
11941193 var it = call.params.iterator(0);
11951194 var i: usize = 0;
11961195 while (it.next()) |arg_node_ptr| : (i += 1) {
1197 args[i] = try await (async irb.genNode(arg_node_ptr.*, scope, LVal.None) catch unreachable);
1196 args[i] = try irb.genNode(arg_node_ptr.*, scope, .None);
11981197 }
11991198
12001199 //bool is_async = node->data.fn_call_expr.is_async;
......@@ -1239,7 +1238,7 @@ pub const Builder = struct {
12391238 //} else {
12401239 // align_value = nullptr;
12411240 //}
1242 const child_type = try await (async irb.genNode(prefix_op.rhs, scope, LVal.None) catch unreachable);
1241 const child_type = try irb.genNode(prefix_op.rhs, scope, .None);
12431242
12441243 //uint32_t bit_offset_start = 0;
12451244 //if (node->data.pointer_type.bit_offset_start != nullptr) {
......@@ -1273,9 +1272,9 @@ pub const Builder = struct {
12731272
12741273 return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{
12751274 .child_type = child_type,
1276 .mut = Type.Pointer.Mut.Mut,
1277 .vol = Type.Pointer.Vol.Non,
1278 .size = Type.Pointer.Size.Many,
1275 .mut = .Mut,
1276 .vol = .Non,
1277 .size = .Many,
12791278 .alignment = null,
12801279 });
12811280 }
......@@ -1287,15 +1286,15 @@ pub const Builder = struct {
12871286 var scope = target_scope;
12881287 while (true) {
12891288 switch (scope.id) {
1290 Scope.Id.CompTime => return true,
1291 Scope.Id.FnDef => return false,
1292 Scope.Id.Decls => unreachable,
1293 Scope.Id.Root => unreachable,
1294 Scope.Id.AstTree => unreachable,
1295 Scope.Id.Block,
1296 Scope.Id.Defer,
1297 Scope.Id.DeferExpr,
1298 Scope.Id.Var,
1289 .CompTime => return true,
1290 .FnDef => return false,
1291 .Decls => unreachable,
1292 .Root => unreachable,
1293 .AstTree => unreachable,
1294 .Block,
1295 .Defer,
1296 .DeferExpr,
1297 .Var,
12991298 => scope = scope.parent.?,
13001299 }
13011300 }
......@@ -1366,23 +1365,23 @@ pub const Builder = struct {
13661365 buf[buf.len - 1] = 0;
13671366
13681367 // next make an array value
1369 const array_val = try await (async Value.Array.createOwnedBuffer(irb.comp, buf) catch unreachable);
1368 const array_val = try Value.Array.createOwnedBuffer(irb.comp, buf);
13701369 buf_cleaned = true;
13711370 defer array_val.base.deref(irb.comp);
13721371
13731372 // then make a pointer value pointing at the first element
1374 const ptr_val = try await (async Value.Ptr.createArrayElemPtr(
1373 const ptr_val = try Value.Ptr.createArrayElemPtr(
13751374 irb.comp,
13761375 array_val,
1377 Type.Pointer.Mut.Const,
1378 Type.Pointer.Size.Many,
1376 .Const,
1377 .Many,
13791378 0,
1380 ) catch unreachable);
1379 );
13811380 defer ptr_val.base.deref(irb.comp);
13821381
13831382 return irb.buildConstValue(scope, src_span, &ptr_val.base);
13841383 } else {
1385 const array_val = try await (async Value.Array.createOwnedBuffer(irb.comp, buf) catch unreachable);
1384 const array_val = try Value.Array.createOwnedBuffer(irb.comp, buf);
13861385 buf_cleaned = true;
13871386 defer array_val.base.deref(irb.comp);
13881387
......@@ -1438,7 +1437,7 @@ pub const Builder = struct {
14381437 child_scope = &defer_child_scope.base;
14391438 continue;
14401439 }
1441 const statement_value = try await (async irb.genNode(statement_node, child_scope, LVal.None) catch unreachable);
1440 const statement_value = try irb.genNode(statement_node, child_scope, .None);
14421441
14431442 is_continuation_unreachable = statement_value.isNoReturn();
14441443 if (is_continuation_unreachable) {
......@@ -1481,7 +1480,7 @@ pub const Builder = struct {
14811480 try block_scope.incoming_values.append(
14821481 try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true),
14831482 );
1484 _ = try await (async irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
1483 _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit);
14851484
14861485 _ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{
14871486 .dest_block = block_scope.end_block,
......@@ -1496,7 +1495,7 @@ pub const Builder = struct {
14961495 });
14971496 }
14981497
1499 _ = try await (async irb.genDefersForBlock(child_scope, outer_block_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
1498 _ = try irb.genDefersForBlock(child_scope, outer_block_scope, .ScopeExit);
15001499 return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
15011500 }
15021501
......@@ -1507,9 +1506,9 @@ pub const Builder = struct {
15071506 lval: LVal,
15081507 ) !*Inst {
15091508 switch (control_flow_expr.kind) {
1510 ast.Node.ControlFlowExpression.Kind.Break => |arg| return error.Unimplemented,
1511 ast.Node.ControlFlowExpression.Kind.Continue => |arg| return error.Unimplemented,
1512 ast.Node.ControlFlowExpression.Kind.Return => {
1509 .Break => |arg| return error.Unimplemented,
1510 .Continue => |arg| return error.Unimplemented,
1511 .Return => {
15131512 const src_span = Span.token(control_flow_expr.ltoken);
15141513 if (scope.findFnDef() == null) {
15151514 try irb.comp.addCompileError(
......@@ -1534,7 +1533,7 @@ pub const Builder = struct {
15341533
15351534 const outer_scope = irb.begin_scope.?;
15361535 const return_value = if (control_flow_expr.rhs) |rhs| blk: {
1537 break :blk try await (async irb.genNode(rhs, scope, LVal.None) catch unreachable);
1536 break :blk try irb.genNode(rhs, scope, .None);
15381537 } else blk: {
15391538 break :blk try irb.buildConstVoid(scope, src_span, true);
15401539 };
......@@ -1545,7 +1544,7 @@ pub const Builder = struct {
15451544 const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");
15461545 const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");
15471546 if (!have_err_defers) {
1548 _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
1547 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
15491548 }
15501549
15511550 const is_err = try irb.build(
......@@ -1568,7 +1567,7 @@ pub const Builder = struct {
15681567
15691568 try irb.setCursorAtEndAndAppendBlock(err_block);
15701569 if (have_err_defers) {
1571 _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ErrorExit) catch unreachable);
1570 _ = try irb.genDefersForBlock(scope, outer_scope, .ErrorExit);
15721571 }
15731572 if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) {
15741573 _ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{});
......@@ -1580,7 +1579,7 @@ pub const Builder = struct {
15801579
15811580 try irb.setCursorAtEndAndAppendBlock(ok_block);
15821581 if (have_err_defers) {
1583 _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
1582 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
15841583 }
15851584 _ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{
15861585 .dest_block = ret_stmt_block,
......@@ -1590,7 +1589,7 @@ pub const Builder = struct {
15901589 try irb.setCursorAtEndAndAppendBlock(ret_stmt_block);
15911590 return irb.genAsyncReturn(scope, src_span, return_value, false);
15921591 } else {
1593 _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
1592 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
15941593 return irb.genAsyncReturn(scope, src_span, return_value, false);
15951594 }
15961595 },
......@@ -1610,14 +1609,14 @@ pub const Builder = struct {
16101609 // return &const_instruction->base;
16111610 //}
16121611
1613 if (await (async irb.comp.getPrimitiveType(name) catch unreachable)) |result| {
1612 if (irb.comp.getPrimitiveType(name)) |result| {
16141613 if (result) |primitive_type| {
16151614 defer primitive_type.base.deref(irb.comp);
16161615 switch (lval) {
16171616 // if (lval == LValPtr) {
16181617 // return ir_build_ref(irb, scope, node, value, false, false);
1619 LVal.Ptr => return error.Unimplemented,
1620 LVal.None => return irb.buildConstValue(scope, src_span, &primitive_type.base),
1618 .Ptr => return error.Unimplemented,
1619 .None => return irb.buildConstValue(scope, src_span, &primitive_type.base),
16211620 }
16221621 }
16231622 } else |err| switch (err) {
......@@ -1628,23 +1627,23 @@ pub const Builder = struct {
16281627 error.OutOfMemory => return error.OutOfMemory,
16291628 }
16301629
1631 switch (await (async irb.findIdent(scope, name) catch unreachable)) {
1632 Ident.Decl => |decl| {
1630 switch (irb.findIdent(scope, name)) {
1631 .Decl => |decl| {
16331632 return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{
16341633 .decl = decl,
16351634 .lval = lval,
16361635 });
16371636 },
1638 Ident.VarScope => |var_scope| {
1637 .VarScope => |var_scope| {
16391638 const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope });
16401639 switch (lval) {
1641 LVal.Ptr => return var_ptr,
1642 LVal.None => {
1640 .Ptr => return var_ptr,
1641 .None => {
16431642 return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr });
16441643 },
16451644 }
16461645 },
1647 Ident.NotFound => {},
1646 .NotFound => {},
16481647 }
16491648
16501649 //if (node->owner->any_imports_failed) {
......@@ -1671,25 +1670,25 @@ pub const Builder = struct {
16711670 var scope = inner_scope;
16721671 while (scope != outer_scope) {
16731672 switch (scope.id) {
1674 Scope.Id.Defer => {
1673 .Defer => {
16751674 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
16761675 switch (defer_scope.kind) {
1677 Scope.Defer.Kind.ScopeExit => result.scope_exit += 1,
1678 Scope.Defer.Kind.ErrorExit => result.error_exit += 1,
1676 .ScopeExit => result.scope_exit += 1,
1677 .ErrorExit => result.error_exit += 1,
16791678 }
16801679 scope = scope.parent orelse break;
16811680 },
1682 Scope.Id.FnDef => break,
1681 .FnDef => break,
16831682
1684 Scope.Id.CompTime,
1685 Scope.Id.Block,
1686 Scope.Id.Decls,
1687 Scope.Id.Root,
1688 Scope.Id.Var,
1683 .CompTime,
1684 .Block,
1685 .Decls,
1686 .Root,
1687 .Var,
16891688 => scope = scope.parent orelse break,
16901689
1691 Scope.Id.DeferExpr => unreachable,
1692 Scope.Id.AstTree => unreachable,
1690 .DeferExpr => unreachable,
1691 .AstTree => unreachable,
16931692 }
16941693 }
16951694 return result;
......@@ -1705,19 +1704,19 @@ pub const Builder = struct {
17051704 var is_noreturn = false;
17061705 while (true) {
17071706 switch (scope.id) {
1708 Scope.Id.Defer => {
1707 .Defer => {
17091708 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
17101709 const generate = switch (defer_scope.kind) {
1711 Scope.Defer.Kind.ScopeExit => true,
1712 Scope.Defer.Kind.ErrorExit => gen_kind == Scope.Defer.Kind.ErrorExit,
1710 .ScopeExit => true,
1711 .ErrorExit => gen_kind == .ErrorExit,
17131712 };
17141713 if (generate) {
17151714 const defer_expr_scope = defer_scope.defer_expr_scope;
1716 const instruction = try await (async irb.genNode(
1715 const instruction = try irb.genNode(
17171716 defer_expr_scope.expr_node,
17181717 &defer_expr_scope.base,
1719 LVal.None,
1720 ) catch unreachable);
1718 .None,
1719 );
17211720 if (instruction.isNoReturn()) {
17221721 is_noreturn = true;
17231722 } else {
......@@ -1730,32 +1729,32 @@ pub const Builder = struct {
17301729 }
17311730 }
17321731 },
1733 Scope.Id.FnDef,
1734 Scope.Id.Decls,
1735 Scope.Id.Root,
1732 .FnDef,
1733 .Decls,
1734 .Root,
17361735 => return is_noreturn,
17371736
1738 Scope.Id.CompTime,
1739 Scope.Id.Block,
1740 Scope.Id.Var,
1737 .CompTime,
1738 .Block,
1739 .Var,
17411740 => scope = scope.parent orelse return is_noreturn,
17421741
1743 Scope.Id.DeferExpr => unreachable,
1744 Scope.Id.AstTree => unreachable,
1742 .DeferExpr => unreachable,
1743 .AstTree => unreachable,
17451744 }
17461745 }
17471746 }
17481747
17491748 pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst {
17501749 switch (lval) {
1751 LVal.None => return instruction,
1752 LVal.Ptr => {
1750 .None => return instruction,
1751 .Ptr => {
17531752 // We needed a pointer to a value, but we got a value. So we create
17541753 // an instruction which just makes a const pointer of it.
17551754 return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{
17561755 .target = instruction,
1757 .mut = Type.Pointer.Mut.Const,
1758 .volatility = Type.Pointer.Vol.Non,
1756 .mut = .Const,
1757 .volatility = .Non,
17591758 });
17601759 },
17611760 }
......@@ -1781,9 +1780,9 @@ pub const Builder = struct {
17811780 .scope = scope,
17821781 .debug_id = self.next_debug_id,
17831782 .val = switch (I.ir_val_init) {
1784 IrVal.Init.Unknown => IrVal.Unknown,
1785 IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
1786 IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
1783 .Unknown => IrVal.Unknown,
1784 .NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
1785 .Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
17871786 },
17881787 .ref_count = 0,
17891788 .span = span,
......@@ -1902,7 +1901,6 @@ pub const Builder = struct {
19021901 );
19031902 }
19041903 return error.Unimplemented;
1905
19061904 }
19071905
19081906 const Ident = union(enum) {
......@@ -1915,16 +1913,16 @@ pub const Builder = struct {
19151913 var s = scope;
19161914 while (true) {
19171915 switch (s.id) {
1918 Scope.Id.Root => return Ident.NotFound,
1919 Scope.Id.Decls => {
1916 .Root => return .NotFound,
1917 .Decls => {
19201918 const decls = @fieldParentPtr(Scope.Decls, "base", s);
1921 const locked_table = await (async decls.table.acquireRead() catch unreachable);
1919 const locked_table = decls.table.acquireRead();
19221920 defer locked_table.release();
19231921 if (locked_table.value.get(name)) |entry| {
19241922 return Ident{ .Decl = entry.value };
19251923 }
19261924 },
1927 Scope.Id.Var => {
1925 .Var => {
19281926 const var_scope = @fieldParentPtr(Scope.Var, "base", s);
19291927 if (mem.eql(u8, var_scope.name, name)) {
19301928 return Ident{ .VarScope = var_scope };
......@@ -2047,7 +2045,7 @@ const Analyze = struct {
20472045 fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst {
20482046 const dest_type = optional_dest_type orelse return target;
20492047 const from_type = target.getKnownType();
2050 if (from_type == dest_type or from_type.id == Type.Id.NoReturn) return target;
2048 if (from_type == dest_type or from_type.id == .NoReturn) return target;
20512049 return self.analyzeCast(target, target, dest_type);
20522050 }
20532051
......@@ -2311,7 +2309,7 @@ const Analyze = struct {
23112309 //}
23122310
23132311 // cast from comptime-known integer to another integer where the value fits
2314 if (target.isCompTime() and (from_type.id == Type.Id.Int or from_type.id == Type.Id.ComptimeInt)) cast: {
2312 if (target.isCompTime() and (from_type.id == .Int or from_type.id == .ComptimeInt)) cast: {
23152313 const target_val = target.val.KnownValue;
23162314 const from_int = &target_val.cast(Value.Int).?.big_int;
23172315 const fits = fits: {
......@@ -2534,7 +2532,7 @@ pub async fn gen(
25342532 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
25352533 try irb.setCursorAtEndAndAppendBlock(entry_block);
25362534
2537 const result = try await (async irb.genNode(body_node, scope, LVal.None) catch unreachable);
2535 const result = try irb.genNode(body_node, scope, .None);
25382536 if (!result.isNoReturn()) {
25392537 // no need for save_err_ret_addr because this cannot return error
25402538 _ = try irb.genAsyncReturn(scope, Span.token(body_node.lastToken()), result, true);
......@@ -2564,7 +2562,7 @@ pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type)
25642562 continue;
25652563 }
25662564
2567 const return_inst = try await (async old_instruction.analyze(&ira) catch unreachable);
2565 const return_inst = try old_instruction.analyze(&ira);
25682566 assert(return_inst.val != IrVal.Unknown); // at least the type should be known at this point
25692567 return_inst.linkToParent(old_instruction);
25702568 // Note: if we ever modify the above to handle error.CompileError by continuing analysis,
src-self-hosted/libc_installation.zig+67-65
......@@ -1,9 +1,11 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const event = std.event;
4const Target = @import("target.zig").Target;
4const util = @import("util.zig");
5const Target = std.Target;
56const c = @import("c.zig");
67const fs = std.fs;
8const Allocator = std.mem.Allocator;
79
810/// See the render function implementation for documentation of the fields.
911pub const LibCInstallation = struct {
......@@ -29,7 +31,7 @@ pub const LibCInstallation = struct {
2931
3032 pub fn parse(
3133 self: *LibCInstallation,
32 allocator: *std.mem.Allocator,
34 allocator: *Allocator,
3335 libc_file: []const u8,
3436 stderr: *std.io.OutStream(fs.File.WriteError),
3537 ) !void {
......@@ -71,7 +73,7 @@ pub const LibCInstallation = struct {
7173 if (std.mem.eql(u8, name, key)) {
7274 found_keys[i].found = true;
7375 switch (@typeInfo(@typeOf(@field(self, key)))) {
74 builtin.TypeId.Optional => {
76 .Optional => {
7577 if (value.len == 0) {
7678 @field(self, key) = null;
7779 } else {
......@@ -136,15 +138,15 @@ pub const LibCInstallation = struct {
136138 self.static_lib_dir orelse "",
137139 self.msvc_lib_dir orelse "",
138140 self.kernel32_lib_dir orelse "",
139 self.dynamic_linker_path orelse Target(Target.Native).getDynamicLinkerPath(),
141 self.dynamic_linker_path orelse util.getDynamicLinkerPath(Target{ .Native = {} }),
140142 );
141143 }
142144
143145 /// Finds the default, native libc.
144 pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void {
146 pub async fn findNative(self: *LibCInstallation, allocator: *Allocator) !void {
145147 self.initEmpty();
146 var group = event.Group(FindError!void).init(loop);
147 errdefer group.deinit();
148 var group = event.Group(FindError!void).init(allocator);
149 errdefer group.wait() catch {};
148150 var windows_sdk: ?*c.ZigWindowsSDK = null;
149151 errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk));
150152
......@@ -156,11 +158,11 @@ pub const LibCInstallation = struct {
156158 windows_sdk = sdk;
157159
158160 if (sdk.msvc_lib_dir_ptr != 0) {
159 self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
161 self.msvc_lib_dir = try std.mem.dupe(allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
160162 }
161 try group.call(findNativeKernel32LibDir, self, loop, sdk);
162 try group.call(findNativeIncludeDirWindows, self, loop, sdk);
163 try group.call(findNativeLibDirWindows, self, loop, sdk);
163 try group.call(findNativeKernel32LibDir, allocator, self, sdk);
164 try group.call(findNativeIncludeDirWindows, self, allocator, sdk);
165 try group.call(findNativeLibDirWindows, self, allocator, sdk);
164166 },
165167 c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory,
166168 c.ZigFindWindowsSdkError.NotFound => return error.NotFound,
......@@ -168,20 +170,20 @@ pub const LibCInstallation = struct {
168170 }
169171 },
170172 .linux => {
171 try group.call(findNativeIncludeDirLinux, self, loop);
172 try group.call(findNativeLibDirLinux, self, loop);
173 try group.call(findNativeStaticLibDir, self, loop);
174 try group.call(findNativeDynamicLinker, self, loop);
173 try group.call(findNativeIncludeDirLinux, self, allocator);
174 try group.call(findNativeLibDirLinux, self, allocator);
175 try group.call(findNativeStaticLibDir, self, allocator);
176 try group.call(findNativeDynamicLinker, self, allocator);
175177 },
176178 .macosx, .freebsd, .netbsd => {
177 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
179 self.include_dir = try std.mem.dupe(allocator, u8, "/usr/include");
178180 },
179181 else => @compileError("unimplemented: find libc for this OS"),
180182 }
181 return await (async group.wait() catch unreachable);
183 return group.wait();
182184 }
183185
184 async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {
186 async fn findNativeIncludeDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
185187 const cc_exe = std.os.getenv("CC") orelse "cc";
186188 const argv = [_][]const u8{
187189 cc_exe,
......@@ -191,7 +193,7 @@ pub const LibCInstallation = struct {
191193 "/dev/null",
192194 };
193195 // TODO make this use event loop
194 const errorable_result = std.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
196 const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
195197 const exec_result = if (std.debug.runtime_safety) blk: {
196198 break :blk errorable_result catch unreachable;
197199 } else blk: {
......@@ -201,12 +203,12 @@ pub const LibCInstallation = struct {
201203 };
202204 };
203205 defer {
204 loop.allocator.free(exec_result.stdout);
205 loop.allocator.free(exec_result.stderr);
206 allocator.free(exec_result.stdout);
207 allocator.free(exec_result.stderr);
206208 }
207209
208210 switch (exec_result.term) {
209 std.ChildProcess.Term.Exited => |code| {
211 .Exited => |code| {
210212 if (code != 0) return error.CCompilerExitCode;
211213 },
212214 else => {
......@@ -215,7 +217,7 @@ pub const LibCInstallation = struct {
215217 }
216218
217219 var it = std.mem.tokenize(exec_result.stderr, "\n\r");
218 var search_paths = std.ArrayList([]const u8).init(loop.allocator);
220 var search_paths = std.ArrayList([]const u8).init(allocator);
219221 defer search_paths.deinit();
220222 while (it.next()) |line| {
221223 if (line.len != 0 and line[0] == ' ') {
......@@ -231,11 +233,11 @@ pub const LibCInstallation = struct {
231233 while (path_i < search_paths.len) : (path_i += 1) {
232234 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
233235 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");
234 const stdlib_path = try fs.path.join(loop.allocator, [_][]const u8{ search_path, "stdlib.h" });
235 defer loop.allocator.free(stdlib_path);
236 const stdlib_path = try fs.path.join(allocator, [_][]const u8{ search_path, "stdlib.h" });
237 defer allocator.free(stdlib_path);
236238
237239 if (try fileExists(stdlib_path)) {
238 self.include_dir = try std.mem.dupe(loop.allocator, u8, search_path);
240 self.include_dir = try std.mem.dupe(allocator, u8, search_path);
239241 return;
240242 }
241243 }
......@@ -243,11 +245,11 @@ pub const LibCInstallation = struct {
243245 return error.LibCStdLibHeaderNotFound;
244246 }
245247
246 async fn findNativeIncludeDirWindows(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) !void {
248 async fn findNativeIncludeDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) !void {
247249 var search_buf: [2]Search = undefined;
248250 const searches = fillSearch(&search_buf, sdk);
249251
250 var result_buf = try std.Buffer.initSize(loop.allocator, 0);
252 var result_buf = try std.Buffer.initSize(allocator, 0);
251253 defer result_buf.deinit();
252254
253255 for (searches) |search| {
......@@ -256,10 +258,10 @@ pub const LibCInstallation = struct {
256258 try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);
257259
258260 const stdlib_path = try fs.path.join(
259 loop.allocator,
261 allocator,
260262 [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
261263 );
262 defer loop.allocator.free(stdlib_path);
264 defer allocator.free(stdlib_path);
263265
264266 if (try fileExists(stdlib_path)) {
265267 self.include_dir = result_buf.toOwnedSlice();
......@@ -270,11 +272,11 @@ pub const LibCInstallation = struct {
270272 return error.LibCStdLibHeaderNotFound;
271273 }
272274
273 async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) FindError!void {
275 async fn findNativeLibDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void {
274276 var search_buf: [2]Search = undefined;
275277 const searches = fillSearch(&search_buf, sdk);
276278
277 var result_buf = try std.Buffer.initSize(loop.allocator, 0);
279 var result_buf = try std.Buffer.initSize(allocator, 0);
278280 defer result_buf.deinit();
279281
280282 for (searches) |search| {
......@@ -282,16 +284,16 @@ pub const LibCInstallation = struct {
282284 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
283285 try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version);
284286 switch (builtin.arch) {
285 builtin.Arch.i386 => try stream.write("x86"),
286 builtin.Arch.x86_64 => try stream.write("x64"),
287 builtin.Arch.aarch64 => try stream.write("arm"),
287 .i386 => try stream.write("x86"),
288 .x86_64 => try stream.write("x64"),
289 .aarch64 => try stream.write("arm"),
288290 else => return error.UnsupportedArchitecture,
289291 }
290292 const ucrt_lib_path = try fs.path.join(
291 loop.allocator,
293 allocator,
292294 [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
293295 );
294 defer loop.allocator.free(ucrt_lib_path);
296 defer allocator.free(ucrt_lib_path);
295297 if (try fileExists(ucrt_lib_path)) {
296298 self.lib_dir = result_buf.toOwnedSlice();
297299 return;
......@@ -300,15 +302,15 @@ pub const LibCInstallation = struct {
300302 return error.LibCRuntimeNotFound;
301303 }
302304
303 async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void {
304 self.lib_dir = try await (async ccPrintFileName(loop, "crt1.o", true) catch unreachable);
305 async fn findNativeLibDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
306 self.lib_dir = try ccPrintFileName(allocator, "crt1.o", true);
305307 }
306308
307 async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
308 self.static_lib_dir = try await (async ccPrintFileName(loop, "crtbegin.o", true) catch unreachable);
309 async fn findNativeStaticLibDir(self: *LibCInstallation, allocator: *Allocator) FindError!void {
310 self.static_lib_dir = try ccPrintFileName(allocator, "crtbegin.o", true);
309311 }
310312
311 async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {
313 async fn findNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator) FindError!void {
312314 var dyn_tests = [_]DynTest{
313315 DynTest{
314316 .name = "ld-linux-x86-64.so.2",
......@@ -319,12 +321,12 @@ pub const LibCInstallation = struct {
319321 .result = null,
320322 },
321323 };
322 var group = event.Group(FindError!void).init(loop);
323 errdefer group.deinit();
324 var group = event.Group(FindError!void).init(allocator);
325 errdefer group.wait() catch {};
324326 for (dyn_tests) |*dyn_test| {
325 try group.call(testNativeDynamicLinker, self, loop, dyn_test);
327 try group.call(testNativeDynamicLinker, self, allocator, dyn_test);
326328 }
327 try await (async group.wait() catch unreachable);
329 try group.wait();
328330 for (dyn_tests) |*dyn_test| {
329331 if (dyn_test.result) |result| {
330332 self.dynamic_linker_path = result;
......@@ -338,8 +340,8 @@ pub const LibCInstallation = struct {
338340 result: ?[]const u8,
339341 };
340342
341 async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void {
342 if (await (async ccPrintFileName(loop, dyn_test.name, false) catch unreachable)) |result| {
343 async fn testNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator, dyn_test: *DynTest) FindError!void {
344 if (ccPrintFileName(allocator, dyn_test.name, false)) |result| {
343345 dyn_test.result = result;
344346 return;
345347 } else |err| switch (err) {
......@@ -348,11 +350,11 @@ pub const LibCInstallation = struct {
348350 }
349351 }
350352
351 async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop, sdk: *c.ZigWindowsSDK) FindError!void {
353 async fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *c.ZigWindowsSDK) FindError!void {
352354 var search_buf: [2]Search = undefined;
353355 const searches = fillSearch(&search_buf, sdk);
354356
355 var result_buf = try std.Buffer.initSize(loop.allocator, 0);
357 var result_buf = try std.Buffer.initSize(allocator, 0);
356358 defer result_buf.deinit();
357359
358360 for (searches) |search| {
......@@ -360,16 +362,16 @@ pub const LibCInstallation = struct {
360362 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
361363 try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version);
362364 switch (builtin.arch) {
363 builtin.Arch.i386 => try stream.write("x86\\"),
364 builtin.Arch.x86_64 => try stream.write("x64\\"),
365 builtin.Arch.aarch64 => try stream.write("arm\\"),
365 .i386 => try stream.write("x86\\"),
366 .x86_64 => try stream.write("x64\\"),
367 .aarch64 => try stream.write("arm\\"),
366368 else => return error.UnsupportedArchitecture,
367369 }
368370 const kernel32_path = try fs.path.join(
369 loop.allocator,
371 allocator,
370372 [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
371373 );
372 defer loop.allocator.free(kernel32_path);
374 defer allocator.free(kernel32_path);
373375 if (try fileExists(kernel32_path)) {
374376 self.kernel32_lib_dir = result_buf.toOwnedSlice();
375377 return;
......@@ -380,7 +382,7 @@ pub const LibCInstallation = struct {
380382
381383 fn initEmpty(self: *LibCInstallation) void {
382384 self.* = LibCInstallation{
383 .include_dir = ([*]const u8)(undefined)[0..0],
385 .include_dir = @as([*]const u8, undefined)[0..0],
384386 .lib_dir = null,
385387 .static_lib_dir = null,
386388 .msvc_lib_dir = null,
......@@ -391,15 +393,15 @@ pub const LibCInstallation = struct {
391393};
392394
393395/// caller owns returned memory
394async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bool) ![]u8 {
396async fn ccPrintFileName(allocator: *Allocator, o_file: []const u8, want_dirname: bool) ![]u8 {
395397 const cc_exe = std.os.getenv("CC") orelse "cc";
396 const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
397 defer loop.allocator.free(arg1);
398 const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file);
399 defer allocator.free(arg1);
398400 const argv = [_][]const u8{ cc_exe, arg1 };
399401
400402 // TODO This simulates evented I/O for the child process exec
401 await (async loop.yield() catch unreachable);
402 const errorable_result = std.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
403 std.event.Loop.instance.?.yield();
404 const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
403405 const exec_result = if (std.debug.runtime_safety) blk: {
404406 break :blk errorable_result catch unreachable;
405407 } else blk: {
......@@ -409,8 +411,8 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
409411 };
410412 };
411413 defer {
412 loop.allocator.free(exec_result.stdout);
413 loop.allocator.free(exec_result.stderr);
414 allocator.free(exec_result.stdout);
415 allocator.free(exec_result.stderr);
414416 }
415417 switch (exec_result.term) {
416418 .Exited => |code| {
......@@ -425,9 +427,9 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
425427 const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
426428
427429 if (want_dirname) {
428 return std.mem.dupe(loop.allocator, u8, dirname);
430 return std.mem.dupe(allocator, u8, dirname);
429431 } else {
430 return std.mem.dupe(loop.allocator, u8, line);
432 return std.mem.dupe(allocator, u8, line);
431433 }
432434}
433435
src-self-hosted/link.zig+52-52
......@@ -1,12 +1,12 @@
11const std = @import("std");
22const mem = std.mem;
33const c = @import("c.zig");
4const builtin = @import("builtin");
5const ObjectFormat = builtin.ObjectFormat;
64const Compilation = @import("compilation.zig").Compilation;
7const Target = @import("target.zig").Target;
5const Target = std.Target;
6const ObjectFormat = Target.ObjectFormat;
87const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
98const assert = std.debug.assert;
9const util = @import("util.zig");
1010
1111const Context = struct {
1212 comp: *Compilation,
......@@ -26,7 +26,7 @@ pub async fn link(comp: *Compilation) !void {
2626 .comp = comp,
2727 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
2828 .args = undefined,
29 .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe,
29 .link_in_crt = comp.haveLibC() and comp.kind == .Exe,
3030 .link_err = {},
3131 .link_msg = undefined,
3232 .libc = undefined,
......@@ -41,14 +41,14 @@ pub async fn link(comp: *Compilation) !void {
4141 } else {
4242 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
4343 switch (comp.kind) {
44 Compilation.Kind.Exe => {
44 .Exe => {
4545 try ctx.out_file_path.append(comp.target.exeFileExt());
4646 },
47 Compilation.Kind.Lib => {
48 try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static));
47 .Lib => {
48 try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());
4949 },
50 Compilation.Kind.Obj => {
51 try ctx.out_file_path.append(comp.target.objFileExt());
50 .Obj => {
51 try ctx.out_file_path.append(comp.target.oFileExt());
5252 },
5353 }
5454 }
......@@ -61,7 +61,7 @@ pub async fn link(comp: *Compilation) !void {
6161 ctx.libc = ctx.comp.override_libc orelse blk: {
6262 switch (comp.target) {
6363 Target.Native => {
64 break :blk (await (async comp.zig_compiler.getNativeLibC() catch unreachable)) catch return error.LibCRequiredButNotProvidedOrFound;
64 break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
6565 },
6666 else => return error.LibCRequiredButNotProvidedOrFound,
6767 }
......@@ -78,12 +78,12 @@ pub async fn link(comp: *Compilation) !void {
7878 std.debug.warn("\n");
7979 }
8080
81 const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat());
81 const extern_ofmt = toExternObjectFormatType(util.getObjectFormat(comp.target));
8282 const args_slice = ctx.args.toSlice();
8383
8484 {
8585 // LLD is not thread-safe, so we grab a global lock.
86 const held = await (async comp.zig_compiler.lld_lock.acquire() catch unreachable);
86 const held = comp.zig_compiler.lld_lock.acquire();
8787 defer held.release();
8888
8989 // Not evented I/O. LLD does its own multithreading internally.
......@@ -121,21 +121,21 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void {
121121
122122fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType {
123123 return switch (ofmt) {
124 ObjectFormat.unknown => c.ZigLLVM_UnknownObjectFormat,
125 ObjectFormat.coff => c.ZigLLVM_COFF,
126 ObjectFormat.elf => c.ZigLLVM_ELF,
127 ObjectFormat.macho => c.ZigLLVM_MachO,
128 ObjectFormat.wasm => c.ZigLLVM_Wasm,
124 .unknown => c.ZigLLVM_UnknownObjectFormat,
125 .coff => c.ZigLLVM_COFF,
126 .elf => c.ZigLLVM_ELF,
127 .macho => c.ZigLLVM_MachO,
128 .wasm => c.ZigLLVM_Wasm,
129129 };
130130}
131131
132132fn constructLinkerArgs(ctx: *Context) !void {
133 switch (ctx.comp.target.getObjectFormat()) {
134 ObjectFormat.unknown => unreachable,
135 ObjectFormat.coff => return constructLinkerArgsCoff(ctx),
136 ObjectFormat.elf => return constructLinkerArgsElf(ctx),
137 ObjectFormat.macho => return constructLinkerArgsMachO(ctx),
138 ObjectFormat.wasm => return constructLinkerArgsWasm(ctx),
133 switch (util.getObjectFormat(ctx.comp.target)) {
134 .unknown => unreachable,
135 .coff => return constructLinkerArgsCoff(ctx),
136 .elf => return constructLinkerArgsElf(ctx),
137 .macho => return constructLinkerArgsMachO(ctx),
138 .wasm => return constructLinkerArgsWasm(ctx),
139139 }
140140}
141141
......@@ -154,7 +154,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
154154 //bool shared = !g->is_static && is_lib;
155155 //Buf *soname = nullptr;
156156 if (ctx.comp.is_static) {
157 if (ctx.comp.target.isArmOrThumb()) {
157 if (util.isArmOrThumb(ctx.comp.target)) {
158158 try ctx.args.append(c"-Bstatic");
159159 } else {
160160 try ctx.args.append(c"-static");
......@@ -222,7 +222,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
222222 if (!ctx.comp.is_static) {
223223 const dl = blk: {
224224 if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
225 if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl;
225 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
226226 return error.LibCMissingDynamicLinker;
227227 };
228228 try ctx.args.append(c"-dynamic-linker");
......@@ -324,9 +324,9 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
324324 }
325325
326326 switch (ctx.comp.target.getArch()) {
327 builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
328 builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),
329 builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
327 .i386 => try ctx.args.append(c"-MACHINE:X86"),
328 .x86_64 => try ctx.args.append(c"-MACHINE:X64"),
329 .aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
330330 else => return error.UnsupportedLinkArchitecture,
331331 }
332332
......@@ -336,7 +336,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
336336 try ctx.args.append(c"/SUBSYSTEM:console");
337337 }
338338
339 const is_library = ctx.comp.kind == Compilation.Kind.Lib;
339 const is_library = ctx.comp.kind == .Lib;
340340
341341 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());
342342 try ctx.args.append(out_arg.ptr);
......@@ -349,7 +349,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
349349
350350 if (ctx.link_in_crt) {
351351 const lib_str = if (ctx.comp.is_static) "lib" else "";
352 const d_str = if (ctx.comp.build_mode == builtin.Mode.Debug) "d" else "";
352 const d_str = if (ctx.comp.build_mode == .Debug) "d" else "";
353353
354354 if (ctx.comp.is_static) {
355355 const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);
......@@ -400,7 +400,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
400400 try addFnObjects(ctx);
401401
402402 switch (ctx.comp.kind) {
403 Compilation.Kind.Exe, Compilation.Kind.Lib => {
403 .Exe, .Lib => {
404404 if (!ctx.comp.haveLibC()) {
405405 @panic("TODO");
406406 //Buf *builtin_o_path = build_o(g, "builtin");
......@@ -412,7 +412,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
412412 //Buf *compiler_rt_o_path = build_compiler_rt(g);
413413 //lj->args.append(buf_ptr(compiler_rt_o_path));
414414 },
415 Compilation.Kind.Obj => {},
415 .Obj => {},
416416 }
417417
418418 //Buf *def_contents = buf_alloc();
......@@ -469,7 +469,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
469469 try ctx.args.append(c"-export_dynamic");
470470 }
471471
472 const is_lib = ctx.comp.kind == Compilation.Kind.Lib;
472 const is_lib = ctx.comp.kind == .Lib;
473473 const shared = !ctx.comp.is_static and is_lib;
474474 if (ctx.comp.is_static) {
475475 try ctx.args.append(c"-static");
......@@ -512,14 +512,14 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
512512
513513 const platform = try DarwinPlatform.get(ctx.comp);
514514 switch (platform.kind) {
515 DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"),
516 DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
517 DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
515 .MacOS => try ctx.args.append(c"-macosx_version_min"),
516 .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
517 .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
518518 }
519519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
520520 try ctx.args.append(ver_str.ptr);
521521
522 if (ctx.comp.kind == Compilation.Kind.Exe) {
522 if (ctx.comp.kind == .Exe) {
523523 if (ctx.comp.is_static) {
524524 try ctx.args.append(c"-no_pie");
525525 } else {
......@@ -542,7 +542,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
542542 try ctx.args.append(c"-lcrt0.o");
543543 } else {
544544 switch (platform.kind) {
545 DarwinPlatform.Kind.MacOS => {
545 .MacOS => {
546546 if (platform.versionLessThan(10, 5)) {
547547 try ctx.args.append(c"-lcrt1.o");
548548 } else if (platform.versionLessThan(10, 6)) {
......@@ -551,8 +551,8 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
551551 try ctx.args.append(c"-lcrt1.10.6.o");
552552 }
553553 },
554 DarwinPlatform.Kind.IPhoneOS => {
555 if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
554 .IPhoneOS => {
555 if (ctx.comp.target.getArch() == .aarch64) {
556556 // iOS does not need any crt1 files for arm64
557557 } else if (platform.versionLessThan(3, 1)) {
558558 try ctx.args.append(c"-lcrt1.o");
......@@ -560,7 +560,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
560560 try ctx.args.append(c"-lcrt1.3.1.o");
561561 }
562562 },
563 DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed
563 .IPhoneOSSimulator => {}, // no crt1.o needed
564564 }
565565 }
566566
......@@ -605,7 +605,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
605605 try ctx.args.append(c"dynamic_lookup");
606606 }
607607
608 if (platform.kind == DarwinPlatform.Kind.MacOS) {
608 if (platform.kind == .MacOS) {
609609 if (platform.versionLessThan(10, 5)) {
610610 try ctx.args.append(c"-lgcc_s.10.4");
611611 } else if (platform.versionLessThan(10, 6)) {
......@@ -659,17 +659,17 @@ const DarwinPlatform = struct {
659659 fn get(comp: *Compilation) !DarwinPlatform {
660660 var result: DarwinPlatform = undefined;
661661 const ver_str = switch (comp.darwin_version_min) {
662 Compilation.DarwinVersionMin.MacOS => |ver| blk: {
663 result.kind = Kind.MacOS;
662 .MacOS => |ver| blk: {
663 result.kind = .MacOS;
664664 break :blk ver;
665665 },
666 Compilation.DarwinVersionMin.Ios => |ver| blk: {
667 result.kind = Kind.IPhoneOS;
666 .Ios => |ver| blk: {
667 result.kind = .IPhoneOS;
668668 break :blk ver;
669669 },
670 Compilation.DarwinVersionMin.None => blk: {
670 .None => blk: {
671671 assert(comp.target.getOs() == .macosx);
672 result.kind = Kind.MacOS;
672 result.kind = .MacOS;
673673 break :blk "10.14";
674674 },
675675 };
......@@ -686,11 +686,11 @@ const DarwinPlatform = struct {
686686 return error.InvalidDarwinVersionString;
687687 }
688688
689 if (result.kind == Kind.IPhoneOS) {
689 if (result.kind == .IPhoneOS) {
690690 switch (comp.target.getArch()) {
691 builtin.Arch.i386,
692 builtin.Arch.x86_64,
693 => result.kind = Kind.IPhoneOSSimulator,
691 .i386,
692 .x86_64,
693 => result.kind = .IPhoneOSSimulator,
694694 else => {},
695695 }
696696 }
src-self-hosted/llvm.zig+1-2
......@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
21const c = @import("c.zig");
32const assert = @import("std").debug.assert;
43
......@@ -268,7 +267,7 @@ pub const FnInline = extern enum {
268267};
269268
270269fn removeNullability(comptime T: type) type {
271 comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
270 comptime assert(@typeInfo(T).Pointer.size == .C);
272271 return *T.Child;
273272}
274273
src-self-hosted/main.zig+89-122
......@@ -18,7 +18,7 @@ const Args = arg.Args;
1818const Flag = arg.Flag;
1919const ZigCompiler = @import("compilation.zig").ZigCompiler;
2020const Compilation = @import("compilation.zig").Compilation;
21const Target = @import("target.zig").Target;
21const Target = std.Target;
2222const errmsg = @import("errmsg.zig");
2323const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2424
......@@ -26,6 +26,8 @@ var stderr_file: fs.File = undefined;
2626var stderr: *io.OutStream(fs.File.WriteError) = undefined;
2727var stdout: *io.OutStream(fs.File.WriteError) = undefined;
2828
29pub const io_mode = .evented;
30
2931pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
3032
3133const usage =
......@@ -258,47 +260,47 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
258260 process.exit(0);
259261 }
260262
261 const build_mode = blk: {
263 const build_mode: std.builtin.Mode = blk: {
262264 if (flags.single("mode")) |mode_flag| {
263265 if (mem.eql(u8, mode_flag, "debug")) {
264 break :blk builtin.Mode.Debug;
266 break :blk .Debug;
265267 } else if (mem.eql(u8, mode_flag, "release-fast")) {
266 break :blk builtin.Mode.ReleaseFast;
268 break :blk .ReleaseFast;
267269 } else if (mem.eql(u8, mode_flag, "release-safe")) {
268 break :blk builtin.Mode.ReleaseSafe;
270 break :blk .ReleaseSafe;
269271 } else if (mem.eql(u8, mode_flag, "release-small")) {
270 break :blk builtin.Mode.ReleaseSmall;
272 break :blk .ReleaseSmall;
271273 } else unreachable;
272274 } else {
273 break :blk builtin.Mode.Debug;
275 break :blk .Debug;
274276 }
275277 };
276278
277 const color = blk: {
279 const color: errmsg.Color = blk: {
278280 if (flags.single("color")) |color_flag| {
279281 if (mem.eql(u8, color_flag, "auto")) {
280 break :blk errmsg.Color.Auto;
282 break :blk .Auto;
281283 } else if (mem.eql(u8, color_flag, "on")) {
282 break :blk errmsg.Color.On;
284 break :blk .On;
283285 } else if (mem.eql(u8, color_flag, "off")) {
284 break :blk errmsg.Color.Off;
286 break :blk .Off;
285287 } else unreachable;
286288 } else {
287 break :blk errmsg.Color.Auto;
289 break :blk .Auto;
288290 }
289291 };
290292
291 const emit_type = blk: {
293 const emit_type: Compilation.Emit = blk: {
292294 if (flags.single("emit")) |emit_flag| {
293295 if (mem.eql(u8, emit_flag, "asm")) {
294 break :blk Compilation.Emit.Assembly;
296 break :blk .Assembly;
295297 } else if (mem.eql(u8, emit_flag, "bin")) {
296 break :blk Compilation.Emit.Binary;
298 break :blk .Binary;
297299 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {
298 break :blk Compilation.Emit.LlvmIr;
300 break :blk .LlvmIr;
299301 } else unreachable;
300302 } else {
301 break :blk Compilation.Emit.Binary;
303 break :blk .Binary;
302304 }
303305 };
304306
......@@ -383,11 +385,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
383385
384386 var override_libc: LibCInstallation = undefined;
385387
386 var loop: event.Loop = undefined;
387 try loop.initMultiThreaded(allocator);
388 defer loop.deinit();
389
390 var zig_compiler = try ZigCompiler.init(&loop);
388 var zig_compiler = try ZigCompiler.init(allocator);
391389 defer zig_compiler.deinit();
392390
393391 var comp = try Compilation.create(
......@@ -403,7 +401,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
403401 defer comp.destroy();
404402
405403 if (flags.single("libc")) |libc_path| {
406 parseLibcPaths(loop.allocator, &override_libc, libc_path);
404 parseLibcPaths(allocator, &override_libc, libc_path);
407405 comp.override_libc = &override_libc;
408406 }
409407
......@@ -463,25 +461,24 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
463461 comp.link_objects = link_objects;
464462
465463 comp.start();
466 // TODO const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);
467 loop.run();
464 const frame = async processBuildEvents(comp, color);
468465}
469466
470467async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
471468 var count: usize = 0;
472469 while (true) {
473470 // TODO directly awaiting async should guarantee memory allocation elision
474 const build_event = await (async comp.events.get() catch unreachable);
471 const build_event = comp.events.get();
475472 count += 1;
476473
477474 switch (build_event) {
478 Compilation.Event.Ok => {
475 .Ok => {
479476 stderr.print("Build {} succeeded\n", count) catch process.exit(1);
480477 },
481 Compilation.Event.Error => |err| {
478 .Error => |err| {
482479 stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1);
483480 },
484 Compilation.Event.Fail => |msgs| {
481 .Fail => |msgs| {
485482 stderr.print("Build {} compile errors:\n", count) catch process.exit(1);
486483 for (msgs) |msg| {
487484 defer msg.destroy();
......@@ -536,7 +533,7 @@ const Fmt = struct {
536533 seen: event.Locked(SeenMap),
537534 any_error: bool,
538535 color: errmsg.Color,
539 loop: *event.Loop,
536 allocator: *Allocator,
540537
541538 const SeenMap = std.StringHashMap(void);
542539};
......@@ -567,20 +564,14 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
567564 },
568565 }
569566
570 var loop: event.Loop = undefined;
571 try loop.initMultiThreaded(allocator);
572 defer loop.deinit();
573
574 var zig_compiler = try ZigCompiler.init(&loop);
567 var zig_compiler = try ZigCompiler.init(allocator);
575568 defer zig_compiler.deinit();
576569
577 // TODO const handle = try async<loop.allocator> findLibCAsync(&zig_compiler);
578
579 loop.run();
570 const frame = async findLibCAsync(&zig_compiler);
580571}
581572
582573async fn findLibCAsync(zig_compiler: *ZigCompiler) void {
583 const libc = (await (async zig_compiler.getNativeLibC() catch unreachable)) catch |err| {
574 const libc = zig_compiler.getNativeLibC() catch |err| {
584575 stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);
585576 process.exit(1);
586577 };
......@@ -596,17 +587,17 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
596587 process.exit(0);
597588 }
598589
599 const color = blk: {
590 const color: errmsg.Color = blk: {
600591 if (flags.single("color")) |color_flag| {
601592 if (mem.eql(u8, color_flag, "auto")) {
602 break :blk errmsg.Color.Auto;
593 break :blk .Auto;
603594 } else if (mem.eql(u8, color_flag, "on")) {
604 break :blk errmsg.Color.On;
595 break :blk .On;
605596 } else if (mem.eql(u8, color_flag, "off")) {
606 break :blk errmsg.Color.Off;
597 break :blk .Off;
607598 } else unreachable;
608599 } else {
609 break :blk errmsg.Color.Auto;
600 break :blk .Auto;
610601 }
611602 };
612603
......@@ -640,7 +631,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
640631 }
641632 if (flags.present("check")) {
642633 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
643 const code = if (anything_changed) u8(1) else u8(0);
634 const code: u8 = if (anything_changed) 1 else 0;
644635 process.exit(code);
645636 }
646637
......@@ -653,28 +644,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
653644 process.exit(1);
654645 }
655646
656 var loop: event.Loop = undefined;
657 try loop.initMultiThreaded(allocator);
658 defer loop.deinit();
659
660 var result: FmtError!void = undefined;
661 // TODO const main_handle = try async<allocator> asyncFmtMainChecked(
662 // TODO &result,
663 // TODO &loop,
664 // TODO &flags,
665 // TODO color,
666 // TODO );
667 loop.run();
668 return result;
669}
670
671async fn asyncFmtMainChecked(
672 result: *(FmtError!void),
673 loop: *event.Loop,
674 flags: *const Args,
675 color: errmsg.Color,
676) void {
677 result.* = await (async asyncFmtMain(loop, flags, color) catch unreachable);
647 return asyncFmtMain(
648 allocator,
649 &flags,
650 color,
651 );
678652}
679653
680654const FmtError = error{
......@@ -700,72 +674,69 @@ const FmtError = error{
700674} || fs.File.OpenError;
701675
702676async fn asyncFmtMain(
703 loop: *event.Loop,
677 allocator: *Allocator,
704678 flags: *const Args,
705679 color: errmsg.Color,
706680) FmtError!void {
707 suspend {
708 resume @handle();
709 }
710681 var fmt = Fmt{
711 .seen = event.Locked(Fmt.SeenMap).init(loop, Fmt.SeenMap.init(loop.allocator)),
682 .allocator = allocator,
683 .seen = event.Locked(Fmt.SeenMap).init(Fmt.SeenMap.init(allocator)),
712684 .any_error = false,
713685 .color = color,
714 .loop = loop,
715686 };
716687
717688 const check_mode = flags.present("check");
718689
719 var group = event.Group(FmtError!void).init(loop);
690 var group = event.Group(FmtError!void).init(allocator);
720691 for (flags.positionals.toSliceConst()) |file_path| {
721692 try group.call(fmtPath, &fmt, file_path, check_mode);
722693 }
723 try await (async group.wait() catch unreachable);
694 try group.wait();
724695 if (fmt.any_error) {
725696 process.exit(1);
726697 }
727698}
728699
729700async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
730 const file_path = try std.mem.dupe(fmt.loop.allocator, u8, file_path_ref);
731 defer fmt.loop.allocator.free(file_path);
701 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
702 defer fmt.allocator.free(file_path);
732703
733704 {
734 const held = await (async fmt.seen.acquire() catch unreachable);
705 const held = fmt.seen.acquire();
735706 defer held.release();
736707
737708 if (try held.value.put(file_path, {})) |_| return;
738709 }
739710
740 const source_code = (await try async event.fs.readFile(
741 fmt.loop,
742 file_path,
743 max_src_size,
744 )) catch |err| switch (err) {
745 error.IsDir, error.AccessDenied => {
746 // TODO make event based (and dir.next())
747 var dir = try fs.Dir.open(file_path);
748 defer dir.close();
749
750 var group = event.Group(FmtError!void).init(fmt.loop);
751 while (try dir.next()) |entry| {
752 if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
753 const full_path = try fs.path.join(fmt.loop.allocator, [_][]const u8{ file_path, entry.name });
754 try group.call(fmtPath, fmt, full_path, check_mode);
755 }
756 }
757 return await (async group.wait() catch unreachable);
758 },
759 else => {
760 // TODO lock stderr printing
761 try stderr.print("unable to open '{}': {}\n", file_path, err);
762 fmt.any_error = true;
763 return;
764 },
765 };
766 defer fmt.loop.allocator.free(source_code);
767
768 const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {
711 const source_code = "";
712 // const source_code = event.fs.readFile(
713 // file_path,
714 // max_src_size,
715 // ) catch |err| switch (err) {
716 // error.IsDir, error.AccessDenied => {
717 // // TODO make event based (and dir.next())
718 // var dir = try fs.Dir.open(file_path);
719 // defer dir.close();
720
721 // var group = event.Group(FmtError!void).init(fmt.allocator);
722 // while (try dir.next()) |entry| {
723 // if (entry.kind == fs.Dir.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 });
725 // try group.call(fmtPath, fmt, full_path, check_mode);
726 // }
727 // }
728 // return group.wait();
729 // },
730 // else => {
731 // // TODO lock stderr printing
732 // try stderr.print("unable to open '{}': {}\n", file_path, err);
733 // fmt.any_error = true;
734 // return;
735 // },
736 // };
737 // defer fmt.allocator.free(source_code);
738
739 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
769740 try stderr.print("error parsing file '{}': {}\n", file_path, err);
770741 fmt.any_error = true;
771742 return;
......@@ -774,8 +745,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
774745
775746 var error_it = tree.errors.iterator(0);
776747 while (error_it.next()) |parse_error| {
777 const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, tree, file_path);
778 defer fmt.loop.allocator.destroy(msg);
748 const msg = try errmsg.Msg.createFromParseError(fmt.allocator, parse_error, tree, file_path);
749 defer fmt.allocator.destroy(msg);
779750
780751 try msg.printToFile(stderr_file, fmt.color);
781752 }
......@@ -785,17 +756,17 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
785756 }
786757
787758 if (check_mode) {
788 const anything_changed = try std.zig.render(fmt.loop.allocator, io.null_out_stream, tree);
759 const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree);
789760 if (anything_changed) {
790761 try stderr.print("{}\n", file_path);
791762 fmt.any_error = true;
792763 }
793764 } else {
794765 // TODO make this evented
795 const baf = try io.BufferedAtomicFile.create(fmt.loop.allocator, file_path);
766 const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
796767 defer baf.destroy();
797768
798 const anything_changed = try std.zig.render(fmt.loop.allocator, baf.stream(), tree);
769 const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree);
799770 if (anything_changed) {
800771 try stderr.print("{}\n", file_path);
801772 try baf.finish();
......@@ -822,8 +793,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
822793 try stdout.write("Operating Systems:\n");
823794 {
824795 comptime var i: usize = 0;
825 inline while (i < @memberCount(builtin.Os)) : (i += 1) {
826 comptime const os_tag = @memberName(builtin.Os, i);
796 inline while (i < @memberCount(Target.Os)) : (i += 1) {
797 comptime const os_tag = @memberName(Target.Os, i);
827798 // NOTE: Cannot use empty string, see #918.
828799 comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
829800
......@@ -835,8 +806,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
835806 try stdout.write("C ABIs:\n");
836807 {
837808 comptime var i: usize = 0;
838 inline while (i < @memberCount(builtin.Abi)) : (i += 1) {
839 comptime const abi_tag = @memberName(builtin.Abi, i);
809 inline while (i < @memberCount(Target.Abi)) : (i += 1) {
810 comptime const abi_tag = @memberName(Target.Abi, i);
840811 // NOTE: Cannot use empty string, see #918.
841812 comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";
842813
......@@ -911,21 +882,17 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
911882 try stdout.print(
912883 \\ZIG_CMAKE_BINARY_DIR {}
913884 \\ZIG_CXX_COMPILER {}
914 \\ZIG_LLVM_CONFIG_EXE {}
915885 \\ZIG_LLD_INCLUDE_PATH {}
916886 \\ZIG_LLD_LIBRARIES {}
917 \\ZIG_STD_FILES {}
918 \\ZIG_C_HEADER_FILES {}
887 \\ZIG_LLVM_CONFIG_EXE {}
919888 \\ZIG_DIA_GUIDS_LIB {}
920889 \\
921890 ,
922891 std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),
923892 std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),
924 std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
925893 std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),
926894 std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),
927 std.mem.toSliceConst(u8, c.ZIG_STD_FILES),
928 std.mem.toSliceConst(u8, c.ZIG_C_HEADER_FILES),
895 std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
929896 std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),
930897 );
931898}
src-self-hosted/scope.zig+46-47
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const Allocator = mem.Allocator;
43const Decl = @import("decl.zig").Decl;
54const Compilation = @import("compilation.zig").Compilation;
......@@ -28,15 +27,15 @@ pub const Scope = struct {
2827 if (base.ref_count.decr() == 1) {
2928 if (base.parent) |parent| parent.deref(comp);
3029 switch (base.id) {
31 Id.Root => @fieldParentPtr(Root, "base", base).destroy(comp),
32 Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),
33 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),
34 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
35 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
36 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
37 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
38 Id.Var => @fieldParentPtr(Var, "base", base).destroy(comp),
39 Id.AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),
30 .Root => @fieldParentPtr(Root, "base", base).destroy(comp),
31 .Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),
32 .Block => @fieldParentPtr(Block, "base", base).destroy(comp),
33 .FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
34 .CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
35 .Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
36 .DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
37 .Var => @fieldParentPtr(Var, "base", base).destroy(comp),
38 .AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),
4039 }
4140 }
4241 }
......@@ -46,7 +45,7 @@ pub const Scope = struct {
4645 while (scope.parent) |parent| {
4746 scope = parent;
4847 }
49 assert(scope.id == Id.Root);
48 assert(scope.id == .Root);
5049 return @fieldParentPtr(Root, "base", scope);
5150 }
5251
......@@ -54,17 +53,17 @@ pub const Scope = struct {
5453 var scope = base;
5554 while (true) {
5655 switch (scope.id) {
57 Id.FnDef => return @fieldParentPtr(FnDef, "base", scope),
58 Id.Root, Id.Decls => return null,
59
60 Id.Block,
61 Id.Defer,
62 Id.DeferExpr,
63 Id.CompTime,
64 Id.Var,
56 .FnDef => return @fieldParentPtr(FnDef, "base", scope),
57 .Root, .Decls => return null,
58
59 .Block,
60 .Defer,
61 .DeferExpr,
62 .CompTime,
63 .Var,
6564 => scope = scope.parent.?,
6665
67 Id.AstTree => unreachable,
66 .AstTree => unreachable,
6867 }
6968 }
7069 }
......@@ -73,20 +72,20 @@ pub const Scope = struct {
7372 var scope = base;
7473 while (true) {
7574 switch (scope.id) {
76 Id.DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),
75 .DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),
7776
78 Id.FnDef,
79 Id.Decls,
77 .FnDef,
78 .Decls,
8079 => return null,
8180
82 Id.Block,
83 Id.Defer,
84 Id.CompTime,
85 Id.Root,
86 Id.Var,
81 .Block,
82 .Defer,
83 .CompTime,
84 .Root,
85 .Var,
8786 => scope = scope.parent orelse return null,
8887
89 Id.AstTree => unreachable,
88 .AstTree => unreachable,
9089 }
9190 }
9291 }
......@@ -123,7 +122,7 @@ pub const Scope = struct {
123122 const self = try comp.gpa().create(Root);
124123 self.* = Root{
125124 .base = Scope{
126 .id = Id.Root,
125 .id = .Root,
127126 .parent = null,
128127 .ref_count = std.atomic.Int(usize).init(1),
129128 },
......@@ -155,7 +154,7 @@ pub const Scope = struct {
155154 .base = undefined,
156155 .tree = tree,
157156 };
158 self.base.init(Id.AstTree, &root_scope.base);
157 self.base.init(.AstTree, &root_scope.base);
159158
160159 return self;
161160 }
......@@ -184,9 +183,9 @@ pub const Scope = struct {
184183 const self = try comp.gpa().create(Decls);
185184 self.* = Decls{
186185 .base = undefined,
187 .table = event.RwLocked(Decl.Table).init(comp.loop, Decl.Table.init(comp.gpa())),
186 .table = event.RwLocked(Decl.Table).init(Decl.Table.init(comp.gpa())),
188187 };
189 self.base.init(Id.Decls, parent);
188 self.base.init(.Decls, parent);
190189 return self;
191190 }
192191
......@@ -219,15 +218,15 @@ pub const Scope = struct {
219218
220219 fn get(self: Safety, comp: *Compilation) bool {
221220 return switch (self) {
222 Safety.Auto => switch (comp.build_mode) {
223 builtin.Mode.Debug,
224 builtin.Mode.ReleaseSafe,
221 .Auto => switch (comp.build_mode) {
222 .Debug,
223 .ReleaseSafe,
225224 => true,
226 builtin.Mode.ReleaseFast,
227 builtin.Mode.ReleaseSmall,
225 .ReleaseFast,
226 .ReleaseSmall,
228227 => false,
229228 },
230 @TagType(Safety).Manual => |man| man.enabled,
229 .Manual => |man| man.enabled,
231230 };
232231 }
233232 };
......@@ -243,7 +242,7 @@ pub const Scope = struct {
243242 .is_comptime = undefined,
244243 .safety = Safety.Auto,
245244 };
246 self.base.init(Id.Block, parent);
245 self.base.init(.Block, parent);
247246 return self;
248247 }
249248
......@@ -266,7 +265,7 @@ pub const Scope = struct {
266265 .base = undefined,
267266 .fn_val = null,
268267 };
269 self.base.init(Id.FnDef, parent);
268 self.base.init(.FnDef, parent);
270269 return self;
271270 }
272271
......@@ -282,7 +281,7 @@ pub const Scope = struct {
282281 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
283282 const self = try comp.gpa().create(CompTime);
284283 self.* = CompTime{ .base = undefined };
285 self.base.init(Id.CompTime, parent);
284 self.base.init(.CompTime, parent);
286285 return self;
287286 }
288287
......@@ -314,7 +313,7 @@ pub const Scope = struct {
314313 .defer_expr_scope = defer_expr_scope,
315314 .kind = kind,
316315 };
317 self.base.init(Id.Defer, parent);
316 self.base.init(.Defer, parent);
318317 defer_expr_scope.base.ref();
319318 return self;
320319 }
......@@ -338,7 +337,7 @@ pub const Scope = struct {
338337 .expr_node = expr_node,
339338 .reported_err = false,
340339 };
341 self.base.init(Id.DeferExpr, parent);
340 self.base.init(.DeferExpr, parent);
342341 return self;
343342 }
344343
......@@ -404,14 +403,14 @@ pub const Scope = struct {
404403 .src_node = src_node,
405404 .data = undefined,
406405 };
407 self.base.init(Id.Var, parent);
406 self.base.init(.Var, parent);
408407 return self;
409408 }
410409
411410 pub fn destroy(self: *Var, comp: *Compilation) void {
412411 switch (self.data) {
413 Data.Param => {},
414 Data.Const => |value| value.deref(comp),
412 .Param => {},
413 .Const => |value| value.deref(comp),
415414 }
416415 comp.gpa().destroy(self);
417416 }
src-self-hosted/stage1.zig+5-6
......@@ -1,7 +1,6 @@
11// This is Zig code that is used by both stage1 and stage2.
22// The prototypes in src/userland.h must match these definitions.
33
4const builtin = @import("builtin");
54const std = @import("std");
65const io = std.io;
76const mem = std.mem;
......@@ -354,9 +353,9 @@ fn printErrMsgToFile(
354353 color: errmsg.Color,
355354) !void {
356355 const color_on = switch (color) {
357 errmsg.Color.Auto => file.isTty(),
358 errmsg.Color.On => true,
359 errmsg.Color.Off => false,
356 .Auto => file.isTty(),
357 .On => true,
358 .Off => false,
360359 };
361360 const lok_token = parse_error.loc();
362361 const span = errmsg.Span{
......@@ -421,8 +420,8 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes
421420 const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
422421 return stage2_DepNextResult{
423422 .type_id = switch (token.id) {
424 .target => stage2_DepNextResult.TypeId.target,
425 .prereq => stage2_DepNextResult.TypeId.prereq,
423 .target => .target,
424 .prereq => .prereq,
426425 },
427426 .textz = textz.toSlice().ptr,
428427 };
src-self-hosted/target.zig deleted-440
......@@ -1,440 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const llvm = @import("llvm.zig");
4const CInt = @import("c_int.zig").CInt;
5
6// TODO delete this file and use std.Target
7
8pub const FloatAbi = enum {
9 Hard,
10 Soft,
11 SoftFp,
12};
13
14pub const Target = union(enum) {
15 Native,
16 Cross: Cross,
17
18 pub const Cross = struct {
19 arch: builtin.Arch,
20 os: builtin.Os,
21 abi: builtin.Abi,
22 object_format: builtin.ObjectFormat,
23 };
24
25 pub fn objFileExt(self: Target) []const u8 {
26 return switch (self.getObjectFormat()) {
27 builtin.ObjectFormat.coff => ".obj",
28 else => ".o",
29 };
30 }
31
32 pub fn exeFileExt(self: Target) []const u8 {
33 return switch (self.getOs()) {
34 builtin.Os.windows => ".exe",
35 else => "",
36 };
37 }
38
39 pub fn libFileExt(self: Target, is_static: bool) []const u8 {
40 return switch (self.getOs()) {
41 builtin.Os.windows => if (is_static) ".lib" else ".dll",
42 else => if (is_static) ".a" else ".so",
43 };
44 }
45
46 pub fn getOs(self: Target) builtin.Os {
47 return switch (self) {
48 Target.Native => builtin.os,
49 @TagType(Target).Cross => |t| t.os,
50 };
51 }
52
53 pub fn getArch(self: Target) builtin.Arch {
54 switch (self) {
55 Target.Native => return builtin.arch,
56 @TagType(Target).Cross => |t| return t.arch,
57 }
58 }
59
60 pub fn getAbi(self: Target) builtin.Abi {
61 return switch (self) {
62 Target.Native => builtin.abi,
63 @TagType(Target).Cross => |t| t.abi,
64 };
65 }
66
67 pub fn getObjectFormat(self: Target) builtin.ObjectFormat {
68 return switch (self) {
69 Target.Native => builtin.object_format,
70 @TagType(Target).Cross => |t| t.object_format,
71 };
72 }
73
74 pub fn isWasm(self: Target) bool {
75 return switch (self.getArch()) {
76 builtin.Arch.wasm32, builtin.Arch.wasm64 => true,
77 else => false,
78 };
79 }
80
81 pub fn isDarwin(self: Target) bool {
82 return switch (self.getOs()) {
83 builtin.Os.ios, builtin.Os.macosx => true,
84 else => false,
85 };
86 }
87
88 pub fn isWindows(self: Target) bool {
89 return switch (self.getOs()) {
90 builtin.Os.windows => true,
91 else => false,
92 };
93 }
94
95 /// TODO expose the arch and subarch separately
96 pub fn isArmOrThumb(self: Target) bool {
97 return switch (self.getArch()) {
98 builtin.Arch.arm,
99 builtin.Arch.armeb,
100 builtin.Arch.aarch64,
101 builtin.Arch.aarch64_be,
102 builtin.Arch.thumb,
103 builtin.Arch.thumbeb,
104 => true,
105 else => false,
106 };
107 }
108
109 pub fn initializeAll() void {
110 llvm.InitializeAllTargets();
111 llvm.InitializeAllTargetInfos();
112 llvm.InitializeAllTargetMCs();
113 llvm.InitializeAllAsmPrinters();
114 llvm.InitializeAllAsmParsers();
115 }
116
117 pub fn getTriple(self: Target, allocator: *std.mem.Allocator) !std.Buffer {
118 var result = try std.Buffer.initSize(allocator, 0);
119 errdefer result.deinit();
120
121 // LLVM WebAssembly output support requires the target to be activated at
122 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
123 //
124 // LLVM determines the output format based on the abi suffix,
125 // defaulting to an object based on the architecture. The default format in
126 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
127 // explicitly set this ourself in order for it to work.
128 //
129 // This is fixed in LLVM 7 and you will be able to get wasm output by
130 // using the target triple `wasm32-unknown-unknown-unknown`.
131 const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi());
132
133 var out = &std.io.BufferOutStream.init(&result).stream;
134 try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);
135
136 return result;
137 }
138
139 pub fn is64bit(self: Target) bool {
140 return self.getArchPtrBitWidth() == 64;
141 }
142
143 pub fn getArchPtrBitWidth(self: Target) u32 {
144 switch (self.getArch()) {
145 builtin.Arch.avr,
146 builtin.Arch.msp430,
147 => return 16,
148
149 builtin.Arch.arc,
150 builtin.Arch.arm,
151 builtin.Arch.armeb,
152 builtin.Arch.hexagon,
153 builtin.Arch.le32,
154 builtin.Arch.mips,
155 builtin.Arch.mipsel,
156 builtin.Arch.powerpc,
157 builtin.Arch.r600,
158 builtin.Arch.riscv32,
159 builtin.Arch.sparc,
160 builtin.Arch.sparcel,
161 builtin.Arch.tce,
162 builtin.Arch.tcele,
163 builtin.Arch.thumb,
164 builtin.Arch.thumbeb,
165 builtin.Arch.i386,
166 builtin.Arch.xcore,
167 builtin.Arch.nvptx,
168 builtin.Arch.amdil,
169 builtin.Arch.hsail,
170 builtin.Arch.spir,
171 builtin.Arch.kalimba,
172 builtin.Arch.shave,
173 builtin.Arch.lanai,
174 builtin.Arch.wasm32,
175 builtin.Arch.renderscript32,
176 => return 32,
177
178 builtin.Arch.aarch64,
179 builtin.Arch.aarch64_be,
180 builtin.Arch.mips64,
181 builtin.Arch.mips64el,
182 builtin.Arch.powerpc64,
183 builtin.Arch.powerpc64le,
184 builtin.Arch.riscv64,
185 builtin.Arch.x86_64,
186 builtin.Arch.nvptx64,
187 builtin.Arch.le64,
188 builtin.Arch.amdil64,
189 builtin.Arch.hsail64,
190 builtin.Arch.spir64,
191 builtin.Arch.wasm64,
192 builtin.Arch.renderscript64,
193 builtin.Arch.amdgcn,
194 builtin.Arch.bpfel,
195 builtin.Arch.bpfeb,
196 builtin.Arch.sparcv9,
197 builtin.Arch.s390x,
198 => return 64,
199 }
200 }
201
202 pub fn getFloatAbi(self: Target) FloatAbi {
203 return switch (self.getAbi()) {
204 builtin.Abi.gnueabihf,
205 builtin.Abi.eabihf,
206 builtin.Abi.musleabihf,
207 => FloatAbi.Hard,
208 else => FloatAbi.Soft,
209 };
210 }
211
212 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
213 const env = self.getAbi();
214 const arch = self.getArch();
215 const os = self.getOs();
216 switch (os) {
217 builtin.Os.freebsd => {
218 return "/libexec/ld-elf.so.1";
219 },
220 builtin.Os.linux => {
221 switch (env) {
222 builtin.Abi.android => {
223 if (self.is64bit()) {
224 return "/system/bin/linker64";
225 } else {
226 return "/system/bin/linker";
227 }
228 },
229 builtin.Abi.gnux32 => {
230 if (arch == builtin.Arch.x86_64) {
231 return "/libx32/ld-linux-x32.so.2";
232 }
233 },
234 builtin.Abi.musl,
235 builtin.Abi.musleabi,
236 builtin.Abi.musleabihf,
237 => {
238 if (arch == builtin.Arch.x86_64) {
239 return "/lib/ld-musl-x86_64.so.1";
240 }
241 },
242 else => {},
243 }
244 switch (arch) {
245 builtin.Arch.i386,
246 builtin.Arch.sparc,
247 builtin.Arch.sparcel,
248 => return "/lib/ld-linux.so.2",
249
250 builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
251
252 builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
253
254 builtin.Arch.arm,
255 builtin.Arch.thumb,
256 => return switch (self.getFloatAbi()) {
257 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
258 else => return "/lib/ld-linux.so.3",
259 },
260
261 builtin.Arch.armeb,
262 builtin.Arch.thumbeb,
263 => return switch (self.getFloatAbi()) {
264 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
265 else => return "/lib/ld-linux.so.3",
266 },
267
268 builtin.Arch.mips,
269 builtin.Arch.mipsel,
270 builtin.Arch.mips64,
271 builtin.Arch.mips64el,
272 => return null,
273
274 builtin.Arch.powerpc => return "/lib/ld.so.1",
275 builtin.Arch.powerpc64 => return "/lib64/ld64.so.2",
276 builtin.Arch.powerpc64le => return "/lib64/ld64.so.2",
277 builtin.Arch.s390x => return "/lib64/ld64.so.1",
278 builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2",
279 builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2",
280
281 builtin.Arch.arc,
282 builtin.Arch.avr,
283 builtin.Arch.bpfel,
284 builtin.Arch.bpfeb,
285 builtin.Arch.hexagon,
286 builtin.Arch.msp430,
287 builtin.Arch.r600,
288 builtin.Arch.amdgcn,
289 builtin.Arch.riscv32,
290 builtin.Arch.riscv64,
291 builtin.Arch.tce,
292 builtin.Arch.tcele,
293 builtin.Arch.xcore,
294 builtin.Arch.nvptx,
295 builtin.Arch.nvptx64,
296 builtin.Arch.le32,
297 builtin.Arch.le64,
298 builtin.Arch.amdil,
299 builtin.Arch.amdil64,
300 builtin.Arch.hsail,
301 builtin.Arch.hsail64,
302 builtin.Arch.spir,
303 builtin.Arch.spir64,
304 builtin.Arch.kalimba,
305 builtin.Arch.shave,
306 builtin.Arch.lanai,
307 builtin.Arch.wasm32,
308 builtin.Arch.wasm64,
309 builtin.Arch.renderscript32,
310 builtin.Arch.renderscript64,
311 => return null,
312 }
313 },
314 else => return null,
315 }
316 }
317
318 pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
319 var result: *llvm.Target = undefined;
320 var err_msg: [*]u8 = undefined;
321 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
322 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
323 return error.UnsupportedTarget;
324 }
325 return result;
326 }
327
328 pub fn cIntTypeSizeInBits(self: Target, id: CInt.Id) u32 {
329 const arch = self.getArch();
330 switch (self.getOs()) {
331 builtin.Os.freestanding => switch (self.getArch()) {
332 builtin.Arch.msp430 => switch (id) {
333 CInt.Id.Short,
334 CInt.Id.UShort,
335 CInt.Id.Int,
336 CInt.Id.UInt,
337 => return 16,
338 CInt.Id.Long,
339 CInt.Id.ULong,
340 => return 32,
341 CInt.Id.LongLong,
342 CInt.Id.ULongLong,
343 => return 64,
344 },
345 else => switch (id) {
346 CInt.Id.Short,
347 CInt.Id.UShort,
348 => return 16,
349 CInt.Id.Int,
350 CInt.Id.UInt,
351 => return 32,
352 CInt.Id.Long,
353 CInt.Id.ULong,
354 => return self.getArchPtrBitWidth(),
355 CInt.Id.LongLong,
356 CInt.Id.ULongLong,
357 => return 64,
358 },
359 },
360
361 builtin.Os.linux,
362 builtin.Os.macosx,
363 builtin.Os.freebsd,
364 builtin.Os.openbsd,
365 builtin.Os.zen,
366 => switch (id) {
367 CInt.Id.Short,
368 CInt.Id.UShort,
369 => return 16,
370 CInt.Id.Int,
371 CInt.Id.UInt,
372 => return 32,
373 CInt.Id.Long,
374 CInt.Id.ULong,
375 => return self.getArchPtrBitWidth(),
376 CInt.Id.LongLong,
377 CInt.Id.ULongLong,
378 => return 64,
379 },
380
381 builtin.Os.windows, builtin.Os.uefi => switch (id) {
382 CInt.Id.Short,
383 CInt.Id.UShort,
384 => return 16,
385 CInt.Id.Int,
386 CInt.Id.UInt,
387 => return 32,
388 CInt.Id.Long,
389 CInt.Id.ULong,
390 CInt.Id.LongLong,
391 CInt.Id.ULongLong,
392 => return 64,
393 },
394
395 builtin.Os.ananas,
396 builtin.Os.cloudabi,
397 builtin.Os.dragonfly,
398 builtin.Os.fuchsia,
399 builtin.Os.ios,
400 builtin.Os.kfreebsd,
401 builtin.Os.lv2,
402 builtin.Os.netbsd,
403 builtin.Os.solaris,
404 builtin.Os.haiku,
405 builtin.Os.minix,
406 builtin.Os.rtems,
407 builtin.Os.nacl,
408 builtin.Os.cnk,
409 builtin.Os.aix,
410 builtin.Os.cuda,
411 builtin.Os.nvcl,
412 builtin.Os.amdhsa,
413 builtin.Os.ps4,
414 builtin.Os.elfiamcu,
415 builtin.Os.tvos,
416 builtin.Os.watchos,
417 builtin.Os.mesa3d,
418 builtin.Os.contiki,
419 builtin.Os.amdpal,
420 builtin.Os.hermit,
421 builtin.Os.hurd,
422 builtin.Os.wasi,
423 => @panic("TODO specify the C integer type sizes for this OS"),
424 }
425 }
426
427 pub fn getDarwinArchString(self: Target) []const u8 {
428 const arch = self.getArch();
429 switch (arch) {
430 builtin.Arch.aarch64 => return "arm64",
431 builtin.Arch.thumb,
432 builtin.Arch.arm,
433 => return "arm",
434 builtin.Arch.powerpc => return "ppc",
435 builtin.Arch.powerpc64 => return "ppc64",
436 builtin.Arch.powerpc64le => return "ppc64le",
437 else => return @tagName(arch),
438 }
439 }
440};
src-self-hosted/test.zig+28-34
......@@ -1,7 +1,6 @@
11const std = @import("std");
22const mem = std.mem;
3const builtin = @import("builtin");
4const Target = @import("target.zig").Target;
3const Target = std.Target;
54const Compilation = @import("compilation.zig").Compilation;
65const introspect = @import("introspect.zig");
76const testing = std.testing;
......@@ -11,11 +10,17 @@ const ZigCompiler = @import("compilation.zig").ZigCompiler;
1110var ctx: TestContext = undefined;
1211
1312test "stage2" {
13 // TODO provide a way to run tests in evented I/O mode
14 if (!std.io.is_async) return error.SkipZigTest;
15
16 // TODO https://github.com/ziglang/zig/issues/1364
17 // TODO https://github.com/ziglang/zig/issues/3117
18 if (true) return error.SkipZigTest;
19
1420 try ctx.init();
1521 defer ctx.deinit();
1622
17 try @import("../test/stage2/compile_errors.zig").addCases(&ctx);
18 try @import("../test/stage2/compare_output.zig").addCases(&ctx);
23 try @import("stage2_tests").addCases(&ctx);
1924
2025 try ctx.run();
2126}
......@@ -24,7 +29,6 @@ const file1 = "1.zig";
2429const allocator = std.heap.c_allocator;
2530
2631pub const TestContext = struct {
27 loop: std.event.Loop,
2832 zig_compiler: ZigCompiler,
2933 zig_lib_dir: []u8,
3034 file_index: std.atomic.Int(usize),
......@@ -36,21 +40,17 @@ pub const TestContext = struct {
3640 fn init(self: *TestContext) !void {
3741 self.* = TestContext{
3842 .any_err = {},
39 .loop = undefined,
4043 .zig_compiler = undefined,
4144 .zig_lib_dir = undefined,
4245 .group = undefined,
4346 .file_index = std.atomic.Int(usize).init(0),
4447 };
4548
46 try self.loop.initSingleThreaded(allocator);
47 errdefer self.loop.deinit();
48
49 self.zig_compiler = try ZigCompiler.init(&self.loop);
49 self.zig_compiler = try ZigCompiler.init(allocator);
5050 errdefer self.zig_compiler.deinit();
5151
52 self.group = std.event.Group(anyerror!void).init(&self.loop);
53 errdefer self.group.deinit();
52 self.group = std.event.Group(anyerror!void).init(allocator);
53 errdefer self.group.wait() catch {};
5454
5555 self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
5656 errdefer allocator.free(self.zig_lib_dir);
......@@ -63,20 +63,14 @@ pub const TestContext = struct {
6363 std.fs.deleteTree(tmp_dir_name) catch {};
6464 allocator.free(self.zig_lib_dir);
6565 self.zig_compiler.deinit();
66 self.loop.deinit();
6766 }
6867
6968 fn run(self: *TestContext) !void {
70 const handle = try self.loop.call(waitForGroup, self);
71 defer cancel handle;
72 self.loop.run();
69 std.event.Loop.startCpuBoundOperation();
70 self.any_err = self.group.wait();
7371 return self.any_err;
7472 }
7573
76 async fn waitForGroup(self: *TestContext) void {
77 self.any_err = await (async self.group.wait() catch unreachable);
78 }
79
8074 fn testCompileError(
8175 self: *TestContext,
8276 source: []const u8,
......@@ -87,7 +81,7 @@ pub const TestContext = struct {
8781 ) !void {
8882 var file_index_buf: [20]u8 = undefined;
8983 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
90 const file1_path = try std.fs.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
84 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
9185
9286 if (std.fs.path.dirname(file1_path)) |dirname| {
9387 try std.fs.makePath(allocator, dirname);
......@@ -102,7 +96,7 @@ pub const TestContext = struct {
10296 file1_path,
10397 Target.Native,
10498 Compilation.Kind.Obj,
105 builtin.Mode.Debug,
99 .Debug,
106100 true, // is_static
107101 self.zig_lib_dir,
108102 );
......@@ -120,9 +114,9 @@ pub const TestContext = struct {
120114 ) !void {
121115 var file_index_buf: [20]u8 = undefined;
122116 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());
123 const file1_path = try std.fs.path.join(allocator, [][]const u8{ tmp_dir_name, file_index, file1 });
117 const file1_path = try std.fs.path.join(allocator, [_][]const u8{ tmp_dir_name, file_index, file1 });
124118
125 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, Target(Target.Native).exeFileExt());
119 const output_file = try std.fmt.allocPrint(allocator, "{}-out{}", file1_path, (Target{.Native = {}}).exeFileExt());
126120 if (std.fs.path.dirname(file1_path)) |dirname| {
127121 try std.fs.makePath(allocator, dirname);
128122 }
......@@ -136,7 +130,7 @@ pub const TestContext = struct {
136130 file1_path,
137131 Target.Native,
138132 Compilation.Kind.Exe,
139 builtin.Mode.Debug,
133 .Debug,
140134 false,
141135 self.zig_lib_dir,
142136 );
......@@ -153,16 +147,16 @@ pub const TestContext = struct {
153147 comp: *Compilation,
154148 exe_file: []const u8,
155149 expected_output: []const u8,
156 ) !void {
150 ) anyerror!void {
157151 // TODO this should not be necessary
158152 const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);
159153
160154 defer comp.destroy();
161 const build_event = await (async comp.events.get() catch unreachable);
155 const build_event = comp.events.get();
162156
163157 switch (build_event) {
164 Compilation.Event.Ok => {
165 const argv = []const []const u8{exe_file_2};
158 .Ok => {
159 const argv = [_][]const u8{exe_file_2};
166160 // TODO use event loop
167161 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
168162 switch (child.term) {
......@@ -198,18 +192,18 @@ pub const TestContext = struct {
198192 line: usize,
199193 column: usize,
200194 text: []const u8,
201 ) !void {
195 ) anyerror!void {
202196 defer comp.destroy();
203 const build_event = await (async comp.events.get() catch unreachable);
197 const build_event = comp.events.get();
204198
205199 switch (build_event) {
206 Compilation.Event.Ok => {
200 .Ok => {
207201 @panic("build incorrectly succeeded");
208202 },
209 Compilation.Event.Error => |err| {
203 .Error => |err| {
210204 @panic("build incorrectly failed");
211205 },
212 Compilation.Event.Fail => |msgs| {
206 .Fail => |msgs| {
213207 testing.expect(msgs.len != 0);
214208 for (msgs) |msg| {
215209 if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {
src-self-hosted/translate_c.zig+1-3
......@@ -2,7 +2,6 @@
22// and stage2. Currently the only way it is used is with `zig translate-c-2`.
33
44const std = @import("std");
5const builtin = @import("builtin");
65const assert = std.debug.assert;
76const ast = std.zig.ast;
87const Token = std.zig.Token;
......@@ -13,8 +12,7 @@ pub const Mode = enum {
1312 translate,
1413};
1514
16// TODO merge with Type.Fn.CallingConvention
17const CallingConvention = builtin.TypeInfo.CallingConvention;
15const CallingConvention = std.builtin.TypeInfo.CallingConvention;
1816
1917pub const ClangErrMsg = Stage2ErrorMsg;
2018
src-self-hosted/type.zig+202-230
......@@ -1,5 +1,5 @@
11const std = @import("std");
2const builtin = @import("builtin");
2const builtin = std.builtin;
33const Scope = @import("scope.zig").Scope;
44const Compilation = @import("compilation.zig").Compilation;
55const Value = @import("value.zig").Value;
......@@ -20,31 +20,32 @@ pub const Type = struct {
2020
2121 pub fn destroy(base: *Type, comp: *Compilation) void {
2222 switch (base.id) {
23 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
25 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
26 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
27 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
28 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
29 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
30 Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),
31 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
32 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
33 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
34 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
35 Id.EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp),
36 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
37 Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),
38 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
39 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
40 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
41 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
42 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),
43 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
23 .Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
24 .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
25 .Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
26 .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
27 .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
28 .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
29 .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
30 .Float => @fieldParentPtr(Float, "base", base).destroy(comp),
31 .Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
32 .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
33 .ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
34 .ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
35 .EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp),
36 .Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
37 .Null => @fieldParentPtr(Null, "base", base).destroy(comp),
38 .Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
39 .ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
40 .ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
41 .Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
42 .Union => @fieldParentPtr(Union, "base", base).destroy(comp),
43 .BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
44 .ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
45 .Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
46 .Frame => @fieldParentPtr(Frame, "base", base).destroy(comp),
47 .AnyFrame => @fieldParentPtr(AnyFrame, "base", base).destroy(comp),
48 .Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
4849 }
4950 }
5051
......@@ -54,105 +55,108 @@ pub const Type = struct {
5455 llvm_context: *llvm.Context,
5556 ) (error{OutOfMemory}!*llvm.Type) {
5657 switch (base.id) {
57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
59 Id.Type => unreachable,
60 Id.Void => unreachable,
61 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context),
62 Id.NoReturn => unreachable,
63 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context),
64 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context),
65 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context),
66 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context),
67 Id.ComptimeFloat => unreachable,
68 Id.ComptimeInt => unreachable,
69 Id.EnumLiteral => unreachable,
70 Id.Undefined => unreachable,
71 Id.Null => unreachable,
72 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context),
73 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context),
74 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context),
75 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
76 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
77 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
78 Id.ArgTuple => unreachable,
79 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
80 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "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),
60 .Type => unreachable,
61 .Void => unreachable,
62 .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context),
63 .NoReturn => unreachable,
64 .Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context),
65 .Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context),
66 .Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context),
67 .Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context),
68 .ComptimeFloat => unreachable,
69 .ComptimeInt => unreachable,
70 .EnumLiteral => unreachable,
71 .Undefined => unreachable,
72 .Null => unreachable,
73 .Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context),
74 .ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context),
75 .ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context),
76 .Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
77 .Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
78 .BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
79 .ArgTuple => unreachable,
80 .Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
81 .Frame => return @fieldParentPtr(Frame, "base", base).getLlvmType(allocator, llvm_context),
82 .AnyFrame => return @fieldParentPtr(AnyFrame, "base", base).getLlvmType(allocator, llvm_context),
83 .Vector => return @fieldParentPtr(Vector, "base", base).getLlvmType(allocator, llvm_context),
8284 }
8385 }
8486
8587 pub fn handleIsPtr(base: *Type) bool {
8688 switch (base.id) {
87 Id.Type,
88 Id.ComptimeFloat,
89 Id.ComptimeInt,
90 Id.EnumLiteral,
91 Id.Undefined,
92 Id.Null,
93 Id.BoundFn,
94 Id.ArgTuple,
95 Id.Opaque,
89 .Type,
90 .ComptimeFloat,
91 .ComptimeInt,
92 .EnumLiteral,
93 .Undefined,
94 .Null,
95 .BoundFn,
96 .ArgTuple,
97 .Opaque,
9698 => unreachable,
9799
98 Id.NoReturn,
99 Id.Void,
100 Id.Bool,
101 Id.Int,
102 Id.Float,
103 Id.Pointer,
104 Id.ErrorSet,
105 Id.Enum,
106 Id.Fn,
107 Id.Promise,
108 Id.Vector,
100 .NoReturn,
101 .Void,
102 .Bool,
103 .Int,
104 .Float,
105 .Pointer,
106 .ErrorSet,
107 .Enum,
108 .Fn,
109 .Frame,
110 .AnyFrame,
111 .Vector,
109112 => return false,
110113
111 Id.Struct => @panic("TODO"),
112 Id.Array => @panic("TODO"),
113 Id.Optional => @panic("TODO"),
114 Id.ErrorUnion => @panic("TODO"),
115 Id.Union => @panic("TODO"),
114 .Struct => @panic("TODO"),
115 .Array => @panic("TODO"),
116 .Optional => @panic("TODO"),
117 .ErrorUnion => @panic("TODO"),
118 .Union => @panic("TODO"),
116119 }
117120 }
118121
119122 pub fn hasBits(base: *Type) bool {
120123 switch (base.id) {
121 Id.Type,
122 Id.ComptimeFloat,
123 Id.ComptimeInt,
124 Id.EnumLiteral,
125 Id.Undefined,
126 Id.Null,
127 Id.BoundFn,
128 Id.ArgTuple,
129 Id.Opaque,
124 .Type,
125 .ComptimeFloat,
126 .ComptimeInt,
127 .EnumLiteral,
128 .Undefined,
129 .Null,
130 .BoundFn,
131 .ArgTuple,
132 .Opaque,
130133 => unreachable,
131134
132 Id.Void,
133 Id.NoReturn,
135 .Void,
136 .NoReturn,
134137 => return false,
135138
136 Id.Bool,
137 Id.Int,
138 Id.Float,
139 Id.Fn,
140 Id.Promise,
141 Id.Vector,
139 .Bool,
140 .Int,
141 .Float,
142 .Fn,
143 .Frame,
144 .AnyFrame,
145 .Vector,
142146 => return true,
143147
144 Id.Pointer => {
148 .Pointer => {
145149 const ptr_type = @fieldParentPtr(Pointer, "base", base);
146150 return ptr_type.key.child_type.hasBits();
147151 },
148152
149 Id.ErrorSet => @panic("TODO"),
150 Id.Enum => @panic("TODO"),
151 Id.Struct => @panic("TODO"),
152 Id.Array => @panic("TODO"),
153 Id.Optional => @panic("TODO"),
154 Id.ErrorUnion => @panic("TODO"),
155 Id.Union => @panic("TODO"),
153 .ErrorSet => @panic("TODO"),
154 .Enum => @panic("TODO"),
155 .Struct => @panic("TODO"),
156 .Array => @panic("TODO"),
157 .Optional => @panic("TODO"),
158 .ErrorUnion => @panic("TODO"),
159 .Union => @panic("TODO"),
156160 }
157161 }
158162
......@@ -168,20 +172,20 @@ pub const Type = struct {
168172 fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {
169173 base.* = Type{
170174 .base = Value{
171 .id = Value.Id.Type,
175 .id = .Type,
172176 .typ = &MetaType.get(comp).base,
173177 .ref_count = std.atomic.Int(usize).init(1),
174178 },
175179 .id = id,
176180 .name = name,
177 .abi_alignment = AbiAlignment.init(comp.loop),
181 .abi_alignment = AbiAlignment.init(),
178182 };
179183 }
180184
181185 /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.
182186 /// Otherwise, this one will grab one from the pool and then release it.
183187 pub async fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {
184 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
188 if (base.abi_alignment.start()) |ptr| return ptr.*;
185189
186190 {
187191 const held = try comp.zig_compiler.getAnyLlvmContext();
......@@ -189,7 +193,7 @@ pub const Type = struct {
189193
190194 const llvm_context = held.node.data;
191195
192 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
196 base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);
193197 }
194198 base.abi_alignment.resolve();
195199 return base.abi_alignment.data;
......@@ -197,9 +201,9 @@ pub const Type = struct {
197201
198202 /// If you have an llvm conext handy, you can use it here.
199203 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
200 if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
204 if (base.abi_alignment.start()) |ptr| return ptr.*;
201205
202 base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
206 base.abi_alignment.data = base.resolveAbiAlignment(comp, llvm_context);
203207 base.abi_alignment.resolve();
204208 return base.abi_alignment.data;
205209 }
......@@ -261,30 +265,18 @@ pub const Type = struct {
261265
262266 pub const Generic = struct {
263267 param_count: usize,
264 cc: CC,
265
266 pub const CC = union(CallingConvention) {
267 Auto,
268 C,
269 Cold,
270 Naked,
271 Stdcall,
272 Async: *Type, // allocator type
273 };
268 cc: CallingConvention,
274269 };
275270
276271 pub fn hash(self: *const Key) u32 {
277272 var result: u32 = 0;
278273 result +%= hashAny(self.alignment, 0);
279274 switch (self.data) {
280 Kind.Generic => |generic| {
275 .Generic => |generic| {
281276 result +%= hashAny(generic.param_count, 1);
282 switch (generic.cc) {
283 CallingConvention.Async => |allocator_type| result +%= hashAny(allocator_type, 2),
284 else => result +%= hashAny(CallingConvention(generic.cc), 3),
285 }
277 result +%= hashAny(generic.cc, 3);
286278 },
287 Kind.Normal => |normal| {
279 .Normal => |normal| {
288280 result +%= hashAny(normal.return_type, 4);
289281 result +%= hashAny(normal.is_var_args, 5);
290282 result +%= hashAny(normal.cc, 6);
......@@ -302,21 +294,14 @@ pub const Type = struct {
302294 if (self.alignment) |self_align| {
303295 if (self_align != other.alignment.?) return false;
304296 }
305 if (@TagType(Data)(self.data) != @TagType(Data)(other.data)) return false;
297 if (@as(@TagType(Data), self.data) != @as(@TagType(Data), other.data)) return false;
306298 switch (self.data) {
307 Kind.Generic => |*self_generic| {
299 .Generic => |*self_generic| {
308300 const other_generic = &other.data.Generic;
309301 if (self_generic.param_count != other_generic.param_count) return false;
310 if (CallingConvention(self_generic.cc) != CallingConvention(other_generic.cc)) return false;
311 switch (self_generic.cc) {
312 CallingConvention.Async => |self_allocator_type| {
313 const other_allocator_type = other_generic.cc.Async;
314 if (self_allocator_type != other_allocator_type) return false;
315 },
316 else => {},
317 }
302 if (self_generic.cc != other_generic.cc) return false;
318303 },
319 Kind.Normal => |*self_normal| {
304 .Normal => |*self_normal| {
320305 const other_normal = &other.data.Normal;
321306 if (self_normal.cc != other_normal.cc) return false;
322307 if (self_normal.is_var_args != other_normal.is_var_args) return false;
......@@ -333,13 +318,8 @@ pub const Type = struct {
333318
334319 pub fn deref(key: Key, comp: *Compilation) void {
335320 switch (key.data) {
336 Kind.Generic => |generic| {
337 switch (generic.cc) {
338 CallingConvention.Async => |allocator_type| allocator_type.base.deref(comp),
339 else => {},
340 }
341 },
342 Kind.Normal => |normal| {
321 .Generic => {},
322 .Normal => |normal| {
343323 normal.return_type.base.deref(comp);
344324 for (normal.params) |param| {
345325 param.typ.base.deref(comp);
......@@ -350,13 +330,8 @@ pub const Type = struct {
350330
351331 pub fn ref(key: Key) void {
352332 switch (key.data) {
353 Kind.Generic => |generic| {
354 switch (generic.cc) {
355 CallingConvention.Async => |allocator_type| allocator_type.base.ref(),
356 else => {},
357 }
358 },
359 Kind.Normal => |normal| {
333 .Generic => {},
334 .Normal => |normal| {
360335 normal.return_type.base.ref();
361336 for (normal.params) |param| {
362337 param.typ.base.ref();
......@@ -366,14 +341,7 @@ pub const Type = struct {
366341 }
367342 };
368343
369 pub const CallingConvention = enum {
370 Auto,
371 C,
372 Cold,
373 Naked,
374 Stdcall,
375 Async,
376 };
344 const CallingConvention = builtin.TypeInfo.CallingConvention;
377345
378346 pub const Param = struct {
379347 is_noalias: bool,
......@@ -382,26 +350,26 @@ pub const Type = struct {
382350
383351 fn ccFnTypeStr(cc: CallingConvention) []const u8 {
384352 return switch (cc) {
385 CallingConvention.Auto => "",
386 CallingConvention.C => "extern ",
387 CallingConvention.Cold => "coldcc ",
388 CallingConvention.Naked => "nakedcc ",
389 CallingConvention.Stdcall => "stdcallcc ",
390 CallingConvention.Async => unreachable,
353 .Unspecified => "",
354 .C => "extern ",
355 .Cold => "coldcc ",
356 .Naked => "nakedcc ",
357 .Stdcall => "stdcallcc ",
358 .Async => "async ",
391359 };
392360 }
393361
394362 pub fn paramCount(self: *Fn) usize {
395363 return switch (self.key.data) {
396 Kind.Generic => |generic| generic.param_count,
397 Kind.Normal => |normal| normal.params.len,
364 .Generic => |generic| generic.param_count,
365 .Normal => |normal| normal.params.len,
398366 };
399367 }
400368
401369 /// takes ownership of key.Normal.params on success
402370 pub async fn get(comp: *Compilation, key: Key) !*Fn {
403371 {
404 const held = await (async comp.fn_type_table.acquire() catch unreachable);
372 const held = comp.fn_type_table.acquire();
405373 defer held.release();
406374
407375 if (held.value.get(&key)) |entry| {
......@@ -428,18 +396,10 @@ pub const Type = struct {
428396 const name_stream = &std.io.BufferOutStream.init(&name_buf).stream;
429397
430398 switch (key.data) {
431 Kind.Generic => |generic| {
399 .Generic => |generic| {
432400 self.non_key = NonKey{ .Generic = {} };
433 switch (generic.cc) {
434 CallingConvention.Async => |async_allocator_type| {
435 try name_stream.print("async<{}> ", async_allocator_type.name);
436 },
437 else => {
438 const cc_str = ccFnTypeStr(generic.cc);
439 try name_stream.write(cc_str);
440 },
441 }
442 try name_stream.write("fn(");
401 const cc_str = ccFnTypeStr(generic.cc);
402 try name_stream.print("{}fn(", cc_str);
443403 var param_i: usize = 0;
444404 while (param_i < generic.param_count) : (param_i += 1) {
445405 const arg = if (param_i == 0) "var" else ", var";
......@@ -447,11 +407,11 @@ pub const Type = struct {
447407 }
448408 try name_stream.write(")");
449409 if (key.alignment) |alignment| {
450 try name_stream.print(" align<{}>", alignment);
410 try name_stream.print(" align({})", alignment);
451411 }
452412 try name_stream.write(" var");
453413 },
454 Kind.Normal => |normal| {
414 .Normal => |normal| {
455415 self.non_key = NonKey{
456416 .Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },
457417 };
......@@ -468,16 +428,16 @@ pub const Type = struct {
468428 }
469429 try name_stream.write(")");
470430 if (key.alignment) |alignment| {
471 try name_stream.print(" align<{}>", alignment);
431 try name_stream.print(" align({})", alignment);
472432 }
473433 try name_stream.print(" {}", normal.return_type.name);
474434 },
475435 }
476436
477 self.base.init(comp, Id.Fn, name_buf.toOwnedSlice());
437 self.base.init(comp, .Fn, name_buf.toOwnedSlice());
478438
479439 {
480 const held = await (async comp.fn_type_table.acquire() catch unreachable);
440 const held = comp.fn_type_table.acquire();
481441 defer held.release();
482442
483443 _ = try held.value.put(&self.key, self);
......@@ -488,8 +448,8 @@ pub const Type = struct {
488448 pub fn destroy(self: *Fn, comp: *Compilation) void {
489449 self.key.deref(comp);
490450 switch (self.key.data) {
491 Kind.Generic => {},
492 Kind.Normal => {
451 .Generic => {},
452 .Normal => {
493453 self.non_key.Normal.variable_list.deinit();
494454 },
495455 }
......@@ -499,7 +459,7 @@ pub const Type = struct {
499459 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
500460 const normal = &self.key.data.Normal;
501461 const llvm_return_type = switch (normal.return_type.id) {
502 Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
462 .Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
503463 else => try normal.return_type.getLlvmType(allocator, llvm_context),
504464 };
505465 const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
......@@ -606,7 +566,7 @@ pub const Type = struct {
606566
607567 pub async fn get(comp: *Compilation, key: Key) !*Int {
608568 {
609 const held = await (async comp.int_type_table.acquire() catch unreachable);
569 const held = comp.int_type_table.acquire();
610570 defer held.release();
611571
612572 if (held.value.get(&key)) |entry| {
......@@ -627,10 +587,10 @@ pub const Type = struct {
627587 const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count);
628588 errdefer comp.gpa().free(name);
629589
630 self.base.init(comp, Id.Int, name);
590 self.base.init(comp, .Int, name);
631591
632592 {
633 const held = await (async comp.int_type_table.acquire() catch unreachable);
593 const held = comp.int_type_table.acquire();
634594 defer held.release();
635595
636596 _ = try held.value.put(&self.key, self);
......@@ -648,7 +608,7 @@ pub const Type = struct {
648608
649609 pub async fn gcDestroy(self: *Int, comp: *Compilation) void {
650610 {
651 const held = await (async comp.int_type_table.acquire() catch unreachable);
611 const held = comp.int_type_table.acquire();
652612 defer held.release();
653613
654614 _ = held.value.remove(&self.key).?;
......@@ -689,8 +649,8 @@ pub const Type = struct {
689649 pub fn hash(self: *const Key) u32 {
690650 var result: u32 = 0;
691651 result +%= switch (self.alignment) {
692 Align.Abi => 0xf201c090,
693 Align.Override => |x| hashAny(x, 0),
652 .Abi => 0xf201c090,
653 .Override => |x| hashAny(x, 0),
694654 };
695655 result +%= hashAny(self.child_type, 1);
696656 result +%= hashAny(self.mut, 2);
......@@ -704,13 +664,13 @@ pub const Type = struct {
704664 self.mut != other.mut or
705665 self.vol != other.vol or
706666 self.size != other.size or
707 @TagType(Align)(self.alignment) != @TagType(Align)(other.alignment))
667 @as(@TagType(Align), self.alignment) != @as(@TagType(Align), other.alignment))
708668 {
709669 return false;
710670 }
711671 switch (self.alignment) {
712 Align.Abi => return true,
713 Align.Override => |x| return x == other.alignment.Override,
672 .Abi => return true,
673 .Override => |x| return x == other.alignment.Override,
714674 }
715675 }
716676 };
......@@ -742,7 +702,7 @@ pub const Type = struct {
742702
743703 pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {
744704 {
745 const held = await (async comp.ptr_type_table.acquire() catch unreachable);
705 const held = comp.ptr_type_table.acquire();
746706 defer held.release();
747707
748708 _ = held.value.remove(&self.key).?;
......@@ -753,8 +713,8 @@ pub const Type = struct {
753713
754714 pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
755715 switch (self.key.alignment) {
756 Align.Abi => return await (async self.key.child_type.getAbiAlignment(comp) catch unreachable),
757 Align.Override => |alignment| return alignment,
716 .Abi => return self.key.child_type.getAbiAlignment(comp),
717 .Override => |alignment| return alignment,
758718 }
759719 }
760720
......@@ -764,16 +724,16 @@ pub const Type = struct {
764724 ) !*Pointer {
765725 var normal_key = key;
766726 switch (key.alignment) {
767 Align.Abi => {},
768 Align.Override => |alignment| {
769 const abi_align = try await (async key.child_type.getAbiAlignment(comp) catch unreachable);
727 .Abi => {},
728 .Override => |alignment| {
729 const abi_align = try key.child_type.getAbiAlignment(comp);
770730 if (abi_align == alignment) {
771 normal_key.alignment = Align.Abi;
731 normal_key.alignment = .Abi;
772732 }
773733 },
774734 }
775735 {
776 const held = await (async comp.ptr_type_table.acquire() catch unreachable);
736 const held = comp.ptr_type_table.acquire();
777737 defer held.release();
778738
779739 if (held.value.get(&normal_key)) |entry| {
......@@ -791,21 +751,21 @@ pub const Type = struct {
791751 errdefer comp.gpa().destroy(self);
792752
793753 const size_str = switch (self.key.size) {
794 Size.One => "*",
795 Size.Many => "[*]",
796 Size.Slice => "[]",
797 Size.C => "[*c]",
754 .One => "*",
755 .Many => "[*]",
756 .Slice => "[]",
757 .C => "[*c]",
798758 };
799759 const mut_str = switch (self.key.mut) {
800 Mut.Const => "const ",
801 Mut.Mut => "",
760 .Const => "const ",
761 .Mut => "",
802762 };
803763 const vol_str = switch (self.key.vol) {
804 Vol.Volatile => "volatile ",
805 Vol.Non => "",
764 .Volatile => "volatile ",
765 .Non => "",
806766 };
807767 const name = switch (self.key.alignment) {
808 Align.Abi => try std.fmt.allocPrint(
768 .Abi => try std.fmt.allocPrint(
809769 comp.gpa(),
810770 "{}{}{}{}",
811771 size_str,
......@@ -813,7 +773,7 @@ pub const Type = struct {
813773 vol_str,
814774 self.key.child_type.name,
815775 ),
816 Align.Override => |alignment| try std.fmt.allocPrint(
776 .Override => |alignment| try std.fmt.allocPrint(
817777 comp.gpa(),
818778 "{}align<{}> {}{}{}",
819779 size_str,
......@@ -825,10 +785,10 @@ pub const Type = struct {
825785 };
826786 errdefer comp.gpa().free(name);
827787
828 self.base.init(comp, Id.Pointer, name);
788 self.base.init(comp, .Pointer, name);
829789
830790 {
831 const held = await (async comp.ptr_type_table.acquire() catch unreachable);
791 const held = comp.ptr_type_table.acquire();
832792 defer held.release();
833793
834794 _ = try held.value.put(&self.key, self);
......@@ -873,7 +833,7 @@ pub const Type = struct {
873833 errdefer key.elem_type.base.deref(comp);
874834
875835 {
876 const held = await (async comp.array_type_table.acquire() catch unreachable);
836 const held = comp.array_type_table.acquire();
877837 defer held.release();
878838
879839 if (held.value.get(&key)) |entry| {
......@@ -893,10 +853,10 @@ pub const Type = struct {
893853 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
894854 errdefer comp.gpa().free(name);
895855
896 self.base.init(comp, Id.Array, name);
856 self.base.init(comp, .Array, name);
897857
898858 {
899 const held = await (async comp.array_type_table.acquire() catch unreachable);
859 const held = comp.array_type_table.acquire();
900860 defer held.release();
901861
902862 _ = try held.value.put(&self.key, self);
......@@ -1066,14 +1026,26 @@ pub const Type = struct {
10661026 }
10671027 };
10681028
1069 pub const Promise = struct {
1029 pub const Frame = struct {
1030 base: Type,
1031
1032 pub fn destroy(self: *Frame, comp: *Compilation) void {
1033 comp.gpa().destroy(self);
1034 }
1035
1036 pub fn getLlvmType(self: *Frame, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
1037 @panic("TODO");
1038 }
1039 };
1040
1041 pub const AnyFrame = struct {
10701042 base: Type,
10711043
1072 pub fn destroy(self: *Promise, comp: *Compilation) void {
1044 pub fn destroy(self: *AnyFrame, comp: *Compilation) void {
10731045 comp.gpa().destroy(self);
10741046 }
10751047
1076 pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
1048 pub fn getLlvmType(self: *AnyFrame, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
10771049 @panic("TODO");
10781050 }
10791051 };
......@@ -1081,34 +1053,34 @@ pub const Type = struct {
10811053
10821054fn hashAny(x: var, comptime seed: u64) u32 {
10831055 switch (@typeInfo(@typeOf(x))) {
1084 builtin.TypeId.Int => |info| {
1056 .Int => |info| {
10851057 comptime var rng = comptime std.rand.DefaultPrng.init(seed);
10861058 const unsigned_x = @bitCast(@IntType(false, info.bits), x);
10871059 if (info.bits <= 32) {
1088 return u32(unsigned_x) *% comptime rng.random.scalar(u32);
1060 return @as(u32, unsigned_x) *% comptime rng.random.scalar(u32);
10891061 } else {
10901062 return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x)));
10911063 }
10921064 },
1093 builtin.TypeId.Pointer => |info| {
1065 .Pointer => |info| {
10941066 switch (info.size) {
1095 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
1096 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
1097 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
1098 builtin.TypeInfo.Pointer.Size.C => unreachable,
1067 .One => return hashAny(@ptrToInt(x), seed),
1068 .Many => @compileError("implement hash function"),
1069 .Slice => @compileError("implement hash function"),
1070 .C => unreachable,
10991071 }
11001072 },
1101 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
1102 builtin.TypeId.Bool => {
1073 .Enum => return hashAny(@enumToInt(x), seed),
1074 .Bool => {
11031075 comptime var rng = comptime std.rand.DefaultPrng.init(seed);
11041076 const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) };
11051077 return vals[@boolToInt(x)];
11061078 },
1107 builtin.TypeId.Optional => {
1079 .Optional => {
11081080 if (x) |non_opt| {
11091081 return hashAny(non_opt, seed);
11101082 } else {
1111 return hashAny(u32(1), seed);
1083 return hashAny(@as(u32, 1), seed);
11121084 }
11131085 },
11141086 else => @compileError("implement hash function for " ++ @typeName(@typeOf(x))),
src-self-hosted/util.zig created+211
......@@ -0,0 +1,211 @@
1const std = @import("std");
2const Target = std.Target;
3const llvm = @import("llvm.zig");
4
5pub const FloatAbi = enum {
6 Hard,
7 Soft,
8 SoftFp,
9};
10
11/// TODO expose the arch and subarch separately
12pub fn isArmOrThumb(self: Target) bool {
13 return switch (self.getArch()) {
14 .arm,
15 .armeb,
16 .aarch64,
17 .aarch64_be,
18 .thumb,
19 .thumbeb,
20 => true,
21 else => false,
22 };
23}
24
25pub fn getFloatAbi(self: Target) FloatAbi {
26 return switch (self.getAbi()) {
27 .gnueabihf,
28 .eabihf,
29 .musleabihf,
30 => .Hard,
31 else => .Soft,
32 };
33}
34
35pub fn getObjectFormat(self: Target) Target.ObjectFormat {
36 return switch (self) {
37 .Native => @import("builtin").object_format,
38 .Cross => {
39 if (target.isWindows() or target.isUefi()) {
40 break .coff;
41 } else if (target.isDarwin()) {
42 break .macho;
43 }
44 if (target.isWasm()) {
45 break .wasm;
46 }
47 break .elf;
48 },
49 };
50}
51
52pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
53 const env = self.getAbi();
54 const arch = self.getArch();
55 const os = self.getOs();
56 switch (os) {
57 .freebsd => {
58 return "/libexec/ld-elf.so.1";
59 },
60 .linux => {
61 switch (env) {
62 .android => {
63 if (self.getArchPtrBitWidth() == 64) {
64 return "/system/bin/linker64";
65 } else {
66 return "/system/bin/linker";
67 }
68 },
69 .gnux32 => {
70 if (arch == .x86_64) {
71 return "/libx32/ld-linux-x32.so.2";
72 }
73 },
74 .musl,
75 .musleabi,
76 .musleabihf,
77 => {
78 if (arch == .x86_64) {
79 return "/lib/ld-musl-x86_64.so.1";
80 }
81 },
82 else => {},
83 }
84 switch (arch) {
85 .i386,
86 .sparc,
87 .sparcel,
88 => return "/lib/ld-linux.so.2",
89
90 .aarch64 => return "/lib/ld-linux-aarch64.so.1",
91
92 .aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
93
94 .arm,
95 .thumb,
96 => return switch (getFloatAbi(self)) {
97 .Hard => return "/lib/ld-linux-armhf.so.3",
98 else => return "/lib/ld-linux.so.3",
99 },
100
101 .armeb,
102 .thumbeb,
103 => return switch (getFloatAbi(self)) {
104 .Hard => return "/lib/ld-linux-armhf.so.3",
105 else => return "/lib/ld-linux.so.3",
106 },
107
108 .mips,
109 .mipsel,
110 .mips64,
111 .mips64el,
112 => return null,
113
114 .powerpc => return "/lib/ld.so.1",
115 .powerpc64 => return "/lib64/ld64.so.2",
116 .powerpc64le => return "/lib64/ld64.so.2",
117 .s390x => return "/lib64/ld64.so.1",
118 .sparcv9 => return "/lib64/ld-linux.so.2",
119 .x86_64 => return "/lib64/ld-linux-x86-64.so.2",
120
121 .arc,
122 .avr,
123 .bpfel,
124 .bpfeb,
125 .hexagon,
126 .msp430,
127 .r600,
128 .amdgcn,
129 .riscv32,
130 .riscv64,
131 .tce,
132 .tcele,
133 .xcore,
134 .nvptx,
135 .nvptx64,
136 .le32,
137 .le64,
138 .amdil,
139 .amdil64,
140 .hsail,
141 .hsail64,
142 .spir,
143 .spir64,
144 .kalimba,
145 .shave,
146 .lanai,
147 .wasm32,
148 .wasm64,
149 .renderscript32,
150 .renderscript64,
151 .aarch64_32,
152 => return null,
153 }
154 },
155 else => return null,
156 }
157}
158
159pub fn getDarwinArchString(self: Target) []const u8 {
160 const arch = self.getArch();
161 switch (arch) {
162 .aarch64 => return "arm64",
163 .thumb,
164 .arm,
165 => return "arm",
166 .powerpc => return "ppc",
167 .powerpc64 => return "ppc64",
168 .powerpc64le => return "ppc64le",
169 else => return @tagName(arch),
170 }
171}
172
173pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
174 var result: *llvm.Target = undefined;
175 var err_msg: [*]u8 = undefined;
176 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
177 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
178 return error.UnsupportedTarget;
179 }
180 return result;
181}
182
183pub fn initializeAllTargets() void {
184 llvm.InitializeAllTargets();
185 llvm.InitializeAllTargetInfos();
186 llvm.InitializeAllTargetMCs();
187 llvm.InitializeAllAsmPrinters();
188 llvm.InitializeAllAsmParsers();
189}
190
191pub fn getTriple(allocator: *std.mem.Allocator, self: std.Target) !std.Buffer {
192 var result = try std.Buffer.initSize(allocator, 0);
193 errdefer result.deinit();
194
195 // LLVM WebAssembly output support requires the target to be activated at
196 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
197 //
198 // LLVM determines the output format based on the abi suffix,
199 // defaulting to an object based on the architecture. The default format in
200 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
201 // explicitly set this ourself in order for it to work.
202 //
203 // This is fixed in LLVM 7 and you will be able to get wasm output by
204 // using the target triple `wasm32-unknown-unknown-unknown`.
205 const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi());
206
207 var out = &std.io.BufferOutStream.init(&result).stream;
208 try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);
209
210 return result;
211}
src-self-hosted/value.zig+50-51
......@@ -1,5 +1,4 @@
11const std = @import("std");
2const builtin = @import("builtin");
32const Scope = @import("scope.zig").Scope;
43const Compilation = @import("compilation.zig").Compilation;
54const ObjectFile = @import("codegen.zig").ObjectFile;
......@@ -24,15 +23,15 @@ pub const Value = struct {
2423 if (base.ref_count.decr() == 1) {
2524 base.typ.base.deref(comp);
2625 switch (base.id) {
27 Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),
28 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
29 Id.FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp),
30 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),
31 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
32 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
33 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
34 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),
35 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),
26 .Type => @fieldParentPtr(Type, "base", base).destroy(comp),
27 .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
28 .FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp),
29 .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
30 .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
31 .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
32 .Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
33 .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
34 .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
3635 }
3736 }
3837 }
......@@ -59,15 +58,15 @@ pub const Value = struct {
5958
6059 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
6160 switch (base.id) {
62 Id.Type => unreachable,
63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
64 Id.FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile),
65 Id.Void => return null,
66 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
67 Id.NoReturn => unreachable,
68 Id.Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile),
69 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),
70 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile),
61 .Type => unreachable,
62 .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
63 .FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile),
64 .Void => return null,
65 .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
66 .NoReturn => unreachable,
67 .Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile),
68 .Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),
69 .Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile),
7170 }
7271 }
7372
......@@ -83,15 +82,15 @@ pub const Value = struct {
8382
8483 pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
8584 switch (base.id) {
86 Id.Type => unreachable,
87 Id.Fn => unreachable,
88 Id.FnProto => unreachable,
89 Id.Void => unreachable,
90 Id.Bool => unreachable,
91 Id.NoReturn => unreachable,
92 Id.Ptr => unreachable,
93 Id.Array => unreachable,
94 Id.Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,
85 .Type => unreachable,
86 .Fn => unreachable,
87 .FnProto => unreachable,
88 .Void => unreachable,
89 .Bool => unreachable,
90 .NoReturn => unreachable,
91 .Ptr => unreachable,
92 .Array => unreachable,
93 .Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,
9594 }
9695 }
9796
......@@ -138,7 +137,7 @@ pub const Value = struct {
138137 const self = try comp.gpa().create(FnProto);
139138 self.* = FnProto{
140139 .base = Value{
141 .id = Value.Id.FnProto,
140 .id = .FnProto,
142141 .typ = &fn_type.base,
143142 .ref_count = std.atomic.Int(usize).init(1),
144143 },
......@@ -202,7 +201,7 @@ pub const Value = struct {
202201 const self = try comp.gpa().create(Fn);
203202 self.* = Fn{
204203 .base = Value{
205 .id = Value.Id.Fn,
204 .id = .Fn,
206205 .typ = &fn_type.base,
207206 .ref_count = std.atomic.Int(usize).init(1),
208207 },
......@@ -346,20 +345,20 @@ pub const Value = struct {
346345 errdefer array_val.base.deref(comp);
347346
348347 const elem_type = array_val.base.typ.cast(Type.Array).?.key.elem_type;
349 const ptr_type = try await (async Type.Pointer.get(comp, Type.Pointer.Key{
348 const ptr_type = try Type.Pointer.get(comp, Type.Pointer.Key{
350349 .child_type = elem_type,
351350 .mut = mut,
352351 .vol = Type.Pointer.Vol.Non,
353352 .size = size,
354353 .alignment = Type.Pointer.Align.Abi,
355 }) catch unreachable);
354 });
356355 var ptr_type_consumed = false;
357356 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
358357
359358 const self = try comp.gpa().create(Value.Ptr);
360359 self.* = Value.Ptr{
361360 .base = Value{
362 .id = Value.Id.Ptr,
361 .id = .Ptr,
363362 .typ = &ptr_type.base,
364363 .ref_count = std.atomic.Int(usize).init(1),
365364 },
......@@ -385,8 +384,8 @@ pub const Value = struct {
385384 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386385 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387386 switch (self.special) {
388 Special.Scalar => |scalar| @panic("TODO"),
389 Special.BaseArray => |base_array| {
387 .Scalar => |scalar| @panic("TODO"),
388 .BaseArray => |base_array| {
390389 // TODO put this in one .o file only, and after that, generate extern references to it
391390 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392391 const ptr_bit_count = ofile.comp.target_ptr_bits;
......@@ -401,9 +400,9 @@ pub const Value = struct {
401400 @intCast(c_uint, indices.len),
402401 ) orelse return error.OutOfMemory;
403402 },
404 Special.BaseStruct => |base_struct| @panic("TODO"),
405 Special.HardCodedAddr => |addr| @panic("TODO"),
406 Special.Discard => unreachable,
403 .BaseStruct => |base_struct| @panic("TODO"),
404 .HardCodedAddr => |addr| @panic("TODO"),
405 .Discard => unreachable,
407406 }
408407 }
409408 };
......@@ -428,16 +427,16 @@ pub const Value = struct {
428427 const u8_type = Type.Int.get_u8(comp);
429428 defer u8_type.base.base.deref(comp);
430429
431 const array_type = try await (async Type.Array.get(comp, Type.Array.Key{
430 const array_type = try Type.Array.get(comp, Type.Array.Key{
432431 .elem_type = &u8_type.base,
433432 .len = buffer.len,
434 }) catch unreachable);
433 });
435434 errdefer array_type.base.base.deref(comp);
436435
437436 const self = try comp.gpa().create(Value.Array);
438437 self.* = Value.Array{
439438 .base = Value{
440 .id = Value.Id.Array,
439 .id = .Array,
441440 .typ = &array_type.base,
442441 .ref_count = std.atomic.Int(usize).init(1),
443442 },
......@@ -450,22 +449,22 @@ pub const Value = struct {
450449
451450 pub fn destroy(self: *Array, comp: *Compilation) void {
452451 switch (self.special) {
453 Special.Undefined => {},
454 Special.OwnedBuffer => |buf| {
452 .Undefined => {},
453 .OwnedBuffer => |buf| {
455454 comp.gpa().free(buf);
456455 },
457 Special.Explicit => {},
456 .Explicit => {},
458457 }
459458 comp.gpa().destroy(self);
460459 }
461460
462461 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463462 switch (self.special) {
464 Special.Undefined => {
463 .Undefined => {
465464 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
466465 return llvm.GetUndef(llvm_type);
467466 },
468 Special.OwnedBuffer => |buf| {
467 .OwnedBuffer => |buf| {
469468 const dont_null_terminate = 1;
470469 const llvm_str_init = llvm.ConstStringInContext(
471470 ofile.context,
......@@ -482,7 +481,7 @@ pub const Value = struct {
482481 llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type));
483482 return global;
484483 },
485 Special.Explicit => @panic("TODO"),
484 .Explicit => @panic("TODO"),
486485 }
487486
488487 //{
......@@ -517,7 +516,7 @@ pub const Value = struct {
517516 const self = try comp.gpa().create(Value.Int);
518517 self.* = Value.Int{
519518 .base = Value{
520 .id = Value.Id.Int,
519 .id = .Int,
521520 .typ = typ,
522521 .ref_count = std.atomic.Int(usize).init(1),
523522 },
......@@ -536,7 +535,7 @@ pub const Value = struct {
536535
537536 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538537 switch (self.base.typ.id) {
539 Type.Id.Int => {
538 .Int => {
540539 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
541540 if (self.big_int.len() == 0) {
542541 return llvm.ConstNull(type_ref);
......@@ -554,7 +553,7 @@ pub const Value = struct {
554553 };
555554 return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
556555 },
557 Type.Id.ComptimeInt => unreachable,
556 .ComptimeInt => unreachable,
558557 else => unreachable,
559558 }
560559 }
......@@ -566,7 +565,7 @@ pub const Value = struct {
566565 const new = try comp.gpa().create(Value.Int);
567566 new.* = Value.Int{
568567 .base = Value{
569 .id = Value.Id.Int,
568 .id = .Int,
570569 .typ = old.base.typ,
571570 .ref_count = std.atomic.Int(usize).init(1),
572571 },
src/zig_llvm.h+1-1
......@@ -465,7 +465,7 @@ ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char *
465465ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
466466 enum ZigLLVM_OSType os_type);
467467
468bool ZigLLVMWriteImportLibrary(const char *def_path, const ZigLLVM_ArchType arch,
468bool ZigLLVMWriteImportLibrary(const char *def_path, const enum ZigLLVM_ArchType arch,
469469 const char *output_lib_path, const bool kill_at);
470470
471471ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,
test/stage2/test.zig created+6
......@@ -0,0 +1,6 @@
1const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
2
3pub fn addCases(ctx: *TestContext) !void {
4 try @import("compile_errors.zig").addCases(ctx);
5 try @import("compare_output.zig").addCases(ctx);
6}