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 {...@@ -54,6 +54,7 @@ pub fn build(b: *Builder) !void {
5454
55 var test_stage2 = b.addTest("src-self-hosted/test.zig");55 var test_stage2 = b.addTest("src-self-hosted/test.zig");
56 test_stage2.setBuildMode(builtin.Mode.Debug);56 test_stage2.setBuildMode(builtin.Mode.Debug);
57 test_stage2.addPackagePath("stage2_tests", "test/stage2/test.zig");
5758
58 const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"});59 const fmt_build_zig = b.addFmt([_][]const u8{"build.zig"});
5960
...@@ -72,9 +73,9 @@ pub fn build(b: *Builder) !void {...@@ -72,9 +73,9 @@ pub fn build(b: *Builder) !void {
72 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;73 const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false;
73 const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;74 const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false;
74 const skip_self_hosted = b.option(bool, "skip-self-hosted", "Main test suite skips building self hosted compiler") orelse false;75 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 if (!skip_self_hosted and builtin.os == .linux) {
76 // TODO re-enable this after https://github.com/ziglang/zig/issues/237777 // TODO evented I/O other OS's
77 //test_step.dependOn(&exe.step);78 test_step.dependOn(&exe.step);
78 }79 }
7980
80 const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false;81 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 {...@@ -98,11 +99,7 @@ pub fn build(b: *Builder) !void {
9899
99 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");100 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
100 test_stage2_step.dependOn(&test_stage2.step);101 test_stage2_step.dependOn(&test_stage2.step);
101102 test_step.dependOn(test_stage2_step);
102 // TODO see https://github.com/ziglang/zig/issues/1364
103 if (false) {
104 test_step.dependOn(test_stage2_step);
105 }
106103
107 var chosen_modes: [4]builtin.Mode = undefined;104 var chosen_modes: [4]builtin.Mode = undefined;
108 var chosen_mode_index: usize = 0;105 var chosen_mode_index: usize = 0;
...@@ -235,6 +232,9 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {...@@ -235,6 +232,9 @@ fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
235 if (fs.path.isAbsolute(lib_arg)) {232 if (fs.path.isAbsolute(lib_arg)) {
236 try result.libs.append(lib_arg);233 try result.libs.append(lib_arg);
237 } else {234 } else {
235 if (mem.endsWith(u8, lib_arg, ".lib")) {
236 lib_arg = lib_arg[0 .. lib_arg.len - 4];
237 }
238 try result.system_libs.append(lib_arg);238 try result.system_libs.append(lib_arg);
239 }239 }
240 }240 }
lib/std/child_process.zig+3-1
...@@ -259,7 +259,9 @@ pub const ChildProcess = struct {...@@ -259,7 +259,9 @@ pub const ChildProcess = struct {
259 }259 }
260260
261 fn handleWaitResult(self: *ChildProcess, status: u32) void {261 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;
263 }265 }
264266
265 fn cleanupStreams(self: *ChildProcess) void {267 fn cleanupStreams(self: *ChildProcess) void {
lib/std/event/group.zig+1-2
...@@ -66,11 +66,10 @@ pub fn Group(comptime ReturnType: type) type {...@@ -66,11 +66,10 @@ pub fn Group(comptime ReturnType: type) type {
66 node.* = AllocStack.Node{66 node.* = AllocStack.Node{
67 .next = undefined,67 .next = undefined,
68 .data = Node{68 .data = Node{
69 .handle = frame,69 .handle = @asyncCall(frame, {}, func, args),
70 .bytes = std.mem.asBytes(frame),70 .bytes = std.mem.asBytes(frame),
71 },71 },
72 };72 };
73 _ = @asyncCall(frame, {}, func, args);
74 self.alloc_stack.push(node);73 self.alloc_stack.push(node);
75 }74 }
7675
src-self-hosted/arg.zig+5-5
...@@ -119,9 +119,9 @@ pub const Args = struct {...@@ -119,9 +119,9 @@ pub const Args = struct {
119119
120 // MergeN creation disallows 0 length flag entry (doesn't make sense)120 // MergeN creation disallows 0 length flag entry (doesn't make sense)
121 switch (flag_args) {121 switch (flag_args) {
122 FlagArg.None => unreachable,122 .None => unreachable,
123 FlagArg.Single => |inner| try prev.append(inner),123 .Single => |inner| try prev.append(inner),
124 FlagArg.Many => |inner| try prev.appendSlice(inner.toSliceConst()),124 .Many => |inner| try prev.appendSlice(inner.toSliceConst()),
125 }125 }
126126
127 _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });127 _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
...@@ -158,7 +158,7 @@ pub const Args = struct {...@@ -158,7 +158,7 @@ pub const Args = struct {
158 pub fn single(self: *Args, name: []const u8) ?[]const u8 {158 pub fn single(self: *Args, name: []const u8) ?[]const u8 {
159 if (self.flags.get(name)) |entry| {159 if (self.flags.get(name)) |entry| {
160 switch (entry.value) {160 switch (entry.value) {
161 FlagArg.Single => |inner| {161 .Single => |inner| {
162 return inner;162 return inner;
163 },163 },
164 else => @panic("attempted to retrieve flag with wrong type"),164 else => @panic("attempted to retrieve flag with wrong type"),
...@@ -172,7 +172,7 @@ pub const Args = struct {...@@ -172,7 +172,7 @@ pub const Args = struct {
172 pub fn many(self: *Args, name: []const u8) []const []const u8 {172 pub fn many(self: *Args, name: []const u8) []const []const u8 {
173 if (self.flags.get(name)) |entry| {173 if (self.flags.get(name)) |entry| {
174 switch (entry.value) {174 switch (entry.value) {
175 FlagArg.Many => |inner| {175 .Many => |inner| {
176 return inner.toSliceConst();176 return inner.toSliceConst();
177 },177 },
178 else => @panic("attempted to retrieve flag with wrong type"),178 else => @panic("attempted to retrieve flag with wrong type"),
src-self-hosted/c_int.zig+110-8
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1const Target = @import("std").Target;
2
1pub const CInt = struct {3pub const CInt = struct {
2 id: Id,4 id: Id,
3 zig_name: []const u8,5 zig_name: []const u8,
...@@ -17,52 +19,152 @@ pub const CInt = struct {...@@ -17,52 +19,152 @@ pub const CInt = struct {
1719
18 pub const list = [_]CInt{20 pub const list = [_]CInt{
19 CInt{21 CInt{
20 .id = Id.Short,22 .id = .Short,
21 .zig_name = "c_short",23 .zig_name = "c_short",
22 .c_name = "short",24 .c_name = "short",
23 .is_signed = true,25 .is_signed = true,
24 },26 },
25 CInt{27 CInt{
26 .id = Id.UShort,28 .id = .UShort,
27 .zig_name = "c_ushort",29 .zig_name = "c_ushort",
28 .c_name = "unsigned short",30 .c_name = "unsigned short",
29 .is_signed = false,31 .is_signed = false,
30 },32 },
31 CInt{33 CInt{
32 .id = Id.Int,34 .id = .Int,
33 .zig_name = "c_int",35 .zig_name = "c_int",
34 .c_name = "int",36 .c_name = "int",
35 .is_signed = true,37 .is_signed = true,
36 },38 },
37 CInt{39 CInt{
38 .id = Id.UInt,40 .id = .UInt,
39 .zig_name = "c_uint",41 .zig_name = "c_uint",
40 .c_name = "unsigned int",42 .c_name = "unsigned int",
41 .is_signed = false,43 .is_signed = false,
42 },44 },
43 CInt{45 CInt{
44 .id = Id.Long,46 .id = .Long,
45 .zig_name = "c_long",47 .zig_name = "c_long",
46 .c_name = "long",48 .c_name = "long",
47 .is_signed = true,49 .is_signed = true,
48 },50 },
49 CInt{51 CInt{
50 .id = Id.ULong,52 .id = .ULong,
51 .zig_name = "c_ulong",53 .zig_name = "c_ulong",
52 .c_name = "unsigned long",54 .c_name = "unsigned long",
53 .is_signed = false,55 .is_signed = false,
54 },56 },
55 CInt{57 CInt{
56 .id = Id.LongLong,58 .id = .LongLong,
57 .zig_name = "c_longlong",59 .zig_name = "c_longlong",
58 .c_name = "long long",60 .c_name = "long long",
59 .is_signed = true,61 .is_signed = true,
60 },62 },
61 CInt{63 CInt{
62 .id = Id.ULongLong,64 .id = .ULongLong,
63 .zig_name = "c_ulonglong",65 .zig_name = "c_ulonglong",
64 .c_name = "unsigned long long",66 .c_name = "unsigned long long",
65 .is_signed = false,67 .is_signed = false,
66 },68 },
67 };69 };
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 }
68};170};
src-self-hosted/codegen.zig+19-19
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const Compilation = @import("compilation.zig").Compilation;2const Compilation = @import("compilation.zig").Compilation;
4const llvm = @import("llvm.zig");3const llvm = @import("llvm.zig");
5const c = @import("c.zig");4const c = @import("c.zig");
...@@ -7,17 +6,18 @@ const ir = @import("ir.zig");...@@ -7,17 +6,18 @@ const ir = @import("ir.zig");
7const Value = @import("value.zig").Value;6const Value = @import("value.zig").Value;
8const Type = @import("type.zig").Type;7const Type = @import("type.zig").Type;
9const Scope = @import("scope.zig").Scope;8const Scope = @import("scope.zig").Scope;
9const util = @import("util.zig");
10const event = std.event;10const event = std.event;
11const assert = std.debug.assert;11const assert = std.debug.assert;
12const DW = std.dwarf;12const DW = std.dwarf;
13const maxInt = std.math.maxInt;13const 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 {
16 fn_val.base.ref();16 fn_val.base.ref();
17 defer fn_val.base.deref(comp);17 defer fn_val.base.deref(comp);
18 defer code.destroy(comp.gpa());18 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());
21 errdefer output_path.deinit();21 errdefer output_path.deinit();
2222
23 const llvm_handle = try comp.zig_compiler.getAnyLlvmContext();23 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)...@@ -31,7 +31,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
31 llvm.SetTarget(module, comp.llvm_triple.ptr());31 llvm.SetTarget(module, comp.llvm_triple.ptr());
32 llvm.SetDataLayout(module, comp.target_layout_str);32 llvm.SetDataLayout(module, comp.target_layout_str);
3333
34 if (comp.target.getObjectFormat() == builtin.ObjectFormat.coff) {34 if (util.getObjectFormat(comp.target) == .coff) {
35 llvm.AddModuleCodeViewFlag(module);35 llvm.AddModuleCodeViewFlag(module);
36 } else {36 } else {
37 llvm.AddModuleDebugInfoFlag(module);37 llvm.AddModuleDebugInfoFlag(module);
...@@ -59,7 +59,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -59,7 +59,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
59 comp.name.ptr(),59 comp.name.ptr(),
60 comp.root_package.root_src_dir.ptr(),60 comp.root_package.root_src_dir.ptr(),
61 ) orelse return error.OutOfMemory;61 ) orelse return error.OutOfMemory;
62 const is_optimized = comp.build_mode != builtin.Mode.Debug;62 const is_optimized = comp.build_mode != .Debug;
63 const compile_unit = llvm.CreateCompileUnit(63 const compile_unit = llvm.CreateCompileUnit(
64 dibuilder,64 dibuilder,
65 DW.LANG_C99,65 DW.LANG_C99,
...@@ -79,7 +79,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -79,7 +79,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
79 .builder = builder,79 .builder = builder,
80 .dibuilder = dibuilder,80 .dibuilder = dibuilder,
81 .context = context,81 .context = context,
82 .lock = event.Lock.init(comp.loop),82 .lock = event.Lock.init(),
83 .arena = &code.arena.allocator,83 .arena = &code.arena.allocator,
84 };84 };
8585
...@@ -105,8 +105,8 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -105,8 +105,8 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
105105
106 assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types106 assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types
107107
108 const is_small = comp.build_mode == builtin.Mode.ReleaseSmall;108 const is_small = comp.build_mode == .ReleaseSmall;
109 const is_debug = comp.build_mode == builtin.Mode.Debug;109 const is_debug = comp.build_mode == .Debug;
110110
111 var err_msg: [*]u8 = undefined;111 var err_msg: [*]u8 = undefined;
112 // TODO integrate this with evented I/O112 // TODO integrate this with evented I/O
...@@ -234,8 +234,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -234,8 +234,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
234 // create debug variable declarations for variables and allocate all local variables234 // create debug variable declarations for variables and allocate all local variables
235 for (var_list) |var_scope, i| {235 for (var_list) |var_scope, i| {
236 const var_type = switch (var_scope.data) {236 const var_type = switch (var_scope.data) {
237 Scope.Var.Data.Const => unreachable,237 .Const => unreachable,
238 Scope.Var.Data.Param => |param| param.typ,238 .Param => |param| param.typ,
239 };239 };
240 // if (!type_has_bits(var->value->type)) {240 // if (!type_has_bits(var->value->type)) {
241 // continue;241 // continue;
...@@ -266,7 +266,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)...@@ -266,7 +266,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
266 var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i));266 var_scope.data.Param.llvm_value = llvm.GetParam(llvm_fn, @intCast(c_uint, i));
267 } else {267 } else {
268 // gen_type = var->value->type;268 // 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);
270 }270 }
271 // if (var->decl_node) {271 // if (var->decl_node) {
272 // var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope),272 // 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)...@@ -300,8 +300,8 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
300 ofile,300 ofile,
301 llvm_param,301 llvm_param,
302 scope_var.data.Param.llvm_value,302 scope_var.data.Param.llvm_value,
303 Type.Pointer.Align.Abi,303 .Abi,
304 Type.Pointer.Vol.Non,304 .Non,
305 );305 );
306 }306 }
307307
...@@ -383,8 +383,8 @@ fn renderLoadUntyped(...@@ -383,8 +383,8 @@ fn renderLoadUntyped(
383) !*llvm.Value {383) !*llvm.Value {
384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;384 const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
385 switch (vol) {385 switch (vol) {
386 Type.Pointer.Vol.Non => {},386 .Non => {},
387 Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1),387 .Volatile => llvm.SetVolatile(result, 1),
388 }388 }
389 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr))));389 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.GetElementType(llvm.TypeOf(ptr))));
390 return result;390 return result;
...@@ -414,8 +414,8 @@ pub fn renderStoreUntyped(...@@ -414,8 +414,8 @@ pub fn renderStoreUntyped(
414) !*llvm.Value {414) !*llvm.Value {
415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;415 const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
416 switch (vol) {416 switch (vol) {
417 Type.Pointer.Vol.Non => {},417 .Non => {},
418 Type.Pointer.Vol.Volatile => llvm.SetVolatile(result, 1),418 .Volatile => llvm.SetVolatile(result, 1),
419 }419 }
420 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value)));420 llvm.SetAlignment(result, resolveAlign(ofile, alignment, llvm.TypeOf(value)));
421 return result;421 return result;
...@@ -445,7 +445,7 @@ pub fn renderAlloca(...@@ -445,7 +445,7 @@ pub fn renderAlloca(
445445
446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {446pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
447 return switch (alignment) {447 return switch (alignment) {
448 Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),448 .Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
449 Type.Pointer.Align.Override => |a| a,449 .Override => |a| a,
450 };450 };
451}451}
src-self-hosted/compilation.zig+187-204
...@@ -5,8 +5,8 @@ const Allocator = mem.Allocator;...@@ -5,8 +5,8 @@ const Allocator = mem.Allocator;
5const Buffer = std.Buffer;5const Buffer = std.Buffer;
6const llvm = @import("llvm.zig");6const llvm = @import("llvm.zig");
7const c = @import("c.zig");7const c = @import("c.zig");
8const builtin = @import("builtin");8const builtin = std.builtin;
9const Target = @import("target.zig").Target;9const Target = std.Target;
10const warn = std.debug.warn;10const warn = std.debug.warn;
11const Token = std.zig.Token;11const Token = std.zig.Token;
12const ArrayList = std.ArrayList;12const ArrayList = std.ArrayList;
...@@ -30,14 +30,15 @@ const link = @import("link.zig").link;...@@ -30,14 +30,15 @@ const link = @import("link.zig").link;
30const LibCInstallation = @import("libc_installation.zig").LibCInstallation;30const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
31const CInt = @import("c_int.zig").CInt;31const CInt = @import("c_int.zig").CInt;
32const fs = event.fs;32const fs = event.fs;
33const util = @import("util.zig");
3334
34const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB35const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
3536
36/// Data that is local to the event loop.37/// Data that is local to the event loop.
37pub const ZigCompiler = struct {38pub const ZigCompiler = struct {
38 loop: *event.Loop,
39 llvm_handle_pool: std.atomic.Stack(*llvm.Context),39 llvm_handle_pool: std.atomic.Stack(*llvm.Context),
40 lld_lock: event.Lock,40 lld_lock: event.Lock,
41 allocator: *Allocator,
4142
42 /// TODO pool these so that it doesn't have to lock43 /// TODO pool these so that it doesn't have to lock
43 prng: event.Locked(std.rand.DefaultPrng),44 prng: event.Locked(std.rand.DefaultPrng),
...@@ -46,9 +47,9 @@ pub const ZigCompiler = struct {...@@ -46,9 +47,9 @@ pub const ZigCompiler = struct {
4647
47 var lazy_init_targets = std.lazyInit(void);48 var lazy_init_targets = std.lazyInit(void);
4849
49 pub fn init(loop: *event.Loop) !ZigCompiler {50 pub fn init(allocator: *Allocator) !ZigCompiler {
50 lazy_init_targets.get() orelse {51 lazy_init_targets.get() orelse {
51 Target.initializeAll();52 util.initializeAllTargets();
52 lazy_init_targets.resolve();53 lazy_init_targets.resolve();
53 };54 };
5455
...@@ -57,11 +58,11 @@ pub const ZigCompiler = struct {...@@ -57,11 +58,11 @@ pub const ZigCompiler = struct {
57 const seed = mem.readIntNative(u64, &seed_bytes);58 const seed = mem.readIntNative(u64, &seed_bytes);
5859
59 return ZigCompiler{60 return ZigCompiler{
60 .loop = loop,61 .allocator = allocator,
61 .lld_lock = event.Lock.init(loop),62 .lld_lock = event.Lock.init(),
62 .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),63 .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
63 .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),64 .prng = event.Locked(std.rand.DefaultPrng).init(std.rand.DefaultPrng.init(seed)),
64 .native_libc = event.Future(LibCInstallation).init(loop),65 .native_libc = event.Future(LibCInstallation).init(),
65 };66 };
66 }67 }
6768
...@@ -70,7 +71,7 @@ pub const ZigCompiler = struct {...@@ -70,7 +71,7 @@ pub const ZigCompiler = struct {
70 self.lld_lock.deinit();71 self.lld_lock.deinit();
71 while (self.llvm_handle_pool.pop()) |node| {72 while (self.llvm_handle_pool.pop()) |node| {
72 llvm.ContextDispose(node.data);73 llvm.ContextDispose(node.data);
73 self.loop.allocator.destroy(node);74 self.allocator.destroy(node);
74 }75 }
75 }76 }
7677
...@@ -82,19 +83,19 @@ pub const ZigCompiler = struct {...@@ -82,19 +83,19 @@ pub const ZigCompiler = struct {
82 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;83 const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
83 errdefer llvm.ContextDispose(context_ref);84 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);
86 node.* = std.atomic.Stack(*llvm.Context).Node{87 node.* = std.atomic.Stack(*llvm.Context).Node{
87 .next = undefined,88 .next = undefined,
88 .data = context_ref,89 .data = context_ref,
89 };90 };
90 errdefer self.loop.allocator.destroy(node);91 errdefer self.allocator.destroy(node);
9192
92 return LlvmHandle{ .node = node };93 return LlvmHandle{ .node = node };
93 }94 }
9495
95 pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {96 pub async fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
96 if (await (async self.native_libc.start() catch unreachable)) |ptr| return ptr;97 if (self.native_libc.start()) |ptr| return ptr;
97 try await (async self.native_libc.data.findNative(self.loop) catch unreachable);98 try self.native_libc.data.findNative(self.allocator);
98 self.native_libc.resolve();99 self.native_libc.resolve();
99 return &self.native_libc.data;100 return &self.native_libc.data;
100 }101 }
...@@ -122,7 +123,6 @@ pub const LlvmHandle = struct {...@@ -122,7 +123,6 @@ pub const LlvmHandle = struct {
122123
123pub const Compilation = struct {124pub const Compilation = struct {
124 zig_compiler: *ZigCompiler,125 zig_compiler: *ZigCompiler,
125 loop: *event.Loop,
126 name: Buffer,126 name: Buffer,
127 llvm_triple: Buffer,127 llvm_triple: Buffer,
128 root_src_path: ?[]const u8,128 root_src_path: ?[]const u8,
...@@ -227,8 +227,8 @@ pub const Compilation = struct {...@@ -227,8 +227,8 @@ pub const Compilation = struct {
227 /// need to wait on this group before deinitializing227 /// need to wait on this group before deinitializing
228 deinit_group: event.Group(void),228 deinit_group: event.Group(void),
229229
230 destroy_handle: promise,230 // destroy_frame: @Frame(createAsync),
231 main_loop_handle: promise,231 // main_loop_frame: @Frame(Compilation.mainLoop),
232 main_loop_future: event.Future(void),232 main_loop_future: event.Future(void),
233233
234 have_err_ret_tracing: bool,234 have_err_ret_tracing: bool,
...@@ -243,7 +243,7 @@ pub const Compilation = struct {...@@ -243,7 +243,7 @@ pub const Compilation = struct {
243243
244 c_int_types: [CInt.list.len]*Type.Int,244 c_int_types: [CInt.list.len]*Type.Int,
245245
246 fs_watch: *fs.Watch(*Scope.Root),246 // fs_watch: *fs.Watch(*Scope.Root),
247247
248 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);248 const IntTypeTable = std.HashMap(*const Type.Int.Key, *Type.Int, Type.Int.Key.hash, Type.Int.Key.eql);
249 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);249 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 {...@@ -348,7 +348,7 @@ pub const Compilation = struct {
348 zig_lib_dir: []const u8,348 zig_lib_dir: []const u8,
349 ) !*Compilation {349 ) !*Compilation {
350 var optional_comp: ?*Compilation = null;350 var optional_comp: ?*Compilation = null;
351 const handle = try async<zig_compiler.loop.allocator> createAsync(351 var frame = async createAsync(
352 &optional_comp,352 &optional_comp,
353 zig_compiler,353 zig_compiler,
354 name,354 name,
...@@ -359,10 +359,7 @@ pub const Compilation = struct {...@@ -359,10 +359,7 @@ pub const Compilation = struct {
359 is_static,359 is_static,
360 zig_lib_dir,360 zig_lib_dir,
361 );361 );
362 return optional_comp orelse if (getAwaitResult(362 return optional_comp orelse if (await frame) |_| unreachable else |err| err;
363 zig_compiler.loop.allocator,
364 handle,
365 )) |_| unreachable else |err| err;
366 }363 }
367364
368 async fn createAsync(365 async fn createAsync(
...@@ -376,15 +373,9 @@ pub const Compilation = struct {...@@ -376,15 +373,9 @@ pub const Compilation = struct {
376 is_static: bool,373 is_static: bool,
377 zig_lib_dir: []const u8,374 zig_lib_dir: []const u8,
378 ) !void {375 ) !void {
379 // workaround for https://github.com/ziglang/zig/issues/1194376 const allocator = zig_compiler.allocator;
380 suspend {
381 resume @handle();
382 }
383
384 const loop = zig_compiler.loop;
385 var comp = Compilation{377 var comp = Compilation{
386 .loop = loop,378 .arena_allocator = std.heap.ArenaAllocator.init(allocator),
387 .arena_allocator = std.heap.ArenaAllocator.init(loop.allocator),
388 .zig_compiler = zig_compiler,379 .zig_compiler = zig_compiler,
389 .events = undefined,380 .events = undefined,
390 .root_src_path = root_src_path,381 .root_src_path = root_src_path,
...@@ -394,10 +385,10 @@ pub const Compilation = struct {...@@ -394,10 +385,10 @@ pub const Compilation = struct {
394 .build_mode = build_mode,385 .build_mode = build_mode,
395 .zig_lib_dir = zig_lib_dir,386 .zig_lib_dir = zig_lib_dir,
396 .zig_std_dir = undefined,387 .zig_std_dir = undefined,
397 .tmp_dir = event.Future(BuildError![]u8).init(loop),388 .tmp_dir = event.Future(BuildError![]u8).init(),
398 .destroy_handle = @handle(),389 // .destroy_frame = @frame(),
399 .main_loop_handle = undefined,390 // .main_loop_frame = undefined,
400 .main_loop_future = event.Future(void).init(loop),391 .main_loop_future = event.Future(void).init(),
401392
402 .name = undefined,393 .name = undefined,
403 .llvm_triple = undefined,394 .llvm_triple = undefined,
...@@ -426,7 +417,7 @@ pub const Compilation = struct {...@@ -426,7 +417,7 @@ pub const Compilation = struct {
426 .rpath_list = [_][]const u8{},417 .rpath_list = [_][]const u8{},
427 .assembly_files = [_][]const u8{},418 .assembly_files = [_][]const u8{},
428 .link_objects = [_][]const u8{},419 .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()),
430 .windows_subsystem_windows = false,421 .windows_subsystem_windows = false,
431 .windows_subsystem_console = false,422 .windows_subsystem_console = false,
432 .link_libs_list = undefined,423 .link_libs_list = undefined,
...@@ -438,14 +429,14 @@ pub const Compilation = struct {...@@ -438,14 +429,14 @@ pub const Compilation = struct {
438 .test_name_prefix = null,429 .test_name_prefix = null,
439 .emit_file_type = Emit.Binary,430 .emit_file_type = Emit.Binary,
440 .link_out_file = null,431 .link_out_file = null,
441 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),432 .exported_symbol_names = event.Locked(Decl.Table).init(Decl.Table.init(allocator)),
442 .prelink_group = event.Group(BuildError!void).init(loop),433 .prelink_group = event.Group(BuildError!void).init(allocator),
443 .deinit_group = event.Group(void).init(loop),434 .deinit_group = event.Group(void).init(allocator),
444 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),435 .compile_errors = event.Locked(CompileErrList).init(CompileErrList.init(allocator)),
445 .int_type_table = event.Locked(IntTypeTable).init(loop, IntTypeTable.init(loop.allocator)),436 .int_type_table = event.Locked(IntTypeTable).init(IntTypeTable.init(allocator)),
446 .array_type_table = event.Locked(ArrayTypeTable).init(loop, ArrayTypeTable.init(loop.allocator)),437 .array_type_table = event.Locked(ArrayTypeTable).init(ArrayTypeTable.init(allocator)),
447 .ptr_type_table = event.Locked(PtrTypeTable).init(loop, PtrTypeTable.init(loop.allocator)),438 .ptr_type_table = event.Locked(PtrTypeTable).init(PtrTypeTable.init(allocator)),
448 .fn_type_table = event.Locked(FnTypeTable).init(loop, FnTypeTable.init(loop.allocator)),439 .fn_type_table = event.Locked(FnTypeTable).init(FnTypeTable.init(allocator)),
449 .c_int_types = undefined,440 .c_int_types = undefined,
450441
451 .meta_type = undefined,442 .meta_type = undefined,
...@@ -471,7 +462,7 @@ pub const Compilation = struct {...@@ -471,7 +462,7 @@ pub const Compilation = struct {
471 .have_err_ret_tracing = false,462 .have_err_ret_tracing = false,
472 .primitive_type_table = undefined,463 .primitive_type_table = undefined,
473464
474 .fs_watch = undefined,465 // .fs_watch = undefined,
475 };466 };
476 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());467 comp.link_libs_list = ArrayList(*LinkLib).init(comp.arena());
477 comp.primitive_type_table = TypeTable.init(comp.arena());468 comp.primitive_type_table = TypeTable.init(comp.arena());
...@@ -485,12 +476,12 @@ pub const Compilation = struct {...@@ -485,12 +476,12 @@ pub const Compilation = struct {
485 }476 }
486477
487 comp.name = try Buffer.init(comp.arena(), name);478 comp.name = try Buffer.init(comp.arena(), name);
488 comp.llvm_triple = try target.getTriple(comp.arena());479 comp.llvm_triple = try util.getTriple(comp.arena(), target);
489 comp.llvm_target = try Target.llvmTargetFromTriple(comp.llvm_triple);480 comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);
490 comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" });481 comp.zig_std_dir = try std.fs.path.join(comp.arena(), [_][]const u8{ zig_lib_dir, "std" });
491482
492 const opt_level = switch (build_mode) {483 const opt_level = switch (build_mode) {
493 builtin.Mode.Debug => llvm.CodeGenLevelNone,484 .Debug => llvm.CodeGenLevelNone,
494 else => llvm.CodeGenLevelAggressive,485 else => llvm.CodeGenLevelAggressive,
495 };486 };
496487
...@@ -516,7 +507,7 @@ pub const Compilation = struct {...@@ -516,7 +507,7 @@ pub const Compilation = struct {
516 opt_level,507 opt_level,
517 reloc_mode,508 reloc_mode,
518 llvm.CodeModelDefault,509 llvm.CodeModelDefault,
519 false // TODO: add -ffunction-sections option510 false, // TODO: add -ffunction-sections option
520 ) orelse return error.OutOfMemory;511 ) orelse return error.OutOfMemory;
521 defer llvm.DisposeTargetMachine(comp.target_machine);512 defer llvm.DisposeTargetMachine(comp.target_machine);
522513
...@@ -526,8 +517,11 @@ pub const Compilation = struct {...@@ -526,8 +517,11 @@ pub const Compilation = struct {
526 comp.target_layout_str = llvm.CopyStringRepOfTargetData(comp.target_data_ref) orelse return error.OutOfMemory;517 comp.target_layout_str = llvm.CopyStringRepOfTargetData(comp.target_data_ref) orelse return error.OutOfMemory;
527 defer llvm.DisposeMessage(comp.target_layout_str);518 defer llvm.DisposeMessage(comp.target_layout_str);
528519
529 comp.events = try event.Channel(Event).create(comp.loop, 0);520 comp.events = try allocator.create(event.Channel(Event));
530 defer comp.events.destroy();521 defer allocator.destroy(comp.events);
522
523 comp.events.init([0]Event{});
524 defer comp.events.deinit();
531525
532 if (root_src_path) |root_src| {526 if (root_src_path) |root_src| {
533 const dirname = std.fs.path.dirname(root_src) orelse ".";527 const dirname = std.fs.path.dirname(root_src) orelse ".";
...@@ -540,13 +534,13 @@ pub const Compilation = struct {...@@ -540,13 +534,13 @@ pub const Compilation = struct {
540 comp.root_package = try Package.create(comp.arena(), ".", "");534 comp.root_package = try Package.create(comp.arena(), ".", "");
541 }535 }
542536
543 comp.fs_watch = try fs.Watch(*Scope.Root).create(loop, 16);537 // comp.fs_watch = try fs.Watch(*Scope.Root).create(16);
544 defer comp.fs_watch.destroy();538 // defer comp.fs_watch.destroy();
545539
546 try comp.initTypes();540 try comp.initTypes();
547 defer comp.primitive_type_table.deinit();541 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();
550 // Set this to indicate that initialization completed successfully.544 // Set this to indicate that initialization completed successfully.
551 // from here on out we must not return an error.545 // from here on out we must not return an error.
552 // This must occur before the first suspend/await.546 // This must occur before the first suspend/await.
...@@ -555,12 +549,13 @@ pub const Compilation = struct {...@@ -555,12 +549,13 @@ pub const Compilation = struct {
555 suspend;549 suspend;
556 // From here on is cleanup.550 // 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| {554 if (comp.tmp_dir.getOrNull()) |tmp_dir_result|
561 // TODO evented I/O?555 if (tmp_dir_result.*) |tmp_dir| {
562 std.fs.deleteTree(comp.arena(), tmp_dir) catch {};556 // TODO evented I/O?
563 } else |_| {};557 std.fs.deleteTree(tmp_dir) catch {};
558 } else |_| {};
564 }559 }
565560
566 /// it does ref the result because it could be an arbitrary integer size561 /// it does ref the result because it could be an arbitrary integer size
...@@ -578,10 +573,10 @@ pub const Compilation = struct {...@@ -578,10 +573,10 @@ pub const Compilation = struct {
578 error.Overflow => return error.Overflow,573 error.Overflow => return error.Overflow,
579 error.InvalidCharacter => unreachable, // we just checked the characters above574 error.InvalidCharacter => unreachable, // we just checked the characters above
580 };575 };
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{
582 .bit_count = bit_count,577 .bit_count = bit_count,
583 .is_signed = is_signed,578 .is_signed = is_signed,
584 }) catch unreachable);579 });
585 errdefer int_type.base.base.deref();580 errdefer int_type.base.base.deref();
586 return &int_type.base;581 return &int_type.base;
587 },582 },
...@@ -603,12 +598,12 @@ pub const Compilation = struct {...@@ -603,12 +598,12 @@ pub const Compilation = struct {
603 .base = Type{598 .base = Type{
604 .name = "type",599 .name = "type",
605 .base = Value{600 .base = Value{
606 .id = Value.Id.Type,601 .id = .Type,
607 .typ = undefined,602 .typ = undefined,
608 .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice603 .ref_count = std.atomic.Int(usize).init(3), // 3 because it references itself twice
609 },604 },
610 .id = builtin.TypeId.Type,605 .id = .Type,
611 .abi_alignment = Type.AbiAlignment.init(comp.loop),606 .abi_alignment = Type.AbiAlignment.init(),
612 },607 },
613 .value = undefined,608 .value = undefined,
614 };609 };
...@@ -621,12 +616,12 @@ pub const Compilation = struct {...@@ -621,12 +616,12 @@ pub const Compilation = struct {
621 .base = Type{616 .base = Type{
622 .name = "void",617 .name = "void",
623 .base = Value{618 .base = Value{
624 .id = Value.Id.Type,619 .id = .Type,
625 .typ = &Type.MetaType.get(comp).base,620 .typ = &Type.MetaType.get(comp).base,
626 .ref_count = std.atomic.Int(usize).init(1),621 .ref_count = std.atomic.Int(usize).init(1),
627 },622 },
628 .id = builtin.TypeId.Void,623 .id = .Void,
629 .abi_alignment = Type.AbiAlignment.init(comp.loop),624 .abi_alignment = Type.AbiAlignment.init(),
630 },625 },
631 };626 };
632 assert((try comp.primitive_type_table.put(comp.void_type.base.name, &comp.void_type.base)) == null);627 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 {...@@ -636,12 +631,12 @@ pub const Compilation = struct {
636 .base = Type{631 .base = Type{
637 .name = "noreturn",632 .name = "noreturn",
638 .base = Value{633 .base = Value{
639 .id = Value.Id.Type,634 .id = .Type,
640 .typ = &Type.MetaType.get(comp).base,635 .typ = &Type.MetaType.get(comp).base,
641 .ref_count = std.atomic.Int(usize).init(1),636 .ref_count = std.atomic.Int(usize).init(1),
642 },637 },
643 .id = builtin.TypeId.NoReturn,638 .id = .NoReturn,
644 .abi_alignment = Type.AbiAlignment.init(comp.loop),639 .abi_alignment = Type.AbiAlignment.init(),
645 },640 },
646 };641 };
647 assert((try comp.primitive_type_table.put(comp.noreturn_type.base.name, &comp.noreturn_type.base)) == null);642 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 {...@@ -651,12 +646,12 @@ pub const Compilation = struct {
651 .base = Type{646 .base = Type{
652 .name = "comptime_int",647 .name = "comptime_int",
653 .base = Value{648 .base = Value{
654 .id = Value.Id.Type,649 .id = .Type,
655 .typ = &Type.MetaType.get(comp).base,650 .typ = &Type.MetaType.get(comp).base,
656 .ref_count = std.atomic.Int(usize).init(1),651 .ref_count = std.atomic.Int(usize).init(1),
657 },652 },
658 .id = builtin.TypeId.ComptimeInt,653 .id = .ComptimeInt,
659 .abi_alignment = Type.AbiAlignment.init(comp.loop),654 .abi_alignment = Type.AbiAlignment.init(),
660 },655 },
661 };656 };
662 assert((try comp.primitive_type_table.put(comp.comptime_int_type.base.name, &comp.comptime_int_type.base)) == null);657 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 {...@@ -666,12 +661,12 @@ pub const Compilation = struct {
666 .base = Type{661 .base = Type{
667 .name = "bool",662 .name = "bool",
668 .base = Value{663 .base = Value{
669 .id = Value.Id.Type,664 .id = .Type,
670 .typ = &Type.MetaType.get(comp).base,665 .typ = &Type.MetaType.get(comp).base,
671 .ref_count = std.atomic.Int(usize).init(1),666 .ref_count = std.atomic.Int(usize).init(1),
672 },667 },
673 .id = builtin.TypeId.Bool,668 .id = .Bool,
674 .abi_alignment = Type.AbiAlignment.init(comp.loop),669 .abi_alignment = Type.AbiAlignment.init(),
675 },670 },
676 };671 };
677 assert((try comp.primitive_type_table.put(comp.bool_type.base.name, &comp.bool_type.base)) == null);672 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 {...@@ -679,7 +674,7 @@ pub const Compilation = struct {
679 comp.void_value = try comp.arena().create(Value.Void);674 comp.void_value = try comp.arena().create(Value.Void);
680 comp.void_value.* = Value.Void{675 comp.void_value.* = Value.Void{
681 .base = Value{676 .base = Value{
682 .id = Value.Id.Void,677 .id = .Void,
683 .typ = &Type.Void.get(comp).base,678 .typ = &Type.Void.get(comp).base,
684 .ref_count = std.atomic.Int(usize).init(1),679 .ref_count = std.atomic.Int(usize).init(1),
685 },680 },
...@@ -688,7 +683,7 @@ pub const Compilation = struct {...@@ -688,7 +683,7 @@ pub const Compilation = struct {
688 comp.true_value = try comp.arena().create(Value.Bool);683 comp.true_value = try comp.arena().create(Value.Bool);
689 comp.true_value.* = Value.Bool{684 comp.true_value.* = Value.Bool{
690 .base = Value{685 .base = Value{
691 .id = Value.Id.Bool,686 .id = .Bool,
692 .typ = &Type.Bool.get(comp).base,687 .typ = &Type.Bool.get(comp).base,
693 .ref_count = std.atomic.Int(usize).init(1),688 .ref_count = std.atomic.Int(usize).init(1),
694 },689 },
...@@ -698,7 +693,7 @@ pub const Compilation = struct {...@@ -698,7 +693,7 @@ pub const Compilation = struct {
698 comp.false_value = try comp.arena().create(Value.Bool);693 comp.false_value = try comp.arena().create(Value.Bool);
699 comp.false_value.* = Value.Bool{694 comp.false_value.* = Value.Bool{
700 .base = Value{695 .base = Value{
701 .id = Value.Id.Bool,696 .id = .Bool,
702 .typ = &Type.Bool.get(comp).base,697 .typ = &Type.Bool.get(comp).base,
703 .ref_count = std.atomic.Int(usize).init(1),698 .ref_count = std.atomic.Int(usize).init(1),
704 },699 },
...@@ -708,7 +703,7 @@ pub const Compilation = struct {...@@ -708,7 +703,7 @@ pub const Compilation = struct {
708 comp.noreturn_value = try comp.arena().create(Value.NoReturn);703 comp.noreturn_value = try comp.arena().create(Value.NoReturn);
709 comp.noreturn_value.* = Value.NoReturn{704 comp.noreturn_value.* = Value.NoReturn{
710 .base = Value{705 .base = Value{
711 .id = Value.Id.NoReturn,706 .id = .NoReturn,
712 .typ = &Type.NoReturn.get(comp).base,707 .typ = &Type.NoReturn.get(comp).base,
713 .ref_count = std.atomic.Int(usize).init(1),708 .ref_count = std.atomic.Int(usize).init(1),
714 },709 },
...@@ -720,16 +715,16 @@ pub const Compilation = struct {...@@ -720,16 +715,16 @@ pub const Compilation = struct {
720 .base = Type{715 .base = Type{
721 .name = cint.zig_name,716 .name = cint.zig_name,
722 .base = Value{717 .base = Value{
723 .id = Value.Id.Type,718 .id = .Type,
724 .typ = &Type.MetaType.get(comp).base,719 .typ = &Type.MetaType.get(comp).base,
725 .ref_count = std.atomic.Int(usize).init(1),720 .ref_count = std.atomic.Int(usize).init(1),
726 },721 },
727 .id = builtin.TypeId.Int,722 .id = .Int,
728 .abi_alignment = Type.AbiAlignment.init(comp.loop),723 .abi_alignment = Type.AbiAlignment.init(),
729 },724 },
730 .key = Type.Int.Key{725 .key = Type.Int.Key{
731 .is_signed = cint.is_signed,726 .is_signed = cint.is_signed,
732 .bit_count = comp.target.cIntTypeSizeInBits(cint.id),727 .bit_count = cint.sizeInBits(comp.target),
733 },728 },
734 .garbage_node = undefined,729 .garbage_node = undefined,
735 };730 };
...@@ -741,12 +736,12 @@ pub const Compilation = struct {...@@ -741,12 +736,12 @@ pub const Compilation = struct {
741 .base = Type{736 .base = Type{
742 .name = "u8",737 .name = "u8",
743 .base = Value{738 .base = Value{
744 .id = Value.Id.Type,739 .id = .Type,
745 .typ = &Type.MetaType.get(comp).base,740 .typ = &Type.MetaType.get(comp).base,
746 .ref_count = std.atomic.Int(usize).init(1),741 .ref_count = std.atomic.Int(usize).init(1),
747 },742 },
748 .id = builtin.TypeId.Int,743 .id = .Int,
749 .abi_alignment = Type.AbiAlignment.init(comp.loop),744 .abi_alignment = Type.AbiAlignment.init(),
750 },745 },
751 .key = Type.Int.Key{746 .key = Type.Int.Key{
752 .is_signed = false,747 .is_signed = false,
...@@ -758,8 +753,8 @@ pub const Compilation = struct {...@@ -758,8 +753,8 @@ pub const Compilation = struct {
758 }753 }
759754
760 pub fn destroy(self: *Compilation) void {755 pub fn destroy(self: *Compilation) void {
761 cancel self.main_loop_handle;756 // await self.main_loop_frame;
762 resume self.destroy_handle;757 // resume self.destroy_frame;
763 }758 }
764759
765 fn start(self: *Compilation) void {760 fn start(self: *Compilation) void {
...@@ -768,13 +763,13 @@ pub const Compilation = struct {...@@ -768,13 +763,13 @@ pub const Compilation = struct {
768763
769 async fn mainLoop(self: *Compilation) void {764 async fn mainLoop(self: *Compilation) void {
770 // wait until start() is called765 // 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
775 while (true) {770 while (true) {
776 const link_result = if (build_result) blk: {771 const link_result = if (build_result) blk: {
777 break :blk await (async self.maybeLink() catch unreachable);772 break :blk self.maybeLink();
778 } else |err| err;773 } else |err| err;
779 // this makes a handy error return trace and stack trace in debug mode774 // this makes a handy error return trace and stack trace in debug mode
780 if (std.debug.runtime_safety) {775 if (std.debug.runtime_safety) {
...@@ -782,65 +777,65 @@ pub const Compilation = struct {...@@ -782,65 +777,65 @@ pub const Compilation = struct {
782 }777 }
783778
784 const compile_errors = blk: {779 const compile_errors = blk: {
785 const held = await (async self.compile_errors.acquire() catch unreachable);780 const held = self.compile_errors.acquire();
786 defer held.release();781 defer held.release();
787 break :blk held.value.toOwnedSlice();782 break :blk held.value.toOwnedSlice();
788 };783 };
789784
790 if (link_result) |_| {785 if (link_result) |_| {
791 if (compile_errors.len == 0) {786 if (compile_errors.len == 0) {
792 await (async self.events.put(Event.Ok) catch unreachable);787 self.events.put(Event.Ok);
793 } else {788 } else {
794 await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);789 self.events.put(Event{ .Fail = compile_errors });
795 }790 }
796 } else |err| {791 } else |err| {
797 // if there's an error then the compile errors have dangling references792 // if there's an error then the compile errors have dangling references
798 self.gpa().free(compile_errors);793 self.gpa().free(compile_errors);
799794
800 await (async self.events.put(Event{ .Error = err }) catch unreachable);795 self.events.put(Event{ .Error = err });
801 }796 }
802797
803 // First, get an item from the watch channel, waiting on the channel.798 // // First, get an item from the watch channel, waiting on the channel.
804 var group = event.Group(BuildError!void).init(self.loop);799 // var group = event.Group(BuildError!void).init(self.gpa());
805 {800 // {
806 const ev = (await (async self.fs_watch.channel.get() catch unreachable)) catch |err| {801 // const ev = (self.fs_watch.channel.get()) catch |err| {
807 build_result = err;802 // build_result = err;
808 continue;803 // continue;
809 };804 // };
810 const root_scope = ev.data;805 // const root_scope = ev.data;
811 group.call(rebuildFile, self, root_scope) catch |err| {806 // group.call(rebuildFile, self, root_scope) catch |err| {
812 build_result = err;807 // build_result = err;
813 continue;808 // continue;
814 };809 // };
815 }810 // }
816 // Next, get all the items from the channel that are buffered up.811 // // 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| {812 // while (self.fs_watch.channel.getOrNull()) |ev_or_err| {
818 if (ev_or_err) |ev| {813 // if (ev_or_err) |ev| {
819 const root_scope = ev.data;814 // const root_scope = ev.data;
820 group.call(rebuildFile, self, root_scope) catch |err| {815 // group.call(rebuildFile, self, root_scope) catch |err| {
821 build_result = err;816 // build_result = err;
822 continue;817 // continue;
823 };818 // };
824 } else |err| {819 // } else |err| {
825 build_result = err;820 // build_result = err;
826 continue;821 // continue;
827 }822 // }
828 }823 // }
829 build_result = await (async group.wait() catch unreachable);824 // build_result = group.wait();
830 }825 }
831 }826 }
832827
833 async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {828 async fn rebuildFile(self: *Compilation, root_scope: *Scope.Root) !void {
834 const tree_scope = blk: {829 const tree_scope = blk: {
835 const source_code = (await (async fs.readFile(830 const source_code = "";
836 self.loop,831 // const source_code = fs.readFile(
837 root_scope.realpath,832 // root_scope.realpath,
838 max_src_size,833 // max_src_size,
839 ) catch unreachable)) catch |err| {834 // ) catch |err| {
840 try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));835 // try self.addCompileErrorCli(root_scope.realpath, "unable to open: {}", @errorName(err));
841 return;836 // return;
842 };837 // };
843 errdefer self.gpa().free(source_code);838 // errdefer self.gpa().free(source_code);
844839
845 const tree = try std.zig.parse(self.gpa(), source_code);840 const tree = try std.zig.parse(self.gpa(), source_code);
846 errdefer {841 errdefer {
...@@ -856,19 +851,18 @@ pub const Compilation = struct {...@@ -856,19 +851,18 @@ pub const Compilation = struct {
856 const msg = try Msg.createFromParseErrorAndScope(self, tree_scope, parse_error);851 const msg = try Msg.createFromParseErrorAndScope(self, tree_scope, parse_error);
857 errdefer msg.destroy();852 errdefer msg.destroy();
858853
859 try await (async self.addCompileErrorAsync(msg) catch unreachable);854 try self.addCompileErrorAsync(msg);
860 }855 }
861 if (tree_scope.tree.errors.len != 0) {856 if (tree_scope.tree.errors.len != 0) {
862 return;857 return;
863 }858 }
864859
865 const locked_table = await (async root_scope.decls.table.acquireWrite() catch unreachable);860 const locked_table = root_scope.decls.table.acquireWrite();
866 defer locked_table.release();861 defer locked_table.release();
867862
868 var decl_group = event.Group(BuildError!void).init(self.loop);863 var decl_group = event.Group(BuildError!void).init(self.gpa());
869 defer decl_group.deinit();
870864
871 try await try async self.rebuildChangedDecls(865 try self.rebuildChangedDecls(
872 &decl_group,866 &decl_group,
873 locked_table.value,867 locked_table.value,
874 root_scope.decls,868 root_scope.decls,
...@@ -876,7 +870,7 @@ pub const Compilation = struct {...@@ -876,7 +870,7 @@ pub const Compilation = struct {
876 tree_scope,870 tree_scope,
877 );871 );
878872
879 try await (async decl_group.wait() catch unreachable);873 try decl_group.wait();
880 }874 }
881875
882 async fn rebuildChangedDecls(876 async fn rebuildChangedDecls(
...@@ -894,15 +888,15 @@ pub const Compilation = struct {...@@ -894,15 +888,15 @@ pub const Compilation = struct {
894 while (ast_it.next()) |decl_ptr| {888 while (ast_it.next()) |decl_ptr| {
895 const decl = decl_ptr.*;889 const decl = decl_ptr.*;
896 switch (decl.id) {890 switch (decl.id) {
897 ast.Node.Id.Comptime => {891 .Comptime => {
898 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl);892 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", decl);
899893
900 // TODO connect existing comptime decls to updated source files894 // TODO connect existing comptime decls to updated source files
901895
902 try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node);896 try self.prelink_group.call(addCompTimeBlock, self, tree_scope, &decl_scope.base, comptime_node);
903 },897 },
904 ast.Node.Id.VarDecl => @panic("TODO"),898 .VarDecl => @panic("TODO"),
905 ast.Node.Id.FnProto => {899 .FnProto => {
906 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);900 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);
907901
908 const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else {902 const name = if (fn_proto.name_token) |name_token| tree_scope.tree.tokenSlice(name_token) else {
...@@ -942,11 +936,11 @@ pub const Compilation = struct {...@@ -942,11 +936,11 @@ pub const Compilation = struct {
942 .id = Decl.Id.Fn,936 .id = Decl.Id.Fn,
943 .name = name,937 .name = name,
944 .visib = parseVisibToken(tree_scope.tree, fn_proto.visib_token),938 .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(),
946 .parent_scope = &decl_scope.base,940 .parent_scope = &decl_scope.base,
947 .tree_scope = tree_scope,941 .tree_scope = tree_scope,
948 },942 },
949 .value = Decl.Fn.Val{ .Unresolved = {} },943 .value = .Unresolved,
950 .fn_proto = fn_proto,944 .fn_proto = fn_proto,
951 };945 };
952 tree_scope.base.ref();946 tree_scope.base.ref();
...@@ -955,7 +949,7 @@ pub const Compilation = struct {...@@ -955,7 +949,7 @@ pub const Compilation = struct {
955 try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table);949 try group.call(addTopLevelDecl, self, &fn_decl.base, locked_table);
956 }950 }
957 },951 },
958 ast.Node.Id.TestDecl => @panic("TODO"),952 .TestDecl => @panic("TODO"),
959 else => unreachable,953 else => unreachable,
960 }954 }
961 }955 }
...@@ -982,26 +976,26 @@ pub const Compilation = struct {...@@ -982,26 +976,26 @@ pub const Compilation = struct {
982 };976 };
983 defer root_scope.base.deref(self);977 defer root_scope.base.deref(self);
984978
985 assert((try await try async self.fs_watch.addFile(root_scope.realpath, root_scope)) == null);979 // assert((try self.fs_watch.addFile(root_scope.realpath, root_scope)) == null);
986 try await try async self.rebuildFile(root_scope);980 try self.rebuildFile(root_scope);
987 }981 }
988 }982 }
989983
990 async fn maybeLink(self: *Compilation) !void {984 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) {
992 error.SemanticAnalysisFailed => {},986 error.SemanticAnalysisFailed => {},
993 else => return err,987 else => return err,
994 };988 };
995989
996 const any_prelink_errors = blk: {990 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();
998 defer compile_errors.release();992 defer compile_errors.release();
999993
1000 break :blk compile_errors.value.len != 0;994 break :blk compile_errors.value.len != 0;
1001 };995 };
1002996
1003 if (!any_prelink_errors) {997 if (!any_prelink_errors) {
1004 try await (async link(self) catch unreachable);998 try link(self);
1005 }999 }
1006 }1000 }
10071001
...@@ -1013,12 +1007,12 @@ pub const Compilation = struct {...@@ -1013,12 +1007,12 @@ pub const Compilation = struct {
1013 node: *ast.Node,1007 node: *ast.Node,
1014 expected_type: ?*Type,1008 expected_type: ?*Type,
1015 ) !*ir.Code {1009 ) !*ir.Code {
1016 const unanalyzed_code = try await (async ir.gen(1010 const unanalyzed_code = try ir.gen(
1017 comp,1011 comp,
1018 node,1012 node,
1019 tree_scope,1013 tree_scope,
1020 scope,1014 scope,
1021 ) catch unreachable);1015 );
1022 defer unanalyzed_code.destroy(comp.gpa());1016 defer unanalyzed_code.destroy(comp.gpa());
10231017
1024 if (comp.verbose_ir) {1018 if (comp.verbose_ir) {
...@@ -1026,11 +1020,11 @@ pub const Compilation = struct {...@@ -1026,11 +1020,11 @@ pub const Compilation = struct {
1026 unanalyzed_code.dump();1020 unanalyzed_code.dump();
1027 }1021 }
10281022
1029 const analyzed_code = try await (async ir.analyze(1023 const analyzed_code = try ir.analyze(
1030 comp,1024 comp,
1031 unanalyzed_code,1025 unanalyzed_code,
1032 expected_type,1026 expected_type,
1033 ) catch unreachable);1027 );
1034 errdefer analyzed_code.destroy(comp.gpa());1028 errdefer analyzed_code.destroy(comp.gpa());
10351029
1036 if (comp.verbose_ir) {1030 if (comp.verbose_ir) {
...@@ -1046,17 +1040,17 @@ pub const Compilation = struct {...@@ -1046,17 +1040,17 @@ pub const Compilation = struct {
1046 tree_scope: *Scope.AstTree,1040 tree_scope: *Scope.AstTree,
1047 scope: *Scope,1041 scope: *Scope,
1048 comptime_node: *ast.Node.Comptime,1042 comptime_node: *ast.Node.Comptime,
1049 ) !void {1043 ) BuildError!void {
1050 const void_type = Type.Void.get(comp);1044 const void_type = Type.Void.get(comp);
1051 defer void_type.base.base.deref(comp);1045 defer void_type.base.base.deref(comp);
10521046
1053 const analyzed_code = (await (async genAndAnalyzeCode(1047 const analyzed_code = genAndAnalyzeCode(
1054 comp,1048 comp,
1055 tree_scope,1049 tree_scope,
1056 scope,1050 scope,
1057 comptime_node.expr,1051 comptime_node.expr,
1058 &void_type.base,1052 &void_type.base,
1059 ) catch unreachable)) catch |err| switch (err) {1053 ) catch |err| switch (err) {
1060 // This poison value should not cause the errdefers to run. It simply means1054 // This poison value should not cause the errdefers to run. It simply means
1061 // that comp.compile_errors is populated.1055 // that comp.compile_errors is populated.
1062 error.SemanticAnalysisFailed => return {},1056 error.SemanticAnalysisFailed => return {},
...@@ -1069,7 +1063,7 @@ pub const Compilation = struct {...@@ -1069,7 +1063,7 @@ pub const Compilation = struct {
1069 self: *Compilation,1063 self: *Compilation,
1070 decl: *Decl,1064 decl: *Decl,
1071 locked_table: *Decl.Table,1065 locked_table: *Decl.Table,
1072 ) !void {1066 ) BuildError!void {
1073 const is_export = decl.isExported(decl.tree_scope.tree);1067 const is_export = decl.isExported(decl.tree_scope.tree);
10741068
1075 if (is_export) {1069 if (is_export) {
...@@ -1109,17 +1103,17 @@ pub const Compilation = struct {...@@ -1109,17 +1103,17 @@ pub const Compilation = struct {
1109 async fn addCompileErrorAsync(1103 async fn addCompileErrorAsync(
1110 self: *Compilation,1104 self: *Compilation,
1111 msg: *Msg,1105 msg: *Msg,
1112 ) !void {1106 ) BuildError!void {
1113 errdefer msg.destroy();1107 errdefer msg.destroy();
11141108
1115 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);1109 const compile_errors = self.compile_errors.acquire();
1116 defer compile_errors.release();1110 defer compile_errors.release();
11171111
1118 try compile_errors.value.append(msg);1112 try compile_errors.value.append(msg);
1119 }1113 }
11201114
1121 async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) !void {1115 async fn verifyUniqueSymbol(self: *Compilation, decl: *Decl) BuildError!void {
1122 const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);1116 const exported_symbol_names = self.exported_symbol_names.acquire();
1123 defer exported_symbol_names.release();1117 defer exported_symbol_names.release();
11241118
1125 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {1119 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
...@@ -1173,14 +1167,14 @@ pub const Compilation = struct {...@@ -1173,14 +1167,14 @@ pub const Compilation = struct {
11731167
1174 /// cancels itself so no need to await or cancel the promise.1168 /// cancels itself so no need to await or cancel the promise.
1175 async fn startFindingNativeLibC(self: *Compilation) void {1169 async fn startFindingNativeLibC(self: *Compilation) void {
1176 await (async self.loop.yield() catch unreachable);1170 std.event.Loop.instance.?.yield();
1177 // we don't care if it fails, we're just trying to kick off the future resolution1171 // 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;
1179 }1173 }
11801174
1181 /// General Purpose Allocator. Must free when done.1175 /// General Purpose Allocator. Must free when done.
1182 fn gpa(self: Compilation) *mem.Allocator {1176 fn gpa(self: Compilation) *mem.Allocator {
1183 return self.loop.allocator;1177 return self.zig_compiler.allocator;
1184 }1178 }
11851179
1186 /// Arena Allocator. Automatically freed when the Compilation is destroyed.1180 /// Arena Allocator. Automatically freed when the Compilation is destroyed.
...@@ -1191,8 +1185,8 @@ pub const Compilation = struct {...@@ -1191,8 +1185,8 @@ pub const Compilation = struct {
1191 /// If the temporary directory for this compilation has not been created, it creates it.1185 /// If the temporary directory for this compilation has not been created, it creates it.
1192 /// Then it creates a random file name in that dir and returns it.1186 /// Then it creates a random file name in that dir and returns it.
1193 pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {1187 pub async fn createRandomOutputPath(self: *Compilation, suffix: []const u8) !Buffer {
1194 const tmp_dir = try await (async self.getTmpDir() catch unreachable);1188 const tmp_dir = try self.getTmpDir();
1195 const file_prefix = await (async self.getRandomFileName() catch unreachable);1189 const file_prefix = self.getRandomFileName();
11961190
1197 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);1191 const file_name = try std.fmt.allocPrint(self.gpa(), "{}{}", file_prefix[0..], suffix);
1198 defer self.gpa().free(file_name);1192 defer self.gpa().free(file_name);
...@@ -1207,14 +1201,14 @@ pub const Compilation = struct {...@@ -1207,14 +1201,14 @@ pub const Compilation = struct {
1207 /// Then returns it. The directory is unique to this Compilation and cleaned up when1201 /// Then returns it. The directory is unique to this Compilation and cleaned up when
1208 /// the Compilation deinitializes.1202 /// the Compilation deinitializes.
1209 async fn getTmpDir(self: *Compilation) ![]const u8 {1203 async fn getTmpDir(self: *Compilation) ![]const u8 {
1210 if (await (async self.tmp_dir.start() catch unreachable)) |ptr| return ptr.*;1204 if (self.tmp_dir.start()) |ptr| return ptr.*;
1211 self.tmp_dir.data = await (async self.getTmpDirImpl() catch unreachable);1205 self.tmp_dir.data = self.getTmpDirImpl();
1212 self.tmp_dir.resolve();1206 self.tmp_dir.resolve();
1213 return self.tmp_dir.data;1207 return self.tmp_dir.data;
1214 }1208 }
12151209
1216 async fn getTmpDirImpl(self: *Compilation) ![]u8 {1210 async fn getTmpDirImpl(self: *Compilation) ![]u8 {
1217 const comp_dir_name = await (async self.getRandomFileName() catch unreachable);1211 const comp_dir_name = self.getRandomFileName();
1218 const zig_dir_path = try getZigDir(self.gpa());1212 const zig_dir_path = try getZigDir(self.gpa());
1219 defer self.gpa().free(zig_dir_path);1213 defer self.gpa().free(zig_dir_path);
12201214
...@@ -1233,7 +1227,7 @@ pub const Compilation = struct {...@@ -1233,7 +1227,7 @@ pub const Compilation = struct {
1233 var rand_bytes: [9]u8 = undefined;1227 var rand_bytes: [9]u8 = undefined;
12341228
1235 {1229 {
1236 const held = await (async self.zig_compiler.prng.acquire() catch unreachable);1230 const held = self.zig_compiler.prng.acquire();
1237 defer held.release();1231 defer held.release();
12381232
1239 held.value.random.bytes(rand_bytes[0..]);1233 held.value.random.bytes(rand_bytes[0..]);
...@@ -1256,7 +1250,7 @@ pub const Compilation = struct {...@@ -1256,7 +1250,7 @@ pub const Compilation = struct {
1256 node: *ast.Node,1250 node: *ast.Node,
1257 expected_type: *Type,1251 expected_type: *Type,
1258 ) !*Value {1252 ) !*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);
1260 defer analyzed_code.destroy(comp.gpa());1254 defer analyzed_code.destroy(comp.gpa());
12611255
1262 return analyzed_code.getCompTimeResult(comp);1256 return analyzed_code.getCompTimeResult(comp);
...@@ -1266,17 +1260,17 @@ pub const Compilation = struct {...@@ -1266,17 +1260,17 @@ pub const Compilation = struct {
1266 const meta_type = &Type.MetaType.get(comp).base;1260 const meta_type = &Type.MetaType.get(comp).base;
1267 defer meta_type.base.deref(comp);1261 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);
1270 errdefer result_val.base.deref(comp);1264 errdefer result_val.base.deref(comp);
12711265
1272 return result_val.cast(Type).?;1266 return result_val.cast(Type).?;
1273 }1267 }
12741268
1275 /// This declaration has been blessed as going into the final code generation.1269 /// This declaration has been blessed as going into the final code generation.
1276 pub async fn resolveDecl(comp: *Compilation, decl: *Decl) !void {1270 pub async fn resolveDecl(comp: *Compilation, decl: *Decl) BuildError!void {
1277 if (await (async decl.resolution.start() catch unreachable)) |ptr| return ptr.*;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);
1280 decl.resolution.resolve();1274 decl.resolution.resolve();
1281 return decl.resolution.data;1275 return decl.resolution.data;
1282 }1276 }
...@@ -1295,24 +1289,24 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib...@@ -1295,24 +1289,24 @@ fn parseVisibToken(tree: *ast.Tree, optional_token_index: ?ast.TokenIndex) Visib
1295/// The function that actually does the generation.1289/// The function that actually does the generation.
1296async fn generateDecl(comp: *Compilation, decl: *Decl) !void {1290async fn generateDecl(comp: *Compilation, decl: *Decl) !void {
1297 switch (decl.id) {1291 switch (decl.id) {
1298 Decl.Id.Var => @panic("TODO"),1292 .Var => @panic("TODO"),
1299 Decl.Id.Fn => {1293 .Fn => {
1300 const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);1294 const fn_decl = @fieldParentPtr(Decl.Fn, "base", decl);
1301 return await (async generateDeclFn(comp, fn_decl) catch unreachable);1295 return generateDeclFn(comp, fn_decl);
1302 },1296 },
1303 Decl.Id.CompTime => @panic("TODO"),1297 .CompTime => @panic("TODO"),
1304 }1298 }
1305}1299}
13061300
1307async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {1301async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1308 const tree_scope = fn_decl.base.tree_scope;1302 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
1312 const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);1306 const fndef_scope = try Scope.FnDef.create(comp, fn_decl.base.parent_scope);
1313 defer fndef_scope.base.deref(comp);1307 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);
1316 defer fn_type.base.base.deref(comp);1310 defer fn_type.base.base.deref(comp);
13171311
1318 var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name);1312 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 {...@@ -1356,12 +1350,12 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1356 try fn_type.non_key.Normal.variable_list.append(var_scope);1350 try fn_type.non_key.Normal.variable_list.append(var_scope);
1357 }1351 }
13581352
1359 const analyzed_code = try await (async comp.genAndAnalyzeCode(1353 const analyzed_code = try comp.genAndAnalyzeCode(
1360 tree_scope,1354 tree_scope,
1361 fn_val.child_scope,1355 fn_val.child_scope,
1362 body_node,1356 body_node,
1363 fn_type.key.data.Normal.return_type,1357 fn_type.key.data.Normal.return_type,
1364 ) catch unreachable);1358 );
1365 errdefer analyzed_code.destroy(comp.gpa());1359 errdefer analyzed_code.destroy(comp.gpa());
13661360
1367 assert(fn_val.block_scope != null);1361 assert(fn_val.block_scope != null);
...@@ -1372,13 +1366,13 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {...@@ -1372,13 +1366,13 @@ async fn generateDeclFn(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1372 try comp.prelink_group.call(addFnToLinkSet, comp, fn_val);1366 try comp.prelink_group.call(addFnToLinkSet, comp, fn_val);
1373}1367}
13741368
1375async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) void {1369async fn addFnToLinkSet(comp: *Compilation, fn_val: *Value.Fn) Compilation.BuildError!void {
1376 fn_val.base.ref();1370 fn_val.base.ref();
1377 defer fn_val.base.deref(comp);1371 defer fn_val.base.deref(comp);
13781372
1379 fn_val.link_set_node.data = fn_val;1373 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();
1382 defer held.release();1376 defer held.release();
13831377
1384 held.value.append(fn_val.link_set_node);1378 held.value.append(fn_val.link_set_node);
...@@ -1395,10 +1389,10 @@ async fn analyzeFnType(...@@ -1395,10 +1389,10 @@ async fn analyzeFnType(
1395 fn_proto: *ast.Node.FnProto,1389 fn_proto: *ast.Node.FnProto,
1396) !*Type.Fn {1390) !*Type.Fn {
1397 const return_type_node = switch (fn_proto.return_type) {1391 const return_type_node = switch (fn_proto.return_type) {
1398 ast.Node.FnProto.ReturnType.Explicit => |n| n,1392 .Explicit => |n| n,
1399 ast.Node.FnProto.ReturnType.InferErrorSet => |n| n,1393 .InferErrorSet => |n| n,
1400 };1394 };
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);
1402 return_type.base.deref(comp);1396 return_type.base.deref(comp);
14031397
1404 var params = ArrayList(Type.Fn.Param).init(comp.gpa());1398 var params = ArrayList(Type.Fn.Param).init(comp.gpa());
...@@ -1414,7 +1408,7 @@ async fn analyzeFnType(...@@ -1414,7 +1408,7 @@ async fn analyzeFnType(
1414 var it = fn_proto.params.iterator(0);1408 var it = fn_proto.params.iterator(0);
1415 while (it.next()) |param_node_ptr| {1409 while (it.next()) |param_node_ptr| {
1416 const param_node = param_node_ptr.*.cast(ast.Node.ParamDecl).?;1410 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);
1418 errdefer param_type.base.deref(comp);1412 errdefer param_type.base.deref(comp);
1419 try params.append(Type.Fn.Param{1413 try params.append(Type.Fn.Param{
1420 .typ = param_type,1414 .typ = param_type,
...@@ -1430,7 +1424,7 @@ async fn analyzeFnType(...@@ -1430,7 +1424,7 @@ async fn analyzeFnType(
1430 .return_type = return_type,1424 .return_type = return_type,
1431 .params = params.toOwnedSlice(),1425 .params = params.toOwnedSlice(),
1432 .is_var_args = false, // TODO1426 .is_var_args = false, // TODO
1433 .cc = Type.Fn.CallingConvention.Auto, // TODO1427 .cc = .Unspecified, // TODO
1434 },1428 },
1435 },1429 },
1436 };1430 };
...@@ -1443,7 +1437,7 @@ async fn analyzeFnType(...@@ -1443,7 +1437,7 @@ async fn analyzeFnType(
1443 comp.gpa().free(key.data.Normal.params);1437 comp.gpa().free(key.data.Normal.params);
1444 };1438 };
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);
1447 key_consumed = true;1441 key_consumed = true;
1448 errdefer fn_type.base.base.deref(comp);1442 errdefer fn_type.base.base.deref(comp);
14491443
...@@ -1451,12 +1445,12 @@ async fn analyzeFnType(...@@ -1451,12 +1445,12 @@ async fn analyzeFnType(
1451}1445}
14521446
1453async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {1447async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1454 const fn_type = try await (async analyzeFnType(1448 const fn_type = try analyzeFnType(
1455 comp,1449 comp,
1456 fn_decl.base.tree_scope,1450 fn_decl.base.tree_scope,
1457 fn_decl.base.parent_scope,1451 fn_decl.base.parent_scope,
1458 fn_decl.fn_proto,1452 fn_decl.fn_proto,
1459 ) catch unreachable);1453 );
1460 defer fn_type.base.base.deref(comp);1454 defer fn_type.base.base.deref(comp);
14611455
1462 var symbol_name = try std.Buffer.init(comp.gpa(), fn_decl.base.name);1456 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 {...@@ -1468,14 +1462,3 @@ async fn generateDeclFnProto(comp: *Compilation, fn_decl: *Decl.Fn) !void {
1468 fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };1462 fn_decl.value = Decl.Fn.Val{ .FnProto = fn_proto_val };
1469 symbol_name_consumed = true;1463 symbol_name_consumed = true;
1470}1464}
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 {...@@ -29,7 +29,7 @@ pub const Decl = struct {
2929
30 pub fn isExported(base: *const Decl, tree: *ast.Tree) bool {30 pub fn isExported(base: *const Decl, tree: *ast.Tree) bool {
31 switch (base.id) {31 switch (base.id) {
32 Id.Fn => {32 .Fn => {
33 const fn_decl = @fieldParentPtr(Fn, "base", base);33 const fn_decl = @fieldParentPtr(Fn, "base", base);
34 return fn_decl.isExported(tree);34 return fn_decl.isExported(tree);
35 },35 },
...@@ -39,7 +39,7 @@ pub const Decl = struct {...@@ -39,7 +39,7 @@ pub const Decl = struct {
3939
40 pub fn getSpan(base: *const Decl) errmsg.Span {40 pub fn getSpan(base: *const Decl) errmsg.Span {
41 switch (base.id) {41 switch (base.id) {
42 Id.Fn => {42 .Fn => {
43 const fn_decl = @fieldParentPtr(Fn, "base", base);43 const fn_decl = @fieldParentPtr(Fn, "base", base);
44 const fn_proto = fn_decl.fn_proto;44 const fn_proto = fn_decl.fn_proto;
45 const start = fn_proto.fn_token;45 const start = fn_proto.fn_token;
...@@ -74,7 +74,7 @@ pub const Decl = struct {...@@ -74,7 +74,7 @@ pub const Decl = struct {
7474
75 // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous75 // TODO https://github.com/ziglang/zig/issues/683 and then make this anonymous
76 pub const Val = union(enum) {76 pub const Val = union(enum) {
77 Unresolved: void,77 Unresolved,
78 Fn: *Value.Fn,78 Fn: *Value.Fn,
79 FnProto: *Value.FnProto,79 FnProto: *Value.FnProto,
80 };80 };
...@@ -83,7 +83,7 @@ pub const Decl = struct {...@@ -83,7 +83,7 @@ pub const Decl = struct {
83 return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {83 return if (self.fn_proto.extern_export_inline_token) |tok_index| x: {
84 const token = tree.tokens.at(tok_index);84 const token = tree.tokens.at(tok_index);
85 break :x switch (token.id) {85 break :x switch (token.id) {
86 Token.Id.Extern => tree.tokenSlicePtr(token),86 .Extern => tree.tokenSlicePtr(token),
87 else => null,87 else => null,
88 };88 };
89 } else null;89 } else null;
...@@ -92,7 +92,7 @@ pub const Decl = struct {...@@ -92,7 +92,7 @@ pub const Decl = struct {
92 pub fn isExported(self: Fn, tree: *ast.Tree) bool {92 pub fn isExported(self: Fn, tree: *ast.Tree) bool {
93 if (self.fn_proto.extern_export_inline_token) |tok_index| {93 if (self.fn_proto.extern_export_inline_token) |tok_index| {
94 const token = tree.tokens.at(tok_index);94 const token = tree.tokens.at(tok_index);
95 return token.id == Token.Id.Keyword_export;95 return token.id == .Keyword_export;
96 } else {96 } else {
97 return false;97 return false;
98 }98 }
src-self-hosted/errmsg.zig+16-16
...@@ -62,17 +62,17 @@ pub const Msg = struct {...@@ -62,17 +62,17 @@ pub const Msg = struct {
6262
63 pub fn destroy(self: *Msg) void {63 pub fn destroy(self: *Msg) void {
64 switch (self.data) {64 switch (self.data) {
65 Data.Cli => |cli| {65 .Cli => |cli| {
66 cli.allocator.free(self.text);66 cli.allocator.free(self.text);
67 cli.allocator.free(self.realpath);67 cli.allocator.free(self.realpath);
68 cli.allocator.destroy(self);68 cli.allocator.destroy(self);
69 },69 },
70 Data.PathAndTree => |path_and_tree| {70 .PathAndTree => |path_and_tree| {
71 path_and_tree.allocator.free(self.text);71 path_and_tree.allocator.free(self.text);
72 path_and_tree.allocator.free(self.realpath);72 path_and_tree.allocator.free(self.realpath);
73 path_and_tree.allocator.destroy(self);73 path_and_tree.allocator.destroy(self);
74 },74 },
75 Data.ScopeAndComp => |scope_and_comp| {75 .ScopeAndComp => |scope_and_comp| {
76 scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation);76 scope_and_comp.tree_scope.base.deref(scope_and_comp.compilation);
77 scope_and_comp.compilation.gpa().free(self.text);77 scope_and_comp.compilation.gpa().free(self.text);
78 scope_and_comp.compilation.gpa().free(self.realpath);78 scope_and_comp.compilation.gpa().free(self.realpath);
...@@ -83,11 +83,11 @@ pub const Msg = struct {...@@ -83,11 +83,11 @@ pub const Msg = struct {
8383
84 fn getAllocator(self: *const Msg) *mem.Allocator {84 fn getAllocator(self: *const Msg) *mem.Allocator {
85 switch (self.data) {85 switch (self.data) {
86 Data.Cli => |cli| return cli.allocator,86 .Cli => |cli| return cli.allocator,
87 Data.PathAndTree => |path_and_tree| {87 .PathAndTree => |path_and_tree| {
88 return path_and_tree.allocator;88 return path_and_tree.allocator;
89 },89 },
90 Data.ScopeAndComp => |scope_and_comp| {90 .ScopeAndComp => |scope_and_comp| {
91 return scope_and_comp.compilation.gpa();91 return scope_and_comp.compilation.gpa();
92 },92 },
93 }93 }
...@@ -95,11 +95,11 @@ pub const Msg = struct {...@@ -95,11 +95,11 @@ pub const Msg = struct {
9595
96 pub fn getTree(self: *const Msg) *ast.Tree {96 pub fn getTree(self: *const Msg) *ast.Tree {
97 switch (self.data) {97 switch (self.data) {
98 Data.Cli => unreachable,98 .Cli => unreachable,
99 Data.PathAndTree => |path_and_tree| {99 .PathAndTree => |path_and_tree| {
100 return path_and_tree.tree;100 return path_and_tree.tree;
101 },101 },
102 Data.ScopeAndComp => |scope_and_comp| {102 .ScopeAndComp => |scope_and_comp| {
103 return scope_and_comp.tree_scope.tree;103 return scope_and_comp.tree_scope.tree;
104 },104 },
105 }105 }
...@@ -107,9 +107,9 @@ pub const Msg = struct {...@@ -107,9 +107,9 @@ pub const Msg = struct {
107107
108 pub fn getSpan(self: *const Msg) Span {108 pub fn getSpan(self: *const Msg) Span {
109 return switch (self.data) {109 return switch (self.data) {
110 Data.Cli => unreachable,110 .Cli => unreachable,
111 Data.PathAndTree => |path_and_tree| path_and_tree.span,111 .PathAndTree => |path_and_tree| path_and_tree.span,
112 Data.ScopeAndComp => |scope_and_comp| scope_and_comp.span,112 .ScopeAndComp => |scope_and_comp| scope_and_comp.span,
113 };113 };
114 }114 }
115115
...@@ -230,7 +230,7 @@ pub const Msg = struct {...@@ -230,7 +230,7 @@ pub const Msg = struct {
230230
231 pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void {231 pub fn printToStream(msg: *const Msg, stream: var, color_on: bool) !void {
232 switch (msg.data) {232 switch (msg.data) {
233 Data.Cli => {233 .Cli => {
234 try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text);234 try stream.print("{}:-:-: error: {}\n", msg.realpath, msg.text);
235 return;235 return;
236 },236 },
...@@ -279,9 +279,9 @@ pub const Msg = struct {...@@ -279,9 +279,9 @@ pub const Msg = struct {
279279
280 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {280 pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
281 const color_on = switch (color) {281 const color_on = switch (color) {
282 Color.Auto => file.isTty(),282 .Auto => file.isTty(),
283 Color.On => true,283 .On => true,
284 Color.Off => false,284 .Off => false,
285 };285 };
286 var stream = &file.outStream().stream;286 var stream = &file.outStream().stream;
287 return msg.printToStream(stream, color_on);287 return msg.printToStream(stream, color_on);
src-self-hosted/ir.zig+223-225
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const Compilation = @import("compilation.zig").Compilation;2const Compilation = @import("compilation.zig").Compilation;
4const Scope = @import("scope.zig").Scope;3const Scope = @import("scope.zig").Scope;
5const ast = std.zig.ast;4const ast = std.zig.ast;
...@@ -33,13 +32,13 @@ pub const IrVal = union(enum) {...@@ -33,13 +32,13 @@ pub const IrVal = union(enum) {
3332
34 pub fn dump(self: IrVal) void {33 pub fn dump(self: IrVal) void {
35 switch (self) {34 switch (self) {
36 IrVal.Unknown => std.debug.warn("Unknown"),35 .Unknown => std.debug.warn("Unknown"),
37 IrVal.KnownType => |typ| {36 .KnownType => |typ| {
38 std.debug.warn("KnownType(");37 std.debug.warn("KnownType(");
39 typ.dump();38 typ.dump();
40 std.debug.warn(")");39 std.debug.warn(")");
41 },40 },
42 IrVal.KnownValue => |value| {41 .KnownValue => |value| {
43 std.debug.warn("KnownValue(");42 std.debug.warn("KnownValue(");
44 value.dump();43 value.dump();
45 std.debug.warn(")");44 std.debug.warn(")");
...@@ -113,37 +112,37 @@ pub const Inst = struct {...@@ -113,37 +112,37 @@ pub const Inst = struct {
113112
114 pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {113 pub async fn analyze(base: *Inst, ira: *Analyze) Analyze.Error!*Inst {
115 switch (base.id) {114 switch (base.id) {
116 Id.Return => return @fieldParentPtr(Return, "base", base).analyze(ira),115 .Return => return @fieldParentPtr(Return, "base", base).analyze(ira),
117 Id.Const => return @fieldParentPtr(Const, "base", base).analyze(ira),116 .Const => return @fieldParentPtr(Const, "base", base).analyze(ira),
118 Id.Call => return @fieldParentPtr(Call, "base", base).analyze(ira),117 .Call => return @fieldParentPtr(Call, "base", base).analyze(ira),
119 Id.DeclRef => return await (async @fieldParentPtr(DeclRef, "base", base).analyze(ira) catch unreachable),118 .DeclRef => return @fieldParentPtr(DeclRef, "base", base).analyze(ira),
120 Id.Ref => return await (async @fieldParentPtr(Ref, "base", base).analyze(ira) catch unreachable),119 .Ref => return @fieldParentPtr(Ref, "base", base).analyze(ira),
121 Id.DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira),120 .DeclVar => return @fieldParentPtr(DeclVar, "base", base).analyze(ira),
122 Id.CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira),121 .CheckVoidStmt => return @fieldParentPtr(CheckVoidStmt, "base", base).analyze(ira),
123 Id.Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira),122 .Phi => return @fieldParentPtr(Phi, "base", base).analyze(ira),
124 Id.Br => return @fieldParentPtr(Br, "base", base).analyze(ira),123 .Br => return @fieldParentPtr(Br, "base", base).analyze(ira),
125 Id.AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira),124 .AddImplicitReturnType => return @fieldParentPtr(AddImplicitReturnType, "base", base).analyze(ira),
126 Id.PtrType => return await (async @fieldParentPtr(PtrType, "base", base).analyze(ira) catch unreachable),125 .PtrType => return @fieldParentPtr(PtrType, "base", base).analyze(ira),
127 Id.VarPtr => return await (async @fieldParentPtr(VarPtr, "base", base).analyze(ira) catch unreachable),126 .VarPtr => return @fieldParentPtr(VarPtr, "base", base).analyze(ira),
128 Id.LoadPtr => return await (async @fieldParentPtr(LoadPtr, "base", base).analyze(ira) catch unreachable),127 .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).analyze(ira),
129 }128 }
130 }129 }
131130
132 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {131 pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
133 switch (base.id) {132 switch (base.id) {
134 Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),133 .Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
135 Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),134 .Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
136 Id.Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val),135 .Call => return @fieldParentPtr(Call, "base", base).render(ofile, fn_val),
137 Id.VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val),136 .VarPtr => return @fieldParentPtr(VarPtr, "base", base).render(ofile, fn_val),
138 Id.LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val),137 .LoadPtr => return @fieldParentPtr(LoadPtr, "base", base).render(ofile, fn_val),
139 Id.DeclRef => unreachable,138 .DeclRef => unreachable,
140 Id.PtrType => unreachable,139 .PtrType => unreachable,
141 Id.Ref => @panic("TODO"),140 .Ref => @panic("TODO"),
142 Id.DeclVar => @panic("TODO"),141 .DeclVar => @panic("TODO"),
143 Id.CheckVoidStmt => @panic("TODO"),142 .CheckVoidStmt => @panic("TODO"),
144 Id.Phi => @panic("TODO"),143 .Phi => @panic("TODO"),
145 Id.Br => @panic("TODO"),144 .Br => @panic("TODO"),
146 Id.AddImplicitReturnType => @panic("TODO"),145 .AddImplicitReturnType => @panic("TODO"),
147 }146 }
148 }147 }
149148
...@@ -165,7 +164,7 @@ pub const Inst = struct {...@@ -165,7 +164,7 @@ pub const Inst = struct {
165 param.ref_count -= 1;164 param.ref_count -= 1;
166 const child = param.child orelse return error.SemanticAnalysisFailed;165 const child = param.child orelse return error.SemanticAnalysisFailed;
167 switch (child.val) {166 switch (child.val) {
168 IrVal.Unknown => return error.SemanticAnalysisFailed,167 .Unknown => return error.SemanticAnalysisFailed,
169 else => return child,168 else => return child,
170 }169 }
171 }170 }
...@@ -213,9 +212,9 @@ pub const Inst = struct {...@@ -213,9 +212,9 @@ pub const Inst = struct {
213 /// asserts that the type is known212 /// asserts that the type is known
214 fn getKnownType(self: *Inst) *Type {213 fn getKnownType(self: *Inst) *Type {
215 switch (self.val) {214 switch (self.val) {
216 IrVal.KnownType => |typ| return typ,215 .KnownType => |typ| return typ,
217 IrVal.KnownValue => |value| return value.typ,216 .KnownValue => |value| return value.typ,
218 IrVal.Unknown => unreachable,217 .Unknown => unreachable,
219 }218 }
220 }219 }
221220
...@@ -225,14 +224,14 @@ pub const Inst = struct {...@@ -225,14 +224,14 @@ pub const Inst = struct {
225224
226 pub fn isNoReturn(base: *const Inst) bool {225 pub fn isNoReturn(base: *const Inst) bool {
227 switch (base.val) {226 switch (base.val) {
228 IrVal.Unknown => return false,227 .Unknown => return false,
229 IrVal.KnownValue => |x| return x.typ.id == Type.Id.NoReturn,228 .KnownValue => |x| return x.typ.id == .NoReturn,
230 IrVal.KnownType => |typ| return typ.id == Type.Id.NoReturn,229 .KnownType => |typ| return typ.id == .NoReturn,
231 }230 }
232 }231 }
233232
234 pub fn isCompTime(base: *const Inst) bool {233 pub fn isCompTime(base: *const Inst) bool {
235 return base.val == IrVal.KnownValue;234 return base.val == .KnownValue;
236 }235 }
237236
238 pub fn linkToParent(self: *Inst, parent: *Inst) void {237 pub fn linkToParent(self: *Inst, parent: *Inst) void {
...@@ -441,13 +440,13 @@ pub const Inst = struct {...@@ -441,13 +440,13 @@ pub const Inst = struct {
441 .volatility = self.params.volatility,440 .volatility = self.params.volatility,
442 });441 });
443 const elem_type = target.getKnownType();442 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{
445 .child_type = elem_type,444 .child_type = elem_type,
446 .mut = self.params.mut,445 .mut = self.params.mut,
447 .vol = self.params.volatility,446 .vol = self.params.volatility,
448 .size = Type.Pointer.Size.One,447 .size = .One,
449 .alignment = Type.Pointer.Align.Abi,448 .alignment = .Abi,
450 }) catch unreachable);449 });
451 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this450 // TODO: potentially set the hint that this is a stack pointer. But it might not be - this
452 // could be a ref of a global, for example451 // could be a ref of a global, for example
453 new_inst.val = IrVal{ .KnownType = &ptr_type.base };452 new_inst.val = IrVal{ .KnownType = &ptr_type.base };
...@@ -474,25 +473,25 @@ pub const Inst = struct {...@@ -474,25 +473,25 @@ pub const Inst = struct {
474 }473 }
475474
476 pub async fn analyze(self: *const DeclRef, ira: *Analyze) !*Inst {475 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) {
478 error.OutOfMemory => return error.OutOfMemory,477 error.OutOfMemory => return error.OutOfMemory,
479 else => return error.SemanticAnalysisFailed,478 else => return error.SemanticAnalysisFailed,
480 };479 };
481 switch (self.params.decl.id) {480 switch (self.params.decl.id) {
482 Decl.Id.CompTime => unreachable,481 .CompTime => unreachable,
483 Decl.Id.Var => return error.Unimplemented,482 .Var => return error.Unimplemented,
484 Decl.Id.Fn => {483 .Fn => {
485 const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl);484 const fn_decl = @fieldParentPtr(Decl.Fn, "base", self.params.decl);
486 const decl_val = switch (fn_decl.value) {485 const decl_val = switch (fn_decl.value) {
487 Decl.Fn.Val.Unresolved => unreachable,486 .Unresolved => unreachable,
488 Decl.Fn.Val.Fn => |fn_val| &fn_val.base,487 .Fn => |fn_val| &fn_val.base,
489 Decl.Fn.Val.FnProto => |fn_proto| &fn_proto.base,488 .FnProto => |fn_proto| &fn_proto.base,
490 };489 };
491 switch (self.params.lval) {490 switch (self.params.lval) {
492 LVal.None => {491 .None => {
493 return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val);492 return ira.irb.buildConstValue(self.base.scope, self.base.span, decl_val);
494 },493 },
495 LVal.Ptr => return error.Unimplemented,494 .Ptr => return error.Unimplemented,
496 }495 }
497 },496 },
498 }497 }
...@@ -519,21 +518,21 @@ pub const Inst = struct {...@@ -519,21 +518,21 @@ pub const Inst = struct {
519518
520 pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {519 pub async fn analyze(self: *const VarPtr, ira: *Analyze) !*Inst {
521 switch (self.params.var_scope.data) {520 switch (self.params.var_scope.data) {
522 Scope.Var.Data.Const => @panic("TODO"),521 .Const => @panic("TODO"),
523 Scope.Var.Data.Param => |param| {522 .Param => |param| {
524 const new_inst = try ira.irb.build(523 const new_inst = try ira.irb.build(
525 Inst.VarPtr,524 Inst.VarPtr,
526 self.base.scope,525 self.base.scope,
527 self.base.span,526 self.base.span,
528 Inst.VarPtr.Params{ .var_scope = self.params.var_scope },527 Inst.VarPtr.Params{ .var_scope = self.params.var_scope },
529 );528 );
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{
531 .child_type = param.typ,530 .child_type = param.typ,
532 .mut = Type.Pointer.Mut.Const,531 .mut = .Const,
533 .vol = Type.Pointer.Vol.Non,532 .vol = .Non,
534 .size = Type.Pointer.Size.One,533 .size = .One,
535 .alignment = Type.Pointer.Align.Abi,534 .alignment = .Abi,
536 }) catch unreachable);535 });
537 new_inst.val = IrVal{ .KnownType = &ptr_type.base };536 new_inst.val = IrVal{ .KnownType = &ptr_type.base };
538 return new_inst;537 return new_inst;
539 },538 },
...@@ -542,8 +541,8 @@ pub const Inst = struct {...@@ -542,8 +541,8 @@ pub const Inst = struct {
542541
543 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {542 pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
544 switch (self.params.var_scope.data) {543 switch (self.params.var_scope.data) {
545 Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass544 .Const => unreachable, // turned into Inst.Const in analyze pass
546 Scope.Var.Data.Param => |param| return param.llvm_value,545 .Param => |param| return param.llvm_value,
547 }546 }
548 }547 }
549 };548 };
...@@ -567,7 +566,7 @@ pub const Inst = struct {...@@ -567,7 +566,7 @@ pub const Inst = struct {
567 pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {566 pub async fn analyze(self: *const LoadPtr, ira: *Analyze) !*Inst {
568 const target = try self.params.target.getAsParam();567 const target = try self.params.target.getAsParam();
569 const target_type = target.getKnownType();568 const target_type = target.getKnownType();
570 if (target_type.id != Type.Id.Pointer) {569 if (target_type.id != .Pointer) {
571 try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name);570 try ira.addCompileError(self.base.span, "dereference of non pointer type '{}'", target_type.name);
572 return error.SemanticAnalysisFailed;571 return error.SemanticAnalysisFailed;
573 }572 }
...@@ -661,13 +660,13 @@ pub const Inst = struct {...@@ -661,13 +660,13 @@ pub const Inst = struct {
661 } else blk: {660 } else blk: {
662 break :blk Type.Pointer.Align{ .Abi = {} };661 break :blk Type.Pointer.Align{ .Abi = {} };
663 };662 };
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{
665 .child_type = child_type,664 .child_type = child_type,
666 .mut = self.params.mut,665 .mut = self.params.mut,
667 .vol = self.params.vol,666 .vol = self.params.vol,
668 .size = self.params.size,667 .size = self.params.size,
669 .alignment = alignment,668 .alignment = alignment,
670 }) catch unreachable);669 });
671 ptr_type.base.base.deref(ira.irb.comp);670 ptr_type.base.base.deref(ira.irb.comp);
672671
673 return ira.irb.buildConstValue(self.base.scope, self.base.span, &ptr_type.base.base);672 return ira.irb.buildConstValue(self.base.scope, self.base.span, &ptr_type.base.base);
...@@ -715,7 +714,7 @@ pub const Inst = struct {...@@ -715,7 +714,7 @@ pub const Inst = struct {
715714
716 pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst {715 pub fn analyze(self: *const CheckVoidStmt, ira: *Analyze) !*Inst {
717 const target = try self.params.target.getAsParam();716 const target = try self.params.target.getAsParam();
718 if (target.getKnownType().id != Type.Id.Void) {717 if (target.getKnownType().id != .Void) {
719 try ira.addCompileError(self.base.span, "expression value is ignored");718 try ira.addCompileError(self.base.span, "expression value is ignored");
720 return error.SemanticAnalysisFailed;719 return error.SemanticAnalysisFailed;
721 }720 }
...@@ -838,7 +837,7 @@ pub const Inst = struct {...@@ -838,7 +837,7 @@ pub const Inst = struct {
838 const target = try self.params.target.getAsParam();837 const target = try self.params.target.getAsParam();
839 const target_type = target.getKnownType();838 const target_type = target.getKnownType();
840 switch (target_type.id) {839 switch (target_type.id) {
841 Type.Id.ErrorUnion => {840 .ErrorUnion => {
842 return error.Unimplemented;841 return error.Unimplemented;
843 // if (instr_is_comptime(value)) {842 // if (instr_is_comptime(value)) {
844 // ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);843 // ConstExprValue *err_union_val = ir_resolve_const(ira, value, UndefBad);
...@@ -868,7 +867,7 @@ pub const Inst = struct {...@@ -868,7 +867,7 @@ pub const Inst = struct {
868 // ir_build_test_err_from(&ira->new_irb, &instruction->base, value);867 // ir_build_test_err_from(&ira->new_irb, &instruction->base, value);
869 // return ira->codegen->builtin_types.entry_bool;868 // return ira->codegen->builtin_types.entry_bool;
870 },869 },
871 Type.Id.ErrorSet => {870 .ErrorSet => {
872 return ira.irb.buildConstBool(self.base.scope, self.base.span, true);871 return ira.irb.buildConstBool(self.base.scope, self.base.span, true);
873 },872 },
874 else => {873 else => {
...@@ -1081,120 +1080,120 @@ pub const Builder = struct {...@@ -1081,120 +1080,120 @@ pub const Builder = struct {
10811080
1082 pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {1081 pub async fn genNode(irb: *Builder, node: *ast.Node, scope: *Scope, lval: LVal) Error!*Inst {
1083 switch (node.id) {1082 switch (node.id) {
1084 ast.Node.Id.Root => unreachable,1083 .Root => unreachable,
1085 ast.Node.Id.Use => unreachable,1084 .Use => unreachable,
1086 ast.Node.Id.TestDecl => unreachable,1085 .TestDecl => unreachable,
1087 ast.Node.Id.VarDecl => return error.Unimplemented,1086 .VarDecl => return error.Unimplemented,
1088 ast.Node.Id.Defer => return error.Unimplemented,1087 .Defer => return error.Unimplemented,
1089 ast.Node.Id.InfixOp => return error.Unimplemented,1088 .InfixOp => return error.Unimplemented,
1090 ast.Node.Id.PrefixOp => {1089 .PrefixOp => {
1091 const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node);1090 const prefix_op = @fieldParentPtr(ast.Node.PrefixOp, "base", node);
1092 switch (prefix_op.op) {1091 switch (prefix_op.op) {
1093 ast.Node.PrefixOp.Op.AddressOf => return error.Unimplemented,1092 .AddressOf => return error.Unimplemented,
1094 ast.Node.PrefixOp.Op.ArrayType => |n| return error.Unimplemented,1093 .ArrayType => |n| return error.Unimplemented,
1095 ast.Node.PrefixOp.Op.Await => return error.Unimplemented,1094 .Await => return error.Unimplemented,
1096 ast.Node.PrefixOp.Op.BitNot => return error.Unimplemented,1095 .BitNot => return error.Unimplemented,
1097 ast.Node.PrefixOp.Op.BoolNot => return error.Unimplemented,1096 .BoolNot => return error.Unimplemented,
1098 ast.Node.PrefixOp.Op.Cancel => return error.Unimplemented,1097 .Cancel => return error.Unimplemented,
1099 ast.Node.PrefixOp.Op.OptionalType => return error.Unimplemented,1098 .OptionalType => return error.Unimplemented,
1100 ast.Node.PrefixOp.Op.Negation => return error.Unimplemented,1099 .Negation => return error.Unimplemented,
1101 ast.Node.PrefixOp.Op.NegationWrap => return error.Unimplemented,1100 .NegationWrap => return error.Unimplemented,
1102 ast.Node.PrefixOp.Op.Resume => return error.Unimplemented,1101 .Resume => return error.Unimplemented,
1103 ast.Node.PrefixOp.Op.PtrType => |ptr_info| {1102 .PtrType => |ptr_info| {
1104 const inst = try await (async irb.genPtrType(prefix_op, ptr_info, scope) catch unreachable);1103 const inst = try irb.genPtrType(prefix_op, ptr_info, scope);
1105 return irb.lvalWrap(scope, inst, lval);1104 return irb.lvalWrap(scope, inst, lval);
1106 },1105 },
1107 ast.Node.PrefixOp.Op.SliceType => |ptr_info| return error.Unimplemented,1106 .SliceType => |ptr_info| return error.Unimplemented,
1108 ast.Node.PrefixOp.Op.Try => return error.Unimplemented,1107 .Try => return error.Unimplemented,
1109 }1108 }
1110 },1109 },
1111 ast.Node.Id.SuffixOp => {1110 .SuffixOp => {
1112 const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node);1111 const suffix_op = @fieldParentPtr(ast.Node.SuffixOp, "base", node);
1113 switch (suffix_op.op) {1112 switch (suffix_op.op) {
1114 @TagType(ast.Node.SuffixOp.Op).Call => |*call| {1113 .Call => |*call| {
1115 const inst = try await (async irb.genCall(suffix_op, call, scope) catch unreachable);1114 const inst = try irb.genCall(suffix_op, call, scope);
1116 return irb.lvalWrap(scope, inst, lval);1115 return irb.lvalWrap(scope, inst, lval);
1117 },1116 },
1118 @TagType(ast.Node.SuffixOp.Op).ArrayAccess => |n| return error.Unimplemented,1117 .ArrayAccess => |n| return error.Unimplemented,
1119 @TagType(ast.Node.SuffixOp.Op).Slice => |slice| return error.Unimplemented,1118 .Slice => |slice| return error.Unimplemented,
1120 @TagType(ast.Node.SuffixOp.Op).ArrayInitializer => |init_list| return error.Unimplemented,1119 .ArrayInitializer => |init_list| return error.Unimplemented,
1121 @TagType(ast.Node.SuffixOp.Op).StructInitializer => |init_list| return error.Unimplemented,1120 .StructInitializer => |init_list| return error.Unimplemented,
1122 @TagType(ast.Node.SuffixOp.Op).Deref => return error.Unimplemented,1121 .Deref => return error.Unimplemented,
1123 @TagType(ast.Node.SuffixOp.Op).UnwrapOptional => return error.Unimplemented,1122 .UnwrapOptional => return error.Unimplemented,
1124 }1123 }
1125 },1124 },
1126 ast.Node.Id.Switch => return error.Unimplemented,1125 .Switch => return error.Unimplemented,
1127 ast.Node.Id.While => return error.Unimplemented,1126 .While => return error.Unimplemented,
1128 ast.Node.Id.For => return error.Unimplemented,1127 .For => return error.Unimplemented,
1129 ast.Node.Id.If => return error.Unimplemented,1128 .If => return error.Unimplemented,
1130 ast.Node.Id.ControlFlowExpression => {1129 .ControlFlowExpression => {
1131 const control_flow_expr = @fieldParentPtr(ast.Node.ControlFlowExpression, "base", node);1130 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);
1133 },1132 },
1134 ast.Node.Id.Suspend => return error.Unimplemented,1133 .Suspend => return error.Unimplemented,
1135 ast.Node.Id.VarType => return error.Unimplemented,1134 .VarType => return error.Unimplemented,
1136 ast.Node.Id.ErrorType => return error.Unimplemented,1135 .ErrorType => return error.Unimplemented,
1137 ast.Node.Id.FnProto => return error.Unimplemented,1136 .FnProto => return error.Unimplemented,
1138 ast.Node.Id.PromiseType => return error.Unimplemented,1137 .AnyFrameType => return error.Unimplemented,
1139 ast.Node.Id.IntegerLiteral => {1138 .IntegerLiteral => {
1140 const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node);1139 const int_lit = @fieldParentPtr(ast.Node.IntegerLiteral, "base", node);
1141 return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval);1140 return irb.lvalWrap(scope, try irb.genIntLit(int_lit, scope), lval);
1142 },1141 },
1143 ast.Node.Id.FloatLiteral => return error.Unimplemented,1142 .FloatLiteral => return error.Unimplemented,
1144 ast.Node.Id.StringLiteral => {1143 .StringLiteral => {
1145 const str_lit = @fieldParentPtr(ast.Node.StringLiteral, "base", node);1144 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);
1147 return irb.lvalWrap(scope, inst, lval);1146 return irb.lvalWrap(scope, inst, lval);
1148 },1147 },
1149 ast.Node.Id.MultilineStringLiteral => return error.Unimplemented,1148 .MultilineStringLiteral => return error.Unimplemented,
1150 ast.Node.Id.CharLiteral => return error.Unimplemented,1149 .CharLiteral => return error.Unimplemented,
1151 ast.Node.Id.BoolLiteral => return error.Unimplemented,1150 .BoolLiteral => return error.Unimplemented,
1152 ast.Node.Id.NullLiteral => return error.Unimplemented,1151 .NullLiteral => return error.Unimplemented,
1153 ast.Node.Id.UndefinedLiteral => return error.Unimplemented,1152 .UndefinedLiteral => return error.Unimplemented,
1154 ast.Node.Id.Unreachable => return error.Unimplemented,1153 .Unreachable => return error.Unimplemented,
1155 ast.Node.Id.Identifier => {1154 .Identifier => {
1156 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", node);1155 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);
1158 },1157 },
1159 ast.Node.Id.GroupedExpression => {1158 .GroupedExpression => {
1160 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", node);1159 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);
1162 },1161 },
1163 ast.Node.Id.BuiltinCall => return error.Unimplemented,1162 .BuiltinCall => return error.Unimplemented,
1164 ast.Node.Id.ErrorSetDecl => return error.Unimplemented,1163 .ErrorSetDecl => return error.Unimplemented,
1165 ast.Node.Id.ContainerDecl => return error.Unimplemented,1164 .ContainerDecl => return error.Unimplemented,
1166 ast.Node.Id.Asm => return error.Unimplemented,1165 .Asm => return error.Unimplemented,
1167 ast.Node.Id.Comptime => return error.Unimplemented,1166 .Comptime => return error.Unimplemented,
1168 ast.Node.Id.Block => {1167 .Block => {
1169 const block = @fieldParentPtr(ast.Node.Block, "base", node);1168 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);
1171 return irb.lvalWrap(scope, inst, lval);1170 return irb.lvalWrap(scope, inst, lval);
1172 },1171 },
1173 ast.Node.Id.DocComment => return error.Unimplemented,1172 .DocComment => return error.Unimplemented,
1174 ast.Node.Id.SwitchCase => return error.Unimplemented,1173 .SwitchCase => return error.Unimplemented,
1175 ast.Node.Id.SwitchElse => return error.Unimplemented,1174 .SwitchElse => return error.Unimplemented,
1176 ast.Node.Id.Else => return error.Unimplemented,1175 .Else => return error.Unimplemented,
1177 ast.Node.Id.Payload => return error.Unimplemented,1176 .Payload => return error.Unimplemented,
1178 ast.Node.Id.PointerPayload => return error.Unimplemented,1177 .PointerPayload => return error.Unimplemented,
1179 ast.Node.Id.PointerIndexPayload => return error.Unimplemented,1178 .PointerIndexPayload => return error.Unimplemented,
1180 ast.Node.Id.ContainerField => return error.Unimplemented,1179 .ContainerField => return error.Unimplemented,
1181 ast.Node.Id.ErrorTag => return error.Unimplemented,1180 .ErrorTag => return error.Unimplemented,
1182 ast.Node.Id.AsmInput => return error.Unimplemented,1181 .AsmInput => return error.Unimplemented,
1183 ast.Node.Id.AsmOutput => return error.Unimplemented,1182 .AsmOutput => return error.Unimplemented,
1184 ast.Node.Id.ParamDecl => return error.Unimplemented,1183 .ParamDecl => return error.Unimplemented,
1185 ast.Node.Id.FieldInitializer => return error.Unimplemented,1184 .FieldInitializer => return error.Unimplemented,
1186 ast.Node.Id.EnumLiteral => return error.Unimplemented,1185 .EnumLiteral => return error.Unimplemented,
1187 }1186 }
1188 }1187 }
11891188
1190 async fn genCall(irb: *Builder, suffix_op: *ast.Node.SuffixOp, call: *ast.Node.SuffixOp.Op.Call, scope: *Scope) !*Inst {1189 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
1193 const args = try irb.arena().alloc(*Inst, call.params.len);1192 const args = try irb.arena().alloc(*Inst, call.params.len);
1194 var it = call.params.iterator(0);1193 var it = call.params.iterator(0);
1195 var i: usize = 0;1194 var i: usize = 0;
1196 while (it.next()) |arg_node_ptr| : (i += 1) {1195 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);
1198 }1197 }
11991198
1200 //bool is_async = node->data.fn_call_expr.is_async;1199 //bool is_async = node->data.fn_call_expr.is_async;
...@@ -1239,7 +1238,7 @@ pub const Builder = struct {...@@ -1239,7 +1238,7 @@ pub const Builder = struct {
1239 //} else {1238 //} else {
1240 // align_value = nullptr;1239 // align_value = nullptr;
1241 //}1240 //}
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
1244 //uint32_t bit_offset_start = 0;1243 //uint32_t bit_offset_start = 0;
1245 //if (node->data.pointer_type.bit_offset_start != nullptr) {1244 //if (node->data.pointer_type.bit_offset_start != nullptr) {
...@@ -1273,9 +1272,9 @@ pub const Builder = struct {...@@ -1273,9 +1272,9 @@ pub const Builder = struct {
12731272
1274 return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{1273 return irb.build(Inst.PtrType, scope, Span.node(&prefix_op.base), Inst.PtrType.Params{
1275 .child_type = child_type,1274 .child_type = child_type,
1276 .mut = Type.Pointer.Mut.Mut,1275 .mut = .Mut,
1277 .vol = Type.Pointer.Vol.Non,1276 .vol = .Non,
1278 .size = Type.Pointer.Size.Many,1277 .size = .Many,
1279 .alignment = null,1278 .alignment = null,
1280 });1279 });
1281 }1280 }
...@@ -1287,15 +1286,15 @@ pub const Builder = struct {...@@ -1287,15 +1286,15 @@ pub const Builder = struct {
1287 var scope = target_scope;1286 var scope = target_scope;
1288 while (true) {1287 while (true) {
1289 switch (scope.id) {1288 switch (scope.id) {
1290 Scope.Id.CompTime => return true,1289 .CompTime => return true,
1291 Scope.Id.FnDef => return false,1290 .FnDef => return false,
1292 Scope.Id.Decls => unreachable,1291 .Decls => unreachable,
1293 Scope.Id.Root => unreachable,1292 .Root => unreachable,
1294 Scope.Id.AstTree => unreachable,1293 .AstTree => unreachable,
1295 Scope.Id.Block,1294 .Block,
1296 Scope.Id.Defer,1295 .Defer,
1297 Scope.Id.DeferExpr,1296 .DeferExpr,
1298 Scope.Id.Var,1297 .Var,
1299 => scope = scope.parent.?,1298 => scope = scope.parent.?,
1300 }1299 }
1301 }1300 }
...@@ -1366,23 +1365,23 @@ pub const Builder = struct {...@@ -1366,23 +1365,23 @@ pub const Builder = struct {
1366 buf[buf.len - 1] = 0;1365 buf[buf.len - 1] = 0;
13671366
1368 // next make an array value1367 // 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);
1370 buf_cleaned = true;1369 buf_cleaned = true;
1371 defer array_val.base.deref(irb.comp);1370 defer array_val.base.deref(irb.comp);
13721371
1373 // then make a pointer value pointing at the first element1372 // 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(
1375 irb.comp,1374 irb.comp,
1376 array_val,1375 array_val,
1377 Type.Pointer.Mut.Const,1376 .Const,
1378 Type.Pointer.Size.Many,1377 .Many,
1379 0,1378 0,
1380 ) catch unreachable);1379 );
1381 defer ptr_val.base.deref(irb.comp);1380 defer ptr_val.base.deref(irb.comp);
13821381
1383 return irb.buildConstValue(scope, src_span, &ptr_val.base);1382 return irb.buildConstValue(scope, src_span, &ptr_val.base);
1384 } else {1383 } 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);
1386 buf_cleaned = true;1385 buf_cleaned = true;
1387 defer array_val.base.deref(irb.comp);1386 defer array_val.base.deref(irb.comp);
13881387
...@@ -1438,7 +1437,7 @@ pub const Builder = struct {...@@ -1438,7 +1437,7 @@ pub const Builder = struct {
1438 child_scope = &defer_child_scope.base;1437 child_scope = &defer_child_scope.base;
1439 continue;1438 continue;
1440 }1439 }
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
1443 is_continuation_unreachable = statement_value.isNoReturn();1442 is_continuation_unreachable = statement_value.isNoReturn();
1444 if (is_continuation_unreachable) {1443 if (is_continuation_unreachable) {
...@@ -1481,7 +1480,7 @@ pub const Builder = struct {...@@ -1481,7 +1480,7 @@ pub const Builder = struct {
1481 try block_scope.incoming_values.append(1480 try block_scope.incoming_values.append(
1482 try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true),1481 try irb.buildConstVoid(parent_scope, Span.token(block.rbrace), true),
1483 );1482 );
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
1486 _ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{1485 _ = try irb.buildGen(Inst.Br, parent_scope, Span.token(block.rbrace), Inst.Br.Params{
1487 .dest_block = block_scope.end_block,1486 .dest_block = block_scope.end_block,
...@@ -1496,7 +1495,7 @@ pub const Builder = struct {...@@ -1496,7 +1495,7 @@ pub const Builder = struct {
1496 });1495 });
1497 }1496 }
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);
1500 return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);1499 return irb.buildConstVoid(child_scope, Span.token(block.rbrace), true);
1501 }1500 }
15021501
...@@ -1507,9 +1506,9 @@ pub const Builder = struct {...@@ -1507,9 +1506,9 @@ pub const Builder = struct {
1507 lval: LVal,1506 lval: LVal,
1508 ) !*Inst {1507 ) !*Inst {
1509 switch (control_flow_expr.kind) {1508 switch (control_flow_expr.kind) {
1510 ast.Node.ControlFlowExpression.Kind.Break => |arg| return error.Unimplemented,1509 .Break => |arg| return error.Unimplemented,
1511 ast.Node.ControlFlowExpression.Kind.Continue => |arg| return error.Unimplemented,1510 .Continue => |arg| return error.Unimplemented,
1512 ast.Node.ControlFlowExpression.Kind.Return => {1511 .Return => {
1513 const src_span = Span.token(control_flow_expr.ltoken);1512 const src_span = Span.token(control_flow_expr.ltoken);
1514 if (scope.findFnDef() == null) {1513 if (scope.findFnDef() == null) {
1515 try irb.comp.addCompileError(1514 try irb.comp.addCompileError(
...@@ -1534,7 +1533,7 @@ pub const Builder = struct {...@@ -1534,7 +1533,7 @@ pub const Builder = struct {
15341533
1535 const outer_scope = irb.begin_scope.?;1534 const outer_scope = irb.begin_scope.?;
1536 const return_value = if (control_flow_expr.rhs) |rhs| blk: {1535 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);
1538 } else blk: {1537 } else blk: {
1539 break :blk try irb.buildConstVoid(scope, src_span, true);1538 break :blk try irb.buildConstVoid(scope, src_span, true);
1540 };1539 };
...@@ -1545,7 +1544,7 @@ pub const Builder = struct {...@@ -1545,7 +1544,7 @@ pub const Builder = struct {
1545 const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");1544 const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");
1546 const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");1545 const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");
1547 if (!have_err_defers) {1546 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);
1549 }1548 }
15501549
1551 const is_err = try irb.build(1550 const is_err = try irb.build(
...@@ -1568,7 +1567,7 @@ pub const Builder = struct {...@@ -1568,7 +1567,7 @@ pub const Builder = struct {
15681567
1569 try irb.setCursorAtEndAndAppendBlock(err_block);1568 try irb.setCursorAtEndAndAppendBlock(err_block);
1570 if (have_err_defers) {1569 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);
1572 }1571 }
1573 if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) {1572 if (irb.comp.have_err_ret_tracing and !irb.isCompTime(scope)) {
1574 _ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{});1573 _ = try irb.build(Inst.SaveErrRetAddr, scope, src_span, Inst.SaveErrRetAddr.Params{});
...@@ -1580,7 +1579,7 @@ pub const Builder = struct {...@@ -1580,7 +1579,7 @@ pub const Builder = struct {
15801579
1581 try irb.setCursorAtEndAndAppendBlock(ok_block);1580 try irb.setCursorAtEndAndAppendBlock(ok_block);
1582 if (have_err_defers) {1581 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);
1584 }1583 }
1585 _ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{1584 _ = try irb.build(Inst.Br, scope, src_span, Inst.Br.Params{
1586 .dest_block = ret_stmt_block,1585 .dest_block = ret_stmt_block,
...@@ -1590,7 +1589,7 @@ pub const Builder = struct {...@@ -1590,7 +1589,7 @@ pub const Builder = struct {
1590 try irb.setCursorAtEndAndAppendBlock(ret_stmt_block);1589 try irb.setCursorAtEndAndAppendBlock(ret_stmt_block);
1591 return irb.genAsyncReturn(scope, src_span, return_value, false);1590 return irb.genAsyncReturn(scope, src_span, return_value, false);
1592 } else {1591 } else {
1593 _ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);1592 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
1594 return irb.genAsyncReturn(scope, src_span, return_value, false);1593 return irb.genAsyncReturn(scope, src_span, return_value, false);
1595 }1594 }
1596 },1595 },
...@@ -1610,14 +1609,14 @@ pub const Builder = struct {...@@ -1610,14 +1609,14 @@ pub const Builder = struct {
1610 // return &const_instruction->base;1609 // return &const_instruction->base;
1611 //}1610 //}
16121611
1613 if (await (async irb.comp.getPrimitiveType(name) catch unreachable)) |result| {1612 if (irb.comp.getPrimitiveType(name)) |result| {
1614 if (result) |primitive_type| {1613 if (result) |primitive_type| {
1615 defer primitive_type.base.deref(irb.comp);1614 defer primitive_type.base.deref(irb.comp);
1616 switch (lval) {1615 switch (lval) {
1617 // if (lval == LValPtr) {1616 // if (lval == LValPtr) {
1618 // return ir_build_ref(irb, scope, node, value, false, false);1617 // return ir_build_ref(irb, scope, node, value, false, false);
1619 LVal.Ptr => return error.Unimplemented,1618 .Ptr => return error.Unimplemented,
1620 LVal.None => return irb.buildConstValue(scope, src_span, &primitive_type.base),1619 .None => return irb.buildConstValue(scope, src_span, &primitive_type.base),
1621 }1620 }
1622 }1621 }
1623 } else |err| switch (err) {1622 } else |err| switch (err) {
...@@ -1628,23 +1627,23 @@ pub const Builder = struct {...@@ -1628,23 +1627,23 @@ pub const Builder = struct {
1628 error.OutOfMemory => return error.OutOfMemory,1627 error.OutOfMemory => return error.OutOfMemory,
1629 }1628 }
16301629
1631 switch (await (async irb.findIdent(scope, name) catch unreachable)) {1630 switch (irb.findIdent(scope, name)) {
1632 Ident.Decl => |decl| {1631 .Decl => |decl| {
1633 return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{1632 return irb.build(Inst.DeclRef, scope, src_span, Inst.DeclRef.Params{
1634 .decl = decl,1633 .decl = decl,
1635 .lval = lval,1634 .lval = lval,
1636 });1635 });
1637 },1636 },
1638 Ident.VarScope => |var_scope| {1637 .VarScope => |var_scope| {
1639 const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope });1638 const var_ptr = try irb.build(Inst.VarPtr, scope, src_span, Inst.VarPtr.Params{ .var_scope = var_scope });
1640 switch (lval) {1639 switch (lval) {
1641 LVal.Ptr => return var_ptr,1640 .Ptr => return var_ptr,
1642 LVal.None => {1641 .None => {
1643 return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr });1642 return irb.build(Inst.LoadPtr, scope, src_span, Inst.LoadPtr.Params{ .target = var_ptr });
1644 },1643 },
1645 }1644 }
1646 },1645 },
1647 Ident.NotFound => {},1646 .NotFound => {},
1648 }1647 }
16491648
1650 //if (node->owner->any_imports_failed) {1649 //if (node->owner->any_imports_failed) {
...@@ -1671,25 +1670,25 @@ pub const Builder = struct {...@@ -1671,25 +1670,25 @@ pub const Builder = struct {
1671 var scope = inner_scope;1670 var scope = inner_scope;
1672 while (scope != outer_scope) {1671 while (scope != outer_scope) {
1673 switch (scope.id) {1672 switch (scope.id) {
1674 Scope.Id.Defer => {1673 .Defer => {
1675 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);1674 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
1676 switch (defer_scope.kind) {1675 switch (defer_scope.kind) {
1677 Scope.Defer.Kind.ScopeExit => result.scope_exit += 1,1676 .ScopeExit => result.scope_exit += 1,
1678 Scope.Defer.Kind.ErrorExit => result.error_exit += 1,1677 .ErrorExit => result.error_exit += 1,
1679 }1678 }
1680 scope = scope.parent orelse break;1679 scope = scope.parent orelse break;
1681 },1680 },
1682 Scope.Id.FnDef => break,1681 .FnDef => break,
16831682
1684 Scope.Id.CompTime,1683 .CompTime,
1685 Scope.Id.Block,1684 .Block,
1686 Scope.Id.Decls,1685 .Decls,
1687 Scope.Id.Root,1686 .Root,
1688 Scope.Id.Var,1687 .Var,
1689 => scope = scope.parent orelse break,1688 => scope = scope.parent orelse break,
16901689
1691 Scope.Id.DeferExpr => unreachable,1690 .DeferExpr => unreachable,
1692 Scope.Id.AstTree => unreachable,1691 .AstTree => unreachable,
1693 }1692 }
1694 }1693 }
1695 return result;1694 return result;
...@@ -1705,19 +1704,19 @@ pub const Builder = struct {...@@ -1705,19 +1704,19 @@ pub const Builder = struct {
1705 var is_noreturn = false;1704 var is_noreturn = false;
1706 while (true) {1705 while (true) {
1707 switch (scope.id) {1706 switch (scope.id) {
1708 Scope.Id.Defer => {1707 .Defer => {
1709 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);1708 const defer_scope = @fieldParentPtr(Scope.Defer, "base", scope);
1710 const generate = switch (defer_scope.kind) {1709 const generate = switch (defer_scope.kind) {
1711 Scope.Defer.Kind.ScopeExit => true,1710 .ScopeExit => true,
1712 Scope.Defer.Kind.ErrorExit => gen_kind == Scope.Defer.Kind.ErrorExit,1711 .ErrorExit => gen_kind == .ErrorExit,
1713 };1712 };
1714 if (generate) {1713 if (generate) {
1715 const defer_expr_scope = defer_scope.defer_expr_scope;1714 const defer_expr_scope = defer_scope.defer_expr_scope;
1716 const instruction = try await (async irb.genNode(1715 const instruction = try irb.genNode(
1717 defer_expr_scope.expr_node,1716 defer_expr_scope.expr_node,
1718 &defer_expr_scope.base,1717 &defer_expr_scope.base,
1719 LVal.None,1718 .None,
1720 ) catch unreachable);1719 );
1721 if (instruction.isNoReturn()) {1720 if (instruction.isNoReturn()) {
1722 is_noreturn = true;1721 is_noreturn = true;
1723 } else {1722 } else {
...@@ -1730,32 +1729,32 @@ pub const Builder = struct {...@@ -1730,32 +1729,32 @@ pub const Builder = struct {
1730 }1729 }
1731 }1730 }
1732 },1731 },
1733 Scope.Id.FnDef,1732 .FnDef,
1734 Scope.Id.Decls,1733 .Decls,
1735 Scope.Id.Root,1734 .Root,
1736 => return is_noreturn,1735 => return is_noreturn,
17371736
1738 Scope.Id.CompTime,1737 .CompTime,
1739 Scope.Id.Block,1738 .Block,
1740 Scope.Id.Var,1739 .Var,
1741 => scope = scope.parent orelse return is_noreturn,1740 => scope = scope.parent orelse return is_noreturn,
17421741
1743 Scope.Id.DeferExpr => unreachable,1742 .DeferExpr => unreachable,
1744 Scope.Id.AstTree => unreachable,1743 .AstTree => unreachable,
1745 }1744 }
1746 }1745 }
1747 }1746 }
17481747
1749 pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst {1748 pub fn lvalWrap(irb: *Builder, scope: *Scope, instruction: *Inst, lval: LVal) !*Inst {
1750 switch (lval) {1749 switch (lval) {
1751 LVal.None => return instruction,1750 .None => return instruction,
1752 LVal.Ptr => {1751 .Ptr => {
1753 // We needed a pointer to a value, but we got a value. So we create1752 // We needed a pointer to a value, but we got a value. So we create
1754 // an instruction which just makes a const pointer of it.1753 // an instruction which just makes a const pointer of it.
1755 return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{1754 return irb.build(Inst.Ref, scope, instruction.span, Inst.Ref.Params{
1756 .target = instruction,1755 .target = instruction,
1757 .mut = Type.Pointer.Mut.Const,1756 .mut = .Const,
1758 .volatility = Type.Pointer.Vol.Non,1757 .volatility = .Non,
1759 });1758 });
1760 },1759 },
1761 }1760 }
...@@ -1781,9 +1780,9 @@ pub const Builder = struct {...@@ -1781,9 +1780,9 @@ pub const Builder = struct {
1781 .scope = scope,1780 .scope = scope,
1782 .debug_id = self.next_debug_id,1781 .debug_id = self.next_debug_id,
1783 .val = switch (I.ir_val_init) {1782 .val = switch (I.ir_val_init) {
1784 IrVal.Init.Unknown => IrVal.Unknown,1783 .Unknown => IrVal.Unknown,
1785 IrVal.Init.NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },1784 .NoReturn => IrVal{ .KnownValue = &Value.NoReturn.get(self.comp).base },
1786 IrVal.Init.Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },1785 .Void => IrVal{ .KnownValue = &Value.Void.get(self.comp).base },
1787 },1786 },
1788 .ref_count = 0,1787 .ref_count = 0,
1789 .span = span,1788 .span = span,
...@@ -1902,7 +1901,6 @@ pub const Builder = struct {...@@ -1902,7 +1901,6 @@ pub const Builder = struct {
1902 );1901 );
1903 }1902 }
1904 return error.Unimplemented;1903 return error.Unimplemented;
1905
1906 }1904 }
19071905
1908 const Ident = union(enum) {1906 const Ident = union(enum) {
...@@ -1915,16 +1913,16 @@ pub const Builder = struct {...@@ -1915,16 +1913,16 @@ pub const Builder = struct {
1915 var s = scope;1913 var s = scope;
1916 while (true) {1914 while (true) {
1917 switch (s.id) {1915 switch (s.id) {
1918 Scope.Id.Root => return Ident.NotFound,1916 .Root => return .NotFound,
1919 Scope.Id.Decls => {1917 .Decls => {
1920 const decls = @fieldParentPtr(Scope.Decls, "base", s);1918 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();
1922 defer locked_table.release();1920 defer locked_table.release();
1923 if (locked_table.value.get(name)) |entry| {1921 if (locked_table.value.get(name)) |entry| {
1924 return Ident{ .Decl = entry.value };1922 return Ident{ .Decl = entry.value };
1925 }1923 }
1926 },1924 },
1927 Scope.Id.Var => {1925 .Var => {
1928 const var_scope = @fieldParentPtr(Scope.Var, "base", s);1926 const var_scope = @fieldParentPtr(Scope.Var, "base", s);
1929 if (mem.eql(u8, var_scope.name, name)) {1927 if (mem.eql(u8, var_scope.name, name)) {
1930 return Ident{ .VarScope = var_scope };1928 return Ident{ .VarScope = var_scope };
...@@ -2047,7 +2045,7 @@ const Analyze = struct {...@@ -2047,7 +2045,7 @@ const Analyze = struct {
2047 fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst {2045 fn implicitCast(self: *Analyze, target: *Inst, optional_dest_type: ?*Type) Analyze.Error!*Inst {
2048 const dest_type = optional_dest_type orelse return target;2046 const dest_type = optional_dest_type orelse return target;
2049 const from_type = target.getKnownType();2047 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;
2051 return self.analyzeCast(target, target, dest_type);2049 return self.analyzeCast(target, target, dest_type);
2052 }2050 }
20532051
...@@ -2311,7 +2309,7 @@ const Analyze = struct {...@@ -2311,7 +2309,7 @@ const Analyze = struct {
2311 //}2309 //}
23122310
2313 // cast from comptime-known integer to another integer where the value fits2311 // 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: {
2315 const target_val = target.val.KnownValue;2313 const target_val = target.val.KnownValue;
2316 const from_int = &target_val.cast(Value.Int).?.big_int;2314 const from_int = &target_val.cast(Value.Int).?.big_int;
2317 const fits = fits: {2315 const fits = fits: {
...@@ -2534,7 +2532,7 @@ pub async fn gen(...@@ -2534,7 +2532,7 @@ pub async fn gen(
2534 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.2532 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
2535 try irb.setCursorAtEndAndAppendBlock(entry_block);2533 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);
2538 if (!result.isNoReturn()) {2536 if (!result.isNoReturn()) {
2539 // no need for save_err_ret_addr because this cannot return error2537 // no need for save_err_ret_addr because this cannot return error
2540 _ = try irb.genAsyncReturn(scope, Span.token(body_node.lastToken()), result, true);2538 _ = 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)...@@ -2564,7 +2562,7 @@ pub async fn analyze(comp: *Compilation, old_code: *Code, expected_type: ?*Type)
2564 continue;2562 continue;
2565 }2563 }
25662564
2567 const return_inst = try await (async old_instruction.analyze(&ira) catch unreachable);2565 const return_inst = try old_instruction.analyze(&ira);
2568 assert(return_inst.val != IrVal.Unknown); // at least the type should be known at this point2566 assert(return_inst.val != IrVal.Unknown); // at least the type should be known at this point
2569 return_inst.linkToParent(old_instruction);2567 return_inst.linkToParent(old_instruction);
2570 // Note: if we ever modify the above to handle error.CompileError by continuing analysis,2568 // 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 @@...@@ -1,9 +1,11 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const event = std.event;3const event = std.event;
4const Target = @import("target.zig").Target;4const util = @import("util.zig");
5const Target = std.Target;
5const c = @import("c.zig");6const c = @import("c.zig");
6const fs = std.fs;7const fs = std.fs;
8const Allocator = std.mem.Allocator;
79
8/// See the render function implementation for documentation of the fields.10/// See the render function implementation for documentation of the fields.
9pub const LibCInstallation = struct {11pub const LibCInstallation = struct {
...@@ -29,7 +31,7 @@ pub const LibCInstallation = struct {...@@ -29,7 +31,7 @@ pub const LibCInstallation = struct {
2931
30 pub fn parse(32 pub fn parse(
31 self: *LibCInstallation,33 self: *LibCInstallation,
32 allocator: *std.mem.Allocator,34 allocator: *Allocator,
33 libc_file: []const u8,35 libc_file: []const u8,
34 stderr: *std.io.OutStream(fs.File.WriteError),36 stderr: *std.io.OutStream(fs.File.WriteError),
35 ) !void {37 ) !void {
...@@ -71,7 +73,7 @@ pub const LibCInstallation = struct {...@@ -71,7 +73,7 @@ pub const LibCInstallation = struct {
71 if (std.mem.eql(u8, name, key)) {73 if (std.mem.eql(u8, name, key)) {
72 found_keys[i].found = true;74 found_keys[i].found = true;
73 switch (@typeInfo(@typeOf(@field(self, key)))) {75 switch (@typeInfo(@typeOf(@field(self, key)))) {
74 builtin.TypeId.Optional => {76 .Optional => {
75 if (value.len == 0) {77 if (value.len == 0) {
76 @field(self, key) = null;78 @field(self, key) = null;
77 } else {79 } else {
...@@ -136,15 +138,15 @@ pub const LibCInstallation = struct {...@@ -136,15 +138,15 @@ pub const LibCInstallation = struct {
136 self.static_lib_dir orelse "",138 self.static_lib_dir orelse "",
137 self.msvc_lib_dir orelse "",139 self.msvc_lib_dir orelse "",
138 self.kernel32_lib_dir orelse "",140 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 = {} }),
140 );142 );
141 }143 }
142144
143 /// Finds the default, native libc.145 /// 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 {
145 self.initEmpty();147 self.initEmpty();
146 var group = event.Group(FindError!void).init(loop);148 var group = event.Group(FindError!void).init(allocator);
147 errdefer group.deinit();149 errdefer group.wait() catch {};
148 var windows_sdk: ?*c.ZigWindowsSDK = null;150 var windows_sdk: ?*c.ZigWindowsSDK = null;
149 errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk));151 errdefer if (windows_sdk) |sdk| c.zig_free_windows_sdk(@ptrCast(?[*]c.ZigWindowsSDK, sdk));
150152
...@@ -156,11 +158,11 @@ pub const LibCInstallation = struct {...@@ -156,11 +158,11 @@ pub const LibCInstallation = struct {
156 windows_sdk = sdk;158 windows_sdk = sdk;
157159
158 if (sdk.msvc_lib_dir_ptr != 0) {160 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]);
160 }162 }
161 try group.call(findNativeKernel32LibDir, self, loop, sdk);163 try group.call(findNativeKernel32LibDir, allocator, self, sdk);
162 try group.call(findNativeIncludeDirWindows, self, loop, sdk);164 try group.call(findNativeIncludeDirWindows, self, allocator, sdk);
163 try group.call(findNativeLibDirWindows, self, loop, sdk);165 try group.call(findNativeLibDirWindows, self, allocator, sdk);
164 },166 },
165 c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory,167 c.ZigFindWindowsSdkError.OutOfMemory => return error.OutOfMemory,
166 c.ZigFindWindowsSdkError.NotFound => return error.NotFound,168 c.ZigFindWindowsSdkError.NotFound => return error.NotFound,
...@@ -168,20 +170,20 @@ pub const LibCInstallation = struct {...@@ -168,20 +170,20 @@ pub const LibCInstallation = struct {
168 }170 }
169 },171 },
170 .linux => {172 .linux => {
171 try group.call(findNativeIncludeDirLinux, self, loop);173 try group.call(findNativeIncludeDirLinux, self, allocator);
172 try group.call(findNativeLibDirLinux, self, loop);174 try group.call(findNativeLibDirLinux, self, allocator);
173 try group.call(findNativeStaticLibDir, self, loop);175 try group.call(findNativeStaticLibDir, self, allocator);
174 try group.call(findNativeDynamicLinker, self, loop);176 try group.call(findNativeDynamicLinker, self, allocator);
175 },177 },
176 .macosx, .freebsd, .netbsd => {178 .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");
178 },180 },
179 else => @compileError("unimplemented: find libc for this OS"),181 else => @compileError("unimplemented: find libc for this OS"),
180 }182 }
181 return await (async group.wait() catch unreachable);183 return group.wait();
182 }184 }
183185
184 async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void {186 async fn findNativeIncludeDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
185 const cc_exe = std.os.getenv("CC") orelse "cc";187 const cc_exe = std.os.getenv("CC") orelse "cc";
186 const argv = [_][]const u8{188 const argv = [_][]const u8{
187 cc_exe,189 cc_exe,
...@@ -191,7 +193,7 @@ pub const LibCInstallation = struct {...@@ -191,7 +193,7 @@ pub const LibCInstallation = struct {
191 "/dev/null",193 "/dev/null",
192 };194 };
193 // TODO make this use event loop195 // 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);
195 const exec_result = if (std.debug.runtime_safety) blk: {197 const exec_result = if (std.debug.runtime_safety) blk: {
196 break :blk errorable_result catch unreachable;198 break :blk errorable_result catch unreachable;
197 } else blk: {199 } else blk: {
...@@ -201,12 +203,12 @@ pub const LibCInstallation = struct {...@@ -201,12 +203,12 @@ pub const LibCInstallation = struct {
201 };203 };
202 };204 };
203 defer {205 defer {
204 loop.allocator.free(exec_result.stdout);206 allocator.free(exec_result.stdout);
205 loop.allocator.free(exec_result.stderr);207 allocator.free(exec_result.stderr);
206 }208 }
207209
208 switch (exec_result.term) {210 switch (exec_result.term) {
209 std.ChildProcess.Term.Exited => |code| {211 .Exited => |code| {
210 if (code != 0) return error.CCompilerExitCode;212 if (code != 0) return error.CCompilerExitCode;
211 },213 },
212 else => {214 else => {
...@@ -215,7 +217,7 @@ pub const LibCInstallation = struct {...@@ -215,7 +217,7 @@ pub const LibCInstallation = struct {
215 }217 }
216218
217 var it = std.mem.tokenize(exec_result.stderr, "\n\r");219 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);
219 defer search_paths.deinit();221 defer search_paths.deinit();
220 while (it.next()) |line| {222 while (it.next()) |line| {
221 if (line.len != 0 and line[0] == ' ') {223 if (line.len != 0 and line[0] == ' ') {
...@@ -231,11 +233,11 @@ pub const LibCInstallation = struct {...@@ -231,11 +233,11 @@ pub const LibCInstallation = struct {
231 while (path_i < search_paths.len) : (path_i += 1) {233 while (path_i < search_paths.len) : (path_i += 1) {
232 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);234 const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1);
233 const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " ");235 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" });236 const stdlib_path = try fs.path.join(allocator, [_][]const u8{ search_path, "stdlib.h" });
235 defer loop.allocator.free(stdlib_path);237 defer allocator.free(stdlib_path);
236238
237 if (try fileExists(stdlib_path)) {239 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);
239 return;241 return;
240 }242 }
241 }243 }
...@@ -243,11 +245,11 @@ pub const LibCInstallation = struct {...@@ -243,11 +245,11 @@ pub const LibCInstallation = struct {
243 return error.LibCStdLibHeaderNotFound;245 return error.LibCStdLibHeaderNotFound;
244 }246 }
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 {
247 var search_buf: [2]Search = undefined;249 var search_buf: [2]Search = undefined;
248 const searches = fillSearch(&search_buf, sdk);250 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);
251 defer result_buf.deinit();253 defer result_buf.deinit();
252254
253 for (searches) |search| {255 for (searches) |search| {
...@@ -256,10 +258,10 @@ pub const LibCInstallation = struct {...@@ -256,10 +258,10 @@ pub const LibCInstallation = struct {
256 try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);258 try stream.print("{}\\Include\\{}\\ucrt", search.path, search.version);
257259
258 const stdlib_path = try fs.path.join(260 const stdlib_path = try fs.path.join(
259 loop.allocator,261 allocator,
260 [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" },262 [_][]const u8{ result_buf.toSliceConst(), "stdlib.h" },
261 );263 );
262 defer loop.allocator.free(stdlib_path);264 defer allocator.free(stdlib_path);
263265
264 if (try fileExists(stdlib_path)) {266 if (try fileExists(stdlib_path)) {
265 self.include_dir = result_buf.toOwnedSlice();267 self.include_dir = result_buf.toOwnedSlice();
...@@ -270,11 +272,11 @@ pub const LibCInstallation = struct {...@@ -270,11 +272,11 @@ pub const LibCInstallation = struct {
270 return error.LibCStdLibHeaderNotFound;272 return error.LibCStdLibHeaderNotFound;
271 }273 }
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 {
274 var search_buf: [2]Search = undefined;276 var search_buf: [2]Search = undefined;
275 const searches = fillSearch(&search_buf, sdk);277 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);
278 defer result_buf.deinit();280 defer result_buf.deinit();
279281
280 for (searches) |search| {282 for (searches) |search| {
...@@ -282,16 +284,16 @@ pub const LibCInstallation = struct {...@@ -282,16 +284,16 @@ pub const LibCInstallation = struct {
282 const stream = &std.io.BufferOutStream.init(&result_buf).stream;284 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
283 try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version);285 try stream.print("{}\\Lib\\{}\\ucrt\\", search.path, search.version);
284 switch (builtin.arch) {286 switch (builtin.arch) {
285 builtin.Arch.i386 => try stream.write("x86"),287 .i386 => try stream.write("x86"),
286 builtin.Arch.x86_64 => try stream.write("x64"),288 .x86_64 => try stream.write("x64"),
287 builtin.Arch.aarch64 => try stream.write("arm"),289 .aarch64 => try stream.write("arm"),
288 else => return error.UnsupportedArchitecture,290 else => return error.UnsupportedArchitecture,
289 }291 }
290 const ucrt_lib_path = try fs.path.join(292 const ucrt_lib_path = try fs.path.join(
291 loop.allocator,293 allocator,
292 [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },294 [_][]const u8{ result_buf.toSliceConst(), "ucrt.lib" },
293 );295 );
294 defer loop.allocator.free(ucrt_lib_path);296 defer allocator.free(ucrt_lib_path);
295 if (try fileExists(ucrt_lib_path)) {297 if (try fileExists(ucrt_lib_path)) {
296 self.lib_dir = result_buf.toOwnedSlice();298 self.lib_dir = result_buf.toOwnedSlice();
297 return;299 return;
...@@ -300,15 +302,15 @@ pub const LibCInstallation = struct {...@@ -300,15 +302,15 @@ pub const LibCInstallation = struct {
300 return error.LibCRuntimeNotFound;302 return error.LibCRuntimeNotFound;
301 }303 }
302304
303 async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void {305 async fn findNativeLibDirLinux(self: *LibCInstallation, allocator: *Allocator) FindError!void {
304 self.lib_dir = try await (async ccPrintFileName(loop, "crt1.o", true) catch unreachable);306 self.lib_dir = try ccPrintFileName(allocator, "crt1.o", true);
305 }307 }
306308
307 async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {309 async fn findNativeStaticLibDir(self: *LibCInstallation, allocator: *Allocator) FindError!void {
308 self.static_lib_dir = try await (async ccPrintFileName(loop, "crtbegin.o", true) catch unreachable);310 self.static_lib_dir = try ccPrintFileName(allocator, "crtbegin.o", true);
309 }311 }
310312
311 async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {313 async fn findNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator) FindError!void {
312 var dyn_tests = [_]DynTest{314 var dyn_tests = [_]DynTest{
313 DynTest{315 DynTest{
314 .name = "ld-linux-x86-64.so.2",316 .name = "ld-linux-x86-64.so.2",
...@@ -319,12 +321,12 @@ pub const LibCInstallation = struct {...@@ -319,12 +321,12 @@ pub const LibCInstallation = struct {
319 .result = null,321 .result = null,
320 },322 },
321 };323 };
322 var group = event.Group(FindError!void).init(loop);324 var group = event.Group(FindError!void).init(allocator);
323 errdefer group.deinit();325 errdefer group.wait() catch {};
324 for (dyn_tests) |*dyn_test| {326 for (dyn_tests) |*dyn_test| {
325 try group.call(testNativeDynamicLinker, self, loop, dyn_test);327 try group.call(testNativeDynamicLinker, self, allocator, dyn_test);
326 }328 }
327 try await (async group.wait() catch unreachable);329 try group.wait();
328 for (dyn_tests) |*dyn_test| {330 for (dyn_tests) |*dyn_test| {
329 if (dyn_test.result) |result| {331 if (dyn_test.result) |result| {
330 self.dynamic_linker_path = result;332 self.dynamic_linker_path = result;
...@@ -338,8 +340,8 @@ pub const LibCInstallation = struct {...@@ -338,8 +340,8 @@ pub const LibCInstallation = struct {
338 result: ?[]const u8,340 result: ?[]const u8,
339 };341 };
340342
341 async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void {343 async fn testNativeDynamicLinker(self: *LibCInstallation, allocator: *Allocator, dyn_test: *DynTest) FindError!void {
342 if (await (async ccPrintFileName(loop, dyn_test.name, false) catch unreachable)) |result| {344 if (ccPrintFileName(allocator, dyn_test.name, false)) |result| {
343 dyn_test.result = result;345 dyn_test.result = result;
344 return;346 return;
345 } else |err| switch (err) {347 } else |err| switch (err) {
...@@ -348,11 +350,11 @@ pub const LibCInstallation = struct {...@@ -348,11 +350,11 @@ pub const LibCInstallation = struct {
348 }350 }
349 }351 }
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 {
352 var search_buf: [2]Search = undefined;354 var search_buf: [2]Search = undefined;
353 const searches = fillSearch(&search_buf, sdk);355 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);
356 defer result_buf.deinit();358 defer result_buf.deinit();
357359
358 for (searches) |search| {360 for (searches) |search| {
...@@ -360,16 +362,16 @@ pub const LibCInstallation = struct {...@@ -360,16 +362,16 @@ pub const LibCInstallation = struct {
360 const stream = &std.io.BufferOutStream.init(&result_buf).stream;362 const stream = &std.io.BufferOutStream.init(&result_buf).stream;
361 try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version);363 try stream.print("{}\\Lib\\{}\\um\\", search.path, search.version);
362 switch (builtin.arch) {364 switch (builtin.arch) {
363 builtin.Arch.i386 => try stream.write("x86\\"),365 .i386 => try stream.write("x86\\"),
364 builtin.Arch.x86_64 => try stream.write("x64\\"),366 .x86_64 => try stream.write("x64\\"),
365 builtin.Arch.aarch64 => try stream.write("arm\\"),367 .aarch64 => try stream.write("arm\\"),
366 else => return error.UnsupportedArchitecture,368 else => return error.UnsupportedArchitecture,
367 }369 }
368 const kernel32_path = try fs.path.join(370 const kernel32_path = try fs.path.join(
369 loop.allocator,371 allocator,
370 [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },372 [_][]const u8{ result_buf.toSliceConst(), "kernel32.lib" },
371 );373 );
372 defer loop.allocator.free(kernel32_path);374 defer allocator.free(kernel32_path);
373 if (try fileExists(kernel32_path)) {375 if (try fileExists(kernel32_path)) {
374 self.kernel32_lib_dir = result_buf.toOwnedSlice();376 self.kernel32_lib_dir = result_buf.toOwnedSlice();
375 return;377 return;
...@@ -380,7 +382,7 @@ pub const LibCInstallation = struct {...@@ -380,7 +382,7 @@ pub const LibCInstallation = struct {
380382
381 fn initEmpty(self: *LibCInstallation) void {383 fn initEmpty(self: *LibCInstallation) void {
382 self.* = LibCInstallation{384 self.* = LibCInstallation{
383 .include_dir = ([*]const u8)(undefined)[0..0],385 .include_dir = @as([*]const u8, undefined)[0..0],
384 .lib_dir = null,386 .lib_dir = null,
385 .static_lib_dir = null,387 .static_lib_dir = null,
386 .msvc_lib_dir = null,388 .msvc_lib_dir = null,
...@@ -391,15 +393,15 @@ pub const LibCInstallation = struct {...@@ -391,15 +393,15 @@ pub const LibCInstallation = struct {
391};393};
392394
393/// caller owns returned memory395/// 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 {
395 const cc_exe = std.os.getenv("CC") orelse "cc";397 const cc_exe = std.os.getenv("CC") orelse "cc";
396 const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);398 const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", o_file);
397 defer loop.allocator.free(arg1);399 defer allocator.free(arg1);
398 const argv = [_][]const u8{ cc_exe, arg1 };400 const argv = [_][]const u8{ cc_exe, arg1 };
399401
400 // TODO This simulates evented I/O for the child process exec402 // TODO This simulates evented I/O for the child process exec
401 await (async loop.yield() catch unreachable);403 std.event.Loop.instance.?.yield();
402 const errorable_result = std.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);404 const errorable_result = std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
403 const exec_result = if (std.debug.runtime_safety) blk: {405 const exec_result = if (std.debug.runtime_safety) blk: {
404 break :blk errorable_result catch unreachable;406 break :blk errorable_result catch unreachable;
405 } else blk: {407 } else blk: {
...@@ -409,8 +411,8 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo...@@ -409,8 +411,8 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
409 };411 };
410 };412 };
411 defer {413 defer {
412 loop.allocator.free(exec_result.stdout);414 allocator.free(exec_result.stdout);
413 loop.allocator.free(exec_result.stderr);415 allocator.free(exec_result.stderr);
414 }416 }
415 switch (exec_result.term) {417 switch (exec_result.term) {
416 .Exited => |code| {418 .Exited => |code| {
...@@ -425,9 +427,9 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo...@@ -425,9 +427,9 @@ async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bo
425 const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;427 const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
426428
427 if (want_dirname) {429 if (want_dirname) {
428 return std.mem.dupe(loop.allocator, u8, dirname);430 return std.mem.dupe(allocator, u8, dirname);
429 } else {431 } else {
430 return std.mem.dupe(loop.allocator, u8, line);432 return std.mem.dupe(allocator, u8, line);
431 }433 }
432}434}
433435
src-self-hosted/link.zig+52-52
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const c = @import("c.zig");3const c = @import("c.zig");
4const builtin = @import("builtin");
5const ObjectFormat = builtin.ObjectFormat;
6const Compilation = @import("compilation.zig").Compilation;4const Compilation = @import("compilation.zig").Compilation;
7const Target = @import("target.zig").Target;5const Target = std.Target;
6const ObjectFormat = Target.ObjectFormat;
8const LibCInstallation = @import("libc_installation.zig").LibCInstallation;7const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
9const assert = std.debug.assert;8const assert = std.debug.assert;
9const util = @import("util.zig");
1010
11const Context = struct {11const Context = struct {
12 comp: *Compilation,12 comp: *Compilation,
...@@ -26,7 +26,7 @@ pub async fn link(comp: *Compilation) !void {...@@ -26,7 +26,7 @@ pub async fn link(comp: *Compilation) !void {
26 .comp = comp,26 .comp = comp,
27 .arena = std.heap.ArenaAllocator.init(comp.gpa()),27 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
28 .args = undefined,28 .args = undefined,
29 .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe,29 .link_in_crt = comp.haveLibC() and comp.kind == .Exe,
30 .link_err = {},30 .link_err = {},
31 .link_msg = undefined,31 .link_msg = undefined,
32 .libc = undefined,32 .libc = undefined,
...@@ -41,14 +41,14 @@ pub async fn link(comp: *Compilation) !void {...@@ -41,14 +41,14 @@ pub async fn link(comp: *Compilation) !void {
41 } else {41 } else {
42 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());42 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
43 switch (comp.kind) {43 switch (comp.kind) {
44 Compilation.Kind.Exe => {44 .Exe => {
45 try ctx.out_file_path.append(comp.target.exeFileExt());45 try ctx.out_file_path.append(comp.target.exeFileExt());
46 },46 },
47 Compilation.Kind.Lib => {47 .Lib => {
48 try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static));48 try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());
49 },49 },
50 Compilation.Kind.Obj => {50 .Obj => {
51 try ctx.out_file_path.append(comp.target.objFileExt());51 try ctx.out_file_path.append(comp.target.oFileExt());
52 },52 },
53 }53 }
54 }54 }
...@@ -61,7 +61,7 @@ pub async fn link(comp: *Compilation) !void {...@@ -61,7 +61,7 @@ pub async fn link(comp: *Compilation) !void {
61 ctx.libc = ctx.comp.override_libc orelse blk: {61 ctx.libc = ctx.comp.override_libc orelse blk: {
62 switch (comp.target) {62 switch (comp.target) {
63 Target.Native => {63 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;
65 },65 },
66 else => return error.LibCRequiredButNotProvidedOrFound,66 else => return error.LibCRequiredButNotProvidedOrFound,
67 }67 }
...@@ -78,12 +78,12 @@ pub async fn link(comp: *Compilation) !void {...@@ -78,12 +78,12 @@ pub async fn link(comp: *Compilation) !void {
78 std.debug.warn("\n");78 std.debug.warn("\n");
79 }79 }
8080
81 const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat());81 const extern_ofmt = toExternObjectFormatType(util.getObjectFormat(comp.target));
82 const args_slice = ctx.args.toSlice();82 const args_slice = ctx.args.toSlice();
8383
84 {84 {
85 // LLD is not thread-safe, so we grab a global lock.85 // 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();
87 defer held.release();87 defer held.release();
8888
89 // Not evented I/O. LLD does its own multithreading internally.89 // Not evented I/O. LLD does its own multithreading internally.
...@@ -121,21 +121,21 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void {...@@ -121,21 +121,21 @@ fn linkDiagCallbackErrorable(ctx: *Context, msg: []const u8) !void {
121121
122fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType {122fn toExternObjectFormatType(ofmt: ObjectFormat) c.ZigLLVM_ObjectFormatType {
123 return switch (ofmt) {123 return switch (ofmt) {
124 ObjectFormat.unknown => c.ZigLLVM_UnknownObjectFormat,124 .unknown => c.ZigLLVM_UnknownObjectFormat,
125 ObjectFormat.coff => c.ZigLLVM_COFF,125 .coff => c.ZigLLVM_COFF,
126 ObjectFormat.elf => c.ZigLLVM_ELF,126 .elf => c.ZigLLVM_ELF,
127 ObjectFormat.macho => c.ZigLLVM_MachO,127 .macho => c.ZigLLVM_MachO,
128 ObjectFormat.wasm => c.ZigLLVM_Wasm,128 .wasm => c.ZigLLVM_Wasm,
129 };129 };
130}130}
131131
132fn constructLinkerArgs(ctx: *Context) !void {132fn constructLinkerArgs(ctx: *Context) !void {
133 switch (ctx.comp.target.getObjectFormat()) {133 switch (util.getObjectFormat(ctx.comp.target)) {
134 ObjectFormat.unknown => unreachable,134 .unknown => unreachable,
135 ObjectFormat.coff => return constructLinkerArgsCoff(ctx),135 .coff => return constructLinkerArgsCoff(ctx),
136 ObjectFormat.elf => return constructLinkerArgsElf(ctx),136 .elf => return constructLinkerArgsElf(ctx),
137 ObjectFormat.macho => return constructLinkerArgsMachO(ctx),137 .macho => return constructLinkerArgsMachO(ctx),
138 ObjectFormat.wasm => return constructLinkerArgsWasm(ctx),138 .wasm => return constructLinkerArgsWasm(ctx),
139 }139 }
140}140}
141141
...@@ -154,7 +154,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -154,7 +154,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
154 //bool shared = !g->is_static && is_lib;154 //bool shared = !g->is_static && is_lib;
155 //Buf *soname = nullptr;155 //Buf *soname = nullptr;
156 if (ctx.comp.is_static) {156 if (ctx.comp.is_static) {
157 if (ctx.comp.target.isArmOrThumb()) {157 if (util.isArmOrThumb(ctx.comp.target)) {
158 try ctx.args.append(c"-Bstatic");158 try ctx.args.append(c"-Bstatic");
159 } else {159 } else {
160 try ctx.args.append(c"-static");160 try ctx.args.append(c"-static");
...@@ -222,7 +222,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -222,7 +222,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
222 if (!ctx.comp.is_static) {222 if (!ctx.comp.is_static) {
223 const dl = blk: {223 const dl = blk: {
224 if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;224 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;
226 return error.LibCMissingDynamicLinker;226 return error.LibCMissingDynamicLinker;
227 };227 };
228 try ctx.args.append(c"-dynamic-linker");228 try ctx.args.append(c"-dynamic-linker");
...@@ -324,9 +324,9 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -324,9 +324,9 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
324 }324 }
325325
326 switch (ctx.comp.target.getArch()) {326 switch (ctx.comp.target.getArch()) {
327 builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),327 .i386 => try ctx.args.append(c"-MACHINE:X86"),
328 builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),328 .x86_64 => try ctx.args.append(c"-MACHINE:X64"),
329 builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"),329 .aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
330 else => return error.UnsupportedLinkArchitecture,330 else => return error.UnsupportedLinkArchitecture,
331 }331 }
332332
...@@ -336,7 +336,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -336,7 +336,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
336 try ctx.args.append(c"/SUBSYSTEM:console");336 try ctx.args.append(c"/SUBSYSTEM:console");
337 }337 }
338338
339 const is_library = ctx.comp.kind == Compilation.Kind.Lib;339 const is_library = ctx.comp.kind == .Lib;
340340
341 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());341 const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", ctx.out_file_path.toSliceConst());
342 try ctx.args.append(out_arg.ptr);342 try ctx.args.append(out_arg.ptr);
...@@ -349,7 +349,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -349,7 +349,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
349349
350 if (ctx.link_in_crt) {350 if (ctx.link_in_crt) {
351 const lib_str = if (ctx.comp.is_static) "lib" else "";351 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
354 if (ctx.comp.is_static) {354 if (ctx.comp.is_static) {
355 const cmt_lib_name = try std.fmt.allocPrint(&ctx.arena.allocator, "libcmt{}.lib\x00", d_str);355 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 {...@@ -400,7 +400,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
400 try addFnObjects(ctx);400 try addFnObjects(ctx);
401401
402 switch (ctx.comp.kind) {402 switch (ctx.comp.kind) {
403 Compilation.Kind.Exe, Compilation.Kind.Lib => {403 .Exe, .Lib => {
404 if (!ctx.comp.haveLibC()) {404 if (!ctx.comp.haveLibC()) {
405 @panic("TODO");405 @panic("TODO");
406 //Buf *builtin_o_path = build_o(g, "builtin");406 //Buf *builtin_o_path = build_o(g, "builtin");
...@@ -412,7 +412,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -412,7 +412,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
412 //Buf *compiler_rt_o_path = build_compiler_rt(g);412 //Buf *compiler_rt_o_path = build_compiler_rt(g);
413 //lj->args.append(buf_ptr(compiler_rt_o_path));413 //lj->args.append(buf_ptr(compiler_rt_o_path));
414 },414 },
415 Compilation.Kind.Obj => {},415 .Obj => {},
416 }416 }
417417
418 //Buf *def_contents = buf_alloc();418 //Buf *def_contents = buf_alloc();
...@@ -469,7 +469,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -469,7 +469,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
469 try ctx.args.append(c"-export_dynamic");469 try ctx.args.append(c"-export_dynamic");
470 }470 }
471471
472 const is_lib = ctx.comp.kind == Compilation.Kind.Lib;472 const is_lib = ctx.comp.kind == .Lib;
473 const shared = !ctx.comp.is_static and is_lib;473 const shared = !ctx.comp.is_static and is_lib;
474 if (ctx.comp.is_static) {474 if (ctx.comp.is_static) {
475 try ctx.args.append(c"-static");475 try ctx.args.append(c"-static");
...@@ -512,14 +512,14 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -512,14 +512,14 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
512512
513 const platform = try DarwinPlatform.get(ctx.comp);513 const platform = try DarwinPlatform.get(ctx.comp);
514 switch (platform.kind) {514 switch (platform.kind) {
515 DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"),515 .MacOS => try ctx.args.append(c"-macosx_version_min"),
516 DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),516 .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
517 DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),517 .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
518 }518 }
519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
520 try ctx.args.append(ver_str.ptr);520 try ctx.args.append(ver_str.ptr);
521521
522 if (ctx.comp.kind == Compilation.Kind.Exe) {522 if (ctx.comp.kind == .Exe) {
523 if (ctx.comp.is_static) {523 if (ctx.comp.is_static) {
524 try ctx.args.append(c"-no_pie");524 try ctx.args.append(c"-no_pie");
525 } else {525 } else {
...@@ -542,7 +542,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -542,7 +542,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
542 try ctx.args.append(c"-lcrt0.o");542 try ctx.args.append(c"-lcrt0.o");
543 } else {543 } else {
544 switch (platform.kind) {544 switch (platform.kind) {
545 DarwinPlatform.Kind.MacOS => {545 .MacOS => {
546 if (platform.versionLessThan(10, 5)) {546 if (platform.versionLessThan(10, 5)) {
547 try ctx.args.append(c"-lcrt1.o");547 try ctx.args.append(c"-lcrt1.o");
548 } else if (platform.versionLessThan(10, 6)) {548 } else if (platform.versionLessThan(10, 6)) {
...@@ -551,8 +551,8 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -551,8 +551,8 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
551 try ctx.args.append(c"-lcrt1.10.6.o");551 try ctx.args.append(c"-lcrt1.10.6.o");
552 }552 }
553 },553 },
554 DarwinPlatform.Kind.IPhoneOS => {554 .IPhoneOS => {
555 if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {555 if (ctx.comp.target.getArch() == .aarch64) {
556 // iOS does not need any crt1 files for arm64556 // iOS does not need any crt1 files for arm64
557 } else if (platform.versionLessThan(3, 1)) {557 } else if (platform.versionLessThan(3, 1)) {
558 try ctx.args.append(c"-lcrt1.o");558 try ctx.args.append(c"-lcrt1.o");
...@@ -560,7 +560,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -560,7 +560,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
560 try ctx.args.append(c"-lcrt1.3.1.o");560 try ctx.args.append(c"-lcrt1.3.1.o");
561 }561 }
562 },562 },
563 DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed563 .IPhoneOSSimulator => {}, // no crt1.o needed
564 }564 }
565 }565 }
566566
...@@ -605,7 +605,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -605,7 +605,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
605 try ctx.args.append(c"dynamic_lookup");605 try ctx.args.append(c"dynamic_lookup");
606 }606 }
607607
608 if (platform.kind == DarwinPlatform.Kind.MacOS) {608 if (platform.kind == .MacOS) {
609 if (platform.versionLessThan(10, 5)) {609 if (platform.versionLessThan(10, 5)) {
610 try ctx.args.append(c"-lgcc_s.10.4");610 try ctx.args.append(c"-lgcc_s.10.4");
611 } else if (platform.versionLessThan(10, 6)) {611 } else if (platform.versionLessThan(10, 6)) {
...@@ -659,17 +659,17 @@ const DarwinPlatform = struct {...@@ -659,17 +659,17 @@ const DarwinPlatform = struct {
659 fn get(comp: *Compilation) !DarwinPlatform {659 fn get(comp: *Compilation) !DarwinPlatform {
660 var result: DarwinPlatform = undefined;660 var result: DarwinPlatform = undefined;
661 const ver_str = switch (comp.darwin_version_min) {661 const ver_str = switch (comp.darwin_version_min) {
662 Compilation.DarwinVersionMin.MacOS => |ver| blk: {662 .MacOS => |ver| blk: {
663 result.kind = Kind.MacOS;663 result.kind = .MacOS;
664 break :blk ver;664 break :blk ver;
665 },665 },
666 Compilation.DarwinVersionMin.Ios => |ver| blk: {666 .Ios => |ver| blk: {
667 result.kind = Kind.IPhoneOS;667 result.kind = .IPhoneOS;
668 break :blk ver;668 break :blk ver;
669 },669 },
670 Compilation.DarwinVersionMin.None => blk: {670 .None => blk: {
671 assert(comp.target.getOs() == .macosx);671 assert(comp.target.getOs() == .macosx);
672 result.kind = Kind.MacOS;672 result.kind = .MacOS;
673 break :blk "10.14";673 break :blk "10.14";
674 },674 },
675 };675 };
...@@ -686,11 +686,11 @@ const DarwinPlatform = struct {...@@ -686,11 +686,11 @@ const DarwinPlatform = struct {
686 return error.InvalidDarwinVersionString;686 return error.InvalidDarwinVersionString;
687 }687 }
688688
689 if (result.kind == Kind.IPhoneOS) {689 if (result.kind == .IPhoneOS) {
690 switch (comp.target.getArch()) {690 switch (comp.target.getArch()) {
691 builtin.Arch.i386,691 .i386,
692 builtin.Arch.x86_64,692 .x86_64,
693 => result.kind = Kind.IPhoneOSSimulator,693 => result.kind = .IPhoneOSSimulator,
694 else => {},694 else => {},
695 }695 }
696 }696 }
src-self-hosted/llvm.zig+1-2
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const builtin = @import("builtin");
2const c = @import("c.zig");1const c = @import("c.zig");
3const assert = @import("std").debug.assert;2const assert = @import("std").debug.assert;
43
...@@ -268,7 +267,7 @@ pub const FnInline = extern enum {...@@ -268,7 +267,7 @@ pub const FnInline = extern enum {
268};267};
269268
270fn removeNullability(comptime T: type) type {269fn 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);
272 return *T.Child;271 return *T.Child;
273}272}
274273
src-self-hosted/main.zig+89-122
...@@ -18,7 +18,7 @@ const Args = arg.Args;...@@ -18,7 +18,7 @@ const Args = arg.Args;
18const Flag = arg.Flag;18const Flag = arg.Flag;
19const ZigCompiler = @import("compilation.zig").ZigCompiler;19const ZigCompiler = @import("compilation.zig").ZigCompiler;
20const Compilation = @import("compilation.zig").Compilation;20const Compilation = @import("compilation.zig").Compilation;
21const Target = @import("target.zig").Target;21const Target = std.Target;
22const errmsg = @import("errmsg.zig");22const errmsg = @import("errmsg.zig");
23const LibCInstallation = @import("libc_installation.zig").LibCInstallation;23const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2424
...@@ -26,6 +26,8 @@ var stderr_file: fs.File = undefined;...@@ -26,6 +26,8 @@ var stderr_file: fs.File = undefined;
26var stderr: *io.OutStream(fs.File.WriteError) = undefined;26var stderr: *io.OutStream(fs.File.WriteError) = undefined;
27var stdout: *io.OutStream(fs.File.WriteError) = undefined;27var stdout: *io.OutStream(fs.File.WriteError) = undefined;
2828
29pub const io_mode = .evented;
30
29pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB31pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
3032
31const usage =33const usage =
...@@ -258,47 +260,47 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -258,47 +260,47 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
258 process.exit(0);260 process.exit(0);
259 }261 }
260262
261 const build_mode = blk: {263 const build_mode: std.builtin.Mode = blk: {
262 if (flags.single("mode")) |mode_flag| {264 if (flags.single("mode")) |mode_flag| {
263 if (mem.eql(u8, mode_flag, "debug")) {265 if (mem.eql(u8, mode_flag, "debug")) {
264 break :blk builtin.Mode.Debug;266 break :blk .Debug;
265 } else if (mem.eql(u8, mode_flag, "release-fast")) {267 } else if (mem.eql(u8, mode_flag, "release-fast")) {
266 break :blk builtin.Mode.ReleaseFast;268 break :blk .ReleaseFast;
267 } else if (mem.eql(u8, mode_flag, "release-safe")) {269 } else if (mem.eql(u8, mode_flag, "release-safe")) {
268 break :blk builtin.Mode.ReleaseSafe;270 break :blk .ReleaseSafe;
269 } else if (mem.eql(u8, mode_flag, "release-small")) {271 } else if (mem.eql(u8, mode_flag, "release-small")) {
270 break :blk builtin.Mode.ReleaseSmall;272 break :blk .ReleaseSmall;
271 } else unreachable;273 } else unreachable;
272 } else {274 } else {
273 break :blk builtin.Mode.Debug;275 break :blk .Debug;
274 }276 }
275 };277 };
276278
277 const color = blk: {279 const color: errmsg.Color = blk: {
278 if (flags.single("color")) |color_flag| {280 if (flags.single("color")) |color_flag| {
279 if (mem.eql(u8, color_flag, "auto")) {281 if (mem.eql(u8, color_flag, "auto")) {
280 break :blk errmsg.Color.Auto;282 break :blk .Auto;
281 } else if (mem.eql(u8, color_flag, "on")) {283 } else if (mem.eql(u8, color_flag, "on")) {
282 break :blk errmsg.Color.On;284 break :blk .On;
283 } else if (mem.eql(u8, color_flag, "off")) {285 } else if (mem.eql(u8, color_flag, "off")) {
284 break :blk errmsg.Color.Off;286 break :blk .Off;
285 } else unreachable;287 } else unreachable;
286 } else {288 } else {
287 break :blk errmsg.Color.Auto;289 break :blk .Auto;
288 }290 }
289 };291 };
290292
291 const emit_type = blk: {293 const emit_type: Compilation.Emit = blk: {
292 if (flags.single("emit")) |emit_flag| {294 if (flags.single("emit")) |emit_flag| {
293 if (mem.eql(u8, emit_flag, "asm")) {295 if (mem.eql(u8, emit_flag, "asm")) {
294 break :blk Compilation.Emit.Assembly;296 break :blk .Assembly;
295 } else if (mem.eql(u8, emit_flag, "bin")) {297 } else if (mem.eql(u8, emit_flag, "bin")) {
296 break :blk Compilation.Emit.Binary;298 break :blk .Binary;
297 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {299 } else if (mem.eql(u8, emit_flag, "llvm-ir")) {
298 break :blk Compilation.Emit.LlvmIr;300 break :blk .LlvmIr;
299 } else unreachable;301 } else unreachable;
300 } else {302 } else {
301 break :blk Compilation.Emit.Binary;303 break :blk .Binary;
302 }304 }
303 };305 };
304306
...@@ -383,11 +385,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -383,11 +385,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
383385
384 var override_libc: LibCInstallation = undefined;386 var override_libc: LibCInstallation = undefined;
385387
386 var loop: event.Loop = undefined;388 var zig_compiler = try ZigCompiler.init(allocator);
387 try loop.initMultiThreaded(allocator);
388 defer loop.deinit();
389
390 var zig_compiler = try ZigCompiler.init(&loop);
391 defer zig_compiler.deinit();389 defer zig_compiler.deinit();
392390
393 var comp = try Compilation.create(391 var comp = try Compilation.create(
...@@ -403,7 +401,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -403,7 +401,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
403 defer comp.destroy();401 defer comp.destroy();
404402
405 if (flags.single("libc")) |libc_path| {403 if (flags.single("libc")) |libc_path| {
406 parseLibcPaths(loop.allocator, &override_libc, libc_path);404 parseLibcPaths(allocator, &override_libc, libc_path);
407 comp.override_libc = &override_libc;405 comp.override_libc = &override_libc;
408 }406 }
409407
...@@ -463,25 +461,24 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -463,25 +461,24 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
463 comp.link_objects = link_objects;461 comp.link_objects = link_objects;
464462
465 comp.start();463 comp.start();
466 // TODO const process_build_events_handle = try async<loop.allocator> processBuildEvents(comp, color);464 const frame = async processBuildEvents(comp, color);
467 loop.run();
468}465}
469466
470async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {467async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
471 var count: usize = 0;468 var count: usize = 0;
472 while (true) {469 while (true) {
473 // TODO directly awaiting async should guarantee memory allocation elision470 // 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();
475 count += 1;472 count += 1;
476473
477 switch (build_event) {474 switch (build_event) {
478 Compilation.Event.Ok => {475 .Ok => {
479 stderr.print("Build {} succeeded\n", count) catch process.exit(1);476 stderr.print("Build {} succeeded\n", count) catch process.exit(1);
480 },477 },
481 Compilation.Event.Error => |err| {478 .Error => |err| {
482 stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1);479 stderr.print("Build {} failed: {}\n", count, @errorName(err)) catch process.exit(1);
483 },480 },
484 Compilation.Event.Fail => |msgs| {481 .Fail => |msgs| {
485 stderr.print("Build {} compile errors:\n", count) catch process.exit(1);482 stderr.print("Build {} compile errors:\n", count) catch process.exit(1);
486 for (msgs) |msg| {483 for (msgs) |msg| {
487 defer msg.destroy();484 defer msg.destroy();
...@@ -536,7 +533,7 @@ const Fmt = struct {...@@ -536,7 +533,7 @@ const Fmt = struct {
536 seen: event.Locked(SeenMap),533 seen: event.Locked(SeenMap),
537 any_error: bool,534 any_error: bool,
538 color: errmsg.Color,535 color: errmsg.Color,
539 loop: *event.Loop,536 allocator: *Allocator,
540537
541 const SeenMap = std.StringHashMap(void);538 const SeenMap = std.StringHashMap(void);
542};539};
...@@ -567,20 +564,14 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {...@@ -567,20 +564,14 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
567 },564 },
568 }565 }
569566
570 var loop: event.Loop = undefined;567 var zig_compiler = try ZigCompiler.init(allocator);
571 try loop.initMultiThreaded(allocator);
572 defer loop.deinit();
573
574 var zig_compiler = try ZigCompiler.init(&loop);
575 defer zig_compiler.deinit();568 defer zig_compiler.deinit();
576569
577 // TODO const handle = try async<loop.allocator> findLibCAsync(&zig_compiler);570 const frame = async findLibCAsync(&zig_compiler);
578
579 loop.run();
580}571}
581572
582async fn findLibCAsync(zig_compiler: *ZigCompiler) void {573async 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| {
584 stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);575 stderr.print("unable to find libc: {}\n", @errorName(err)) catch process.exit(1);
585 process.exit(1);576 process.exit(1);
586 };577 };
...@@ -596,17 +587,17 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -596,17 +587,17 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
596 process.exit(0);587 process.exit(0);
597 }588 }
598589
599 const color = blk: {590 const color: errmsg.Color = blk: {
600 if (flags.single("color")) |color_flag| {591 if (flags.single("color")) |color_flag| {
601 if (mem.eql(u8, color_flag, "auto")) {592 if (mem.eql(u8, color_flag, "auto")) {
602 break :blk errmsg.Color.Auto;593 break :blk .Auto;
603 } else if (mem.eql(u8, color_flag, "on")) {594 } else if (mem.eql(u8, color_flag, "on")) {
604 break :blk errmsg.Color.On;595 break :blk .On;
605 } else if (mem.eql(u8, color_flag, "off")) {596 } else if (mem.eql(u8, color_flag, "off")) {
606 break :blk errmsg.Color.Off;597 break :blk .Off;
607 } else unreachable;598 } else unreachable;
608 } else {599 } else {
609 break :blk errmsg.Color.Auto;600 break :blk .Auto;
610 }601 }
611 };602 };
612603
...@@ -640,7 +631,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -640,7 +631,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
640 }631 }
641 if (flags.present("check")) {632 if (flags.present("check")) {
642 const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);633 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;
644 process.exit(code);635 process.exit(code);
645 }636 }
646637
...@@ -653,28 +644,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {...@@ -653,28 +644,11 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
653 process.exit(1);644 process.exit(1);
654 }645 }
655646
656 var loop: event.Loop = undefined;647 return asyncFmtMain(
657 try loop.initMultiThreaded(allocator);648 allocator,
658 defer loop.deinit();649 &flags,
659650 color,
660 var result: FmtError!void = undefined;651 );
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);
678}652}
679653
680const FmtError = error{654const FmtError = error{
...@@ -700,72 +674,69 @@ const FmtError = error{...@@ -700,72 +674,69 @@ const FmtError = error{
700} || fs.File.OpenError;674} || fs.File.OpenError;
701675
702async fn asyncFmtMain(676async fn asyncFmtMain(
703 loop: *event.Loop,677 allocator: *Allocator,
704 flags: *const Args,678 flags: *const Args,
705 color: errmsg.Color,679 color: errmsg.Color,
706) FmtError!void {680) FmtError!void {
707 suspend {
708 resume @handle();
709 }
710 var fmt = Fmt{681 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)),
712 .any_error = false,684 .any_error = false,
713 .color = color,685 .color = color,
714 .loop = loop,
715 };686 };
716687
717 const check_mode = flags.present("check");688 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);
720 for (flags.positionals.toSliceConst()) |file_path| {691 for (flags.positionals.toSliceConst()) |file_path| {
721 try group.call(fmtPath, &fmt, file_path, check_mode);692 try group.call(fmtPath, &fmt, file_path, check_mode);
722 }693 }
723 try await (async group.wait() catch unreachable);694 try group.wait();
724 if (fmt.any_error) {695 if (fmt.any_error) {
725 process.exit(1);696 process.exit(1);
726 }697 }
727}698}
728699
729async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {700async 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);701 const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
731 defer fmt.loop.allocator.free(file_path);702 defer fmt.allocator.free(file_path);
732703
733 {704 {
734 const held = await (async fmt.seen.acquire() catch unreachable);705 const held = fmt.seen.acquire();
735 defer held.release();706 defer held.release();
736707
737 if (try held.value.put(file_path, {})) |_| return;708 if (try held.value.put(file_path, {})) |_| return;
738 }709 }
739710
740 const source_code = (await try async event.fs.readFile(711 const source_code = "";
741 fmt.loop,712 // const source_code = event.fs.readFile(
742 file_path,713 // file_path,
743 max_src_size,714 // max_src_size,
744 )) catch |err| switch (err) {715 // ) catch |err| switch (err) {
745 error.IsDir, error.AccessDenied => {716 // error.IsDir, error.AccessDenied => {
746 // TODO make event based (and dir.next())717 // // TODO make event based (and dir.next())
747 var dir = try fs.Dir.open(file_path);718 // var dir = try fs.Dir.open(file_path);
748 defer dir.close();719 // defer dir.close();
749720
750 var group = event.Group(FmtError!void).init(fmt.loop);721 // var group = event.Group(FmtError!void).init(fmt.allocator);
751 while (try dir.next()) |entry| {722 // while (try dir.next()) |entry| {
752 if (entry.kind == fs.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {723 // 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 });724 // const full_path = try fs.path.join(fmt.allocator, [_][]const u8{ file_path, entry.name });
754 try group.call(fmtPath, fmt, full_path, check_mode);725 // try group.call(fmtPath, fmt, full_path, check_mode);
755 }726 // }
756 }727 // }
757 return await (async group.wait() catch unreachable);728 // return group.wait();
758 },729 // },
759 else => {730 // else => {
760 // TODO lock stderr printing731 // // TODO lock stderr printing
761 try stderr.print("unable to open '{}': {}\n", file_path, err);732 // try stderr.print("unable to open '{}': {}\n", file_path, err);
762 fmt.any_error = true;733 // fmt.any_error = true;
763 return;734 // return;
764 },735 // },
765 };736 // };
766 defer fmt.loop.allocator.free(source_code);737 // defer fmt.allocator.free(source_code);
767738
768 const tree = std.zig.parse(fmt.loop.allocator, source_code) catch |err| {739 const tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
769 try stderr.print("error parsing file '{}': {}\n", file_path, err);740 try stderr.print("error parsing file '{}': {}\n", file_path, err);
770 fmt.any_error = true;741 fmt.any_error = true;
771 return;742 return;
...@@ -774,8 +745,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -774,8 +745,8 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
774745
775 var error_it = tree.errors.iterator(0);746 var error_it = tree.errors.iterator(0);
776 while (error_it.next()) |parse_error| {747 while (error_it.next()) |parse_error| {
777 const msg = try errmsg.Msg.createFromParseError(fmt.loop.allocator, parse_error, tree, file_path);748 const msg = try errmsg.Msg.createFromParseError(fmt.allocator, parse_error, tree, file_path);
778 defer fmt.loop.allocator.destroy(msg);749 defer fmt.allocator.destroy(msg);
779750
780 try msg.printToFile(stderr_file, fmt.color);751 try msg.printToFile(stderr_file, fmt.color);
781 }752 }
...@@ -785,17 +756,17 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro...@@ -785,17 +756,17 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
785 }756 }
786757
787 if (check_mode) {758 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);
789 if (anything_changed) {760 if (anything_changed) {
790 try stderr.print("{}\n", file_path);761 try stderr.print("{}\n", file_path);
791 fmt.any_error = true;762 fmt.any_error = true;
792 }763 }
793 } else {764 } else {
794 // TODO make this evented765 // 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);
796 defer baf.destroy();767 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);
799 if (anything_changed) {770 if (anything_changed) {
800 try stderr.print("{}\n", file_path);771 try stderr.print("{}\n", file_path);
801 try baf.finish();772 try baf.finish();
...@@ -822,8 +793,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {...@@ -822,8 +793,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
822 try stdout.write("Operating Systems:\n");793 try stdout.write("Operating Systems:\n");
823 {794 {
824 comptime var i: usize = 0;795 comptime var i: usize = 0;
825 inline while (i < @memberCount(builtin.Os)) : (i += 1) {796 inline while (i < @memberCount(Target.Os)) : (i += 1) {
826 comptime const os_tag = @memberName(builtin.Os, i);797 comptime const os_tag = @memberName(Target.Os, i);
827 // NOTE: Cannot use empty string, see #918.798 // NOTE: Cannot use empty string, see #918.
828 comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";799 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 {...@@ -835,8 +806,8 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
835 try stdout.write("C ABIs:\n");806 try stdout.write("C ABIs:\n");
836 {807 {
837 comptime var i: usize = 0;808 comptime var i: usize = 0;
838 inline while (i < @memberCount(builtin.Abi)) : (i += 1) {809 inline while (i < @memberCount(Target.Abi)) : (i += 1) {
839 comptime const abi_tag = @memberName(builtin.Abi, i);810 comptime const abi_tag = @memberName(Target.Abi, i);
840 // NOTE: Cannot use empty string, see #918.811 // NOTE: Cannot use empty string, see #918.
841 comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";812 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 {...@@ -911,21 +882,17 @@ fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
911 try stdout.print(882 try stdout.print(
912 \\ZIG_CMAKE_BINARY_DIR {}883 \\ZIG_CMAKE_BINARY_DIR {}
913 \\ZIG_CXX_COMPILER {}884 \\ZIG_CXX_COMPILER {}
914 \\ZIG_LLVM_CONFIG_EXE {}
915 \\ZIG_LLD_INCLUDE_PATH {}885 \\ZIG_LLD_INCLUDE_PATH {}
916 \\ZIG_LLD_LIBRARIES {}886 \\ZIG_LLD_LIBRARIES {}
917 \\ZIG_STD_FILES {}887 \\ZIG_LLVM_CONFIG_EXE {}
918 \\ZIG_C_HEADER_FILES {}
919 \\ZIG_DIA_GUIDS_LIB {}888 \\ZIG_DIA_GUIDS_LIB {}
920 \\889 \\
921 ,890 ,
922 std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),891 std.mem.toSliceConst(u8, c.ZIG_CMAKE_BINARY_DIR),
923 std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),892 std.mem.toSliceConst(u8, c.ZIG_CXX_COMPILER),
924 std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
925 std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),893 std.mem.toSliceConst(u8, c.ZIG_LLD_INCLUDE_PATH),
926 std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),894 std.mem.toSliceConst(u8, c.ZIG_LLD_LIBRARIES),
927 std.mem.toSliceConst(u8, c.ZIG_STD_FILES),895 std.mem.toSliceConst(u8, c.ZIG_LLVM_CONFIG_EXE),
928 std.mem.toSliceConst(u8, c.ZIG_C_HEADER_FILES),
929 std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),896 std.mem.toSliceConst(u8, c.ZIG_DIA_GUIDS_LIB),
930 );897 );
931}898}
src-self-hosted/scope.zig+46-47
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const Allocator = mem.Allocator;2const Allocator = mem.Allocator;
4const Decl = @import("decl.zig").Decl;3const Decl = @import("decl.zig").Decl;
5const Compilation = @import("compilation.zig").Compilation;4const Compilation = @import("compilation.zig").Compilation;
...@@ -28,15 +27,15 @@ pub const Scope = struct {...@@ -28,15 +27,15 @@ pub const Scope = struct {
28 if (base.ref_count.decr() == 1) {27 if (base.ref_count.decr() == 1) {
29 if (base.parent) |parent| parent.deref(comp);28 if (base.parent) |parent| parent.deref(comp);
30 switch (base.id) {29 switch (base.id) {
31 Id.Root => @fieldParentPtr(Root, "base", base).destroy(comp),30 .Root => @fieldParentPtr(Root, "base", base).destroy(comp),
32 Id.Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),31 .Decls => @fieldParentPtr(Decls, "base", base).destroy(comp),
33 Id.Block => @fieldParentPtr(Block, "base", base).destroy(comp),32 .Block => @fieldParentPtr(Block, "base", base).destroy(comp),
34 Id.FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),33 .FnDef => @fieldParentPtr(FnDef, "base", base).destroy(comp),
35 Id.CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),34 .CompTime => @fieldParentPtr(CompTime, "base", base).destroy(comp),
36 Id.Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),35 .Defer => @fieldParentPtr(Defer, "base", base).destroy(comp),
37 Id.DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),36 .DeferExpr => @fieldParentPtr(DeferExpr, "base", base).destroy(comp),
38 Id.Var => @fieldParentPtr(Var, "base", base).destroy(comp),37 .Var => @fieldParentPtr(Var, "base", base).destroy(comp),
39 Id.AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),38 .AstTree => @fieldParentPtr(AstTree, "base", base).destroy(comp),
40 }39 }
41 }40 }
42 }41 }
...@@ -46,7 +45,7 @@ pub const Scope = struct {...@@ -46,7 +45,7 @@ pub const Scope = struct {
46 while (scope.parent) |parent| {45 while (scope.parent) |parent| {
47 scope = parent;46 scope = parent;
48 }47 }
49 assert(scope.id == Id.Root);48 assert(scope.id == .Root);
50 return @fieldParentPtr(Root, "base", scope);49 return @fieldParentPtr(Root, "base", scope);
51 }50 }
5251
...@@ -54,17 +53,17 @@ pub const Scope = struct {...@@ -54,17 +53,17 @@ pub const Scope = struct {
54 var scope = base;53 var scope = base;
55 while (true) {54 while (true) {
56 switch (scope.id) {55 switch (scope.id) {
57 Id.FnDef => return @fieldParentPtr(FnDef, "base", scope),56 .FnDef => return @fieldParentPtr(FnDef, "base", scope),
58 Id.Root, Id.Decls => return null,57 .Root, .Decls => return null,
5958
60 Id.Block,59 .Block,
61 Id.Defer,60 .Defer,
62 Id.DeferExpr,61 .DeferExpr,
63 Id.CompTime,62 .CompTime,
64 Id.Var,63 .Var,
65 => scope = scope.parent.?,64 => scope = scope.parent.?,
6665
67 Id.AstTree => unreachable,66 .AstTree => unreachable,
68 }67 }
69 }68 }
70 }69 }
...@@ -73,20 +72,20 @@ pub const Scope = struct {...@@ -73,20 +72,20 @@ pub const Scope = struct {
73 var scope = base;72 var scope = base;
74 while (true) {73 while (true) {
75 switch (scope.id) {74 switch (scope.id) {
76 Id.DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),75 .DeferExpr => return @fieldParentPtr(DeferExpr, "base", scope),
7776
78 Id.FnDef,77 .FnDef,
79 Id.Decls,78 .Decls,
80 => return null,79 => return null,
8180
82 Id.Block,81 .Block,
83 Id.Defer,82 .Defer,
84 Id.CompTime,83 .CompTime,
85 Id.Root,84 .Root,
86 Id.Var,85 .Var,
87 => scope = scope.parent orelse return null,86 => scope = scope.parent orelse return null,
8887
89 Id.AstTree => unreachable,88 .AstTree => unreachable,
90 }89 }
91 }90 }
92 }91 }
...@@ -123,7 +122,7 @@ pub const Scope = struct {...@@ -123,7 +122,7 @@ pub const Scope = struct {
123 const self = try comp.gpa().create(Root);122 const self = try comp.gpa().create(Root);
124 self.* = Root{123 self.* = Root{
125 .base = Scope{124 .base = Scope{
126 .id = Id.Root,125 .id = .Root,
127 .parent = null,126 .parent = null,
128 .ref_count = std.atomic.Int(usize).init(1),127 .ref_count = std.atomic.Int(usize).init(1),
129 },128 },
...@@ -155,7 +154,7 @@ pub const Scope = struct {...@@ -155,7 +154,7 @@ pub const Scope = struct {
155 .base = undefined,154 .base = undefined,
156 .tree = tree,155 .tree = tree,
157 };156 };
158 self.base.init(Id.AstTree, &root_scope.base);157 self.base.init(.AstTree, &root_scope.base);
159158
160 return self;159 return self;
161 }160 }
...@@ -184,9 +183,9 @@ pub const Scope = struct {...@@ -184,9 +183,9 @@ pub const Scope = struct {
184 const self = try comp.gpa().create(Decls);183 const self = try comp.gpa().create(Decls);
185 self.* = Decls{184 self.* = Decls{
186 .base = undefined,185 .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())),
188 };187 };
189 self.base.init(Id.Decls, parent);188 self.base.init(.Decls, parent);
190 return self;189 return self;
191 }190 }
192191
...@@ -219,15 +218,15 @@ pub const Scope = struct {...@@ -219,15 +218,15 @@ pub const Scope = struct {
219218
220 fn get(self: Safety, comp: *Compilation) bool {219 fn get(self: Safety, comp: *Compilation) bool {
221 return switch (self) {220 return switch (self) {
222 Safety.Auto => switch (comp.build_mode) {221 .Auto => switch (comp.build_mode) {
223 builtin.Mode.Debug,222 .Debug,
224 builtin.Mode.ReleaseSafe,223 .ReleaseSafe,
225 => true,224 => true,
226 builtin.Mode.ReleaseFast,225 .ReleaseFast,
227 builtin.Mode.ReleaseSmall,226 .ReleaseSmall,
228 => false,227 => false,
229 },228 },
230 @TagType(Safety).Manual => |man| man.enabled,229 .Manual => |man| man.enabled,
231 };230 };
232 }231 }
233 };232 };
...@@ -243,7 +242,7 @@ pub const Scope = struct {...@@ -243,7 +242,7 @@ pub const Scope = struct {
243 .is_comptime = undefined,242 .is_comptime = undefined,
244 .safety = Safety.Auto,243 .safety = Safety.Auto,
245 };244 };
246 self.base.init(Id.Block, parent);245 self.base.init(.Block, parent);
247 return self;246 return self;
248 }247 }
249248
...@@ -266,7 +265,7 @@ pub const Scope = struct {...@@ -266,7 +265,7 @@ pub const Scope = struct {
266 .base = undefined,265 .base = undefined,
267 .fn_val = null,266 .fn_val = null,
268 };267 };
269 self.base.init(Id.FnDef, parent);268 self.base.init(.FnDef, parent);
270 return self;269 return self;
271 }270 }
272271
...@@ -282,7 +281,7 @@ pub const Scope = struct {...@@ -282,7 +281,7 @@ pub const Scope = struct {
282 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {281 pub fn create(comp: *Compilation, parent: *Scope) !*CompTime {
283 const self = try comp.gpa().create(CompTime);282 const self = try comp.gpa().create(CompTime);
284 self.* = CompTime{ .base = undefined };283 self.* = CompTime{ .base = undefined };
285 self.base.init(Id.CompTime, parent);284 self.base.init(.CompTime, parent);
286 return self;285 return self;
287 }286 }
288287
...@@ -314,7 +313,7 @@ pub const Scope = struct {...@@ -314,7 +313,7 @@ pub const Scope = struct {
314 .defer_expr_scope = defer_expr_scope,313 .defer_expr_scope = defer_expr_scope,
315 .kind = kind,314 .kind = kind,
316 };315 };
317 self.base.init(Id.Defer, parent);316 self.base.init(.Defer, parent);
318 defer_expr_scope.base.ref();317 defer_expr_scope.base.ref();
319 return self;318 return self;
320 }319 }
...@@ -338,7 +337,7 @@ pub const Scope = struct {...@@ -338,7 +337,7 @@ pub const Scope = struct {
338 .expr_node = expr_node,337 .expr_node = expr_node,
339 .reported_err = false,338 .reported_err = false,
340 };339 };
341 self.base.init(Id.DeferExpr, parent);340 self.base.init(.DeferExpr, parent);
342 return self;341 return self;
343 }342 }
344343
...@@ -404,14 +403,14 @@ pub const Scope = struct {...@@ -404,14 +403,14 @@ pub const Scope = struct {
404 .src_node = src_node,403 .src_node = src_node,
405 .data = undefined,404 .data = undefined,
406 };405 };
407 self.base.init(Id.Var, parent);406 self.base.init(.Var, parent);
408 return self;407 return self;
409 }408 }
410409
411 pub fn destroy(self: *Var, comp: *Compilation) void {410 pub fn destroy(self: *Var, comp: *Compilation) void {
412 switch (self.data) {411 switch (self.data) {
413 Data.Param => {},412 .Param => {},
414 Data.Const => |value| value.deref(comp),413 .Const => |value| value.deref(comp),
415 }414 }
416 comp.gpa().destroy(self);415 comp.gpa().destroy(self);
417 }416 }
src-self-hosted/stage1.zig+5-6
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1// This is Zig code that is used by both stage1 and stage2.1// This is Zig code that is used by both stage1 and stage2.
2// The prototypes in src/userland.h must match these definitions.2// The prototypes in src/userland.h must match these definitions.
33
4const builtin = @import("builtin");
5const std = @import("std");4const std = @import("std");
6const io = std.io;5const io = std.io;
7const mem = std.mem;6const mem = std.mem;
...@@ -354,9 +353,9 @@ fn printErrMsgToFile(...@@ -354,9 +353,9 @@ fn printErrMsgToFile(
354 color: errmsg.Color,353 color: errmsg.Color,
355) !void {354) !void {
356 const color_on = switch (color) {355 const color_on = switch (color) {
357 errmsg.Color.Auto => file.isTty(),356 .Auto => file.isTty(),
358 errmsg.Color.On => true,357 .On => true,
359 errmsg.Color.Off => false,358 .Off => false,
360 };359 };
361 const lok_token = parse_error.loc();360 const lok_token = parse_error.loc();
362 const span = errmsg.Span{361 const span = errmsg.Span{
...@@ -421,8 +420,8 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes...@@ -421,8 +420,8 @@ export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextRes
421 const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");420 const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text");
422 return stage2_DepNextResult{421 return stage2_DepNextResult{
423 .type_id = switch (token.id) {422 .type_id = switch (token.id) {
424 .target => stage2_DepNextResult.TypeId.target,423 .target => .target,
425 .prereq => stage2_DepNextResult.TypeId.prereq,424 .prereq => .prereq,
426 },425 },
427 .textz = textz.toSlice().ptr,426 .textz = textz.toSlice().ptr,
428 };427 };
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 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const builtin = @import("builtin");3const Target = std.Target;
4const Target = @import("target.zig").Target;
5const Compilation = @import("compilation.zig").Compilation;4const Compilation = @import("compilation.zig").Compilation;
6const introspect = @import("introspect.zig");5const introspect = @import("introspect.zig");
7const testing = std.testing;6const testing = std.testing;
...@@ -11,11 +10,17 @@ const ZigCompiler = @import("compilation.zig").ZigCompiler;...@@ -11,11 +10,17 @@ const ZigCompiler = @import("compilation.zig").ZigCompiler;
11var ctx: TestContext = undefined;10var ctx: TestContext = undefined;
1211
13test "stage2" {12test "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
14 try ctx.init();20 try ctx.init();
15 defer ctx.deinit();21 defer ctx.deinit();
1622
17 try @import("../test/stage2/compile_errors.zig").addCases(&ctx);23 try @import("stage2_tests").addCases(&ctx);
18 try @import("../test/stage2/compare_output.zig").addCases(&ctx);
1924
20 try ctx.run();25 try ctx.run();
21}26}
...@@ -24,7 +29,6 @@ const file1 = "1.zig";...@@ -24,7 +29,6 @@ const file1 = "1.zig";
24const allocator = std.heap.c_allocator;29const allocator = std.heap.c_allocator;
2530
26pub const TestContext = struct {31pub const TestContext = struct {
27 loop: std.event.Loop,
28 zig_compiler: ZigCompiler,32 zig_compiler: ZigCompiler,
29 zig_lib_dir: []u8,33 zig_lib_dir: []u8,
30 file_index: std.atomic.Int(usize),34 file_index: std.atomic.Int(usize),
...@@ -36,21 +40,17 @@ pub const TestContext = struct {...@@ -36,21 +40,17 @@ pub const TestContext = struct {
36 fn init(self: *TestContext) !void {40 fn init(self: *TestContext) !void {
37 self.* = TestContext{41 self.* = TestContext{
38 .any_err = {},42 .any_err = {},
39 .loop = undefined,
40 .zig_compiler = undefined,43 .zig_compiler = undefined,
41 .zig_lib_dir = undefined,44 .zig_lib_dir = undefined,
42 .group = undefined,45 .group = undefined,
43 .file_index = std.atomic.Int(usize).init(0),46 .file_index = std.atomic.Int(usize).init(0),
44 };47 };
4548
46 try self.loop.initSingleThreaded(allocator);49 self.zig_compiler = try ZigCompiler.init(allocator);
47 errdefer self.loop.deinit();
48
49 self.zig_compiler = try ZigCompiler.init(&self.loop);
50 errdefer self.zig_compiler.deinit();50 errdefer self.zig_compiler.deinit();
5151
52 self.group = std.event.Group(anyerror!void).init(&self.loop);52 self.group = std.event.Group(anyerror!void).init(allocator);
53 errdefer self.group.deinit();53 errdefer self.group.wait() catch {};
5454
55 self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);55 self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
56 errdefer allocator.free(self.zig_lib_dir);56 errdefer allocator.free(self.zig_lib_dir);
...@@ -63,20 +63,14 @@ pub const TestContext = struct {...@@ -63,20 +63,14 @@ pub const TestContext = struct {
63 std.fs.deleteTree(tmp_dir_name) catch {};63 std.fs.deleteTree(tmp_dir_name) catch {};
64 allocator.free(self.zig_lib_dir);64 allocator.free(self.zig_lib_dir);
65 self.zig_compiler.deinit();65 self.zig_compiler.deinit();
66 self.loop.deinit();
67 }66 }
6867
69 fn run(self: *TestContext) !void {68 fn run(self: *TestContext) !void {
70 const handle = try self.loop.call(waitForGroup, self);69 std.event.Loop.startCpuBoundOperation();
71 defer cancel handle;70 self.any_err = self.group.wait();
72 self.loop.run();
73 return self.any_err;71 return self.any_err;
74 }72 }
7573
76 async fn waitForGroup(self: *TestContext) void {
77 self.any_err = await (async self.group.wait() catch unreachable);
78 }
79
80 fn testCompileError(74 fn testCompileError(
81 self: *TestContext,75 self: *TestContext,
82 source: []const u8,76 source: []const u8,
...@@ -87,7 +81,7 @@ pub const TestContext = struct {...@@ -87,7 +81,7 @@ pub const TestContext = struct {
87 ) !void {81 ) !void {
88 var file_index_buf: [20]u8 = undefined;82 var file_index_buf: [20]u8 = undefined;
89 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());83 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
92 if (std.fs.path.dirname(file1_path)) |dirname| {86 if (std.fs.path.dirname(file1_path)) |dirname| {
93 try std.fs.makePath(allocator, dirname);87 try std.fs.makePath(allocator, dirname);
...@@ -102,7 +96,7 @@ pub const TestContext = struct {...@@ -102,7 +96,7 @@ pub const TestContext = struct {
102 file1_path,96 file1_path,
103 Target.Native,97 Target.Native,
104 Compilation.Kind.Obj,98 Compilation.Kind.Obj,
105 builtin.Mode.Debug,99 .Debug,
106 true, // is_static100 true, // is_static
107 self.zig_lib_dir,101 self.zig_lib_dir,
108 );102 );
...@@ -120,9 +114,9 @@ pub const TestContext = struct {...@@ -120,9 +114,9 @@ pub const TestContext = struct {
120 ) !void {114 ) !void {
121 var file_index_buf: [20]u8 = undefined;115 var file_index_buf: [20]u8 = undefined;
122 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.incr());116 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());
126 if (std.fs.path.dirname(file1_path)) |dirname| {120 if (std.fs.path.dirname(file1_path)) |dirname| {
127 try std.fs.makePath(allocator, dirname);121 try std.fs.makePath(allocator, dirname);
128 }122 }
...@@ -136,7 +130,7 @@ pub const TestContext = struct {...@@ -136,7 +130,7 @@ pub const TestContext = struct {
136 file1_path,130 file1_path,
137 Target.Native,131 Target.Native,
138 Compilation.Kind.Exe,132 Compilation.Kind.Exe,
139 builtin.Mode.Debug,133 .Debug,
140 false,134 false,
141 self.zig_lib_dir,135 self.zig_lib_dir,
142 );136 );
...@@ -153,16 +147,16 @@ pub const TestContext = struct {...@@ -153,16 +147,16 @@ pub const TestContext = struct {
153 comp: *Compilation,147 comp: *Compilation,
154 exe_file: []const u8,148 exe_file: []const u8,
155 expected_output: []const u8,149 expected_output: []const u8,
156 ) !void {150 ) anyerror!void {
157 // TODO this should not be necessary151 // TODO this should not be necessary
158 const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);152 const exe_file_2 = try std.mem.dupe(allocator, u8, exe_file);
159153
160 defer comp.destroy();154 defer comp.destroy();
161 const build_event = await (async comp.events.get() catch unreachable);155 const build_event = comp.events.get();
162156
163 switch (build_event) {157 switch (build_event) {
164 Compilation.Event.Ok => {158 .Ok => {
165 const argv = []const []const u8{exe_file_2};159 const argv = [_][]const u8{exe_file_2};
166 // TODO use event loop160 // TODO use event loop
167 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);161 const child = try std.ChildProcess.exec(allocator, argv, null, null, 1024 * 1024);
168 switch (child.term) {162 switch (child.term) {
...@@ -198,18 +192,18 @@ pub const TestContext = struct {...@@ -198,18 +192,18 @@ pub const TestContext = struct {
198 line: usize,192 line: usize,
199 column: usize,193 column: usize,
200 text: []const u8,194 text: []const u8,
201 ) !void {195 ) anyerror!void {
202 defer comp.destroy();196 defer comp.destroy();
203 const build_event = await (async comp.events.get() catch unreachable);197 const build_event = comp.events.get();
204198
205 switch (build_event) {199 switch (build_event) {
206 Compilation.Event.Ok => {200 .Ok => {
207 @panic("build incorrectly succeeded");201 @panic("build incorrectly succeeded");
208 },202 },
209 Compilation.Event.Error => |err| {203 .Error => |err| {
210 @panic("build incorrectly failed");204 @panic("build incorrectly failed");
211 },205 },
212 Compilation.Event.Fail => |msgs| {206 .Fail => |msgs| {
213 testing.expect(msgs.len != 0);207 testing.expect(msgs.len != 0);
214 for (msgs) |msg| {208 for (msgs) |msg| {
215 if (mem.endsWith(u8, msg.realpath, path) and mem.eql(u8, msg.text, text)) {209 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 @@...@@ -2,7 +2,6 @@
2// and stage2. Currently the only way it is used is with `zig translate-c-2`.2// and stage2. Currently the only way it is used is with `zig translate-c-2`.
33
4const std = @import("std");4const std = @import("std");
5const builtin = @import("builtin");
6const assert = std.debug.assert;5const assert = std.debug.assert;
7const ast = std.zig.ast;6const ast = std.zig.ast;
8const Token = std.zig.Token;7const Token = std.zig.Token;
...@@ -13,8 +12,7 @@ pub const Mode = enum {...@@ -13,8 +12,7 @@ pub const Mode = enum {
13 translate,12 translate,
14};13};
1514
16// TODO merge with Type.Fn.CallingConvention15const CallingConvention = std.builtin.TypeInfo.CallingConvention;
17const CallingConvention = builtin.TypeInfo.CallingConvention;
1816
19pub const ClangErrMsg = Stage2ErrorMsg;17pub const ClangErrMsg = Stage2ErrorMsg;
2018
src-self-hosted/type.zig+202-230
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = std.builtin;
3const Scope = @import("scope.zig").Scope;3const Scope = @import("scope.zig").Scope;
4const Compilation = @import("compilation.zig").Compilation;4const Compilation = @import("compilation.zig").Compilation;
5const Value = @import("value.zig").Value;5const Value = @import("value.zig").Value;
...@@ -20,31 +20,32 @@ pub const Type = struct {...@@ -20,31 +20,32 @@ pub const Type = struct {
2020
21 pub fn destroy(base: *Type, comp: *Compilation) void {21 pub fn destroy(base: *Type, comp: *Compilation) void {
22 switch (base.id) {22 switch (base.id) {
23 Id.Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),23 .Struct => @fieldParentPtr(Struct, "base", base).destroy(comp),
24 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),24 .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
25 Id.Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),25 .Type => @fieldParentPtr(MetaType, "base", base).destroy(comp),
26 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),26 .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
27 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),27 .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
28 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),28 .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
29 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),29 .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
30 Id.Float => @fieldParentPtr(Float, "base", base).destroy(comp),30 .Float => @fieldParentPtr(Float, "base", base).destroy(comp),
31 Id.Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),31 .Pointer => @fieldParentPtr(Pointer, "base", base).destroy(comp),
32 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),32 .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
33 Id.ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),33 .ComptimeFloat => @fieldParentPtr(ComptimeFloat, "base", base).destroy(comp),
34 Id.ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),34 .ComptimeInt => @fieldParentPtr(ComptimeInt, "base", base).destroy(comp),
35 Id.EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp),35 .EnumLiteral => @fieldParentPtr(EnumLiteral, "base", base).destroy(comp),
36 Id.Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),36 .Undefined => @fieldParentPtr(Undefined, "base", base).destroy(comp),
37 Id.Null => @fieldParentPtr(Null, "base", base).destroy(comp),37 .Null => @fieldParentPtr(Null, "base", base).destroy(comp),
38 Id.Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),38 .Optional => @fieldParentPtr(Optional, "base", base).destroy(comp),
39 Id.ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),39 .ErrorUnion => @fieldParentPtr(ErrorUnion, "base", base).destroy(comp),
40 Id.ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),40 .ErrorSet => @fieldParentPtr(ErrorSet, "base", base).destroy(comp),
41 Id.Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),41 .Enum => @fieldParentPtr(Enum, "base", base).destroy(comp),
42 Id.Union => @fieldParentPtr(Union, "base", base).destroy(comp),42 .Union => @fieldParentPtr(Union, "base", base).destroy(comp),
43 Id.BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),43 .BoundFn => @fieldParentPtr(BoundFn, "base", base).destroy(comp),
44 Id.ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),44 .ArgTuple => @fieldParentPtr(ArgTuple, "base", base).destroy(comp),
45 Id.Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),45 .Opaque => @fieldParentPtr(Opaque, "base", base).destroy(comp),
46 Id.Promise => @fieldParentPtr(Promise, "base", base).destroy(comp),46 .Frame => @fieldParentPtr(Frame, "base", base).destroy(comp),
47 Id.Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),47 .AnyFrame => @fieldParentPtr(AnyFrame, "base", base).destroy(comp),
48 .Vector => @fieldParentPtr(Vector, "base", base).destroy(comp),
48 }49 }
49 }50 }
5051
...@@ -54,105 +55,108 @@ pub const Type = struct {...@@ -54,105 +55,108 @@ pub const Type = struct {
54 llvm_context: *llvm.Context,55 llvm_context: *llvm.Context,
55 ) (error{OutOfMemory}!*llvm.Type) {56 ) (error{OutOfMemory}!*llvm.Type) {
56 switch (base.id) {57 switch (base.id) {
57 Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),58 .Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
58 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),59 .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
59 Id.Type => unreachable,60 .Type => unreachable,
60 Id.Void => unreachable,61 .Void => unreachable,
61 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context),62 .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmType(allocator, llvm_context),
62 Id.NoReturn => unreachable,63 .NoReturn => unreachable,
63 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context),64 .Int => return @fieldParentPtr(Int, "base", base).getLlvmType(allocator, llvm_context),
64 Id.Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context),65 .Float => return @fieldParentPtr(Float, "base", base).getLlvmType(allocator, llvm_context),
65 Id.Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context),66 .Pointer => return @fieldParentPtr(Pointer, "base", base).getLlvmType(allocator, llvm_context),
66 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context),67 .Array => return @fieldParentPtr(Array, "base", base).getLlvmType(allocator, llvm_context),
67 Id.ComptimeFloat => unreachable,68 .ComptimeFloat => unreachable,
68 Id.ComptimeInt => unreachable,69 .ComptimeInt => unreachable,
69 Id.EnumLiteral => unreachable,70 .EnumLiteral => unreachable,
70 Id.Undefined => unreachable,71 .Undefined => unreachable,
71 Id.Null => unreachable,72 .Null => unreachable,
72 Id.Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context),73 .Optional => return @fieldParentPtr(Optional, "base", base).getLlvmType(allocator, llvm_context),
73 Id.ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context),74 .ErrorUnion => return @fieldParentPtr(ErrorUnion, "base", base).getLlvmType(allocator, llvm_context),
74 Id.ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context),75 .ErrorSet => return @fieldParentPtr(ErrorSet, "base", base).getLlvmType(allocator, llvm_context),
75 Id.Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),76 .Enum => return @fieldParentPtr(Enum, "base", base).getLlvmType(allocator, llvm_context),
76 Id.Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),77 .Union => return @fieldParentPtr(Union, "base", base).getLlvmType(allocator, llvm_context),
77 Id.BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),78 .BoundFn => return @fieldParentPtr(BoundFn, "base", base).getLlvmType(allocator, llvm_context),
78 Id.ArgTuple => unreachable,79 .ArgTuple => unreachable,
79 Id.Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),80 .Opaque => return @fieldParentPtr(Opaque, "base", base).getLlvmType(allocator, llvm_context),
80 Id.Promise => return @fieldParentPtr(Promise, "base", base).getLlvmType(allocator, llvm_context),81 .Frame => return @fieldParentPtr(Frame, "base", base).getLlvmType(allocator, llvm_context),
81 Id.Vector => return @fieldParentPtr(Vector, "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),
82 }84 }
83 }85 }
8486
85 pub fn handleIsPtr(base: *Type) bool {87 pub fn handleIsPtr(base: *Type) bool {
86 switch (base.id) {88 switch (base.id) {
87 Id.Type,89 .Type,
88 Id.ComptimeFloat,90 .ComptimeFloat,
89 Id.ComptimeInt,91 .ComptimeInt,
90 Id.EnumLiteral,92 .EnumLiteral,
91 Id.Undefined,93 .Undefined,
92 Id.Null,94 .Null,
93 Id.BoundFn,95 .BoundFn,
94 Id.ArgTuple,96 .ArgTuple,
95 Id.Opaque,97 .Opaque,
96 => unreachable,98 => unreachable,
9799
98 Id.NoReturn,100 .NoReturn,
99 Id.Void,101 .Void,
100 Id.Bool,102 .Bool,
101 Id.Int,103 .Int,
102 Id.Float,104 .Float,
103 Id.Pointer,105 .Pointer,
104 Id.ErrorSet,106 .ErrorSet,
105 Id.Enum,107 .Enum,
106 Id.Fn,108 .Fn,
107 Id.Promise,109 .Frame,
108 Id.Vector,110 .AnyFrame,
111 .Vector,
109 => return false,112 => return false,
110113
111 Id.Struct => @panic("TODO"),114 .Struct => @panic("TODO"),
112 Id.Array => @panic("TODO"),115 .Array => @panic("TODO"),
113 Id.Optional => @panic("TODO"),116 .Optional => @panic("TODO"),
114 Id.ErrorUnion => @panic("TODO"),117 .ErrorUnion => @panic("TODO"),
115 Id.Union => @panic("TODO"),118 .Union => @panic("TODO"),
116 }119 }
117 }120 }
118121
119 pub fn hasBits(base: *Type) bool {122 pub fn hasBits(base: *Type) bool {
120 switch (base.id) {123 switch (base.id) {
121 Id.Type,124 .Type,
122 Id.ComptimeFloat,125 .ComptimeFloat,
123 Id.ComptimeInt,126 .ComptimeInt,
124 Id.EnumLiteral,127 .EnumLiteral,
125 Id.Undefined,128 .Undefined,
126 Id.Null,129 .Null,
127 Id.BoundFn,130 .BoundFn,
128 Id.ArgTuple,131 .ArgTuple,
129 Id.Opaque,132 .Opaque,
130 => unreachable,133 => unreachable,
131134
132 Id.Void,135 .Void,
133 Id.NoReturn,136 .NoReturn,
134 => return false,137 => return false,
135138
136 Id.Bool,139 .Bool,
137 Id.Int,140 .Int,
138 Id.Float,141 .Float,
139 Id.Fn,142 .Fn,
140 Id.Promise,143 .Frame,
141 Id.Vector,144 .AnyFrame,
145 .Vector,
142 => return true,146 => return true,
143147
144 Id.Pointer => {148 .Pointer => {
145 const ptr_type = @fieldParentPtr(Pointer, "base", base);149 const ptr_type = @fieldParentPtr(Pointer, "base", base);
146 return ptr_type.key.child_type.hasBits();150 return ptr_type.key.child_type.hasBits();
147 },151 },
148152
149 Id.ErrorSet => @panic("TODO"),153 .ErrorSet => @panic("TODO"),
150 Id.Enum => @panic("TODO"),154 .Enum => @panic("TODO"),
151 Id.Struct => @panic("TODO"),155 .Struct => @panic("TODO"),
152 Id.Array => @panic("TODO"),156 .Array => @panic("TODO"),
153 Id.Optional => @panic("TODO"),157 .Optional => @panic("TODO"),
154 Id.ErrorUnion => @panic("TODO"),158 .ErrorUnion => @panic("TODO"),
155 Id.Union => @panic("TODO"),159 .Union => @panic("TODO"),
156 }160 }
157 }161 }
158162
...@@ -168,20 +172,20 @@ pub const Type = struct {...@@ -168,20 +172,20 @@ pub const Type = struct {
168 fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {172 fn init(base: *Type, comp: *Compilation, id: Id, name: []const u8) void {
169 base.* = Type{173 base.* = Type{
170 .base = Value{174 .base = Value{
171 .id = Value.Id.Type,175 .id = .Type,
172 .typ = &MetaType.get(comp).base,176 .typ = &MetaType.get(comp).base,
173 .ref_count = std.atomic.Int(usize).init(1),177 .ref_count = std.atomic.Int(usize).init(1),
174 },178 },
175 .id = id,179 .id = id,
176 .name = name,180 .name = name,
177 .abi_alignment = AbiAlignment.init(comp.loop),181 .abi_alignment = AbiAlignment.init(),
178 };182 };
179 }183 }
180184
181 /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.185 /// If you happen to have an llvm context handy, use getAbiAlignmentInContext instead.
182 /// Otherwise, this one will grab one from the pool and then release it.186 /// Otherwise, this one will grab one from the pool and then release it.
183 pub async fn getAbiAlignment(base: *Type, comp: *Compilation) !u32 {187 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
186 {190 {
187 const held = try comp.zig_compiler.getAnyLlvmContext();191 const held = try comp.zig_compiler.getAnyLlvmContext();
...@@ -189,7 +193,7 @@ pub const Type = struct {...@@ -189,7 +193,7 @@ pub const Type = struct {
189193
190 const llvm_context = held.node.data;194 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);
193 }197 }
194 base.abi_alignment.resolve();198 base.abi_alignment.resolve();
195 return base.abi_alignment.data;199 return base.abi_alignment.data;
...@@ -197,9 +201,9 @@ pub const Type = struct {...@@ -197,9 +201,9 @@ pub const Type = struct {
197201
198 /// If you have an llvm conext handy, you can use it here.202 /// If you have an llvm conext handy, you can use it here.
199 pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {203 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);
203 base.abi_alignment.resolve();207 base.abi_alignment.resolve();
204 return base.abi_alignment.data;208 return base.abi_alignment.data;
205 }209 }
...@@ -261,30 +265,18 @@ pub const Type = struct {...@@ -261,30 +265,18 @@ pub const Type = struct {
261265
262 pub const Generic = struct {266 pub const Generic = struct {
263 param_count: usize,267 param_count: usize,
264 cc: CC,268 cc: CallingConvention,
265
266 pub const CC = union(CallingConvention) {
267 Auto,
268 C,
269 Cold,
270 Naked,
271 Stdcall,
272 Async: *Type, // allocator type
273 };
274 };269 };
275270
276 pub fn hash(self: *const Key) u32 {271 pub fn hash(self: *const Key) u32 {
277 var result: u32 = 0;272 var result: u32 = 0;
278 result +%= hashAny(self.alignment, 0);273 result +%= hashAny(self.alignment, 0);
279 switch (self.data) {274 switch (self.data) {
280 Kind.Generic => |generic| {275 .Generic => |generic| {
281 result +%= hashAny(generic.param_count, 1);276 result +%= hashAny(generic.param_count, 1);
282 switch (generic.cc) {277 result +%= hashAny(generic.cc, 3);
283 CallingConvention.Async => |allocator_type| result +%= hashAny(allocator_type, 2),
284 else => result +%= hashAny(CallingConvention(generic.cc), 3),
285 }
286 },278 },
287 Kind.Normal => |normal| {279 .Normal => |normal| {
288 result +%= hashAny(normal.return_type, 4);280 result +%= hashAny(normal.return_type, 4);
289 result +%= hashAny(normal.is_var_args, 5);281 result +%= hashAny(normal.is_var_args, 5);
290 result +%= hashAny(normal.cc, 6);282 result +%= hashAny(normal.cc, 6);
...@@ -302,21 +294,14 @@ pub const Type = struct {...@@ -302,21 +294,14 @@ pub const Type = struct {
302 if (self.alignment) |self_align| {294 if (self.alignment) |self_align| {
303 if (self_align != other.alignment.?) return false;295 if (self_align != other.alignment.?) return false;
304 }296 }
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;
306 switch (self.data) {298 switch (self.data) {
307 Kind.Generic => |*self_generic| {299 .Generic => |*self_generic| {
308 const other_generic = &other.data.Generic;300 const other_generic = &other.data.Generic;
309 if (self_generic.param_count != other_generic.param_count) return false;301 if (self_generic.param_count != other_generic.param_count) return false;
310 if (CallingConvention(self_generic.cc) != CallingConvention(other_generic.cc)) return false;302 if (self_generic.cc != 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 }
318 },303 },
319 Kind.Normal => |*self_normal| {304 .Normal => |*self_normal| {
320 const other_normal = &other.data.Normal;305 const other_normal = &other.data.Normal;
321 if (self_normal.cc != other_normal.cc) return false;306 if (self_normal.cc != other_normal.cc) return false;
322 if (self_normal.is_var_args != other_normal.is_var_args) return false;307 if (self_normal.is_var_args != other_normal.is_var_args) return false;
...@@ -333,13 +318,8 @@ pub const Type = struct {...@@ -333,13 +318,8 @@ pub const Type = struct {
333318
334 pub fn deref(key: Key, comp: *Compilation) void {319 pub fn deref(key: Key, comp: *Compilation) void {
335 switch (key.data) {320 switch (key.data) {
336 Kind.Generic => |generic| {321 .Generic => {},
337 switch (generic.cc) {322 .Normal => |normal| {
338 CallingConvention.Async => |allocator_type| allocator_type.base.deref(comp),
339 else => {},
340 }
341 },
342 Kind.Normal => |normal| {
343 normal.return_type.base.deref(comp);323 normal.return_type.base.deref(comp);
344 for (normal.params) |param| {324 for (normal.params) |param| {
345 param.typ.base.deref(comp);325 param.typ.base.deref(comp);
...@@ -350,13 +330,8 @@ pub const Type = struct {...@@ -350,13 +330,8 @@ pub const Type = struct {
350330
351 pub fn ref(key: Key) void {331 pub fn ref(key: Key) void {
352 switch (key.data) {332 switch (key.data) {
353 Kind.Generic => |generic| {333 .Generic => {},
354 switch (generic.cc) {334 .Normal => |normal| {
355 CallingConvention.Async => |allocator_type| allocator_type.base.ref(),
356 else => {},
357 }
358 },
359 Kind.Normal => |normal| {
360 normal.return_type.base.ref();335 normal.return_type.base.ref();
361 for (normal.params) |param| {336 for (normal.params) |param| {
362 param.typ.base.ref();337 param.typ.base.ref();
...@@ -366,14 +341,7 @@ pub const Type = struct {...@@ -366,14 +341,7 @@ pub const Type = struct {
366 }341 }
367 };342 };
368343
369 pub const CallingConvention = enum {344 const CallingConvention = builtin.TypeInfo.CallingConvention;
370 Auto,
371 C,
372 Cold,
373 Naked,
374 Stdcall,
375 Async,
376 };
377345
378 pub const Param = struct {346 pub const Param = struct {
379 is_noalias: bool,347 is_noalias: bool,
...@@ -382,26 +350,26 @@ pub const Type = struct {...@@ -382,26 +350,26 @@ pub const Type = struct {
382350
383 fn ccFnTypeStr(cc: CallingConvention) []const u8 {351 fn ccFnTypeStr(cc: CallingConvention) []const u8 {
384 return switch (cc) {352 return switch (cc) {
385 CallingConvention.Auto => "",353 .Unspecified => "",
386 CallingConvention.C => "extern ",354 .C => "extern ",
387 CallingConvention.Cold => "coldcc ",355 .Cold => "coldcc ",
388 CallingConvention.Naked => "nakedcc ",356 .Naked => "nakedcc ",
389 CallingConvention.Stdcall => "stdcallcc ",357 .Stdcall => "stdcallcc ",
390 CallingConvention.Async => unreachable,358 .Async => "async ",
391 };359 };
392 }360 }
393361
394 pub fn paramCount(self: *Fn) usize {362 pub fn paramCount(self: *Fn) usize {
395 return switch (self.key.data) {363 return switch (self.key.data) {
396 Kind.Generic => |generic| generic.param_count,364 .Generic => |generic| generic.param_count,
397 Kind.Normal => |normal| normal.params.len,365 .Normal => |normal| normal.params.len,
398 };366 };
399 }367 }
400368
401 /// takes ownership of key.Normal.params on success369 /// takes ownership of key.Normal.params on success
402 pub async fn get(comp: *Compilation, key: Key) !*Fn {370 pub async fn get(comp: *Compilation, key: Key) !*Fn {
403 {371 {
404 const held = await (async comp.fn_type_table.acquire() catch unreachable);372 const held = comp.fn_type_table.acquire();
405 defer held.release();373 defer held.release();
406374
407 if (held.value.get(&key)) |entry| {375 if (held.value.get(&key)) |entry| {
...@@ -428,18 +396,10 @@ pub const Type = struct {...@@ -428,18 +396,10 @@ pub const Type = struct {
428 const name_stream = &std.io.BufferOutStream.init(&name_buf).stream;396 const name_stream = &std.io.BufferOutStream.init(&name_buf).stream;
429397
430 switch (key.data) {398 switch (key.data) {
431 Kind.Generic => |generic| {399 .Generic => |generic| {
432 self.non_key = NonKey{ .Generic = {} };400 self.non_key = NonKey{ .Generic = {} };
433 switch (generic.cc) {401 const cc_str = ccFnTypeStr(generic.cc);
434 CallingConvention.Async => |async_allocator_type| {402 try name_stream.print("{}fn(", cc_str);
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(");
443 var param_i: usize = 0;403 var param_i: usize = 0;
444 while (param_i < generic.param_count) : (param_i += 1) {404 while (param_i < generic.param_count) : (param_i += 1) {
445 const arg = if (param_i == 0) "var" else ", var";405 const arg = if (param_i == 0) "var" else ", var";
...@@ -447,11 +407,11 @@ pub const Type = struct {...@@ -447,11 +407,11 @@ pub const Type = struct {
447 }407 }
448 try name_stream.write(")");408 try name_stream.write(")");
449 if (key.alignment) |alignment| {409 if (key.alignment) |alignment| {
450 try name_stream.print(" align<{}>", alignment);410 try name_stream.print(" align({})", alignment);
451 }411 }
452 try name_stream.write(" var");412 try name_stream.write(" var");
453 },413 },
454 Kind.Normal => |normal| {414 .Normal => |normal| {
455 self.non_key = NonKey{415 self.non_key = NonKey{
456 .Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },416 .Normal = NonKey.Normal{ .variable_list = std.ArrayList(*Scope.Var).init(comp.gpa()) },
457 };417 };
...@@ -468,16 +428,16 @@ pub const Type = struct {...@@ -468,16 +428,16 @@ pub const Type = struct {
468 }428 }
469 try name_stream.write(")");429 try name_stream.write(")");
470 if (key.alignment) |alignment| {430 if (key.alignment) |alignment| {
471 try name_stream.print(" align<{}>", alignment);431 try name_stream.print(" align({})", alignment);
472 }432 }
473 try name_stream.print(" {}", normal.return_type.name);433 try name_stream.print(" {}", normal.return_type.name);
474 },434 },
475 }435 }
476436
477 self.base.init(comp, Id.Fn, name_buf.toOwnedSlice());437 self.base.init(comp, .Fn, name_buf.toOwnedSlice());
478438
479 {439 {
480 const held = await (async comp.fn_type_table.acquire() catch unreachable);440 const held = comp.fn_type_table.acquire();
481 defer held.release();441 defer held.release();
482442
483 _ = try held.value.put(&self.key, self);443 _ = try held.value.put(&self.key, self);
...@@ -488,8 +448,8 @@ pub const Type = struct {...@@ -488,8 +448,8 @@ pub const Type = struct {
488 pub fn destroy(self: *Fn, comp: *Compilation) void {448 pub fn destroy(self: *Fn, comp: *Compilation) void {
489 self.key.deref(comp);449 self.key.deref(comp);
490 switch (self.key.data) {450 switch (self.key.data) {
491 Kind.Generic => {},451 .Generic => {},
492 Kind.Normal => {452 .Normal => {
493 self.non_key.Normal.variable_list.deinit();453 self.non_key.Normal.variable_list.deinit();
494 },454 },
495 }455 }
...@@ -499,7 +459,7 @@ pub const Type = struct {...@@ -499,7 +459,7 @@ pub const Type = struct {
499 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {459 pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
500 const normal = &self.key.data.Normal;460 const normal = &self.key.data.Normal;
501 const llvm_return_type = switch (normal.return_type.id) {461 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,
503 else => try normal.return_type.getLlvmType(allocator, llvm_context),463 else => try normal.return_type.getLlvmType(allocator, llvm_context),
504 };464 };
505 const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);465 const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
...@@ -606,7 +566,7 @@ pub const Type = struct {...@@ -606,7 +566,7 @@ pub const Type = struct {
606566
607 pub async fn get(comp: *Compilation, key: Key) !*Int {567 pub async fn get(comp: *Compilation, key: Key) !*Int {
608 {568 {
609 const held = await (async comp.int_type_table.acquire() catch unreachable);569 const held = comp.int_type_table.acquire();
610 defer held.release();570 defer held.release();
611571
612 if (held.value.get(&key)) |entry| {572 if (held.value.get(&key)) |entry| {
...@@ -627,10 +587,10 @@ pub const Type = struct {...@@ -627,10 +587,10 @@ pub const Type = struct {
627 const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count);587 const name = try std.fmt.allocPrint(comp.gpa(), "{c}{}", u_or_i, key.bit_count);
628 errdefer comp.gpa().free(name);588 errdefer comp.gpa().free(name);
629589
630 self.base.init(comp, Id.Int, name);590 self.base.init(comp, .Int, name);
631591
632 {592 {
633 const held = await (async comp.int_type_table.acquire() catch unreachable);593 const held = comp.int_type_table.acquire();
634 defer held.release();594 defer held.release();
635595
636 _ = try held.value.put(&self.key, self);596 _ = try held.value.put(&self.key, self);
...@@ -648,7 +608,7 @@ pub const Type = struct {...@@ -648,7 +608,7 @@ pub const Type = struct {
648608
649 pub async fn gcDestroy(self: *Int, comp: *Compilation) void {609 pub async fn gcDestroy(self: *Int, comp: *Compilation) void {
650 {610 {
651 const held = await (async comp.int_type_table.acquire() catch unreachable);611 const held = comp.int_type_table.acquire();
652 defer held.release();612 defer held.release();
653613
654 _ = held.value.remove(&self.key).?;614 _ = held.value.remove(&self.key).?;
...@@ -689,8 +649,8 @@ pub const Type = struct {...@@ -689,8 +649,8 @@ pub const Type = struct {
689 pub fn hash(self: *const Key) u32 {649 pub fn hash(self: *const Key) u32 {
690 var result: u32 = 0;650 var result: u32 = 0;
691 result +%= switch (self.alignment) {651 result +%= switch (self.alignment) {
692 Align.Abi => 0xf201c090,652 .Abi => 0xf201c090,
693 Align.Override => |x| hashAny(x, 0),653 .Override => |x| hashAny(x, 0),
694 };654 };
695 result +%= hashAny(self.child_type, 1);655 result +%= hashAny(self.child_type, 1);
696 result +%= hashAny(self.mut, 2);656 result +%= hashAny(self.mut, 2);
...@@ -704,13 +664,13 @@ pub const Type = struct {...@@ -704,13 +664,13 @@ pub const Type = struct {
704 self.mut != other.mut or664 self.mut != other.mut or
705 self.vol != other.vol or665 self.vol != other.vol or
706 self.size != other.size or666 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))
708 {668 {
709 return false;669 return false;
710 }670 }
711 switch (self.alignment) {671 switch (self.alignment) {
712 Align.Abi => return true,672 .Abi => return true,
713 Align.Override => |x| return x == other.alignment.Override,673 .Override => |x| return x == other.alignment.Override,
714 }674 }
715 }675 }
716 };676 };
...@@ -742,7 +702,7 @@ pub const Type = struct {...@@ -742,7 +702,7 @@ pub const Type = struct {
742702
743 pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {703 pub async fn gcDestroy(self: *Pointer, comp: *Compilation) void {
744 {704 {
745 const held = await (async comp.ptr_type_table.acquire() catch unreachable);705 const held = comp.ptr_type_table.acquire();
746 defer held.release();706 defer held.release();
747707
748 _ = held.value.remove(&self.key).?;708 _ = held.value.remove(&self.key).?;
...@@ -753,8 +713,8 @@ pub const Type = struct {...@@ -753,8 +713,8 @@ pub const Type = struct {
753713
754 pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {714 pub async fn getAlignAsInt(self: *Pointer, comp: *Compilation) u32 {
755 switch (self.key.alignment) {715 switch (self.key.alignment) {
756 Align.Abi => return await (async self.key.child_type.getAbiAlignment(comp) catch unreachable),716 .Abi => return self.key.child_type.getAbiAlignment(comp),
757 Align.Override => |alignment| return alignment,717 .Override => |alignment| return alignment,
758 }718 }
759 }719 }
760720
...@@ -764,16 +724,16 @@ pub const Type = struct {...@@ -764,16 +724,16 @@ pub const Type = struct {
764 ) !*Pointer {724 ) !*Pointer {
765 var normal_key = key;725 var normal_key = key;
766 switch (key.alignment) {726 switch (key.alignment) {
767 Align.Abi => {},727 .Abi => {},
768 Align.Override => |alignment| {728 .Override => |alignment| {
769 const abi_align = try await (async key.child_type.getAbiAlignment(comp) catch unreachable);729 const abi_align = try key.child_type.getAbiAlignment(comp);
770 if (abi_align == alignment) {730 if (abi_align == alignment) {
771 normal_key.alignment = Align.Abi;731 normal_key.alignment = .Abi;
772 }732 }
773 },733 },
774 }734 }
775 {735 {
776 const held = await (async comp.ptr_type_table.acquire() catch unreachable);736 const held = comp.ptr_type_table.acquire();
777 defer held.release();737 defer held.release();
778738
779 if (held.value.get(&normal_key)) |entry| {739 if (held.value.get(&normal_key)) |entry| {
...@@ -791,21 +751,21 @@ pub const Type = struct {...@@ -791,21 +751,21 @@ pub const Type = struct {
791 errdefer comp.gpa().destroy(self);751 errdefer comp.gpa().destroy(self);
792752
793 const size_str = switch (self.key.size) {753 const size_str = switch (self.key.size) {
794 Size.One => "*",754 .One => "*",
795 Size.Many => "[*]",755 .Many => "[*]",
796 Size.Slice => "[]",756 .Slice => "[]",
797 Size.C => "[*c]",757 .C => "[*c]",
798 };758 };
799 const mut_str = switch (self.key.mut) {759 const mut_str = switch (self.key.mut) {
800 Mut.Const => "const ",760 .Const => "const ",
801 Mut.Mut => "",761 .Mut => "",
802 };762 };
803 const vol_str = switch (self.key.vol) {763 const vol_str = switch (self.key.vol) {
804 Vol.Volatile => "volatile ",764 .Volatile => "volatile ",
805 Vol.Non => "",765 .Non => "",
806 };766 };
807 const name = switch (self.key.alignment) {767 const name = switch (self.key.alignment) {
808 Align.Abi => try std.fmt.allocPrint(768 .Abi => try std.fmt.allocPrint(
809 comp.gpa(),769 comp.gpa(),
810 "{}{}{}{}",770 "{}{}{}{}",
811 size_str,771 size_str,
...@@ -813,7 +773,7 @@ pub const Type = struct {...@@ -813,7 +773,7 @@ pub const Type = struct {
813 vol_str,773 vol_str,
814 self.key.child_type.name,774 self.key.child_type.name,
815 ),775 ),
816 Align.Override => |alignment| try std.fmt.allocPrint(776 .Override => |alignment| try std.fmt.allocPrint(
817 comp.gpa(),777 comp.gpa(),
818 "{}align<{}> {}{}{}",778 "{}align<{}> {}{}{}",
819 size_str,779 size_str,
...@@ -825,10 +785,10 @@ pub const Type = struct {...@@ -825,10 +785,10 @@ pub const Type = struct {
825 };785 };
826 errdefer comp.gpa().free(name);786 errdefer comp.gpa().free(name);
827787
828 self.base.init(comp, Id.Pointer, name);788 self.base.init(comp, .Pointer, name);
829789
830 {790 {
831 const held = await (async comp.ptr_type_table.acquire() catch unreachable);791 const held = comp.ptr_type_table.acquire();
832 defer held.release();792 defer held.release();
833793
834 _ = try held.value.put(&self.key, self);794 _ = try held.value.put(&self.key, self);
...@@ -873,7 +833,7 @@ pub const Type = struct {...@@ -873,7 +833,7 @@ pub const Type = struct {
873 errdefer key.elem_type.base.deref(comp);833 errdefer key.elem_type.base.deref(comp);
874834
875 {835 {
876 const held = await (async comp.array_type_table.acquire() catch unreachable);836 const held = comp.array_type_table.acquire();
877 defer held.release();837 defer held.release();
878838
879 if (held.value.get(&key)) |entry| {839 if (held.value.get(&key)) |entry| {
...@@ -893,10 +853,10 @@ pub const Type = struct {...@@ -893,10 +853,10 @@ pub const Type = struct {
893 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);853 const name = try std.fmt.allocPrint(comp.gpa(), "[{}]{}", key.len, key.elem_type.name);
894 errdefer comp.gpa().free(name);854 errdefer comp.gpa().free(name);
895855
896 self.base.init(comp, Id.Array, name);856 self.base.init(comp, .Array, name);
897857
898 {858 {
899 const held = await (async comp.array_type_table.acquire() catch unreachable);859 const held = comp.array_type_table.acquire();
900 defer held.release();860 defer held.release();
901861
902 _ = try held.value.put(&self.key, self);862 _ = try held.value.put(&self.key, self);
...@@ -1066,14 +1026,26 @@ pub const Type = struct {...@@ -1066,14 +1026,26 @@ pub const Type = struct {
1066 }1026 }
1067 };1027 };
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 {
1070 base: Type,1042 base: Type,
10711043
1072 pub fn destroy(self: *Promise, comp: *Compilation) void {1044 pub fn destroy(self: *AnyFrame, comp: *Compilation) void {
1073 comp.gpa().destroy(self);1045 comp.gpa().destroy(self);
1074 }1046 }
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 {
1077 @panic("TODO");1049 @panic("TODO");
1078 }1050 }
1079 };1051 };
...@@ -1081,34 +1053,34 @@ pub const Type = struct {...@@ -1081,34 +1053,34 @@ pub const Type = struct {
10811053
1082fn hashAny(x: var, comptime seed: u64) u32 {1054fn hashAny(x: var, comptime seed: u64) u32 {
1083 switch (@typeInfo(@typeOf(x))) {1055 switch (@typeInfo(@typeOf(x))) {
1084 builtin.TypeId.Int => |info| {1056 .Int => |info| {
1085 comptime var rng = comptime std.rand.DefaultPrng.init(seed);1057 comptime var rng = comptime std.rand.DefaultPrng.init(seed);
1086 const unsigned_x = @bitCast(@IntType(false, info.bits), x);1058 const unsigned_x = @bitCast(@IntType(false, info.bits), x);
1087 if (info.bits <= 32) {1059 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);
1089 } else {1061 } else {
1090 return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x)));1062 return @truncate(u32, unsigned_x *% comptime rng.random.scalar(@typeOf(unsigned_x)));
1091 }1063 }
1092 },1064 },
1093 builtin.TypeId.Pointer => |info| {1065 .Pointer => |info| {
1094 switch (info.size) {1066 switch (info.size) {
1095 builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),1067 .One => return hashAny(@ptrToInt(x), seed),
1096 builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),1068 .Many => @compileError("implement hash function"),
1097 builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),1069 .Slice => @compileError("implement hash function"),
1098 builtin.TypeInfo.Pointer.Size.C => unreachable,1070 .C => unreachable,
1099 }1071 }
1100 },1072 },
1101 builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),1073 .Enum => return hashAny(@enumToInt(x), seed),
1102 builtin.TypeId.Bool => {1074 .Bool => {
1103 comptime var rng = comptime std.rand.DefaultPrng.init(seed);1075 comptime var rng = comptime std.rand.DefaultPrng.init(seed);
1104 const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) };1076 const vals = comptime [2]u32{ rng.random.scalar(u32), rng.random.scalar(u32) };
1105 return vals[@boolToInt(x)];1077 return vals[@boolToInt(x)];
1106 },1078 },
1107 builtin.TypeId.Optional => {1079 .Optional => {
1108 if (x) |non_opt| {1080 if (x) |non_opt| {
1109 return hashAny(non_opt, seed);1081 return hashAny(non_opt, seed);
1110 } else {1082 } else {
1111 return hashAny(u32(1), seed);1083 return hashAny(@as(u32, 1), seed);
1112 }1084 }
1113 },1085 },
1114 else => @compileError("implement hash function for " ++ @typeName(@typeOf(x))),1086 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 @@...@@ -1,5 +1,4 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
3const Scope = @import("scope.zig").Scope;2const Scope = @import("scope.zig").Scope;
4const Compilation = @import("compilation.zig").Compilation;3const Compilation = @import("compilation.zig").Compilation;
5const ObjectFile = @import("codegen.zig").ObjectFile;4const ObjectFile = @import("codegen.zig").ObjectFile;
...@@ -24,15 +23,15 @@ pub const Value = struct {...@@ -24,15 +23,15 @@ pub const Value = struct {
24 if (base.ref_count.decr() == 1) {23 if (base.ref_count.decr() == 1) {
25 base.typ.base.deref(comp);24 base.typ.base.deref(comp);
26 switch (base.id) {25 switch (base.id) {
27 Id.Type => @fieldParentPtr(Type, "base", base).destroy(comp),26 .Type => @fieldParentPtr(Type, "base", base).destroy(comp),
28 Id.Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),27 .Fn => @fieldParentPtr(Fn, "base", base).destroy(comp),
29 Id.FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp),28 .FnProto => @fieldParentPtr(FnProto, "base", base).destroy(comp),
30 Id.Void => @fieldParentPtr(Void, "base", base).destroy(comp),29 .Void => @fieldParentPtr(Void, "base", base).destroy(comp),
31 Id.Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),30 .Bool => @fieldParentPtr(Bool, "base", base).destroy(comp),
32 Id.NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),31 .NoReturn => @fieldParentPtr(NoReturn, "base", base).destroy(comp),
33 Id.Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),32 .Ptr => @fieldParentPtr(Ptr, "base", base).destroy(comp),
34 Id.Int => @fieldParentPtr(Int, "base", base).destroy(comp),33 .Int => @fieldParentPtr(Int, "base", base).destroy(comp),
35 Id.Array => @fieldParentPtr(Array, "base", base).destroy(comp),34 .Array => @fieldParentPtr(Array, "base", base).destroy(comp),
36 }35 }
37 }36 }
38 }37 }
...@@ -59,15 +58,15 @@ pub const Value = struct {...@@ -59,15 +58,15 @@ pub const Value = struct {
5958
60 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {59 pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
61 switch (base.id) {60 switch (base.id) {
62 Id.Type => unreachable,61 .Type => unreachable,
63 Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),62 .Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
64 Id.FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile),63 .FnProto => return @fieldParentPtr(FnProto, "base", base).getLlvmConst(ofile),
65 Id.Void => return null,64 .Void => return null,
66 Id.Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),65 .Bool => return @fieldParentPtr(Bool, "base", base).getLlvmConst(ofile),
67 Id.NoReturn => unreachable,66 .NoReturn => unreachable,
68 Id.Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile),67 .Ptr => return @fieldParentPtr(Ptr, "base", base).getLlvmConst(ofile),
69 Id.Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),68 .Int => return @fieldParentPtr(Int, "base", base).getLlvmConst(ofile),
70 Id.Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile),69 .Array => return @fieldParentPtr(Array, "base", base).getLlvmConst(ofile),
71 }70 }
72 }71 }
7372
...@@ -83,15 +82,15 @@ pub const Value = struct {...@@ -83,15 +82,15 @@ pub const Value = struct {
8382
84 pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {83 pub fn copy(base: *Value, comp: *Compilation) (error{OutOfMemory}!*Value) {
85 switch (base.id) {84 switch (base.id) {
86 Id.Type => unreachable,85 .Type => unreachable,
87 Id.Fn => unreachable,86 .Fn => unreachable,
88 Id.FnProto => unreachable,87 .FnProto => unreachable,
89 Id.Void => unreachable,88 .Void => unreachable,
90 Id.Bool => unreachable,89 .Bool => unreachable,
91 Id.NoReturn => unreachable,90 .NoReturn => unreachable,
92 Id.Ptr => unreachable,91 .Ptr => unreachable,
93 Id.Array => unreachable,92 .Array => unreachable,
94 Id.Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,93 .Int => return &(try @fieldParentPtr(Int, "base", base).copy(comp)).base,
95 }94 }
96 }95 }
9796
...@@ -138,7 +137,7 @@ pub const Value = struct {...@@ -138,7 +137,7 @@ pub const Value = struct {
138 const self = try comp.gpa().create(FnProto);137 const self = try comp.gpa().create(FnProto);
139 self.* = FnProto{138 self.* = FnProto{
140 .base = Value{139 .base = Value{
141 .id = Value.Id.FnProto,140 .id = .FnProto,
142 .typ = &fn_type.base,141 .typ = &fn_type.base,
143 .ref_count = std.atomic.Int(usize).init(1),142 .ref_count = std.atomic.Int(usize).init(1),
144 },143 },
...@@ -202,7 +201,7 @@ pub const Value = struct {...@@ -202,7 +201,7 @@ pub const Value = struct {
202 const self = try comp.gpa().create(Fn);201 const self = try comp.gpa().create(Fn);
203 self.* = Fn{202 self.* = Fn{
204 .base = Value{203 .base = Value{
205 .id = Value.Id.Fn,204 .id = .Fn,
206 .typ = &fn_type.base,205 .typ = &fn_type.base,
207 .ref_count = std.atomic.Int(usize).init(1),206 .ref_count = std.atomic.Int(usize).init(1),
208 },207 },
...@@ -346,20 +345,20 @@ pub const Value = struct {...@@ -346,20 +345,20 @@ pub const Value = struct {
346 errdefer array_val.base.deref(comp);345 errdefer array_val.base.deref(comp);
347346
348 const elem_type = array_val.base.typ.cast(Type.Array).?.key.elem_type;347 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{
350 .child_type = elem_type,349 .child_type = elem_type,
351 .mut = mut,350 .mut = mut,
352 .vol = Type.Pointer.Vol.Non,351 .vol = Type.Pointer.Vol.Non,
353 .size = size,352 .size = size,
354 .alignment = Type.Pointer.Align.Abi,353 .alignment = Type.Pointer.Align.Abi,
355 }) catch unreachable);354 });
356 var ptr_type_consumed = false;355 var ptr_type_consumed = false;
357 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);356 errdefer if (!ptr_type_consumed) ptr_type.base.base.deref(comp);
358357
359 const self = try comp.gpa().create(Value.Ptr);358 const self = try comp.gpa().create(Value.Ptr);
360 self.* = Value.Ptr{359 self.* = Value.Ptr{
361 .base = Value{360 .base = Value{
362 .id = Value.Id.Ptr,361 .id = .Ptr,
363 .typ = &ptr_type.base,362 .typ = &ptr_type.base,
364 .ref_count = std.atomic.Int(usize).init(1),363 .ref_count = std.atomic.Int(usize).init(1),
365 },364 },
...@@ -385,8 +384,8 @@ pub const Value = struct {...@@ -385,8 +384,8 @@ pub const Value = struct {
385 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);384 const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
386 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr385 // TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
387 switch (self.special) {386 switch (self.special) {
388 Special.Scalar => |scalar| @panic("TODO"),387 .Scalar => |scalar| @panic("TODO"),
389 Special.BaseArray => |base_array| {388 .BaseArray => |base_array| {
390 // TODO put this in one .o file only, and after that, generate extern references to it389 // TODO put this in one .o file only, and after that, generate extern references to it
391 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;390 const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
392 const ptr_bit_count = ofile.comp.target_ptr_bits;391 const ptr_bit_count = ofile.comp.target_ptr_bits;
...@@ -401,9 +400,9 @@ pub const Value = struct {...@@ -401,9 +400,9 @@ pub const Value = struct {
401 @intCast(c_uint, indices.len),400 @intCast(c_uint, indices.len),
402 ) orelse return error.OutOfMemory;401 ) orelse return error.OutOfMemory;
403 },402 },
404 Special.BaseStruct => |base_struct| @panic("TODO"),403 .BaseStruct => |base_struct| @panic("TODO"),
405 Special.HardCodedAddr => |addr| @panic("TODO"),404 .HardCodedAddr => |addr| @panic("TODO"),
406 Special.Discard => unreachable,405 .Discard => unreachable,
407 }406 }
408 }407 }
409 };408 };
...@@ -428,16 +427,16 @@ pub const Value = struct {...@@ -428,16 +427,16 @@ pub const Value = struct {
428 const u8_type = Type.Int.get_u8(comp);427 const u8_type = Type.Int.get_u8(comp);
429 defer u8_type.base.base.deref(comp);428 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{
432 .elem_type = &u8_type.base,431 .elem_type = &u8_type.base,
433 .len = buffer.len,432 .len = buffer.len,
434 }) catch unreachable);433 });
435 errdefer array_type.base.base.deref(comp);434 errdefer array_type.base.base.deref(comp);
436435
437 const self = try comp.gpa().create(Value.Array);436 const self = try comp.gpa().create(Value.Array);
438 self.* = Value.Array{437 self.* = Value.Array{
439 .base = Value{438 .base = Value{
440 .id = Value.Id.Array,439 .id = .Array,
441 .typ = &array_type.base,440 .typ = &array_type.base,
442 .ref_count = std.atomic.Int(usize).init(1),441 .ref_count = std.atomic.Int(usize).init(1),
443 },442 },
...@@ -450,22 +449,22 @@ pub const Value = struct {...@@ -450,22 +449,22 @@ pub const Value = struct {
450449
451 pub fn destroy(self: *Array, comp: *Compilation) void {450 pub fn destroy(self: *Array, comp: *Compilation) void {
452 switch (self.special) {451 switch (self.special) {
453 Special.Undefined => {},452 .Undefined => {},
454 Special.OwnedBuffer => |buf| {453 .OwnedBuffer => |buf| {
455 comp.gpa().free(buf);454 comp.gpa().free(buf);
456 },455 },
457 Special.Explicit => {},456 .Explicit => {},
458 }457 }
459 comp.gpa().destroy(self);458 comp.gpa().destroy(self);
460 }459 }
461460
462 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {461 pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
463 switch (self.special) {462 switch (self.special) {
464 Special.Undefined => {463 .Undefined => {
465 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);464 const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
466 return llvm.GetUndef(llvm_type);465 return llvm.GetUndef(llvm_type);
467 },466 },
468 Special.OwnedBuffer => |buf| {467 .OwnedBuffer => |buf| {
469 const dont_null_terminate = 1;468 const dont_null_terminate = 1;
470 const llvm_str_init = llvm.ConstStringInContext(469 const llvm_str_init = llvm.ConstStringInContext(
471 ofile.context,470 ofile.context,
...@@ -482,7 +481,7 @@ pub const Value = struct {...@@ -482,7 +481,7 @@ pub const Value = struct {
482 llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type));481 llvm.SetAlignment(global, llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, str_init_type));
483 return global;482 return global;
484 },483 },
485 Special.Explicit => @panic("TODO"),484 .Explicit => @panic("TODO"),
486 }485 }
487486
488 //{487 //{
...@@ -517,7 +516,7 @@ pub const Value = struct {...@@ -517,7 +516,7 @@ pub const Value = struct {
517 const self = try comp.gpa().create(Value.Int);516 const self = try comp.gpa().create(Value.Int);
518 self.* = Value.Int{517 self.* = Value.Int{
519 .base = Value{518 .base = Value{
520 .id = Value.Id.Int,519 .id = .Int,
521 .typ = typ,520 .typ = typ,
522 .ref_count = std.atomic.Int(usize).init(1),521 .ref_count = std.atomic.Int(usize).init(1),
523 },522 },
...@@ -536,7 +535,7 @@ pub const Value = struct {...@@ -536,7 +535,7 @@ pub const Value = struct {
536535
537 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {536 pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
538 switch (self.base.typ.id) {537 switch (self.base.typ.id) {
539 Type.Id.Int => {538 .Int => {
540 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);539 const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
541 if (self.big_int.len() == 0) {540 if (self.big_int.len() == 0) {
542 return llvm.ConstNull(type_ref);541 return llvm.ConstNull(type_ref);
...@@ -554,7 +553,7 @@ pub const Value = struct {...@@ -554,7 +553,7 @@ pub const Value = struct {
554 };553 };
555 return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);554 return if (self.big_int.isPositive()) unsigned_val else llvm.ConstNeg(unsigned_val);
556 },555 },
557 Type.Id.ComptimeInt => unreachable,556 .ComptimeInt => unreachable,
558 else => unreachable,557 else => unreachable,
559 }558 }
560 }559 }
...@@ -566,7 +565,7 @@ pub const Value = struct {...@@ -566,7 +565,7 @@ pub const Value = struct {
566 const new = try comp.gpa().create(Value.Int);565 const new = try comp.gpa().create(Value.Int);
567 new.* = Value.Int{566 new.* = Value.Int{
568 .base = Value{567 .base = Value{
569 .id = Value.Id.Int,568 .id = .Int,
570 .typ = old.base.typ,569 .typ = old.base.typ,
571 .ref_count = std.atomic.Int(usize).init(1),570 .ref_count = std.atomic.Int(usize).init(1),
572 },571 },
src/zig_llvm.h+1-1
...@@ -465,7 +465,7 @@ ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char *...@@ -465,7 +465,7 @@ ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char *
465ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,465ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
466 enum ZigLLVM_OSType os_type);466 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,
469 const char *output_lib_path, const bool kill_at);469 const char *output_lib_path, const bool kill_at);
470470
471ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,471ZIG_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}