| author | |
| committer | |
| log | 5aa3f56773f4b06629184a1e3753c3132b18e0bd |
| tree | a70155716f9d2d63f688dd1277505b084ca8fb34 |
| parent | fd7a97b3b2607c6de49e96ed32a7be0a037c67a8 |
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 | 69 | /// contains Decls that need to be deleted if they end up having no references to them. |
| 70 | 70 | deletion_set: std.ArrayListUnmanaged(*Decl) = .{}, |
| 71 | 71 | |
| 72 | keep_source_files_loaded: bool, | |
| 73 | ||
| 72 | 74 | const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql); |
| 73 | 75 | |
| 74 | 76 | const WorkItem = union(enum) { |
| ... | ... | @@ -580,11 +582,13 @@ pub const Scope = struct { |
| 580 | 582 | .loaded_success => { |
| 581 | 583 | self.contents.module.deinit(allocator); |
| 582 | 584 | allocator.destroy(self.contents.module); |
| 585 | self.contents = .{ .not_available = {} }; | |
| 583 | 586 | self.status = .unloaded_success; |
| 584 | 587 | }, |
| 585 | 588 | .loaded_sema_failure => { |
| 586 | 589 | self.contents.module.deinit(allocator); |
| 587 | 590 | allocator.destroy(self.contents.module); |
| 591 | self.contents = .{ .not_available = {} }; | |
| 588 | 592 | self.status = .unloaded_sema_failure; |
| 589 | 593 | }, |
| 590 | 594 | } |
| ... | ... | @@ -719,6 +723,7 @@ pub const InitOptions = struct { |
| 719 | 723 | link_mode: ?std.builtin.LinkMode = null, |
| 720 | 724 | object_format: ?std.builtin.ObjectFormat = null, |
| 721 | 725 | optimize_mode: std.builtin.Mode = .Debug, |
| 726 | keep_source_files_loaded: bool = false, | |
| 722 | 727 | }; |
| 723 | 728 | |
| 724 | 729 | pub fn init(gpa: *Allocator, options: InitOptions) !Module { |
| ... | ... | @@ -772,6 +777,7 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module { |
| 772 | 777 | .failed_files = std.AutoHashMap(*Scope, *ErrorMsg).init(gpa), |
| 773 | 778 | .failed_exports = std.AutoHashMap(*Export, *ErrorMsg).init(gpa), |
| 774 | 779 | .work_queue = std.fifo.LinearFifo(WorkItem, .Dynamic).init(gpa), |
| 780 | .keep_source_files_loaded = options.keep_source_files_loaded, | |
| 775 | 781 | }; |
| 776 | 782 | } |
| 777 | 783 | |
| ... | ... | @@ -869,21 +875,22 @@ pub fn update(self: *Module) !void { |
| 869 | 875 | try self.performAllTheWork(); |
| 870 | 876 | |
| 871 | 877 | // Process the deletion set. |
| 872 | for (self.deletion_set.items) |decl| { | |
| 878 | while (self.deletion_set.popOrNull()) |decl| { | |
| 873 | 879 | if (decl.dependants.items.len != 0) { |
| 874 | 880 | decl.deletion_flag = false; |
| 875 | 881 | continue; |
| 876 | 882 | } |
| 877 | 883 | try self.deleteDecl(decl); |
| 878 | 884 | } |
| 879 | self.deletion_set.shrink(self.allocator, 0); | |
| 880 | 885 | |
| 881 | 886 | self.link_error_flags = self.bin_file.error_flags; |
| 882 | 887 | |
| 883 | 888 | // If there are any errors, we anticipate the source files being loaded |
| 884 | 889 | // to report error messages. Otherwise we unload all source files to save memory. |
| 885 | 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 | 894 | try self.bin_file.flush(); |
| 888 | 895 | } |
| 889 | 896 | } |
| ... | ... | @@ -1025,7 +1032,6 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void { |
| 1025 | 1032 | defer tracy.end(); |
| 1026 | 1033 | |
| 1027 | 1034 | const subsequent_analysis = switch (decl.analysis) { |
| 1028 | .complete => return, | |
| 1029 | 1035 | .in_progress => unreachable, |
| 1030 | 1036 | |
| 1031 | 1037 | .sema_failure, |
| ... | ... | @@ -1035,7 +1041,11 @@ fn ensureDeclAnalyzed(self: *Module, decl: *Decl) InnerError!void { |
| 1035 | 1041 | .codegen_failure_retryable, |
| 1036 | 1042 | => return error.AnalysisFail, |
| 1037 | 1043 | |
| 1038 | .outdated => blk: { | |
| 1044 | .complete, .outdated => blk: { | |
| 1045 | if (decl.generation == self.generation) { | |
| 1046 | assert(decl.analysis == .complete); | |
| 1047 | return; | |
| 1048 | } | |
| 1039 | 1049 | //std.debug.warn("re-analyzing {}\n", .{decl.name}); |
| 1040 | 1050 | |
| 1041 | 1051 | // 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 | 1054 | // Dependencies will be re-discovered, so we remove them here prior to re-analysis. |
| 1045 | 1055 | for (decl.dependencies.items) |dep| { |
| 1046 | 1056 | dep.removeDependant(decl); |
| 1047 | if (dep.dependants.items.len == 0) { | |
| 1057 | if (dep.dependants.items.len == 0 and !dep.deletion_flag) { | |
| 1048 | 1058 | // We don't perform a deletion here, because this Decl or another one |
| 1049 | 1059 | // may end up referencing it before the update is complete. |
| 1050 | assert(!dep.deletion_flag); | |
| 1051 | 1060 | dep.deletion_flag = true; |
| 1052 | 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 | 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 | 1789 | // Handle explicitly deleted decls from the source code. Not to be confused |
| 1778 | 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 | 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 | } |
| 1789 | 1798 | |
| 1790 | 1799 | fn deleteDecl(self: *Module, decl: *Decl) !void { |
| ... | ... | @@ -1800,10 +1809,9 @@ fn deleteDecl(self: *Module, decl: *Decl) !void { |
| 1800 | 1809 | // Remove itself from its dependencies, because we are about to destroy the decl pointer. |
| 1801 | 1810 | for (decl.dependencies.items) |dep| { |
| 1802 | 1811 | dep.removeDependant(decl); |
| 1803 | if (dep.dependants.items.len == 0) { | |
| 1812 | if (dep.dependants.items.len == 0 and !dep.deletion_flag) { | |
| 1804 | 1813 | // We don't recursively perform a deletion here, because during the update, |
| 1805 | 1814 | // another reference to it may turn up. |
| 1806 | assert(!dep.deletion_flag); | |
| 1807 | 1815 | dep.deletion_flag = true; |
| 1808 | 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 | 2034 | }; |
| 2027 | 2035 | const decl = try self.resolveCompleteZirDecl(scope, entry.decl); |
| 2028 | 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); | |
| 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); | |
| 2032 | 2041 | } |
| 2033 | 2042 | |
| 2034 | 2043 | fn 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 | 369 | const file_size = self.options.program_code_size_hint; |
| 370 | 370 | const p_align = 0x1000; |
| 371 | 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 | 373 | try self.program_headers.append(self.allocator, .{ |
| 374 | 374 | .p_type = elf.PT_LOAD, |
| 375 | 375 | .p_offset = off, |
| ... | ... | @@ -390,7 +390,7 @@ pub const ElfFile = struct { |
| 390 | 390 | // page align. |
| 391 | 391 | const p_align = 0x1000; |
| 392 | 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 | 394 | // TODO instead of hard coding the vaddr, make a function to find a vaddr to put things at. |
| 395 | 395 | // we'll need to re-use that function anyway, in case the GOT grows and overlaps something |
| 396 | 396 | // else in virtual memory. |
| ... | ... | @@ -412,7 +412,7 @@ pub const ElfFile = struct { |
| 412 | 412 | assert(self.shstrtab.items.len == 0); |
| 413 | 413 | try self.shstrtab.append(self.allocator, 0); // need a 0 at position 0 |
| 414 | 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 | 416 | try self.sections.append(self.allocator, .{ |
| 417 | 417 | .sh_name = try self.makeString(".shstrtab"), |
| 418 | 418 | .sh_type = elf.SHT_STRTAB, |
| ... | ... | @@ -470,7 +470,7 @@ pub const ElfFile = struct { |
| 470 | 470 | const each_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym); |
| 471 | 471 | const file_size = self.options.symbol_count_hint * each_size; |
| 472 | 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 }); | |
| 474 | 474 | |
| 475 | 475 | try self.sections.append(self.allocator, .{ |
| 476 | 476 | .sh_name = try self.makeString(".symtab"), |
| ... | ... | @@ -586,7 +586,7 @@ pub const ElfFile = struct { |
| 586 | 586 | shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); |
| 587 | 587 | } |
| 588 | 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 }); | |
| 590 | 590 | |
| 591 | 591 | try self.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); |
| 592 | 592 | if (!self.shdr_table_dirty) { |
| ... | ... | @@ -632,7 +632,7 @@ pub const ElfFile = struct { |
| 632 | 632 | |
| 633 | 633 | for (buf) |*shdr, i| { |
| 634 | 634 | shdr.* = self.sections.items[i]; |
| 635 | //std.debug.warn("writing section {}\n", .{shdr.*}); | |
| 635 | //std.log.debug(.link, "writing section {}\n", .{shdr.*}); | |
| 636 | 636 | if (foreign_endian) { |
| 637 | 637 | bswapAllFields(elf.Elf64_Shdr, shdr); |
| 638 | 638 | } |
| ... | ... | @@ -956,10 +956,10 @@ pub const ElfFile = struct { |
| 956 | 956 | try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len); |
| 957 | 957 | |
| 958 | 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 | 960 | decl.link.local_sym_index = i; |
| 961 | 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 | 963 | decl.link.local_sym_index = @intCast(u32, self.local_symbols.items.len); |
| 964 | 964 | _ = self.local_symbols.addOneAssumeCapacity(); |
| 965 | 965 | } |
| ... | ... | @@ -1027,11 +1027,11 @@ pub const ElfFile = struct { |
| 1027 | 1027 | !mem.isAlignedGeneric(u64, local_sym.st_value, required_alignment); |
| 1028 | 1028 | if (need_realloc) { |
| 1029 | 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 | 1031 | if (vaddr != local_sym.st_value) { |
| 1032 | 1032 | local_sym.st_value = vaddr; |
| 1033 | 1033 | |
| 1034 | //std.debug.warn(" (writing new offset table entry)\n", .{}); | |
| 1034 | //std.log.debug(.link, " (writing new offset table entry)\n", .{}); | |
| 1035 | 1035 | self.offset_table.items[decl.link.offset_table_index] = vaddr; |
| 1036 | 1036 | try self.writeOffsetTableEntry(decl.link.offset_table_index); |
| 1037 | 1037 | } |
| ... | ... | @@ -1049,7 +1049,7 @@ pub const ElfFile = struct { |
| 1049 | 1049 | const decl_name = mem.spanZ(decl.name); |
| 1050 | 1050 | const name_str_index = try self.makeString(decl_name); |
| 1051 | 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 | 1053 | errdefer self.freeTextBlock(&decl.link); |
| 1054 | 1054 | |
| 1055 | 1055 | local_sym.* = .{ |
| ... | ... | @@ -1307,7 +1307,6 @@ pub const ElfFile = struct { |
| 1307 | 1307 | .p32 => @sizeOf(elf.Elf32_Sym), |
| 1308 | 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 | 1310 | const foreign_endian = self.options.target.cpu.arch.endian() != std.Target.current.cpu.arch.endian(); |
| 1312 | 1311 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; |
| 1313 | 1312 | switch (self.ptr_width) { |
src-self-hosted/main.zig+25| ... | ... | @@ -38,6 +38,30 @@ const usage = |
| 38 | 38 | \\ |
| 39 | 39 | ; |
| 40 | 40 | |
| 41 | pub 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 | ||
| 41 | 65 | pub fn main() !void { |
| 42 | 66 | // TODO general purpose allocator in the zig std lib |
| 43 | 67 | const gpa = if (std.builtin.link_libc) std.heap.c_allocator else std.heap.page_allocator; |
| ... | ... | @@ -450,6 +474,7 @@ fn buildOutputType( |
| 450 | 474 | .link_mode = link_mode, |
| 451 | 475 | .object_format = object_format, |
| 452 | 476 | .optimize_mode = build_mode, |
| 477 | .keep_source_files_loaded = zir_out_path != null, | |
| 453 | 478 | }); |
| 454 | 479 | defer module.deinit(); |
| 455 | 480 |
src-self-hosted/test.zig+22-13| ... | ... | @@ -226,20 +226,36 @@ pub const TestContext = struct { |
| 226 | 226 | |
| 227 | 227 | for (self.zir_cases.items) |case| { |
| 228 | 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 | 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 | 239 | try std.testing.allocator_instance.validate(); |
| 232 | 240 | } |
| 233 | 241 | |
| 234 | 242 | // TODO: wipe the rest of this function |
| 235 | 243 | for (self.zir_cmp_output_cases.items) |case| { |
| 236 | 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 | 254 | try std.testing.allocator_instance.validate(); |
| 239 | 255 | } |
| 240 | 256 | } |
| 241 | 257 | |
| 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 | 259 | var tmp = std.testing.tmpDir(.{}); |
| 244 | 260 | defer tmp.cleanup(); |
| 245 | 261 | |
| ... | ... | @@ -247,10 +263,6 @@ pub const TestContext = struct { |
| 247 | 263 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); |
| 248 | 264 | defer root_pkg.destroy(); |
| 249 | 265 | |
| 250 | var prg_node = root_node.start(case.name, case.updates.items.len); | |
| 251 | prg_node.activate(); | |
| 252 | defer prg_node.end(); | |
| 253 | ||
| 254 | 266 | var module = try Module.init(allocator, .{ |
| 255 | 267 | .target = target, |
| 256 | 268 | // This is an Executable, as opposed to e.g. a *library*. This does |
| ... | ... | @@ -265,6 +277,7 @@ pub const TestContext = struct { |
| 265 | 277 | .bin_file_dir = tmp.dir, |
| 266 | 278 | .bin_file_path = "test_case.o", |
| 267 | 279 | .root_pkg = root_pkg, |
| 280 | .keep_source_files_loaded = true, | |
| 268 | 281 | }); |
| 269 | 282 | defer module.deinit(); |
| 270 | 283 | |
| ... | ... | @@ -329,7 +342,7 @@ pub const TestContext = struct { |
| 329 | 342 | } |
| 330 | 343 | }, |
| 331 | 344 | |
| 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 | 350 | fn runOneZIRCmpOutputCase( |
| 338 | 351 | self: *TestContext, |
| 339 | 352 | allocator: *Allocator, |
| 340 | root_node: *std.Progress.Node, | |
| 353 | prg_node: *std.Progress.Node, | |
| 341 | 354 | case: ZIRCompareOutputCase, |
| 342 | 355 | target: std.Target, |
| 343 | 356 | ) !void { |
| ... | ... | @@ -348,10 +361,6 @@ pub const TestContext = struct { |
| 348 | 361 | const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path); |
| 349 | 362 | defer root_pkg.destroy(); |
| 350 | 363 | |
| 351 | var prg_node = root_node.start(case.name, case.src_list.len); | |
| 352 | prg_node.activate(); | |
| 353 | defer prg_node.end(); | |
| 354 | ||
| 355 | 364 | var module = try Module.init(allocator, .{ |
| 356 | 365 | .target = target, |
| 357 | 366 | .output_mode = .Exe, |
src-self-hosted/tracy.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | pub const std = @import("std"); |
| 2 | 2 | |
| 3 | pub const enable = @import("build_options").enable_tracy; | |
| 3 | pub const enable = if (std.builtin.is_test) false else @import("build_options").enable_tracy; | |
| 4 | 4 | |
| 5 | 5 | extern fn ___tracy_emit_zone_begin_callstack( |
| 6 | 6 | srcloc: *const ___tracy_source_location_data, |
src-self-hosted/type.zig+6| ... | ... | @@ -113,6 +113,12 @@ pub const Type = extern union { |
| 113 | 113 | .Undefined => return true, |
| 114 | 114 | .Null => return true, |
| 115 | 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 | 122 | const is_slice_a = isSlice(a); |
| 117 | 123 | const is_slice_b = isSlice(b); |
| 118 | 124 | if (is_slice_a != is_slice_b) |
src-self-hosted/zir.zig+64-19| ... | ... | @@ -710,8 +710,9 @@ pub const Module = struct { |
| 710 | 710 | } else if (inst.cast(Inst.DeclValInModule)) |decl_val| { |
| 711 | 711 | try stream.print("@{}", .{decl_val.positionals.decl.name}); |
| 712 | 712 | } 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)}); | |
| 715 | 716 | } |
| 716 | 717 | } |
| 717 | 718 | }; |
| ... | ... | @@ -1175,6 +1176,39 @@ const EmitZIR = struct { |
| 1175 | 1176 | |
| 1176 | 1177 | // Emit all the decls. |
| 1177 | 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 | 1212 | if (self.old_module.export_owners.getValue(ir_decl)) |exports| { |
| 1179 | 1213 | for (exports) |module_export| { |
| 1180 | 1214 | const symbol_name = try self.emitStringLiteral(module_export.src, module_export.options.name); |
| ... | ... | @@ -1199,20 +1233,27 @@ const EmitZIR = struct { |
| 1199 | 1233 | } |
| 1200 | 1234 | } |
| 1201 | 1235 | |
| 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 | 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 | 1244 | const owner_decl = func_pl.func.owner_decl; |
| 1206 | 1245 | break :blk try self.emitDeclVal(inst.src, mem.spanZ(owner_decl.name)); |
| 1207 | 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 | 1250 | } else blk: { |
| 1210 | 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); | |
| 1213 | return new_decl; | |
| 1253 | try new_body.inst_table.putNoClobber(inst, new_inst); | |
| 1254 | return new_inst; | |
| 1214 | 1255 | } else { |
| 1215 | return inst_table.getValue(inst).?; | |
| 1256 | return new_body.inst_table.getValue(inst).?; | |
| 1216 | 1257 | } |
| 1217 | 1258 | } |
| 1218 | 1259 | |
| ... | ... | @@ -1419,6 +1460,10 @@ const EmitZIR = struct { |
| 1419 | 1460 | inst_table: *std.AutoHashMap(*ir.Inst, *Inst), |
| 1420 | 1461 | instructions: *std.ArrayList(*Inst), |
| 1421 | 1462 | ) Allocator.Error!void { |
| 1463 | const new_body = ZirBody{ | |
| 1464 | .inst_table = inst_table, | |
| 1465 | .instructions = instructions, | |
| 1466 | }; | |
| 1422 | 1467 | for (body.instructions) |inst| { |
| 1423 | 1468 | const new_inst = switch (inst.tag) { |
| 1424 | 1469 | .breakpoint => try self.emitTrivial(inst.src, Inst.Breakpoint), |
| ... | ... | @@ -1428,7 +1473,7 @@ const EmitZIR = struct { |
| 1428 | 1473 | |
| 1429 | 1474 | const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len); |
| 1430 | 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 | 1478 | new_inst.* = .{ |
| 1434 | 1479 | .base = .{ |
| ... | ... | @@ -1436,7 +1481,7 @@ const EmitZIR = struct { |
| 1436 | 1481 | .tag = Inst.Call.base_tag, |
| 1437 | 1482 | }, |
| 1438 | 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 | 1485 | .args = args, |
| 1441 | 1486 | }, |
| 1442 | 1487 | .kw_args = .{}, |
| ... | ... | @@ -1453,7 +1498,7 @@ const EmitZIR = struct { |
| 1453 | 1498 | .tag = Inst.Return.base_tag, |
| 1454 | 1499 | }, |
| 1455 | 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 | 1503 | .kw_args = .{}, |
| 1459 | 1504 | }; |
| ... | ... | @@ -1477,7 +1522,7 @@ const EmitZIR = struct { |
| 1477 | 1522 | |
| 1478 | 1523 | const args = try self.arena.allocator.alloc(*Inst, old_inst.args.args.len); |
| 1479 | 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 | } |
| 1482 | 1527 | |
| 1483 | 1528 | new_inst.* = .{ |
| ... | ... | @@ -1511,7 +1556,7 @@ const EmitZIR = struct { |
| 1511 | 1556 | .tag = Inst.PtrToInt.base_tag, |
| 1512 | 1557 | }, |
| 1513 | 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 | 1561 | .kw_args = .{}, |
| 1517 | 1562 | }; |
| ... | ... | @@ -1527,7 +1572,7 @@ const EmitZIR = struct { |
| 1527 | 1572 | }, |
| 1528 | 1573 | .positionals = .{ |
| 1529 | 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 | 1577 | .kw_args = .{}, |
| 1533 | 1578 | }; |
| ... | ... | @@ -1542,8 +1587,8 @@ const EmitZIR = struct { |
| 1542 | 1587 | .tag = Inst.Cmp.base_tag, |
| 1543 | 1588 | }, |
| 1544 | 1589 | .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), | |
| 1547 | 1592 | .op = old_inst.args.op, |
| 1548 | 1593 | }, |
| 1549 | 1594 | .kw_args = .{}, |
| ... | ... | @@ -1569,7 +1614,7 @@ const EmitZIR = struct { |
| 1569 | 1614 | .tag = Inst.CondBr.base_tag, |
| 1570 | 1615 | }, |
| 1571 | 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 | 1618 | .true_body = .{ .instructions = true_body.toOwnedSlice() }, |
| 1574 | 1619 | .false_body = .{ .instructions = false_body.toOwnedSlice() }, |
| 1575 | 1620 | }, |
| ... | ... | @@ -1586,7 +1631,7 @@ const EmitZIR = struct { |
| 1586 | 1631 | .tag = Inst.IsNull.base_tag, |
| 1587 | 1632 | }, |
| 1588 | 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 | 1636 | .kw_args = .{}, |
| 1592 | 1637 | }; |
| ... | ... | @@ -1601,7 +1646,7 @@ const EmitZIR = struct { |
| 1601 | 1646 | .tag = Inst.IsNonNull.base_tag, |
| 1602 | 1647 | }, |
| 1603 | 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 | 1651 | .kw_args = .{}, |
| 1607 | 1652 | }; |
test/stage2/compile_errors.zig+3-5| ... | ... | @@ -27,9 +27,8 @@ pub fn addCases(ctx: *TestContext) !void { |
| 27 | 27 | \\ %0 = call(@notafunc, []) |
| 28 | 28 | \\}) |
| 29 | 29 | \\@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"}); | |
| 33 | 32 | |
| 34 | 33 | // TODO: this error should occur at the call site, not the fntype decl |
| 35 | 34 | ctx.addZIRError("call naked function", linux_x64, |
| ... | ... | @@ -41,8 +40,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 41 | 40 | \\ %0 = call(@s, []) |
| 42 | 41 | \\}) |
| 43 | 42 | \\@0 = str("_start") |
| 44 | \\@1 = ref(@0) | |
| 45 | \\@2 = export(@1, @start) | |
| 43 | \\@1 = export(@0, "start") | |
| 46 | 44 | , &[_][]const u8{":4:9: error: unable to call function with naked calling convention"}); |
| 47 | 45 | |
| 48 | 46 | // TODO: re-enable these tests. |
test/stage2/zir.zig+65-199| ... | ... | @@ -14,23 +14,21 @@ pub fn addCases(ctx: *TestContext) void { |
| 14 | 14 | \\@fnty = fntype([], @void, cc=C) |
| 15 | 15 | \\ |
| 16 | 16 | \\@9 = str("entry") |
| 17 | \\@10 = ref(@9) | |
| 18 | \\@11 = export(@10, @entry) | |
| 17 | \\@11 = export(@9, "entry") | |
| 19 | 18 | \\ |
| 20 | 19 | \\@entry = fn(@fnty, { |
| 21 | \\ %11 = return() | |
| 20 | \\ %11 = returnvoid() | |
| 22 | 21 | \\}) |
| 23 | 22 | , |
| 24 | 23 | \\@void = primitive(void) |
| 25 | 24 | \\@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() | |
| 34 | 32 | \\}) |
| 35 | 33 | \\ |
| 36 | 34 | ); |
| ... | ... | @@ -45,11 +43,10 @@ pub fn addCases(ctx: *TestContext) void { |
| 45 | 43 | \\ |
| 46 | 44 | \\@entry = fn(@fnty, { |
| 47 | 45 | \\ %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) | |
| 53 | 50 | \\ %v0 = deref(%eptr0) |
| 54 | 51 | \\ %v1 = deref(%eptr1) |
| 55 | 52 | \\ %v2 = deref(%eptr2) |
| ... | ... | @@ -61,15 +58,14 @@ pub fn addCases(ctx: *TestContext) void { |
| 61 | 58 | \\ %expected = int(69) |
| 62 | 59 | \\ %ok = cmp(%result, eq, %expected) |
| 63 | 60 | \\ %10 = condbr(%ok, { |
| 64 | \\ %11 = return() | |
| 61 | \\ %11 = returnvoid() | |
| 65 | 62 | \\ }, { |
| 66 | 63 | \\ %12 = breakpoint() |
| 67 | 64 | \\ }) |
| 68 | 65 | \\}) |
| 69 | 66 | \\ |
| 70 | 67 | \\@9 = str("entry") |
| 71 | \\@10 = ref(@9) | |
| 72 | \\@11 = export(@10, @entry) | |
| 68 | \\@11 = export(@9, "entry") | |
| 73 | 69 | , |
| 74 | 70 | \\@void = primitive(void) |
| 75 | 71 | \\@fnty = fntype([], @void, cc=C) |
| ... | ... | @@ -77,16 +73,15 @@ pub fn addCases(ctx: *TestContext) void { |
| 77 | 73 | \\@1 = int(1) |
| 78 | 74 | \\@2 = int(2) |
| 79 | 75 | \\@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() | |
| 83 | 79 | \\}) |
| 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") | |
| 90 | 85 | \\ |
| 91 | 86 | ); |
| 92 | 87 | |
| ... | ... | @@ -97,45 +92,43 @@ pub fn addCases(ctx: *TestContext) void { |
| 97 | 92 | \\@fnty = fntype([], @void, cc=C) |
| 98 | 93 | \\ |
| 99 | 94 | \\@9 = str("entry") |
| 100 | \\@10 = ref(@9) | |
| 101 | \\@11 = export(@10, @entry) | |
| 95 | \\@11 = export(@9, "entry") | |
| 102 | 96 | \\ |
| 103 | 97 | \\@entry = fn(@fnty, { |
| 104 | 98 | \\ %0 = call(@a, []) |
| 105 | \\ %1 = return() | |
| 99 | \\ %1 = returnvoid() | |
| 106 | 100 | \\}) |
| 107 | 101 | \\ |
| 108 | 102 | \\@a = fn(@fnty, { |
| 109 | 103 | \\ %0 = call(@b, []) |
| 110 | \\ %1 = return() | |
| 104 | \\ %1 = returnvoid() | |
| 111 | 105 | \\}) |
| 112 | 106 | \\ |
| 113 | 107 | \\@b = fn(@fnty, { |
| 114 | 108 | \\ %0 = call(@a, []) |
| 115 | \\ %1 = return() | |
| 109 | \\ %1 = returnvoid() | |
| 116 | 110 | \\}) |
| 117 | 111 | , |
| 118 | 112 | \\@void = primitive(void) |
| 119 | 113 | \\@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, { | |
| 127 | 120 | \\ %0 = call(@a, [], modifier=auto) |
| 128 | \\ %1 = return() | |
| 121 | \\ %1 = returnvoid() | |
| 129 | 122 | \\}) |
| 130 | \\@unnamed$17 = fntype([], @void, cc=C) | |
| 131 | \\@a = fn(@unnamed$17, { | |
| 123 | \\@unnamed$8 = fntype([], @void, cc=C) | |
| 124 | \\@a = fn(@unnamed$8, { | |
| 132 | 125 | \\ %0 = call(@b, [], modifier=auto) |
| 133 | \\ %1 = return() | |
| 126 | \\ %1 = returnvoid() | |
| 134 | 127 | \\}) |
| 135 | \\@unnamed$22 = fntype([], @void, cc=C) | |
| 136 | \\@b = fn(@unnamed$22, { | |
| 128 | \\@unnamed$10 = fntype([], @void, cc=C) | |
| 129 | \\@b = fn(@unnamed$10, { | |
| 137 | 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 | 138 | \\@fnty = fntype([], @void, cc=C) |
| 146 | 139 | \\ |
| 147 | 140 | \\@9 = str("entry") |
| 148 | \\@10 = ref(@9) | |
| 149 | \\@11 = export(@10, @entry) | |
| 141 | \\@11 = export(@9, "entry") | |
| 150 | 142 | \\ |
| 151 | 143 | \\@entry = fn(@fnty, { |
| 152 | 144 | \\ %0 = call(@a, []) |
| 153 | \\ %1 = return() | |
| 145 | \\ %1 = returnvoid() | |
| 154 | 146 | \\}) |
| 155 | 147 | \\ |
| 156 | 148 | \\@a = fn(@fnty, { |
| 157 | 149 | \\ %0 = call(@b, []) |
| 158 | \\ %1 = return() | |
| 150 | \\ %1 = returnvoid() | |
| 159 | 151 | \\}) |
| 160 | 152 | \\ |
| 161 | 153 | \\@b = fn(@fnty, { |
| 162 | 154 | \\ %9 = compileerror("message") |
| 163 | 155 | \\ %0 = call(@a, []) |
| 164 | \\ %1 = return() | |
| 156 | \\ %1 = returnvoid() | |
| 165 | 157 | \\}) |
| 166 | 158 | , |
| 167 | 159 | &[_][]const u8{ |
| 168 | ":19:21: error: message", | |
| 160 | ":18:21: error: message", | |
| 169 | 161 | }, |
| 170 | 162 | ); |
| 171 | 163 | // 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 | 168 | \\@fnty = fntype([], @void, cc=C) |
| 177 | 169 | \\ |
| 178 | 170 | \\@9 = str("entry") |
| 179 | \\@10 = ref(@9) | |
| 180 | \\@11 = export(@10, @entry) | |
| 171 | \\@11 = export(@9, "entry") | |
| 181 | 172 | \\ |
| 182 | 173 | \\@entry = fn(@fnty, { |
| 183 | \\ %1 = return() | |
| 174 | \\ %0 = returnvoid() | |
| 184 | 175 | \\}) |
| 185 | 176 | \\ |
| 186 | 177 | \\@a = fn(@fnty, { |
| 187 | 178 | \\ %0 = call(@b, []) |
| 188 | \\ %1 = return() | |
| 179 | \\ %1 = returnvoid() | |
| 189 | 180 | \\}) |
| 190 | 181 | \\ |
| 191 | 182 | \\@b = fn(@fnty, { |
| 192 | 183 | \\ %9 = compileerror("message") |
| 193 | 184 | \\ %0 = call(@a, []) |
| 194 | \\ %1 = return() | |
| 185 | \\ %1 = returnvoid() | |
| 195 | 186 | \\}) |
| 196 | 187 | , |
| 197 | 188 | \\@void = primitive(void) |
| 198 | 189 | \\@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() | |
| 207 | 197 | \\}) |
| 208 | 198 | \\ |
| 209 | 199 | ); |
| ... | ... | @@ -218,7 +208,7 @@ pub fn addCases(ctx: *TestContext) void { |
| 218 | 208 | } |
| 219 | 209 | |
| 220 | 210 | ctx.addZIRCompareOutput( |
| 221 | "hello world ZIR, update msg", | |
| 211 | "hello world ZIR", | |
| 222 | 212 | &[_][]const u8{ |
| 223 | 213 | \\@noreturn = primitive(noreturn) |
| 224 | 214 | \\@void = primitive(void) |
| ... | ... | @@ -272,125 +262,10 @@ pub fn addCases(ctx: *TestContext) void { |
| 272 | 262 | \\ |
| 273 | 263 | \\@9 = str("_start") |
| 274 | 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 | 266 | &[_][]const u8{ |
| 385 | 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 | ); |
| 396 | 271 | |
| ... | ... | @@ -405,26 +280,18 @@ pub fn addCases(ctx: *TestContext) void { |
| 405 | 280 | \\@2 = int(2) |
| 406 | 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 | 283 | \\@exit0_fnty = fntype([], @noreturn) |
| 417 | 284 | \\@exit0 = fn(@exit0_fnty, { |
| 418 | 285 | \\ %SYS_exit_group = int(231) |
| 419 | 286 | \\ %exit_code = as(@usize, @0) |
| 420 | 287 | \\ |
| 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") | |
| 428 | 295 | \\ |
| 429 | 296 | \\ %rc = asm(%syscall, @usize, |
| 430 | 297 | \\ volatile=1, |
| ... | ... | @@ -441,8 +308,7 @@ pub fn addCases(ctx: *TestContext) void { |
| 441 | 308 | \\ %0 = call(@exit0, []) |
| 442 | 309 | \\}) |
| 443 | 310 | \\@9 = str("_start") |
| 444 | \\@10 = ref(@9) | |
| 445 | \\@11 = export(@10, @start) | |
| 311 | \\@11 = export(@9, "start") | |
| 446 | 312 | }, |
| 447 | 313 | &[_][]const u8{""}, |
| 448 | 314 | ); |