| 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,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. |
| 70 | deletion_set: std.ArrayListUnmanaged(*Decl) = .{}, | 70 | deletion_set: std.ArrayListUnmanaged(*Decl) = .{}, |
| 71 | 71 | ||
| 72 | keep_source_files_loaded: bool, | ||
| 73 | |||
| 72 | const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql); | 74 | const DeclTable = std.HashMap(Scope.NameHash, *Decl, Scope.name_hash_hash, Scope.name_hash_eql); |
| 73 | 75 | ||
| 74 | const WorkItem = union(enum) { | 76 | const 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 | }; |
| 723 | 728 | ||
| 724 | pub fn init(gpa: *Allocator, options: InitOptions) !Module { | 729 | pub 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 | } |
| 777 | 783 | ||
| ... | @@ -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(); |
| 870 | 876 | ||
| 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); | ||
| 880 | 885 | ||
| 881 | self.link_error_flags = self.bin_file.error_flags; | 886 | self.link_error_flags = self.bin_file.error_flags; |
| 882 | 887 | ||
| 883 | // If there are any errors, we anticipate the source files being loaded | 888 | // 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(); |
| 1026 | 1033 | ||
| 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, |
| 1030 | 1036 | ||
| 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, |
| 1037 | 1043 | ||
| 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}); |
| 1040 | 1050 | ||
| 1041 | // The exports this Decl performs will be re-discovered, so we remove them here | 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,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 one | 1058 | // 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 confused | 1789 | // 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 | } |
| 1789 | 1798 | ||
| 1790 | fn deleteDecl(self: *Module, decl: *Decl) !void { | 1799 | fn 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 | } |
| 2033 | 2042 | ||
| 2034 | fn requireRuntimeBlock(self: *Module, scope: *Scope, src: usize) !*Scope.Block { | 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,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 something | 395 | // 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 0 | 413 | 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 }); |
| 474 | 474 | ||
| 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 }); |
| 590 | 590 | ||
| 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 { |
| 632 | 632 | ||
| 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); |
| 957 | 957 | ||
| 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; |
| 1033 | 1033 | ||
| 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); |
| 1054 | 1054 | ||
| 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 | ; |
| 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 | pub fn main() !void { | 65 | pub fn main() !void { |
| 42 | // TODO general purpose allocator in the zig std lib | 66 | // 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(); |
| 455 | 480 |
src-self-hosted/test.zig+22-13| ... | @@ -226,20 +226,36 @@ pub const TestContext = struct { | ... | @@ -226,20 +226,36 @@ pub const TestContext = struct { |
| 226 | 226 | ||
| 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 | } |
| 233 | 241 | ||
| 234 | // TODO: wipe the rest of this function | 242 | // 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 | } |
| 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 | var tmp = std.testing.tmpDir(.{}); | 259 | var tmp = std.testing.tmpDir(.{}); |
| 244 | defer tmp.cleanup(); | 260 | defer tmp.cleanup(); |
| 245 | 261 | ||
| ... | @@ -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(); |
| 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 | 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 does | 268 | // 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(); |
| 270 | 283 | ||
| ... | @@ -329,7 +342,7 @@ pub const TestContext = struct { | ... | @@ -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,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(); |
| 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 | 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 @@ |
| 1 | pub const std = @import("std"); | 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 | extern fn ___tracy_emit_zone_begin_callstack( | 5 | extern 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 { |
| 1175 | 1176 | ||
| 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 | } |
| 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 | 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 | } |
| 1218 | 1259 | ||
| ... | @@ -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 { |
| 1428 | 1473 | ||
| 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 { |
| 1477 | 1522 | ||
| 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 | } |
| 1482 | 1527 | ||
| 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'"}); | ||
| 33 | 32 | ||
| 34 | // TODO: this error should occur at the call site, not the fntype decl | 33 | // 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"}); |
| 47 | 45 | ||
| 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 | ); |
| 92 | 87 | ||
| ... | @@ -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 are | 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,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 | } |
| 219 | 209 | ||
| 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 | ); |
| 396 | 271 | ||
| ... | @@ -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 | ); |