authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 20:28:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 20:28:52-04:00
log5aa3f56773f4b06629184a1e3753c3132b18e0bd
treea70155716f9d2d63f688dd1277505b084ca8fb34
parentfd7a97b3b2607c6de49e96ed32a7be0a037c67a8

self-hosted: fix test regressions

I'm allowing incremental compilation of ZIR modules to be broken. This is not a real use case of ZIR, and the feature requires a lot of code duplication with incremental compilation of Zig AST (which works great).

9 files changed, 221 insertions(+), 264 deletions(-)

src-self-hosted/Module.zig+24-15
......@@ -69,6 +69,8 @@ next_anon_name_index: usize = 0,
6969/// contains Decls that need to be deleted if they end up having no references to them.
7070deletion_set: std.ArrayListUnmanaged(*Decl) = .{},
7171
72keep_source_files_loaded: bool,
73
7274const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql);
7375
7476const WorkItem = union(enum) {
......@@ -580,11 +582,13 @@ pub const Scope = struct {
580582 .loaded_success => {
581583 self.contents.module.deinit(allocator);
582584 allocator.destroy(self.contents.module);
585 self.contents = .{ .not_available = {} };
583586 self.status = .unloaded_success;
584587 },
585588 .loaded_sema_failure => {
586589 self.contents.module.deinit(allocator);
587590 allocator.destroy(self.contents.module);
591 self.contents = .{ .not_available = {} };
588592 self.status = .unloaded_sema_failure;
589593 },
590594 }
......@@ -719,6 +723,7 @@ pub const InitOptions = struct {
719723 link_mode: ?std.builtin.LinkMode = null,
720724 object_format: ?std.builtin.ObjectFormat = null,
721725 optimize_mode: std.builtin.Mode = .Debug,
726 keep_source_files_loaded: bool = false,
722727};
723728
724729pub fn init(gpa: *Allocator, options: InitOptions) !Module {
......@@ -772,6 +777,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
772777 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),
773778 .failed_exports = std.AutoHashMap(*Export, *ErrorMsg).init(gpa),
774779 .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa),
780 .keep_source_files_loaded = options.keep_source_files_loaded,
775781 };
776782}
777783
......@@ -869,21 +875,22 @@ pub fn update(self: *Module) !void {
869875 try self.performAllTheWork();
870876
871877 // Process the deletion set.
872 for (self.deletion_set.items) |decl| {
878 while (self.deletion_set.popOrNull()) |decl| {
873879 if (decl.dependants.items.len != 0) {
874880 decl.deletion_flag = false;
875881 continue;
876882 }
877883 try self.deleteDecl(decl);
878884 }
879 self.deletion_set.shrink(self.allocator, 0);
880885
881886 self.link_error_flags = self.bin_file.error_flags;
882887
883888 // If there are any errors, we anticipate the source files being loaded
884889 // to report error messages. Otherwise we unload all source files to save memory.
885890 if (self.totalErrorCount() == 0) {
886 self.root_scope.unload(self.allocator);
891 if (!self.keep_source_files_loaded) {
892 self.root_scope.unload(self.allocator);
893 }
887894 try self.bin_file.flush();
888895 }
889896}
......@@ -1025,7 +1032,6 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
10251032 defer tracy.end();
10261033
10271034 const subsequent_analysis = switch (decl.analysis) {
1028 .complete => return,
10291035 .in_progress => unreachable,
10301036
10311037 .sema_failure,
......@@ -1035,7 +1041,11 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
10351041 .codegen_failure_retryable,
10361042 => return error.AnalysisFail,
10371043
1038 .outdated => blk: {
1044 .complete, .outdated => blk: {
1045 if (decl.generation == self.generation) {
1046 assert(decl.analysis == .complete);
1047 return;
1048 }
10391049 //std.debug.warn("re-analyzing {}\n", .{decl.name});
10401050
10411051 // The exports this Decl performs will be re-discovered, so we remove them here
......@@ -1044,10 +1054,9 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
10441054 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
10451055 for (decl.dependencies.items) |dep| {
10461056 dep.removeDependant(decl);
1047 if (dep.dependants.items.len == 0) {
1057 if (dep.dependants.items.len == 0 and !dep.deletion_flag) {
10481058 // We don't perform a deletion here, because this Decl or another one
10491059 // may end up referencing it before the update is complete.
1050 assert(!dep.deletion_flag);
10511060 dep.deletion_flag = true;
10521061 try self.deletion_set.append(self.allocator, dep);
10531062 }
......@@ -1773,6 +1782,9 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
17731782 }
17741783 }
17751784 }
1785 for (exports_to_resolve.items) |export_decl| {
1786 _ = try self.resolveZirDecl(&root_scope.base, export_decl);
1787 }
17761788 {
17771789 // Handle explicitly deleted decls from the source code. Not to be confused
17781790 // with when we delete decls because they are no longer referenced.
......@@ -1782,9 +1794,6 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
17821794 try self.deleteDecl(kv.key);
17831795 }
17841796 }
1785 for (exports_to_resolve.items) |export_decl| {
1786 _ = try self.resolveZirDecl(&root_scope.base, export_decl);
1787 }
17881797}
17891798
17901799fn deleteDecl(self: *Module, decl: *Decl) !void {
......@@ -1800,10 +1809,9 @@ fn deleteDecl(self: *Module, decl: *Decl) !void {
18001809 // Remove itself from its dependencies, because we are about to destroy the decl pointer.
18011810 for (decl.dependencies.items) |dep| {
18021811 dep.removeDependant(decl);
1803 if (dep.dependants.items.len == 0) {
1812 if (dep.dependants.items.len == 0 and !dep.deletion_flag) {
18041813 // We don't recursively perform a deletion here, because during the update,
18051814 // another reference to it may turn up.
1806 assert(!dep.deletion_flag);
18071815 dep.deletion_flag = true;
18081816 self.deletion_set.appendAssumeCapacity(dep);
18091817 }
......@@ -2026,9 +2034,10 @@ fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
20262034 };
20272035 const decl = try self.resolveCompleteZirDecl(scope, entry.decl);
20282036 const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);
2029 const result = try self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
2030 old_inst.analyzed_inst = result;
2031 return result;
2037 // Note: it would be tempting here to store the result into old_inst.analyzed_inst field,
2038 // but this would prevent the analyzeDeclRef from happening, which is needed to properly
2039 // detect Decl dependencies and dependency failures on updates.
2040 return self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
20322041}
20332042
20342043fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
src-self-hosted/link.zig+11-12
......@@ -369,7 +369,7 @@ pub const ElfFile = struct {
369369 const file_size = self.options.program_code_size_hint;
370370 const p_align = 0x1000;
371371 const off = self.findFreeSpace(file_size, p_align);
372 //std.debug.warn("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
372 //std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
373373 try self.program_headers.append(self.allocator, .{
374374 .p_type = elf.PT_LOAD,
375375 .p_offset = off,
......@@ -390,7 +390,7 @@ pub const ElfFile = struct {
390390 // page align.
391391 const p_align = 0x1000;
392392 const off = self.findFreeSpace(file_size, p_align);
393 //std.debug.warn("found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
393 //std.log.debug(.link, "found PT_LOAD free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
394394 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
395395 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something
396396 // else in virtual memory.
......@@ -412,7 +412,7 @@ pub const ElfFile = struct {
412412 assert(self.shstrtab.items.len == 0);
413413 try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0
414414 const off = self.findFreeSpace(self.shstrtab.items.len, 1);
415 //std.debug.warn("found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
415 //std.log.debug(.link, "found shstrtab free space 0x{x} to 0x{x}\n", .{ off, off + self.shstrtab.items.len });
416416 try self.sections.append(self.allocator, .{
417417 .sh_name = try self.makeString(".shstrtab"),
418418 .sh_type = elf.SHT_STRTAB,
......@@ -470,7 +470,7 @@ pub const ElfFile = struct {
470470 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
471471 const file_size = self.options.symbol_count_hint * each_size;
472472 const off = self.findFreeSpace(file_size, min_align);
473 //std.debug.warn("found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
473 //std.log.debug(.link, "found symtab free space 0x{x} to 0x{x}\n", .{ off, off + file_size });
474474
475475 try self.sections.append(self.allocator, .{
476476 .sh_name = try self.makeString(".symtab"),
......@@ -586,7 +586,7 @@ pub const ElfFile = struct {
586586 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
587587 }
588588 shstrtab_sect.sh_size = needed_size;
589 //std.debug.warn("shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
589 //std.log.debug(.link, "shstrtab start=0x{x} end=0x{x}\n", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
590590
591591 try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
592592 if (!self.shdr_table_dirty) {
......@@ -632,7 +632,7 @@ pub const ElfFile = struct {
632632
633633 for (buf) |*shdr, i| {
634634 shdr.* = self.sections.items[i];
635 //std.debug.warn("writing section {}\n", .{shdr.*});
635 //std.log.debug(.link, "writing section {}\n", .{shdr.*});
636636 if (foreign_endian) {
637637 bswapAllFields(elf.Elf64_Shdr, shdr);
638638 }
......@@ -956,10 +956,10 @@ pub const ElfFile = struct {
956956 try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);
957957
958958 if (self.local_symbol_free_list.popOrNull()) |i| {
959 //std.debug.warn("reusing symbol index {} for {}\n", .{i, decl.name});
959 //std.log.debug(.link, "reusing symbol index {} for {}\n", .{i, decl.name});
960960 decl.link.local_sym_index = i;
961961 } else {
962 //std.debug.warn("allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});
962 //std.log.debug(.link, "allocating symbol index {} for {}\n", .{self.local_symbols.items.len, decl.name});
963963 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);
964964 _ = self.local_symbols.addOneAssumeCapacity();
965965 }
......@@ -1027,11 +1027,11 @@ pub const ElfFile = struct {
10271027 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
10281028 if (need_realloc) {
10291029 const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);
1030 //std.debug.warn("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
1030 //std.log.debug(.link, "growing {} from 0x{x} to 0x{x}\n", .{ decl.name, local_sym.st_value, vaddr });
10311031 if (vaddr != local_sym.st_value) {
10321032 local_sym.st_value = vaddr;
10331033
1034 //std.debug.warn(" (writing new offset table entry)\n", .{});
1034 //std.log.debug(.link, " (writing new offset table entry)\n", .{});
10351035 self.offset_table.items[decl.link.offset_table_index] = vaddr;
10361036 try self.writeOffsetTableEntry(decl.link.offset_table_index);
10371037 }
......@@ -1049,7 +1049,7 @@ pub const ElfFile = struct {
10491049 const decl_name = mem.spanZ(decl.name);
10501050 const name_str_index = try self.makeString(decl_name);
10511051 const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);
1052 //std.debug.warn("allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
1052 //std.log.debug(.link, "allocated text block for {} at 0x{x}\n", .{ decl_name, vaddr });
10531053 errdefer self.freeTextBlock(&decl.link);
10541054
10551055 local_sym.* = .{
......@@ -1307,7 +1307,6 @@ pub const ElfFile = struct {
13071307 .p32 => @sizeOf(elf.Elf32_Sym),
13081308 .p64 => @sizeOf(elf.Elf64_Sym),
13091309 };
1310 //std.debug.warn("symtab start=0x{x} end=0x{x}\n", .{ syms_sect.sh_offset, syms_sect.sh_offset + needed_size });
13111310 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
13121311 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
13131312 switch (self.ptr_width) {
src-self-hosted/main.zig+25
......@@ -38,6 +38,30 @@ const usage =
3838 \\
3939;
4040
41pub fn log(
42 comptime level: std.log.Level,
43 comptime scope: @TypeOf(.EnumLiteral),
44 comptime format: []const u8,
45 args: var,
46) void {
47 if (@enumToInt(level) > @enumToInt(std.log.level))
48 return;
49
50 const scope_prefix = "(" ++ switch (scope) {
51 // Uncomment to hide logs
52 //.compiler,
53 .link,
54 => return,
55
56 else => @tagName(scope),
57 } ++ "): ";
58
59 const prefix = "[" ++ @tagName(level) ++ "] " ++ scope_prefix;
60
61 // Print the message to stderr, silently ignoring any errors
62 std.debug.print(prefix ++ format, args);
63}
64
4165pub fn main() !void {
4266 // TODO general purpose allocator in the zig std lib
4367 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else std.heap.page_allocator;
......@@ -450,6 +474,7 @@ fn buildOutputType(
450474 .link_mode = link_mode,
451475 .object_format = object_format,
452476 .optimize_mode = build_mode,
477 .keep_source_files_loaded = zir_out_path != null,
453478 });
454479 defer module.deinit();
455480
src-self-hosted/test.zig+22-13
......@@ -226,20 +226,36 @@ pub const TestContext = struct {
226226
227227 for (self.zir_cases.items) |case| {
228228 std.testing.base_allocator_instance.reset();
229
230 var prg_node = root_node.start(case.name, case.updates.items.len);
231 prg_node.activate();
232 defer prg_node.end();
233
234 // So that we can see which test case failed when the leak checker goes off.
235 progress.refresh();
236
229237 const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.target);
230 try self.runOneZIRCase(std.testing.allocator, root_node, case, info.target);
238 try self.runOneZIRCase(std.testing.allocator, &prg_node, case, info.target);
231239 try std.testing.allocator_instance.validate();
232240 }
233241
234242 // TODO: wipe the rest of this function
235243 for (self.zir_cmp_output_cases.items) |case| {
236244 std.testing.base_allocator_instance.reset();
237 try self.runOneZIRCmpOutputCase(std.testing.allocator, root_node, case, native_info.target);
245
246 var prg_node = root_node.start(case.name, case.src_list.len);
247 prg_node.activate();
248 defer prg_node.end();
249
250 // So that we can see which test case failed when the leak checker goes off.
251 progress.refresh();
252
253 try self.runOneZIRCmpOutputCase(std.testing.allocator, &prg_node, case, native_info.target);
238254 try std.testing.allocator_instance.validate();
239255 }
240256 }
241257
242 fn runOneZIRCase(self: *TestContext, allocator: *Allocator, root_node: *std.Progress.Node, case: ZIRCase, target: std.Target) !void {
258 fn runOneZIRCase(self: *TestContext, allocator: *Allocator, prg_node: *std.Progress.Node, case: ZIRCase, target: std.Target) !void {
243259 var tmp = std.testing.tmpDir(.{});
244260 defer tmp.cleanup();
245261
......@@ -247,10 +263,6 @@ pub const TestContext = struct {
247263 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
248264 defer root_pkg.destroy();
249265
250 var prg_node = root_node.start(case.name, case.updates.items.len);
251 prg_node.activate();
252 defer prg_node.end();
253
254266 var module = try Module.init(allocator, .{
255267 .target = target,
256268 // This is an Executable, as opposed to e.g. a *library*. This does
......@@ -265,6 +277,7 @@ pub const TestContext = struct {
265277 .bin_file_dir = tmp.dir,
266278 .bin_file_path = "test_case.o",
267279 .root_pkg = root_pkg,
280 .keep_source_files_loaded = true,
268281 });
269282 defer module.deinit();
270283
......@@ -329,7 +342,7 @@ pub const TestContext = struct {
329342 }
330343 },
331344
332 else => return error.unimplemented,
345 else => return error.Unimplemented,
333346 }
334347 }
335348 }
......@@ -337,7 +350,7 @@ pub const TestContext = struct {
337350 fn runOneZIRCmpOutputCase(
338351 self: *TestContext,
339352 allocator: *Allocator,
340 root_node: *std.Progress.Node,
353 prg_node: *std.Progress.Node,
341354 case: ZIRCompareOutputCase,
342355 target: std.Target,
343356 ) !void {
......@@ -348,10 +361,6 @@ pub const TestContext = struct {
348361 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
349362 defer root_pkg.destroy();
350363
351 var prg_node = root_node.start(case.name, case.src_list.len);
352 prg_node.activate();
353 defer prg_node.end();
354
355364 var module = try Module.init(allocator, .{
356365 .target = target,
357366 .output_mode = .Exe,
src-self-hosted/tracy.zig+1-1
......@@ -1,6 +1,6 @@
11pub const std = @import("std");
22
3pub const enable = @import("build_options").enable_tracy;
3pub const enable = if (std.builtin.is_test) false else @import("build_options").enable_tracy;
44
55extern fn ___tracy_emit_zone_begin_callstack(
66 srcloc: *const ___tracy_source_location_data,
src-self-hosted/type.zig+6
......@@ -113,6 +113,12 @@ pub const Type = extern union {
113113 .Undefined => return true,
114114 .Null => return true,
115115 .Pointer => {
116 // Hot path for common case:
117 if (a.cast(Payload.SingleConstPointer)) |a_payload| {
118 if (b.cast(Payload.SingleConstPointer)) |b_payload| {
119 return eql(a_payload.pointee_type, b_payload.pointee_type);
120 }
121 }
116122 const is_slice_a = isSlice(a);
117123 const is_slice_b = isSlice(b);
118124 if (is_slice_a != is_slice_b)
src-self-hosted/zir.zig+64-19
......@@ -710,8 +710,9 @@ pub const Module = struct {
710710 } else if (inst.cast(Inst.DeclValInModule)) |decl_val| {
711711 try stream.print("@{}", .{decl_val.positionals.decl.name});
712712 } else {
713 //try stream.print("?", .{});
714 unreachable;
713 // This should be unreachable in theory, but since ZIR is used for debugging the compiler
714 // we output some debug text instead.
715 try stream.print("?{}?", .{@tagName(inst.tag)});
715716 }
716717 }
717718};
......@@ -1175,6 +1176,39 @@ const EmitZIR = struct {
11751176
11761177 // Emit all the decls.
11771178 for (src_decls.items) |ir_decl| {
1179 switch (ir_decl.analysis) {
1180 .unreferenced => continue,
1181 .complete => {},
1182 .in_progress => unreachable,
1183 .outdated => unreachable,
1184
1185 .sema_failure,
1186 .sema_failure_retryable,
1187 .codegen_failure,
1188 .dependency_failure,
1189 .codegen_failure_retryable,
1190 => if (self.old_module.failed_decls.getValue(ir_decl)) |err_msg| {
1191 const fail_inst = try self.arena.allocator.create(Inst.CompileError);
1192 fail_inst.* = .{
1193 .base = .{
1194 .src = ir_decl.src(),
1195 .tag = Inst.CompileError.base_tag,
1196 },
1197 .positionals = .{
1198 .msg = try self.arena.allocator.dupe(u8, err_msg.msg),
1199 },
1200 .kw_args = .{},
1201 };
1202 const decl = try self.arena.allocator.create(Decl);
1203 decl.* = .{
1204 .name = mem.spanZ(ir_decl.name),
1205 .contents_hash = undefined,
1206 .inst = &fail_inst.base,
1207 };
1208 try self.decls.append(self.allocator, decl);
1209 continue;
1210 },
1211 }
11781212 if (self.old_module.export_owners.getValue(ir_decl)) |exports| {
11791213 for (exports) |module_export| {
11801214 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
......@@ -1199,20 +1233,27 @@ const EmitZIR = struct {
11991233 }
12001234 }
12011235
1202 fn resolveInst(self: *EmitZIR, inst_table: *std.AutoHashMap(*ir.Inst, *Inst), inst: *ir.Inst) !*Inst {
1236 const ZirBody = struct {
1237 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
1238 instructions: *std.ArrayList(*Inst),
1239 };
1240
1241 fn resolveInst(self: *EmitZIR, new_body: ZirBody, inst: *ir.Inst) !*Inst {
12031242 if (inst.cast(ir.Inst.Constant)) |const_inst| {
1204 const new_decl = if (const_inst.val.cast(Value.Payload.Function)) |func_pl| blk: {
1243 const new_inst = if (const_inst.val.cast(Value.Payload.Function)) |func_pl| blk: {
12051244 const owner_decl = func_pl.func.owner_decl;
12061245 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
12071246 } else if (const_inst.val.cast(Value.Payload.DeclRef)) |declref| blk: {
1208 break :blk try self.emitDeclRef(inst.src, declref.decl);
1247 const decl_ref = try self.emitDeclRef(inst.src, declref.decl);
1248 try new_body.instructions.append(decl_ref);
1249 break :blk decl_ref;
12091250 } else blk: {
12101251 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;
12111252 };
1212 try inst_table.putNoClobber(inst, new_decl);
1213 return new_decl;
1253 try new_body.inst_table.putNoClobber(inst, new_inst);
1254 return new_inst;
12141255 } else {
1215 return inst_table.getValue(inst).?;
1256 return new_body.inst_table.getValue(inst).?;
12161257 }
12171258 }
12181259
......@@ -1419,6 +1460,10 @@ const EmitZIR = struct {
14191460 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
14201461 instructions: *std.ArrayList(*Inst),
14211462 ) Allocator.Error!void {
1463 const new_body = ZirBody{
1464 .inst_table = inst_table,
1465 .instructions = instructions,
1466 };
14221467 for (body.instructions) |inst| {
14231468 const new_inst = switch (inst.tag) {
14241469 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),
......@@ -1428,7 +1473,7 @@ const EmitZIR = struct {
14281473
14291474 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);
14301475 for (args) |*elem, i| {
1431 elem.* = try self.resolveInst(inst_table, old_inst.args.args[i]);
1476 elem.* = try self.resolveInst(new_body, old_inst.args.args[i]);
14321477 }
14331478 new_inst.* = .{
14341479 .base = .{
......@@ -1436,7 +1481,7 @@ const EmitZIR = struct {
14361481 .tag = Inst.Call.base_tag,
14371482 },
14381483 .positionals = .{
1439 .func = try self.resolveInst(inst_table, old_inst.args.func),
1484 .func = try self.resolveInst(new_body, old_inst.args.func),
14401485 .args = args,
14411486 },
14421487 .kw_args = .{},
......@@ -1453,7 +1498,7 @@ const EmitZIR = struct {
14531498 .tag = Inst.Return.base_tag,
14541499 },
14551500 .positionals = .{
1456 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1501 .operand = try self.resolveInst(new_body, old_inst.args.operand),
14571502 },
14581503 .kw_args = .{},
14591504 };
......@@ -1477,7 +1522,7 @@ const EmitZIR = struct {
14771522
14781523 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);
14791524 for (args) |*elem, i| {
1480 elem.* = try self.resolveInst(inst_table, old_inst.args.args[i]);
1525 elem.* = try self.resolveInst(new_body, old_inst.args.args[i]);
14811526 }
14821527
14831528 new_inst.* = .{
......@@ -1511,7 +1556,7 @@ const EmitZIR = struct {
15111556 .tag = Inst.PtrToInt.base_tag,
15121557 },
15131558 .positionals = .{
1514 .ptr = try self.resolveInst(inst_table, old_inst.args.ptr),
1559 .ptr = try self.resolveInst(new_body, old_inst.args.ptr),
15151560 },
15161561 .kw_args = .{},
15171562 };
......@@ -1527,7 +1572,7 @@ const EmitZIR = struct {
15271572 },
15281573 .positionals = .{
15291574 .dest_type = (try self.emitType(inst.src, inst.ty)).inst,
1530 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1575 .operand = try self.resolveInst(new_body, old_inst.args.operand),
15311576 },
15321577 .kw_args = .{},
15331578 };
......@@ -1542,8 +1587,8 @@ const EmitZIR = struct {
15421587 .tag = Inst.Cmp.base_tag,
15431588 },
15441589 .positionals = .{
1545 .lhs = try self.resolveInst(inst_table, old_inst.args.lhs),
1546 .rhs = try self.resolveInst(inst_table, old_inst.args.rhs),
1590 .lhs = try self.resolveInst(new_body, old_inst.args.lhs),
1591 .rhs = try self.resolveInst(new_body, old_inst.args.rhs),
15471592 .op = old_inst.args.op,
15481593 },
15491594 .kw_args = .{},
......@@ -1569,7 +1614,7 @@ const EmitZIR = struct {
15691614 .tag = Inst.CondBr.base_tag,
15701615 },
15711616 .positionals = .{
1572 .condition = try self.resolveInst(inst_table, old_inst.args.condition),
1617 .condition = try self.resolveInst(new_body, old_inst.args.condition),
15731618 .true_body = .{ .instructions = true_body.toOwnedSlice() },
15741619 .false_body = .{ .instructions = false_body.toOwnedSlice() },
15751620 },
......@@ -1586,7 +1631,7 @@ const EmitZIR = struct {
15861631 .tag = Inst.IsNull.base_tag,
15871632 },
15881633 .positionals = .{
1589 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1634 .operand = try self.resolveInst(new_body, old_inst.args.operand),
15901635 },
15911636 .kw_args = .{},
15921637 };
......@@ -1601,7 +1646,7 @@ const EmitZIR = struct {
16011646 .tag = Inst.IsNonNull.base_tag,
16021647 },
16031648 .positionals = .{
1604 .operand = try self.resolveInst(inst_table, old_inst.args.operand),
1649 .operand = try self.resolveInst(new_body, old_inst.args.operand),
16051650 },
16061651 .kw_args = .{},
16071652 };
test/stage2/compile_errors.zig+3-5
......@@ -27,9 +27,8 @@ pub fn addCases(ctx: *TestContext) !void {
2727 \\ %0 = call(@notafunc, [])
2828 \\})
2929 \\@0 = str("_start")
30 \\@1 = ref(@0)
31 \\@2 = export(@1, @start)
32 , &[_][]const u8{":5:13: error: use of undeclared identifier 'notafunc'"});
30 \\@1 = export(@0, "start")
31 , &[_][]const u8{":5:13: error: decl 'notafunc' not found"});
3332
3433 // TODO: this error should occur at the call site, not the fntype decl
3534 ctx.addZIRError("call naked function", linux_x64,
......@@ -41,8 +40,7 @@ pub fn addCases(ctx: *TestContext) !void {
4140 \\ %0 = call(@s, [])
4241 \\})
4342 \\@0 = str("_start")
44 \\@1 = ref(@0)
45 \\@2 = export(@1, @start)
43 \\@1 = export(@0, "start")
4644 , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"});
4745
4846 // TODO: re-enable these tests.
test/stage2/zir.zig+65-199
......@@ -14,23 +14,21 @@ pub fn addCases(ctx: *TestContext) void {
1414 \\@fnty = fntype([], @void, cc=C)
1515 \\
1616 \\@9 = str("entry")
17 \\@10 = ref(@9)
18 \\@11 = export(@10, @entry)
17 \\@11 = export(@9, "entry")
1918 \\
2019 \\@entry = fn(@fnty, {
21 \\ %11 = return()
20 \\ %11 = returnvoid()
2221 \\})
2322 ,
2423 \\@void = primitive(void)
2524 \\@fnty = fntype([], @void, cc=C)
26 \\@9 = str("entry")
27 \\@10 = ref(@9)
28 \\@unnamed$6 = str("entry")
29 \\@unnamed$7 = ref(@unnamed$6)
30 \\@unnamed$8 = export(@unnamed$7, @entry)
31 \\@unnamed$10 = fntype([], @void, cc=C)
32 \\@entry = fn(@unnamed$10, {
33 \\ %0 = return()
25 \\@9 = declref("9$0")
26 \\@9$0 = str("entry")
27 \\@unnamed$4 = str("entry")
28 \\@unnamed$5 = export(@unnamed$4, "entry")
29 \\@unnamed$6 = fntype([], @void, cc=C)
30 \\@entry = fn(@unnamed$6, {
31 \\ %0 = returnvoid()
3432 \\})
3533 \\
3634 );
......@@ -45,11 +43,10 @@ pub fn addCases(ctx: *TestContext) void {
4543 \\
4644 \\@entry = fn(@fnty, {
4745 \\ %a = str("\x32\x08\x01\x0a")
48 \\ %aref = ref(%a)
49 \\ %eptr0 = elemptr(%aref, @0)
50 \\ %eptr1 = elemptr(%aref, @1)
51 \\ %eptr2 = elemptr(%aref, @2)
52 \\ %eptr3 = elemptr(%aref, @3)
46 \\ %eptr0 = elemptr(%a, @0)
47 \\ %eptr1 = elemptr(%a, @1)
48 \\ %eptr2 = elemptr(%a, @2)
49 \\ %eptr3 = elemptr(%a, @3)
5350 \\ %v0 = deref(%eptr0)
5451 \\ %v1 = deref(%eptr1)
5552 \\ %v2 = deref(%eptr2)
......@@ -61,15 +58,14 @@ pub fn addCases(ctx: *TestContext) void {
6158 \\ %expected = int(69)
6259 \\ %ok = cmp(%result, eq, %expected)
6360 \\ %10 = condbr(%ok, {
64 \\ %11 = return()
61 \\ %11 = returnvoid()
6562 \\ }, {
6663 \\ %12 = breakpoint()
6764 \\ })
6865 \\})
6966 \\
7067 \\@9 = str("entry")
71 \\@10 = ref(@9)
72 \\@11 = export(@10, @entry)
68 \\@11 = export(@9, "entry")
7369 ,
7470 \\@void = primitive(void)
7571 \\@fnty = fntype([], @void, cc=C)
......@@ -77,16 +73,15 @@ pub fn addCases(ctx: *TestContext) void {
7773 \\@1 = int(1)
7874 \\@2 = int(2)
7975 \\@3 = int(3)
80 \\@unnamed$7 = fntype([], @void, cc=C)
81 \\@entry = fn(@unnamed$7, {
82 \\ %0 = return()
76 \\@unnamed$6 = fntype([], @void, cc=C)
77 \\@entry = fn(@unnamed$6, {
78 \\ %0 = returnvoid()
8379 \\})
84 \\@a = str("2\x08\x01\n")
85 \\@9 = str("entry")
86 \\@10 = ref(@9)
87 \\@unnamed$14 = str("entry")
88 \\@unnamed$15 = ref(@unnamed$14)
89 \\@unnamed$16 = export(@unnamed$15, @entry)
80 \\@entry$1 = str("2\x08\x01\n")
81 \\@9 = declref("9$0")
82 \\@9$0 = str("entry")
83 \\@unnamed$11 = str("entry")
84 \\@unnamed$12 = export(@unnamed$11, "entry")
9085 \\
9186 );
9287
......@@ -97,45 +92,43 @@ pub fn addCases(ctx: *TestContext) void {
9792 \\@fnty = fntype([], @void, cc=C)
9893 \\
9994 \\@9 = str("entry")
100 \\@10 = ref(@9)
101 \\@11 = export(@10, @entry)
95 \\@11 = export(@9, "entry")
10296 \\
10397 \\@entry = fn(@fnty, {
10498 \\ %0 = call(@a, [])
105 \\ %1 = return()
99 \\ %1 = returnvoid()
106100 \\})
107101 \\
108102 \\@a = fn(@fnty, {
109103 \\ %0 = call(@b, [])
110 \\ %1 = return()
104 \\ %1 = returnvoid()
111105 \\})
112106 \\
113107 \\@b = fn(@fnty, {
114108 \\ %0 = call(@a, [])
115 \\ %1 = return()
109 \\ %1 = returnvoid()
116110 \\})
117111 ,
118112 \\@void = primitive(void)
119113 \\@fnty = fntype([], @void, cc=C)
120 \\@9 = str("entry")
121 \\@10 = ref(@9)
122 \\@unnamed$6 = str("entry")
123 \\@unnamed$7 = ref(@unnamed$6)
124 \\@unnamed$8 = export(@unnamed$7, @entry)
125 \\@unnamed$12 = fntype([], @void, cc=C)
126 \\@entry = fn(@unnamed$12, {
114 \\@9 = declref("9$0")
115 \\@9$0 = str("entry")
116 \\@unnamed$4 = str("entry")
117 \\@unnamed$5 = export(@unnamed$4, "entry")
118 \\@unnamed$6 = fntype([], @void, cc=C)
119 \\@entry = fn(@unnamed$6, {
127120 \\ %0 = call(@a, [], modifier=auto)
128 \\ %1 = return()
121 \\ %1 = returnvoid()
129122 \\})
130 \\@unnamed$17 = fntype([], @void, cc=C)
131 \\@a = fn(@unnamed$17, {
123 \\@unnamed$8 = fntype([], @void, cc=C)
124 \\@a = fn(@unnamed$8, {
132125 \\ %0 = call(@b, [], modifier=auto)
133 \\ %1 = return()
126 \\ %1 = returnvoid()
134127 \\})
135 \\@unnamed$22 = fntype([], @void, cc=C)
136 \\@b = fn(@unnamed$22, {
128 \\@unnamed$10 = fntype([], @void, cc=C)
129 \\@b = fn(@unnamed$10, {
137130 \\ %0 = call(@a, [], modifier=auto)
138 \\ %1 = return()
131 \\ %1 = returnvoid()
139132 \\})
140133 \\
141134 );
......@@ -145,27 +138,26 @@ pub fn addCases(ctx: *TestContext) void {
145138 \\@fnty = fntype([], @void, cc=C)
146139 \\
147140 \\@9 = str("entry")
148 \\@10 = ref(@9)
149 \\@11 = export(@10, @entry)
141 \\@11 = export(@9, "entry")
150142 \\
151143 \\@entry = fn(@fnty, {
152144 \\ %0 = call(@a, [])
153 \\ %1 = return()
145 \\ %1 = returnvoid()
154146 \\})
155147 \\
156148 \\@a = fn(@fnty, {
157149 \\ %0 = call(@b, [])
158 \\ %1 = return()
150 \\ %1 = returnvoid()
159151 \\})
160152 \\
161153 \\@b = fn(@fnty, {
162154 \\ %9 = compileerror("message")
163155 \\ %0 = call(@a, [])
164 \\ %1 = return()
156 \\ %1 = returnvoid()
165157 \\})
166158 ,
167159 &[_][]const u8{
168 ":19:21: error: message",
160 ":18:21: error: message",
169161 },
170162 );
171163 // Now we remove the call to `a`. `a` and `b` form a cycle, but no entry points are
......@@ -176,34 +168,32 @@ pub fn addCases(ctx: *TestContext) void {
176168 \\@fnty = fntype([], @void, cc=C)
177169 \\
178170 \\@9 = str("entry")
179 \\@10 = ref(@9)
180 \\@11 = export(@10, @entry)
171 \\@11 = export(@9, "entry")
181172 \\
182173 \\@entry = fn(@fnty, {
183 \\ %1 = return()
174 \\ %0 = returnvoid()
184175 \\})
185176 \\
186177 \\@a = fn(@fnty, {
187178 \\ %0 = call(@b, [])
188 \\ %1 = return()
179 \\ %1 = returnvoid()
189180 \\})
190181 \\
191182 \\@b = fn(@fnty, {
192183 \\ %9 = compileerror("message")
193184 \\ %0 = call(@a, [])
194 \\ %1 = return()
185 \\ %1 = returnvoid()
195186 \\})
196187 ,
197188 \\@void = primitive(void)
198189 \\@fnty = fntype([], @void, cc=C)
199 \\@9 = str("entry")
200 \\@10 = ref(@9)
201 \\@unnamed$6 = str("entry")
202 \\@unnamed$7 = ref(@unnamed$6)
203 \\@unnamed$8 = export(@unnamed$7, @entry)
204 \\@unnamed$10 = fntype([], @void, cc=C)
205 \\@entry = fn(@unnamed$10, {
206 \\ %0 = return()
190 \\@9 = declref("9$2")
191 \\@9$2 = str("entry")
192 \\@unnamed$4 = str("entry")
193 \\@unnamed$5 = export(@unnamed$4, "entry")
194 \\@unnamed$6 = fntype([], @void, cc=C)
195 \\@entry = fn(@unnamed$6, {
196 \\ %0 = returnvoid()
207197 \\})
208198 \\
209199 );
......@@ -218,7 +208,7 @@ pub fn addCases(ctx: *TestContext) void {
218208 }
219209
220210 ctx.addZIRCompareOutput(
221 "hello world ZIR, update msg",
211 "hello world ZIR",
222212 &[_][]const u8{
223213 \\@noreturn = primitive(noreturn)
224214 \\@void = primitive(void)
......@@ -272,125 +262,10 @@ pub fn addCases(ctx: *TestContext) void {
272262 \\
273263 \\@9 = str("_start")
274264 \\@11 = export(@9, "start")
275 ,
276 \\@noreturn = primitive(noreturn)
277 \\@void = primitive(void)
278 \\@usize = primitive(usize)
279 \\@0 = int(0)
280 \\@1 = int(1)
281 \\@2 = int(2)
282 \\@3 = int(3)
283 \\
284 \\@msg = str("Hello, world!\n")
285 \\@msg2 = str("HELL WORLD\n")
286 \\
287 \\@start_fnty = fntype([], @noreturn, cc=Naked)
288 \\@start = fn(@start_fnty, {
289 \\ %SYS_exit_group = int(231)
290 \\ %exit_code = as(@usize, @0)
291 \\
292 \\ %syscall = str("syscall")
293 \\ %sysoutreg = str("={rax}")
294 \\ %rax = str("{rax}")
295 \\ %rdi = str("{rdi}")
296 \\ %rcx = str("rcx")
297 \\ %rdx = str("{rdx}")
298 \\ %rsi = str("{rsi}")
299 \\ %r11 = str("r11")
300 \\ %memory = str("memory")
301 \\
302 \\ %SYS_write = as(@usize, @1)
303 \\ %STDOUT_FILENO = as(@usize, @1)
304 \\
305 \\ %msg_addr = ptrtoint(@msg2)
306 \\
307 \\ %len_name = str("len")
308 \\ %msg_len_ptr = fieldptr(@msg2, %len_name)
309 \\ %msg_len = deref(%msg_len_ptr)
310 \\ %rc_write = asm(%syscall, @usize,
311 \\ volatile=1,
312 \\ output=%sysoutreg,
313 \\ inputs=[%rax, %rdi, %rsi, %rdx],
314 \\ clobbers=[%rcx, %r11, %memory],
315 \\ args=[%SYS_write, %STDOUT_FILENO, %msg_addr, %msg_len])
316 \\
317 \\ %rc_exit = asm(%syscall, @usize,
318 \\ volatile=1,
319 \\ output=%sysoutreg,
320 \\ inputs=[%rax, %rdi],
321 \\ clobbers=[%rcx, %r11, %memory],
322 \\ args=[%SYS_exit_group, %exit_code])
323 \\
324 \\ %99 = unreachable()
325 \\});
326 \\
327 \\@9 = str("_start")
328 \\@11 = export(@9, "start")
329 ,
330 \\@noreturn = primitive(noreturn)
331 \\@void = primitive(void)
332 \\@usize = primitive(usize)
333 \\@0 = int(0)
334 \\@1 = int(1)
335 \\@2 = int(2)
336 \\@3 = int(3)
337 \\
338 \\@msg = str("Hello, world!\n")
339 \\@msg2 = str("Editing the same msg2 decl but this time with a much longer message which will\ncause the data to need to be relocated in virtual address space.\n")
340 \\
341 \\@start_fnty = fntype([], @noreturn, cc=Naked)
342 \\@start = fn(@start_fnty, {
343 \\ %SYS_exit_group = int(231)
344 \\ %exit_code = as(@usize, @0)
345 \\
346 \\ %syscall = str("syscall")
347 \\ %sysoutreg = str("={rax}")
348 \\ %rax = str("{rax}")
349 \\ %rdi = str("{rdi}")
350 \\ %rcx = str("rcx")
351 \\ %rdx = str("{rdx}")
352 \\ %rsi = str("{rsi}")
353 \\ %r11 = str("r11")
354 \\ %memory = str("memory")
355 \\
356 \\ %SYS_write = as(@usize, @1)
357 \\ %STDOUT_FILENO = as(@usize, @1)
358 \\
359 \\ %msg_addr = ptrtoint(@msg2)
360 \\
361 \\ %len_name = str("len")
362 \\ %msg_len_ptr = fieldptr(@msg2, %len_name)
363 \\ %msg_len = deref(%msg_len_ptr)
364 \\ %rc_write = asm(%syscall, @usize,
365 \\ volatile=1,
366 \\ output=%sysoutreg,
367 \\ inputs=[%rax, %rdi, %rsi, %rdx],
368 \\ clobbers=[%rcx, %r11, %memory],
369 \\ args=[%SYS_write, %STDOUT_FILENO, %msg_addr, %msg_len])
370 \\
371 \\ %rc_exit = asm(%syscall, @usize,
372 \\ volatile=1,
373 \\ output=%sysoutreg,
374 \\ inputs=[%rax, %rdi],
375 \\ clobbers=[%rcx, %r11, %memory],
376 \\ args=[%SYS_exit_group, %exit_code])
377 \\
378 \\ %99 = unreachable()
379 \\});
380 \\
381 \\@9 = str("_start")
382 \\@11 = export(@9, "start")
383265 },
384266 &[_][]const u8{
385267 \\Hello, world!
386268 \\
387 ,
388 \\HELL WORLD
389 \\
390 ,
391 \\Editing the same msg2 decl but this time with a much longer message which will
392 \\cause the data to need to be relocated in virtual address space.
393 \\
394269 },
395270 );
396271
......@@ -405,26 +280,18 @@ pub fn addCases(ctx: *TestContext) void {
405280 \\@2 = int(2)
406281 \\@3 = int(3)
407282 \\
408 \\@syscall_array = str("syscall")
409 \\@sysoutreg_array = str("={rax}")
410 \\@rax_array = str("{rax}")
411 \\@rdi_array = str("{rdi}")
412 \\@rcx_array = str("rcx")
413 \\@r11_array = str("r11")
414 \\@memory_array = str("memory")
415 \\
416283 \\@exit0_fnty = fntype([], @noreturn)
417284 \\@exit0 = fn(@exit0_fnty, {
418285 \\ %SYS_exit_group = int(231)
419286 \\ %exit_code = as(@usize, @0)
420287 \\
421 \\ %syscall = ref(@syscall_array)
422 \\ %sysoutreg = ref(@sysoutreg_array)
423 \\ %rax = ref(@rax_array)
424 \\ %rdi = ref(@rdi_array)
425 \\ %rcx = ref(@rcx_array)
426 \\ %r11 = ref(@r11_array)
427 \\ %memory = ref(@memory_array)
288 \\ %syscall = str("syscall")
289 \\ %sysoutreg = str("={rax}")
290 \\ %rax = str("{rax}")
291 \\ %rdi = str("{rdi}")
292 \\ %rcx = str("rcx")
293 \\ %r11 = str("r11")
294 \\ %memory = str("memory")
428295 \\
429296 \\ %rc = asm(%syscall, @usize,
430297 \\ volatile=1,
......@@ -441,8 +308,7 @@ pub fn addCases(ctx: *TestContext) void {
441308 \\ %0 = call(@exit0, [])
442309 \\})
443310 \\@9 = str("_start")
444 \\@10 = ref(@9)
445 \\@11 = export(@10, @start)
311 \\@11 = export(@9, "start")
446312 },
447313 &[_][]const u8{""},
448314 );