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,...@@ -69,6 +69,8 @@ next_anon_name_index: usize = 0,
69/// contains Decls that need to be deleted if they end up having no references to them.69/// contains Decls that need to be deleted if they end up having no references to them.
70deletion_set: std.ArrayListUnmanaged(*Decl) = .{},70deletion_set: std.ArrayListUnmanaged(*Decl) = .{},
7171
72keep_source_files_loaded: bool,
73
72const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql);74const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql);
7375
74const WorkItem = union(enum) {76const WorkItem = union(enum) {
...@@ -580,11 +582,13 @@ pub const Scope = struct {...@@ -580,11 +582,13 @@ pub const Scope = struct {
580 .loaded_success => {582 .loaded_success => {
581 self.contents.module.deinit(allocator);583 self.contents.module.deinit(allocator);
582 allocator.destroy(self.contents.module);584 allocator.destroy(self.contents.module);
585 self.contents = .{ .not_available = {} };
583 self.status = .unloaded_success;586 self.status = .unloaded_success;
584 },587 },
585 .loaded_sema_failure => {588 .loaded_sema_failure => {
586 self.contents.module.deinit(allocator);589 self.contents.module.deinit(allocator);
587 allocator.destroy(self.contents.module);590 allocator.destroy(self.contents.module);
591 self.contents = .{ .not_available = {} };
588 self.status = .unloaded_sema_failure;592 self.status = .unloaded_sema_failure;
589 },593 },
590 }594 }
...@@ -719,6 +723,7 @@ pub const InitOptions = struct {...@@ -719,6 +723,7 @@ pub const InitOptions = struct {
719 link_mode: ?std.builtin.LinkMode = null,723 link_mode: ?std.builtin.LinkMode = null,
720 object_format: ?std.builtin.ObjectFormat = null,724 object_format: ?std.builtin.ObjectFormat = null,
721 optimize_mode: std.builtin.Mode = .Debug,725 optimize_mode: std.builtin.Mode = .Debug,
726 keep_source_files_loaded: bool = false,
722};727};
723728
724pub fn init(gpa: *Allocator, options: InitOptions) !Module {729pub fn init(gpa: *Allocator, options: InitOptions) !Module {
...@@ -772,6 +777,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {...@@ -772,6 +777,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
772 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),777 .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa),
773 .failed_exports = std.AutoHashMap(*Export, *ErrorMsg).init(gpa),778 .failed_exports = std.AutoHashMap(*Export, *ErrorMsg).init(gpa),
774 .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa),779 .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa),
780 .keep_source_files_loaded = options.keep_source_files_loaded,
775 };781 };
776}782}
777783
...@@ -869,21 +875,22 @@ pub fn update(self: *Module) !void {...@@ -869,21 +875,22 @@ pub fn update(self: *Module) !void {
869 try self.performAllTheWork();875 try self.performAllTheWork();
870876
871 // Process the deletion set.877 // Process the deletion set.
872 for (self.deletion_set.items) |decl| {878 while (self.deletion_set.popOrNull()) |decl| {
873 if (decl.dependants.items.len != 0) {879 if (decl.dependants.items.len != 0) {
874 decl.deletion_flag = false;880 decl.deletion_flag = false;
875 continue;881 continue;
876 }882 }
877 try self.deleteDecl(decl);883 try self.deleteDecl(decl);
878 }884 }
879 self.deletion_set.shrink(self.allocator, 0);
880885
881 self.link_error_flags = self.bin_file.error_flags;886 self.link_error_flags = self.bin_file.error_flags;
882887
883 // If there are any errors, we anticipate the source files being loaded888 // If there are any errors, we anticipate the source files being loaded
884 // to report error messages. Otherwise we unload all source files to save memory.889 // to report error messages. Otherwise we unload all source files to save memory.
885 if (self.totalErrorCount() == 0) {890 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 }
887 try self.bin_file.flush();894 try self.bin_file.flush();
888 }895 }
889}896}
...@@ -1025,7 +1032,6 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {...@@ -1025,7 +1032,6 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1025 defer tracy.end();1032 defer tracy.end();
10261033
1027 const subsequent_analysis = switch (decl.analysis) {1034 const subsequent_analysis = switch (decl.analysis) {
1028 .complete => return,
1029 .in_progress => unreachable,1035 .in_progress => unreachable,
10301036
1031 .sema_failure,1037 .sema_failure,
...@@ -1035,7 +1041,11 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {...@@ -1035,7 +1041,11 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1035 .codegen_failure_retryable,1041 .codegen_failure_retryable,
1036 => return error.AnalysisFail,1042 => 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 }
1039 //std.debug.warn("re-analyzing {}\n", .{decl.name});1049 //std.debug.warn("re-analyzing {}\n", .{decl.name});
10401050
1041 // The exports this Decl performs will be re-discovered, so we remove them here1051 // 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 {...@@ -1044,10 +1054,9 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void {
1044 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.1054 // Dependencies will be re-discovered, so we remove them here prior to re-analysis.
1045 for (decl.dependencies.items) |dep| {1055 for (decl.dependencies.items) |dep| {
1046 dep.removeDependant(decl);1056 dep.removeDependant(decl);
1047 if (dep.dependants.items.len == 0) {1057 if (dep.dependants.items.len == 0 and !dep.deletion_flag) {
1048 // We don't perform a deletion here, because this Decl or another one1058 // We don't perform a deletion here, because this Decl or another one
1049 // may end up referencing it before the update is complete.1059 // may end up referencing it before the update is complete.
1050 assert(!dep.deletion_flag);
1051 dep.deletion_flag = true;1060 dep.deletion_flag = true;
1052 try self.deletion_set.append(self.allocator, dep);1061 try self.deletion_set.append(self.allocator, dep);
1053 }1062 }
...@@ -1773,6 +1782,9 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {...@@ -1773,6 +1782,9 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
1773 }1782 }
1774 }1783 }
1775 }1784 }
1785 for (exports_to_resolve.items) |export_decl| {
1786 _ = try self.resolveZirDecl(&root_scope.base, export_decl);
1787 }
1776 {1788 {
1777 // Handle explicitly deleted decls from the source code. Not to be confused1789 // Handle explicitly deleted decls from the source code. Not to be confused
1778 // with when we delete decls because they are no longer referenced.1790 // with when we delete decls because they are no longer referenced.
...@@ -1782,9 +1794,6 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {...@@ -1782,9 +1794,6 @@ fn analyzeRootZIRModule(self: *Module, root_scope: *Scope.ZIRModule) !void {
1782 try self.deleteDecl(kv.key);1794 try self.deleteDecl(kv.key);
1783 }1795 }
1784 }1796 }
1785 for (exports_to_resolve.items) |export_decl| {
1786 _ = try self.resolveZirDecl(&root_scope.base, export_decl);
1787 }
1788}1797}
17891798
1790fn deleteDecl(self: *Module, decl: *Decl) !void {1799fn deleteDecl(self: *Module, decl: *Decl) !void {
...@@ -1800,10 +1809,9 @@ fn deleteDecl(self: *Module, decl: *Decl) !void {...@@ -1800,10 +1809,9 @@ fn deleteDecl(self: *Module, decl: *Decl) !void {
1800 // Remove itself from its dependencies, because we are about to destroy the decl pointer.1809 // Remove itself from its dependencies, because we are about to destroy the decl pointer.
1801 for (decl.dependencies.items) |dep| {1810 for (decl.dependencies.items) |dep| {
1802 dep.removeDependant(decl);1811 dep.removeDependant(decl);
1803 if (dep.dependants.items.len == 0) {1812 if (dep.dependants.items.len == 0 and !dep.deletion_flag) {
1804 // We don't recursively perform a deletion here, because during the update,1813 // We don't recursively perform a deletion here, because during the update,
1805 // another reference to it may turn up.1814 // another reference to it may turn up.
1806 assert(!dep.deletion_flag);
1807 dep.deletion_flag = true;1815 dep.deletion_flag = true;
1808 self.deletion_set.appendAssumeCapacity(dep);1816 self.deletion_set.appendAssumeCapacity(dep);
1809 }1817 }
...@@ -2026,9 +2034,10 @@ fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In...@@ -2026,9 +2034,10 @@ fn resolveInst(self: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!*In
2026 };2034 };
2027 const decl = try self.resolveCompleteZirDecl(scope, entry.decl);2035 const decl = try self.resolveCompleteZirDecl(scope, entry.decl);
2028 const decl_ref = try self.analyzeDeclRef(scope, old_inst.src, decl);2036 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);2037 // Note: it would be tempting here to store the result into old_inst.analyzed_inst field,
2030 old_inst.analyzed_inst = result;2038 // but this would prevent the analyzeDeclRef from happening, which is needed to properly
2031 return result;2039 // detect Decl dependencies and dependency failures on updates.
2040 return self.analyzeDeref(scope, old_inst.src, decl_ref, old_inst.src);
2032}2041}
20332042
2034fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {2043fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block {
src-self-hosted/link.zig+11-12
...@@ -369,7 +369,7 @@ pub const ElfFile = struct {...@@ -369,7 +369,7 @@ pub const ElfFile = struct {
369 const file_size = self.options.program_code_size_hint;369 const file_size = self.options.program_code_size_hint;
370 const p_align = 0x1000;370 const p_align = 0x1000;
371 const off = self.findFreeSpace(file_size, p_align);371 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 });
373 try self.program_headers.append(self.allocator, .{373 try self.program_headers.append(self.allocator, .{
374 .p_type = elf.PT_LOAD,374 .p_type = elf.PT_LOAD,
375 .p_offset = off,375 .p_offset = off,
...@@ -390,7 +390,7 @@ pub const ElfFile = struct {...@@ -390,7 +390,7 @@ pub const ElfFile = struct {
390 // page align.390 // page align.
391 const p_align = 0x1000;391 const p_align = 0x1000;
392 const off = self.findFreeSpace(file_size, p_align);392 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 });
394 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.394 // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at.
395 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something395 // we'll need to re-use that function anyway, in case the GOT grows and overlaps something
396 // else in virtual memory.396 // else in virtual memory.
...@@ -412,7 +412,7 @@ pub const ElfFile = struct {...@@ -412,7 +412,7 @@ pub const ElfFile = struct {
412 assert(self.shstrtab.items.len == 0);412 assert(self.shstrtab.items.len == 0);
413 try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0413 try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0
414 const off = self.findFreeSpace(self.shstrtab.items.len, 1);414 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 });
416 try self.sections.append(self.allocator, .{416 try self.sections.append(self.allocator, .{
417 .sh_name = try self.makeString(".shstrtab"),417 .sh_name = try self.makeString(".shstrtab"),
418 .sh_type = elf.SHT_STRTAB,418 .sh_type = elf.SHT_STRTAB,
...@@ -470,7 +470,7 @@ pub const ElfFile = struct {...@@ -470,7 +470,7 @@ pub const ElfFile = struct {
470 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);470 const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym);
471 const file_size = self.options.symbol_count_hint * each_size;471 const file_size = self.options.symbol_count_hint * each_size;
472 const off = self.findFreeSpace(file_size, min_align);472 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
475 try self.sections.append(self.allocator, .{475 try self.sections.append(self.allocator, .{
476 .sh_name = try self.makeString(".symtab"),476 .sh_name = try self.makeString(".symtab"),
...@@ -586,7 +586,7 @@ pub const ElfFile = struct {...@@ -586,7 +586,7 @@ pub const ElfFile = struct {
586 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);586 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
587 }587 }
588 shstrtab_sect.sh_size = needed_size;588 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
591 try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);591 try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
592 if (!self.shdr_table_dirty) {592 if (!self.shdr_table_dirty) {
...@@ -632,7 +632,7 @@ pub const ElfFile = struct {...@@ -632,7 +632,7 @@ pub const ElfFile = struct {
632632
633 for (buf) |*shdr, i| {633 for (buf) |*shdr, i| {
634 shdr.* = self.sections.items[i];634 shdr.* = self.sections.items[i];
635 //std.debug.warn("writing section {}\n", .{shdr.*});635 //std.log.debug(.link, "writing section {}\n", .{shdr.*});
636 if (foreign_endian) {636 if (foreign_endian) {
637 bswapAllFields(elf.Elf64_Shdr, shdr);637 bswapAllFields(elf.Elf64_Shdr, shdr);
638 }638 }
...@@ -956,10 +956,10 @@ pub const ElfFile = struct {...@@ -956,10 +956,10 @@ pub const ElfFile = struct {
956 try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);956 try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len);
957957
958 if (self.local_symbol_free_list.popOrNull()) |i| {958 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});
960 decl.link.local_sym_index = i;960 decl.link.local_sym_index = i;
961 } else {961 } 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});
963 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);963 decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len);
964 _ = self.local_symbols.addOneAssumeCapacity();964 _ = self.local_symbols.addOneAssumeCapacity();
965 }965 }
...@@ -1027,11 +1027,11 @@ pub const ElfFile = struct {...@@ -1027,11 +1027,11 @@ pub const ElfFile = struct {
1027 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);1027 !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment);
1028 if (need_realloc) {1028 if (need_realloc) {
1029 const vaddr = try self.growTextBlock(&decl.link, code.len, required_alignment);1029 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 });
1031 if (vaddr != local_sym.st_value) {1031 if (vaddr != local_sym.st_value) {
1032 local_sym.st_value = vaddr;1032 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", .{});
1035 self.offset_table.items[decl.link.offset_table_index] = vaddr;1035 self.offset_table.items[decl.link.offset_table_index] = vaddr;
1036 try self.writeOffsetTableEntry(decl.link.offset_table_index);1036 try self.writeOffsetTableEntry(decl.link.offset_table_index);
1037 }1037 }
...@@ -1049,7 +1049,7 @@ pub const ElfFile = struct {...@@ -1049,7 +1049,7 @@ pub const ElfFile = struct {
1049 const decl_name = mem.spanZ(decl.name);1049 const decl_name = mem.spanZ(decl.name);
1050 const name_str_index = try self.makeString(decl_name);1050 const name_str_index = try self.makeString(decl_name);
1051 const vaddr = try self.allocateTextBlock(&decl.link, code.len, required_alignment);1051 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 });
1053 errdefer self.freeTextBlock(&decl.link);1053 errdefer self.freeTextBlock(&decl.link);
10541054
1055 local_sym.* = .{1055 local_sym.* = .{
...@@ -1307,7 +1307,6 @@ pub const ElfFile = struct {...@@ -1307,7 +1307,6 @@ pub const ElfFile = struct {
1307 .p32 => @sizeOf(elf.Elf32_Sym),1307 .p32 => @sizeOf(elf.Elf32_Sym),
1308 .p64 => @sizeOf(elf.Elf64_Sym),1308 .p64 => @sizeOf(elf.Elf64_Sym),
1309 };1309 };
1310 //std.debug.warn("symtab start=0x{x} end=0x{x}\n", .{ syms_sect.sh_offset, syms_sect.sh_offset + needed_size });
1311 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();1310 const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian();
1312 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;1311 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
1313 switch (self.ptr_width) {1312 switch (self.ptr_width) {
src-self-hosted/main.zig+25
...@@ -38,6 +38,30 @@ const usage =...@@ -38,6 +38,30 @@ const usage =
38 \\38 \\
39;39;
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
41pub fn main() !void {65pub fn main() !void {
42 // TODO general purpose allocator in the zig std lib66 // TODO general purpose allocator in the zig std lib
43 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else std.heap.page_allocator;67 const gpa = if (std.builtin.link_libc) std.heap.c_allocator else std.heap.page_allocator;
...@@ -450,6 +474,7 @@ fn buildOutputType(...@@ -450,6 +474,7 @@ fn buildOutputType(
450 .link_mode = link_mode,474 .link_mode = link_mode,
451 .object_format = object_format,475 .object_format = object_format,
452 .optimize_mode = build_mode,476 .optimize_mode = build_mode,
477 .keep_source_files_loaded = zir_out_path != null,
453 });478 });
454 defer module.deinit();479 defer module.deinit();
455480
src-self-hosted/test.zig+22-13
...@@ -226,20 +226,36 @@ pub const TestContext = struct {...@@ -226,20 +226,36 @@ pub const TestContext = struct {
226226
227 for (self.zir_cases.items) |case| {227 for (self.zir_cases.items) |case| {
228 std.testing.base_allocator_instance.reset();228 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
229 const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.target);237 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);
231 try std.testing.allocator_instance.validate();239 try std.testing.allocator_instance.validate();
232 }240 }
233241
234 // TODO: wipe the rest of this function242 // TODO: wipe the rest of this function
235 for (self.zir_cmp_output_cases.items) |case| {243 for (self.zir_cmp_output_cases.items) |case| {
236 std.testing.base_allocator_instance.reset();244 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);
238 try std.testing.allocator_instance.validate();254 try std.testing.allocator_instance.validate();
239 }255 }
240 }256 }
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 {
243 var tmp = std.testing.tmpDir(.{});259 var tmp = std.testing.tmpDir(.{});
244 defer tmp.cleanup();260 defer tmp.cleanup();
245261
...@@ -247,10 +263,6 @@ pub const TestContext = struct {...@@ -247,10 +263,6 @@ pub const TestContext = struct {
247 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);263 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
248 defer root_pkg.destroy();264 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
254 var module = try Module.init(allocator, .{266 var module = try Module.init(allocator, .{
255 .target = target,267 .target = target,
256 // This is an Executable, as opposed to e.g. a *library*. This does268 // This is an Executable, as opposed to e.g. a *library*. This does
...@@ -265,6 +277,7 @@ pub const TestContext = struct {...@@ -265,6 +277,7 @@ pub const TestContext = struct {
265 .bin_file_dir = tmp.dir,277 .bin_file_dir = tmp.dir,
266 .bin_file_path = "test_case.o",278 .bin_file_path = "test_case.o",
267 .root_pkg = root_pkg,279 .root_pkg = root_pkg,
280 .keep_source_files_loaded = true,
268 });281 });
269 defer module.deinit();282 defer module.deinit();
270283
...@@ -329,7 +342,7 @@ pub const TestContext = struct {...@@ -329,7 +342,7 @@ pub const TestContext = struct {
329 }342 }
330 },343 },
331344
332 else => return error.unimplemented,345 else => return error.Unimplemented,
333 }346 }
334 }347 }
335 }348 }
...@@ -337,7 +350,7 @@ pub const TestContext = struct {...@@ -337,7 +350,7 @@ pub const TestContext = struct {
337 fn runOneZIRCmpOutputCase(350 fn runOneZIRCmpOutputCase(
338 self: *TestContext,351 self: *TestContext,
339 allocator: *Allocator,352 allocator: *Allocator,
340 root_node: *std.Progress.Node,353 prg_node: *std.Progress.Node,
341 case: ZIRCompareOutputCase,354 case: ZIRCompareOutputCase,
342 target: std.Target,355 target: std.Target,
343 ) !void {356 ) !void {
...@@ -348,10 +361,6 @@ pub const TestContext = struct {...@@ -348,10 +361,6 @@ pub const TestContext = struct {
348 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);361 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
349 defer root_pkg.destroy();362 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
355 var module = try Module.init(allocator, .{364 var module = try Module.init(allocator, .{
356 .target = target,365 .target = target,
357 .output_mode = .Exe,366 .output_mode = .Exe,
src-self-hosted/tracy.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1pub const std = @import("std");1pub 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
5extern fn ___tracy_emit_zone_begin_callstack(5extern fn ___tracy_emit_zone_begin_callstack(
6 srcloc: *const ___tracy_source_location_data,6 srcloc: *const ___tracy_source_location_data,
src-self-hosted/type.zig+6
...@@ -113,6 +113,12 @@ pub const Type = extern union {...@@ -113,6 +113,12 @@ pub const Type = extern union {
113 .Undefined => return true,113 .Undefined => return true,
114 .Null => return true,114 .Null => return true,
115 .Pointer => {115 .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 }
116 const is_slice_a = isSlice(a);122 const is_slice_a = isSlice(a);
117 const is_slice_b = isSlice(b);123 const is_slice_b = isSlice(b);
118 if (is_slice_a != is_slice_b)124 if (is_slice_a != is_slice_b)
src-self-hosted/zir.zig+64-19
...@@ -710,8 +710,9 @@ pub const Module = struct {...@@ -710,8 +710,9 @@ pub const Module = struct {
710 } else if (inst.cast(Inst.DeclValInModule)) |decl_val| {710 } else if (inst.cast(Inst.DeclValInModule)) |decl_val| {
711 try stream.print("@{}", .{decl_val.positionals.decl.name});711 try stream.print("@{}", .{decl_val.positionals.decl.name});
712 } else {712 } else {
713 //try stream.print("?", .{});713 // This should be unreachable in theory, but since ZIR is used for debugging the compiler
714 unreachable;714 // we output some debug text instead.
715 try stream.print("?{}?", .{@tagName(inst.tag)});
715 }716 }
716 }717 }
717};718};
...@@ -1175,6 +1176,39 @@ const EmitZIR = struct {...@@ -1175,6 +1176,39 @@ const EmitZIR = struct {
11751176
1176 // Emit all the decls.1177 // Emit all the decls.
1177 for (src_decls.items) |ir_decl| {1178 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 }
1178 if (self.old_module.export_owners.getValue(ir_decl)) |exports| {1212 if (self.old_module.export_owners.getValue(ir_decl)) |exports| {
1179 for (exports) |module_export| {1213 for (exports) |module_export| {
1180 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);1214 const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name);
...@@ -1199,20 +1233,27 @@ const EmitZIR = struct {...@@ -1199,20 +1233,27 @@ const EmitZIR = struct {
1199 }1233 }
1200 }1234 }
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 {
1203 if (inst.cast(ir.Inst.Constant)) |const_inst| {1242 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: {
1205 const owner_decl = func_pl.func.owner_decl;1244 const owner_decl = func_pl.func.owner_decl;
1206 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));1245 break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name));
1207 } else if (const_inst.val.cast(Value.Payload.DeclRef)) |declref| blk: {1246 } 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;
1209 } else blk: {1250 } else blk: {
1210 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;1251 break :blk (try self.emitTypedValue(inst.src, .{ .ty = inst.ty, .val = const_inst.val })).inst;
1211 };1252 };
1212 try inst_table.putNoClobber(inst, new_decl);1253 try new_body.inst_table.putNoClobber(inst, new_inst);
1213 return new_decl;1254 return new_inst;
1214 } else {1255 } else {
1215 return inst_table.getValue(inst).?;1256 return new_body.inst_table.getValue(inst).?;
1216 }1257 }
1217 }1258 }
12181259
...@@ -1419,6 +1460,10 @@ const EmitZIR = struct {...@@ -1419,6 +1460,10 @@ const EmitZIR = struct {
1419 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),1460 inst_table: *std.AutoHashMap(*ir.Inst, *Inst),
1420 instructions: *std.ArrayList(*Inst),1461 instructions: *std.ArrayList(*Inst),
1421 ) Allocator.Error!void {1462 ) Allocator.Error!void {
1463 const new_body = ZirBody{
1464 .inst_table = inst_table,
1465 .instructions = instructions,
1466 };
1422 for (body.instructions) |inst| {1467 for (body.instructions) |inst| {
1423 const new_inst = switch (inst.tag) {1468 const new_inst = switch (inst.tag) {
1424 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),1469 .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint),
...@@ -1428,7 +1473,7 @@ const EmitZIR = struct {...@@ -1428,7 +1473,7 @@ const EmitZIR = struct {
14281473
1429 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);1474 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);
1430 for (args) |*elem, i| {1475 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]);
1432 }1477 }
1433 new_inst.* = .{1478 new_inst.* = .{
1434 .base = .{1479 .base = .{
...@@ -1436,7 +1481,7 @@ const EmitZIR = struct {...@@ -1436,7 +1481,7 @@ const EmitZIR = struct {
1436 .tag = Inst.Call.base_tag,1481 .tag = Inst.Call.base_tag,
1437 },1482 },
1438 .positionals = .{1483 .positionals = .{
1439 .func = try self.resolveInst(inst_table, old_inst.args.func),1484 .func = try self.resolveInst(new_body, old_inst.args.func),
1440 .args = args,1485 .args = args,
1441 },1486 },
1442 .kw_args = .{},1487 .kw_args = .{},
...@@ -1453,7 +1498,7 @@ const EmitZIR = struct {...@@ -1453,7 +1498,7 @@ const EmitZIR = struct {
1453 .tag = Inst.Return.base_tag,1498 .tag = Inst.Return.base_tag,
1454 },1499 },
1455 .positionals = .{1500 .positionals = .{
1456 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1501 .operand = try self.resolveInst(new_body, old_inst.args.operand),
1457 },1502 },
1458 .kw_args = .{},1503 .kw_args = .{},
1459 };1504 };
...@@ -1477,7 +1522,7 @@ const EmitZIR = struct {...@@ -1477,7 +1522,7 @@ const EmitZIR = struct {
14771522
1478 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);1523 const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len);
1479 for (args) |*elem, i| {1524 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]);
1481 }1526 }
14821527
1483 new_inst.* = .{1528 new_inst.* = .{
...@@ -1511,7 +1556,7 @@ const EmitZIR = struct {...@@ -1511,7 +1556,7 @@ const EmitZIR = struct {
1511 .tag = Inst.PtrToInt.base_tag,1556 .tag = Inst.PtrToInt.base_tag,
1512 },1557 },
1513 .positionals = .{1558 .positionals = .{
1514 .ptr = try self.resolveInst(inst_table, old_inst.args.ptr),1559 .ptr = try self.resolveInst(new_body, old_inst.args.ptr),
1515 },1560 },
1516 .kw_args = .{},1561 .kw_args = .{},
1517 };1562 };
...@@ -1527,7 +1572,7 @@ const EmitZIR = struct {...@@ -1527,7 +1572,7 @@ const EmitZIR = struct {
1527 },1572 },
1528 .positionals = .{1573 .positionals = .{
1529 .dest_type = (try self.emitType(inst.src, inst.ty)).inst,1574 .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),
1531 },1576 },
1532 .kw_args = .{},1577 .kw_args = .{},
1533 };1578 };
...@@ -1542,8 +1587,8 @@ const EmitZIR = struct {...@@ -1542,8 +1587,8 @@ const EmitZIR = struct {
1542 .tag = Inst.Cmp.base_tag,1587 .tag = Inst.Cmp.base_tag,
1543 },1588 },
1544 .positionals = .{1589 .positionals = .{
1545 .lhs = try self.resolveInst(inst_table, old_inst.args.lhs),1590 .lhs = try self.resolveInst(new_body, old_inst.args.lhs),
1546 .rhs = try self.resolveInst(inst_table, old_inst.args.rhs),1591 .rhs = try self.resolveInst(new_body, old_inst.args.rhs),
1547 .op = old_inst.args.op,1592 .op = old_inst.args.op,
1548 },1593 },
1549 .kw_args = .{},1594 .kw_args = .{},
...@@ -1569,7 +1614,7 @@ const EmitZIR = struct {...@@ -1569,7 +1614,7 @@ const EmitZIR = struct {
1569 .tag = Inst.CondBr.base_tag,1614 .tag = Inst.CondBr.base_tag,
1570 },1615 },
1571 .positionals = .{1616 .positionals = .{
1572 .condition = try self.resolveInst(inst_table, old_inst.args.condition),1617 .condition = try self.resolveInst(new_body, old_inst.args.condition),
1573 .true_body = .{ .instructions = true_body.toOwnedSlice() },1618 .true_body = .{ .instructions = true_body.toOwnedSlice() },
1574 .false_body = .{ .instructions = false_body.toOwnedSlice() },1619 .false_body = .{ .instructions = false_body.toOwnedSlice() },
1575 },1620 },
...@@ -1586,7 +1631,7 @@ const EmitZIR = struct {...@@ -1586,7 +1631,7 @@ const EmitZIR = struct {
1586 .tag = Inst.IsNull.base_tag,1631 .tag = Inst.IsNull.base_tag,
1587 },1632 },
1588 .positionals = .{1633 .positionals = .{
1589 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1634 .operand = try self.resolveInst(new_body, old_inst.args.operand),
1590 },1635 },
1591 .kw_args = .{},1636 .kw_args = .{},
1592 };1637 };
...@@ -1601,7 +1646,7 @@ const EmitZIR = struct {...@@ -1601,7 +1646,7 @@ const EmitZIR = struct {
1601 .tag = Inst.IsNonNull.base_tag,1646 .tag = Inst.IsNonNull.base_tag,
1602 },1647 },
1603 .positionals = .{1648 .positionals = .{
1604 .operand = try self.resolveInst(inst_table, old_inst.args.operand),1649 .operand = try self.resolveInst(new_body, old_inst.args.operand),
1605 },1650 },
1606 .kw_args = .{},1651 .kw_args = .{},
1607 };1652 };
test/stage2/compile_errors.zig+3-5
...@@ -27,9 +27,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -27,9 +27,8 @@ pub fn addCases(ctx: *TestContext) !void {
27 \\ %0 = call(@notafunc, [])27 \\ %0 = call(@notafunc, [])
28 \\})28 \\})
29 \\@0 = str("_start")29 \\@0 = str("_start")
30 \\@1 = ref(@0)30 \\@1 = export(@0, "start")
31 \\@2 = export(@1, @start)31 , &[_][]const u8{":5:13: error: decl 'notafunc' not found"});
32 , &[_][]const u8{":5:13: error: use of undeclared identifier 'notafunc'"});
3332
34 // TODO: this error should occur at the call site, not the fntype decl33 // TODO: this error should occur at the call site, not the fntype decl
35 ctx.addZIRError("call naked function", linux_x64,34 ctx.addZIRError("call naked function", linux_x64,
...@@ -41,8 +40,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -41,8 +40,7 @@ pub fn addCases(ctx: *TestContext) !void {
41 \\ %0 = call(@s, [])40 \\ %0 = call(@s, [])
42 \\})41 \\})
43 \\@0 = str("_start")42 \\@0 = str("_start")
44 \\@1 = ref(@0)43 \\@1 = export(@0, "start")
45 \\@2 = export(@1, @start)
46 , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"});44 , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"});
4745
48 // TODO: re-enable these tests.46 // TODO: re-enable these tests.
test/stage2/zir.zig+65-199
...@@ -14,23 +14,21 @@ pub fn addCases(ctx: *TestContext) void {...@@ -14,23 +14,21 @@ pub fn addCases(ctx: *TestContext) void {
14 \\@fnty = fntype([], @void, cc=C)14 \\@fnty = fntype([], @void, cc=C)
15 \\15 \\
16 \\@9 = str("entry")16 \\@9 = str("entry")
17 \\@10 = ref(@9)17 \\@11 = export(@9, "entry")
18 \\@11 = export(@10, @entry)
19 \\18 \\
20 \\@entry = fn(@fnty, {19 \\@entry = fn(@fnty, {
21 \\ %11 = return()20 \\ %11 = returnvoid()
22 \\})21 \\})
23 ,22 ,
24 \\@void = primitive(void)23 \\@void = primitive(void)
25 \\@fnty = fntype([], @void, cc=C)24 \\@fnty = fntype([], @void, cc=C)
26 \\@9 = str("entry")25 \\@9 = declref("9$0")
27 \\@10 = ref(@9)26 \\@9$0 = str("entry")
28 \\@unnamed$6 = str("entry")27 \\@unnamed$4 = str("entry")
29 \\@unnamed$7 = ref(@unnamed$6)28 \\@unnamed$5 = export(@unnamed$4, "entry")
30 \\@unnamed$8 = export(@unnamed$7, @entry)29 \\@unnamed$6 = fntype([], @void, cc=C)
31 \\@unnamed$10 = fntype([], @void, cc=C)30 \\@entry = fn(@unnamed$6, {
32 \\@entry = fn(@unnamed$10, {31 \\ %0 = returnvoid()
33 \\ %0 = return()
34 \\})32 \\})
35 \\33 \\
36 );34 );
...@@ -45,11 +43,10 @@ pub fn addCases(ctx: *TestContext) void {...@@ -45,11 +43,10 @@ pub fn addCases(ctx: *TestContext) void {
45 \\43 \\
46 \\@entry = fn(@fnty, {44 \\@entry = fn(@fnty, {
47 \\ %a = str("\x32\x08\x01\x0a")45 \\ %a = str("\x32\x08\x01\x0a")
48 \\ %aref = ref(%a)46 \\ %eptr0 = elemptr(%a, @0)
49 \\ %eptr0 = elemptr(%aref, @0)47 \\ %eptr1 = elemptr(%a, @1)
50 \\ %eptr1 = elemptr(%aref, @1)48 \\ %eptr2 = elemptr(%a, @2)
51 \\ %eptr2 = elemptr(%aref, @2)49 \\ %eptr3 = elemptr(%a, @3)
52 \\ %eptr3 = elemptr(%aref, @3)
53 \\ %v0 = deref(%eptr0)50 \\ %v0 = deref(%eptr0)
54 \\ %v1 = deref(%eptr1)51 \\ %v1 = deref(%eptr1)
55 \\ %v2 = deref(%eptr2)52 \\ %v2 = deref(%eptr2)
...@@ -61,15 +58,14 @@ pub fn addCases(ctx: *TestContext) void {...@@ -61,15 +58,14 @@ pub fn addCases(ctx: *TestContext) void {
61 \\ %expected = int(69)58 \\ %expected = int(69)
62 \\ %ok = cmp(%result, eq, %expected)59 \\ %ok = cmp(%result, eq, %expected)
63 \\ %10 = condbr(%ok, {60 \\ %10 = condbr(%ok, {
64 \\ %11 = return()61 \\ %11 = returnvoid()
65 \\ }, {62 \\ }, {
66 \\ %12 = breakpoint()63 \\ %12 = breakpoint()
67 \\ })64 \\ })
68 \\})65 \\})
69 \\66 \\
70 \\@9 = str("entry")67 \\@9 = str("entry")
71 \\@10 = ref(@9)68 \\@11 = export(@9, "entry")
72 \\@11 = export(@10, @entry)
73 ,69 ,
74 \\@void = primitive(void)70 \\@void = primitive(void)
75 \\@fnty = fntype([], @void, cc=C)71 \\@fnty = fntype([], @void, cc=C)
...@@ -77,16 +73,15 @@ pub fn addCases(ctx: *TestContext) void {...@@ -77,16 +73,15 @@ pub fn addCases(ctx: *TestContext) void {
77 \\@1 = int(1)73 \\@1 = int(1)
78 \\@2 = int(2)74 \\@2 = int(2)
79 \\@3 = int(3)75 \\@3 = int(3)
80 \\@unnamed$7 = fntype([], @void, cc=C)76 \\@unnamed$6 = fntype([], @void, cc=C)
81 \\@entry = fn(@unnamed$7, {77 \\@entry = fn(@unnamed$6, {
82 \\ %0 = return()78 \\ %0 = returnvoid()
83 \\})79 \\})
84 \\@a = str("2\x08\x01\n")80 \\@entry$1 = str("2\x08\x01\n")
85 \\@9 = str("entry")81 \\@9 = declref("9$0")
86 \\@10 = ref(@9)82 \\@9$0 = str("entry")
87 \\@unnamed$14 = str("entry")83 \\@unnamed$11 = str("entry")
88 \\@unnamed$15 = ref(@unnamed$14)84 \\@unnamed$12 = export(@unnamed$11, "entry")
89 \\@unnamed$16 = export(@unnamed$15, @entry)
90 \\85 \\
91 );86 );
9287
...@@ -97,45 +92,43 @@ pub fn addCases(ctx: *TestContext) void {...@@ -97,45 +92,43 @@ pub fn addCases(ctx: *TestContext) void {
97 \\@fnty = fntype([], @void, cc=C)92 \\@fnty = fntype([], @void, cc=C)
98 \\93 \\
99 \\@9 = str("entry")94 \\@9 = str("entry")
100 \\@10 = ref(@9)95 \\@11 = export(@9, "entry")
101 \\@11 = export(@10, @entry)
102 \\96 \\
103 \\@entry = fn(@fnty, {97 \\@entry = fn(@fnty, {
104 \\ %0 = call(@a, [])98 \\ %0 = call(@a, [])
105 \\ %1 = return()99 \\ %1 = returnvoid()
106 \\})100 \\})
107 \\101 \\
108 \\@a = fn(@fnty, {102 \\@a = fn(@fnty, {
109 \\ %0 = call(@b, [])103 \\ %0 = call(@b, [])
110 \\ %1 = return()104 \\ %1 = returnvoid()
111 \\})105 \\})
112 \\106 \\
113 \\@b = fn(@fnty, {107 \\@b = fn(@fnty, {
114 \\ %0 = call(@a, [])108 \\ %0 = call(@a, [])
115 \\ %1 = return()109 \\ %1 = returnvoid()
116 \\})110 \\})
117 ,111 ,
118 \\@void = primitive(void)112 \\@void = primitive(void)
119 \\@fnty = fntype([], @void, cc=C)113 \\@fnty = fntype([], @void, cc=C)
120 \\@9 = str("entry")114 \\@9 = declref("9$0")
121 \\@10 = ref(@9)115 \\@9$0 = str("entry")
122 \\@unnamed$6 = str("entry")116 \\@unnamed$4 = str("entry")
123 \\@unnamed$7 = ref(@unnamed$6)117 \\@unnamed$5 = export(@unnamed$4, "entry")
124 \\@unnamed$8 = export(@unnamed$7, @entry)118 \\@unnamed$6 = fntype([], @void, cc=C)
125 \\@unnamed$12 = fntype([], @void, cc=C)119 \\@entry = fn(@unnamed$6, {
126 \\@entry = fn(@unnamed$12, {
127 \\ %0 = call(@a, [], modifier=auto)120 \\ %0 = call(@a, [], modifier=auto)
128 \\ %1 = return()121 \\ %1 = returnvoid()
129 \\})122 \\})
130 \\@unnamed$17 = fntype([], @void, cc=C)123 \\@unnamed$8 = fntype([], @void, cc=C)
131 \\@a = fn(@unnamed$17, {124 \\@a = fn(@unnamed$8, {
132 \\ %0 = call(@b, [], modifier=auto)125 \\ %0 = call(@b, [], modifier=auto)
133 \\ %1 = return()126 \\ %1 = returnvoid()
134 \\})127 \\})
135 \\@unnamed$22 = fntype([], @void, cc=C)128 \\@unnamed$10 = fntype([], @void, cc=C)
136 \\@b = fn(@unnamed$22, {129 \\@b = fn(@unnamed$10, {
137 \\ %0 = call(@a, [], modifier=auto)130 \\ %0 = call(@a, [], modifier=auto)
138 \\ %1 = return()131 \\ %1 = returnvoid()
139 \\})132 \\})
140 \\133 \\
141 );134 );
...@@ -145,27 +138,26 @@ pub fn addCases(ctx: *TestContext) void {...@@ -145,27 +138,26 @@ pub fn addCases(ctx: *TestContext) void {
145 \\@fnty = fntype([], @void, cc=C)138 \\@fnty = fntype([], @void, cc=C)
146 \\139 \\
147 \\@9 = str("entry")140 \\@9 = str("entry")
148 \\@10 = ref(@9)141 \\@11 = export(@9, "entry")
149 \\@11 = export(@10, @entry)
150 \\142 \\
151 \\@entry = fn(@fnty, {143 \\@entry = fn(@fnty, {
152 \\ %0 = call(@a, [])144 \\ %0 = call(@a, [])
153 \\ %1 = return()145 \\ %1 = returnvoid()
154 \\})146 \\})
155 \\147 \\
156 \\@a = fn(@fnty, {148 \\@a = fn(@fnty, {
157 \\ %0 = call(@b, [])149 \\ %0 = call(@b, [])
158 \\ %1 = return()150 \\ %1 = returnvoid()
159 \\})151 \\})
160 \\152 \\
161 \\@b = fn(@fnty, {153 \\@b = fn(@fnty, {
162 \\ %9 = compileerror("message")154 \\ %9 = compileerror("message")
163 \\ %0 = call(@a, [])155 \\ %0 = call(@a, [])
164 \\ %1 = return()156 \\ %1 = returnvoid()
165 \\})157 \\})
166 ,158 ,
167 &[_][]const u8{159 &[_][]const u8{
168 ":19:21: error: message",160 ":18:21: error: message",
169 },161 },
170 );162 );
171 // Now we remove the call to `a`. `a` and `b` form a cycle, but no entry points are163 // 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 {...@@ -176,34 +168,32 @@ pub fn addCases(ctx: *TestContext) void {
176 \\@fnty = fntype([], @void, cc=C)168 \\@fnty = fntype([], @void, cc=C)
177 \\169 \\
178 \\@9 = str("entry")170 \\@9 = str("entry")
179 \\@10 = ref(@9)171 \\@11 = export(@9, "entry")
180 \\@11 = export(@10, @entry)
181 \\172 \\
182 \\@entry = fn(@fnty, {173 \\@entry = fn(@fnty, {
183 \\ %1 = return()174 \\ %0 = returnvoid()
184 \\})175 \\})
185 \\176 \\
186 \\@a = fn(@fnty, {177 \\@a = fn(@fnty, {
187 \\ %0 = call(@b, [])178 \\ %0 = call(@b, [])
188 \\ %1 = return()179 \\ %1 = returnvoid()
189 \\})180 \\})
190 \\181 \\
191 \\@b = fn(@fnty, {182 \\@b = fn(@fnty, {
192 \\ %9 = compileerror("message")183 \\ %9 = compileerror("message")
193 \\ %0 = call(@a, [])184 \\ %0 = call(@a, [])
194 \\ %1 = return()185 \\ %1 = returnvoid()
195 \\})186 \\})
196 ,187 ,
197 \\@void = primitive(void)188 \\@void = primitive(void)
198 \\@fnty = fntype([], @void, cc=C)189 \\@fnty = fntype([], @void, cc=C)
199 \\@9 = str("entry")190 \\@9 = declref("9$2")
200 \\@10 = ref(@9)191 \\@9$2 = str("entry")
201 \\@unnamed$6 = str("entry")192 \\@unnamed$4 = str("entry")
202 \\@unnamed$7 = ref(@unnamed$6)193 \\@unnamed$5 = export(@unnamed$4, "entry")
203 \\@unnamed$8 = export(@unnamed$7, @entry)194 \\@unnamed$6 = fntype([], @void, cc=C)
204 \\@unnamed$10 = fntype([], @void, cc=C)195 \\@entry = fn(@unnamed$6, {
205 \\@entry = fn(@unnamed$10, {196 \\ %0 = returnvoid()
206 \\ %0 = return()
207 \\})197 \\})
208 \\198 \\
209 );199 );
...@@ -218,7 +208,7 @@ pub fn addCases(ctx: *TestContext) void {...@@ -218,7 +208,7 @@ pub fn addCases(ctx: *TestContext) void {
218 }208 }
219209
220 ctx.addZIRCompareOutput(210 ctx.addZIRCompareOutput(
221 "hello world ZIR, update msg",211 "hello world ZIR",
222 &[_][]const u8{212 &[_][]const u8{
223 \\@noreturn = primitive(noreturn)213 \\@noreturn = primitive(noreturn)
224 \\@void = primitive(void)214 \\@void = primitive(void)
...@@ -272,125 +262,10 @@ pub fn addCases(ctx: *TestContext) void {...@@ -272,125 +262,10 @@ pub fn addCases(ctx: *TestContext) void {
272 \\262 \\
273 \\@9 = str("_start")263 \\@9 = str("_start")
274 \\@11 = export(@9, "start")264 \\@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")
383 },265 },
384 &[_][]const u8{266 &[_][]const u8{
385 \\Hello, world!267 \\Hello, world!
386 \\268 \\
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 \\
394 },269 },
395 );270 );
396271
...@@ -405,26 +280,18 @@ pub fn addCases(ctx: *TestContext) void {...@@ -405,26 +280,18 @@ pub fn addCases(ctx: *TestContext) void {
405 \\@2 = int(2)280 \\@2 = int(2)
406 \\@3 = int(3)281 \\@3 = int(3)
407 \\282 \\
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 \\
416 \\@exit0_fnty = fntype([], @noreturn)283 \\@exit0_fnty = fntype([], @noreturn)
417 \\@exit0 = fn(@exit0_fnty, {284 \\@exit0 = fn(@exit0_fnty, {
418 \\ %SYS_exit_group = int(231)285 \\ %SYS_exit_group = int(231)
419 \\ %exit_code = as(@usize, @0)286 \\ %exit_code = as(@usize, @0)
420 \\287 \\
421 \\ %syscall = ref(@syscall_array)288 \\ %syscall = str("syscall")
422 \\ %sysoutreg = ref(@sysoutreg_array)289 \\ %sysoutreg = str("={rax}")
423 \\ %rax = ref(@rax_array)290 \\ %rax = str("{rax}")
424 \\ %rdi = ref(@rdi_array)291 \\ %rdi = str("{rdi}")
425 \\ %rcx = ref(@rcx_array)292 \\ %rcx = str("rcx")
426 \\ %r11 = ref(@r11_array)293 \\ %r11 = str("r11")
427 \\ %memory = ref(@memory_array)294 \\ %memory = str("memory")
428 \\295 \\
429 \\ %rc = asm(%syscall, @usize,296 \\ %rc = asm(%syscall, @usize,
430 \\ volatile=1,297 \\ volatile=1,
...@@ -441,8 +308,7 @@ pub fn addCases(ctx: *TestContext) void {...@@ -441,8 +308,7 @@ pub fn addCases(ctx: *TestContext) void {
441 \\ %0 = call(@exit0, [])308 \\ %0 = call(@exit0, [])
442 \\})309 \\})
443 \\@9 = str("_start")310 \\@9 = str("_start")
444 \\@10 = ref(@9)311 \\@11 = export(@9, "start")
445 \\@11 = export(@10, @start)
446 },312 },
447 &[_][]const u8{""},313 &[_][]const u8{""},
448 );314 );