| author | |
| committer | |
| log | 69abc945e45af3f447f9ee07d426d1ec40cf3f15 |
| tree | 457a9ee76f91135cf7a71192a09c317a63c05961 |
| parent | 1274254c48ee105623c513dfc01451fee2912c5b |
Closes #24553124 files changed, 1078 insertions(+), 365 deletions(-)
src/Compilation.zig+6-4| ... | @@ -1816,10 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1816,10 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1816 | if (options.skip_linker_dependencies) break :s .none; | 1816 | if (options.skip_linker_dependencies) break :s .none; |
| 1817 | const want = options.want_compiler_rt orelse is_exe_or_dyn_lib; | 1817 | const want = options.want_compiler_rt orelse is_exe_or_dyn_lib; |
| 1818 | if (!want) break :s .none; | 1818 | if (!want) break :s .none; |
| 1819 | if (have_zcu) { | 1819 | if (have_zcu and target_util.canBuildLibCompilerRt(target, use_llvm, build_options.have_llvm and use_llvm)) { |
| 1820 | if (output_mode == .Obj) break :s .zcu; | 1820 | if (output_mode == .Obj) break :s .zcu; |
| 1821 | if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64) | 1821 | if (switch (target_util.zigBackend(target, use_llvm)) { |
| 1822 | break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu; | 1822 | else => false, |
| 1823 | .stage2_aarch64, .stage2_x86_64 => target.ofmt == .coff, | ||
| 1824 | }) break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu; | ||
| 1823 | } | 1825 | } |
| 1824 | if (is_exe_or_dyn_lib) break :s .lib; | 1826 | if (is_exe_or_dyn_lib) break :s .lib; |
| 1825 | break :s .obj; | 1827 | break :s .obj; |
| ... | @@ -1854,7 +1856,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1854,7 +1856,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1854 | const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib); | 1856 | const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib); |
| 1855 | if (!want_ubsan_rt) break :s .none; | 1857 | if (!want_ubsan_rt) break :s .none; |
| 1856 | if (options.skip_linker_dependencies) break :s .none; | 1858 | if (options.skip_linker_dependencies) break :s .none; |
| 1857 | if (have_zcu) break :s .zcu; | 1859 | if (have_zcu and target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm and use_llvm)) break :s .zcu; |
| 1858 | if (is_exe_or_dyn_lib) break :s .lib; | 1860 | if (is_exe_or_dyn_lib) break :s .lib; |
| 1859 | break :s .obj; | 1861 | break :s .obj; |
| 1860 | }; | 1862 | }; |
src/arch/x86_64/CodeGen.zig+3-3| ... | @@ -168141,7 +168141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -168141,7 +168141,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168141 | .unused, | 168141 | .unused, |
| 168142 | .unused, | 168142 | .unused, |
| 168143 | }, | 168143 | }, |
| 168144 | .dst_temps = .{ .{ .cc = .b }, .unused }, | 168144 | .dst_temps = .{ .{ .cc = .be }, .unused }, |
| 168145 | .clobbers = .{ .eflags = true }, | 168145 | .clobbers = .{ .eflags = true }, |
| 168146 | .each = .{ .once = &.{ | 168146 | .each = .{ .once = &.{ |
| 168147 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, | 168147 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
| ... | @@ -168165,7 +168165,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -168165,7 +168165,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168165 | .unused, | 168165 | .unused, |
| 168166 | .unused, | 168166 | .unused, |
| 168167 | }, | 168167 | }, |
| 168168 | .dst_temps = .{ .{ .cc = .b }, .unused }, | 168168 | .dst_temps = .{ .{ .cc = .be }, .unused }, |
| 168169 | .clobbers = .{ .eflags = true }, | 168169 | .clobbers = .{ .eflags = true }, |
| 168170 | .each = .{ .once = &.{ | 168170 | .each = .{ .once = &.{ |
| 168171 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, | 168171 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
| ... | @@ -168189,7 +168189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -168189,7 +168189,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 168189 | .unused, | 168189 | .unused, |
| 168190 | .unused, | 168190 | .unused, |
| 168191 | }, | 168191 | }, |
| 168192 | .dst_temps = .{ .{ .cc = .b }, .unused }, | 168192 | .dst_temps = .{ .{ .cc = .be }, .unused }, |
| 168193 | .clobbers = .{ .eflags = true }, | 168193 | .clobbers = .{ .eflags = true }, |
| 168194 | .each = .{ .once = &.{ | 168194 | .each = .{ .once = &.{ |
| 168195 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, | 168195 | .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ }, |
src/arch/x86_64/Emit.zig+6-5| ... | @@ -168,11 +168,12 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -168,11 +168,12 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 168 | else if (emit.bin_file.cast(.macho)) |macho_file| | 168 | else if (emit.bin_file.cast(.macho)) |macho_file| |
| 169 | macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err| | 169 | macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err| |
| 170 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) | 170 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) |
| 171 | else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: { | 171 | else if (emit.bin_file.cast(.coff)) |coff_file| |
| 172 | const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err| | 172 | if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom| |
| 173 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}); | 173 | coff_file.getAtom(atom).getSymbolIndex().? |
| 174 | break :sym_index coff_file.getAtom(atom).getSymbolIndex().?; | 174 | else |err| |
| 175 | } else if (emit.bin_file.cast(.plan9)) |p9_file| | 175 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) |
| 176 | else if (emit.bin_file.cast(.plan9)) |p9_file| | ||
| 176 | p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err| | 177 | p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err| |
| 177 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) | 178 | return emit.fail("{s} creating lazy symbol", .{@errorName(err)}) |
| 178 | else | 179 | else |
src/codegen/aarch64.zig+5-2| ... | @@ -47,6 +47,7 @@ pub fn generate( | ... | @@ -47,6 +47,7 @@ pub fn generate( |
| 47 | .literals = .empty, | 47 | .literals = .empty, |
| 48 | .nav_relocs = .empty, | 48 | .nav_relocs = .empty, |
| 49 | .uav_relocs = .empty, | 49 | .uav_relocs = .empty, |
| 50 | .lazy_relocs = .empty, | ||
| 50 | .global_relocs = .empty, | 51 | .global_relocs = .empty, |
| 51 | .literal_relocs = .empty, | 52 | .literal_relocs = .empty, |
| 52 | 53 | ||
| ... | @@ -101,8 +102,8 @@ pub fn generate( | ... | @@ -101,8 +102,8 @@ pub fn generate( |
| 101 | }; | 102 | }; |
| 102 | switch (passed_vi.parent(&isel)) { | 103 | switch (passed_vi.parent(&isel)) { |
| 103 | .unallocated => if (!mod.strip) { | 104 | .unallocated => if (!mod.strip) { |
| 104 | var part_it = arg_vi.parts(&isel); | 105 | var part_it = passed_vi.parts(&isel); |
| 105 | const first_passed_part_vi = part_it.next() orelse passed_vi; | 106 | const first_passed_part_vi = part_it.next().?; |
| 106 | const hint_ra = first_passed_part_vi.hint(&isel).?; | 107 | const hint_ra = first_passed_part_vi.hint(&isel).?; |
| 107 | passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector()) | 108 | passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector()) |
| 108 | isel.va_list.__vr_top.withOffset(@as(i8, -16) * | 109 | isel.va_list.__vr_top.withOffset(@as(i8, -16) * |
| ... | @@ -167,6 +168,7 @@ pub fn generate( | ... | @@ -167,6 +168,7 @@ pub fn generate( |
| 167 | .literals = &.{}, | 168 | .literals = &.{}, |
| 168 | .nav_relocs = &.{}, | 169 | .nav_relocs = &.{}, |
| 169 | .uav_relocs = &.{}, | 170 | .uav_relocs = &.{}, |
| 171 | .lazy_relocs = &.{}, | ||
| 170 | .global_relocs = &.{}, | 172 | .global_relocs = &.{}, |
| 171 | .literal_relocs = &.{}, | 173 | .literal_relocs = &.{}, |
| 172 | }; | 174 | }; |
| ... | @@ -174,6 +176,7 @@ pub fn generate( | ... | @@ -174,6 +176,7 @@ pub fn generate( |
| 174 | mir.literals = try isel.literals.toOwnedSlice(gpa); | 176 | mir.literals = try isel.literals.toOwnedSlice(gpa); |
| 175 | mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa); | 177 | mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa); |
| 176 | mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa); | 178 | mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa); |
| 179 | mir.lazy_relocs = try isel.lazy_relocs.toOwnedSlice(gpa); | ||
| 177 | mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa); | 180 | mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa); |
| 178 | mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa); | 181 | mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa); |
| 179 | return mir; | 182 | return mir; |
src/codegen/aarch64/Assemble.zig+26-6| ... | @@ -6,14 +6,19 @@ pub const Operand = union(enum) { | ... | @@ -6,14 +6,19 @@ pub const Operand = union(enum) { |
| 6 | }; | 6 | }; |
| 7 | 7 | ||
| 8 | pub fn nextInstruction(as: *Assemble) !?Instruction { | 8 | pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 9 | @setEvalBranchQuota(37_000); | 9 | @setEvalBranchQuota(42_000); |
| 10 | comptime var ct_token_buf: [token_buf_len]u8 = undefined; | 10 | comptime var ct_token_buf: [token_buf_len]u8 = undefined; |
| 11 | var token_buf: [token_buf_len]u8 = undefined; | 11 | var token_buf: [token_buf_len]u8 = undefined; |
| 12 | const original_source = while (true) { | 12 | const original_source = while (true) { |
| 13 | const original_source = as.source; | 13 | const original_source = as.source; |
| 14 | const source_token = try as.nextToken(&token_buf, .{}); | 14 | const source_token = try as.nextToken(&token_buf, .{}); |
| 15 | if (source_token.len == 0) return null; | 15 | switch (source_token.len) { |
| 16 | if (source_token[0] != '\n') break original_source; | 16 | 0 => return null, |
| 17 | else => switch (source_token[0]) { | ||
| 18 | else => break original_source, | ||
| 19 | '\n', ';' => {}, | ||
| 20 | }, | ||
| 21 | } | ||
| 17 | }; | 22 | }; |
| 18 | log.debug( | 23 | log.debug( |
| 19 | \\. | 24 | \\. |
| ... | @@ -52,7 +57,13 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { | ... | @@ -52,7 +57,13 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 52 | std.zig.fmtString(source_token), | 57 | std.zig.fmtString(source_token), |
| 53 | }); | 58 | }); |
| 54 | if (pattern_token.len == 0) { | 59 | if (pattern_token.len == 0) { |
| 55 | if (source_token.len > 0 and source_token[0] != '\n') break :next_pattern; | 60 | switch (source_token.len) { |
| 61 | 0 => {}, | ||
| 62 | else => switch (source_token[0]) { | ||
| 63 | else => break :next_pattern, | ||
| 64 | '\n', ';' => {}, | ||
| 65 | }, | ||
| 66 | } | ||
| 56 | const encode = @field(Instruction, @tagName(instruction.encode[0])); | 67 | const encode = @field(Instruction, @tagName(instruction.encode[0])); |
| 57 | const Encode = @TypeOf(encode); | 68 | const Encode = @TypeOf(encode); |
| 58 | var args: std.meta.ArgsTuple(Encode) = undefined; | 69 | var args: std.meta.ArgsTuple(Encode) = undefined; |
| ... | @@ -65,7 +76,7 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { | ... | @@ -65,7 +76,7 @@ pub fn nextInstruction(as: *Assemble) !?Instruction { |
| 65 | const symbol = &@field(symbols, symbol_name); | 76 | const symbol = &@field(symbols, symbol_name); |
| 66 | symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern; | 77 | symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern; |
| 67 | log.debug("{s} = {any}", .{ symbol_name, symbol.* }); | 78 | log.debug("{s} = {any}", .{ symbol_name, symbol.* }); |
| 68 | } else if (!std.ascii.eqlIgnoreCase(pattern_token, source_token)) break :next_pattern; | 79 | } else if (!toUpperEqlAssertUpper(source_token, pattern_token)) break :next_pattern; |
| 69 | } | 80 | } |
| 70 | } | 81 | } |
| 71 | log.debug("'{s}' not matched...", .{instruction.pattern}); | 82 | log.debug("'{s}' not matched...", .{instruction.pattern}); |
| ... | @@ -125,6 +136,15 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result { | ... | @@ -125,6 +136,15 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result { |
| 125 | } | 136 | } |
| 126 | } | 137 | } |
| 127 | 138 | ||
| 139 | fn toUpperEqlAssertUpper(lhs: []const u8, rhs: []const u8) bool { | ||
| 140 | if (lhs.len != rhs.len) return false; | ||
| 141 | for (lhs, rhs) |l, r| { | ||
| 142 | assert(!std.ascii.isLower(r)); | ||
| 143 | if (std.ascii.toUpper(l) != r) return false; | ||
| 144 | } | ||
| 145 | return true; | ||
| 146 | } | ||
| 147 | |||
| 128 | const token_buf_len = "v31.b[15]".len; | 148 | const token_buf_len = "v31.b[15]".len; |
| 129 | fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { | 149 | fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { |
| 130 | operands: bool = false, | 150 | operands: bool = false, |
| ... | @@ -134,7 +154,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { | ... | @@ -134,7 +154,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct { |
| 134 | while (true) c: switch (as.source[0]) { | 154 | while (true) c: switch (as.source[0]) { |
| 135 | 0 => return as.source[0..0], | 155 | 0 => return as.source[0..0], |
| 136 | '\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..], | 156 | '\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..], |
| 137 | '\n', '!', '#', ',', '[', ']' => { | 157 | '\n', '!', '#', ',', ';', '[', ']' => { |
| 138 | defer as.source = as.source[1..]; | 158 | defer as.source = as.source[1..]; |
| 139 | return as.source[0..1]; | 159 | return as.source[0..1]; |
| 140 | }, | 160 | }, |
src/codegen/aarch64/Mir.zig+106-33| ... | @@ -4,6 +4,7 @@ epilogue: []const Instruction, | ... | @@ -4,6 +4,7 @@ epilogue: []const Instruction, |
| 4 | literals: []const u32, | 4 | literals: []const u32, |
| 5 | nav_relocs: []const Reloc.Nav, | 5 | nav_relocs: []const Reloc.Nav, |
| 6 | uav_relocs: []const Reloc.Uav, | 6 | uav_relocs: []const Reloc.Uav, |
| 7 | lazy_relocs: []const Reloc.Lazy, | ||
| 7 | global_relocs: []const Reloc.Global, | 8 | global_relocs: []const Reloc.Global, |
| 8 | literal_relocs: []const Reloc.Literal, | 9 | literal_relocs: []const Reloc.Literal, |
| 9 | 10 | ||
| ... | @@ -21,8 +22,13 @@ pub const Reloc = struct { | ... | @@ -21,8 +22,13 @@ pub const Reloc = struct { |
| 21 | reloc: Reloc, | 22 | reloc: Reloc, |
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 25 | pub const Lazy = struct { | ||
| 26 | symbol: link.File.LazySymbol, | ||
| 27 | reloc: Reloc, | ||
| 28 | }; | ||
| 29 | |||
| 24 | pub const Global = struct { | 30 | pub const Global = struct { |
| 25 | global: [*:0]const u8, | 31 | name: [*:0]const u8, |
| 26 | reloc: Reloc, | 32 | reloc: Reloc, |
| 27 | }; | 33 | }; |
| 28 | 34 | ||
| ... | @@ -38,6 +44,7 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { | ... | @@ -38,6 +44,7 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void { |
| 38 | gpa.free(mir.literals); | 44 | gpa.free(mir.literals); |
| 39 | gpa.free(mir.nav_relocs); | 45 | gpa.free(mir.nav_relocs); |
| 40 | gpa.free(mir.uav_relocs); | 46 | gpa.free(mir.uav_relocs); |
| 47 | gpa.free(mir.lazy_relocs); | ||
| 41 | gpa.free(mir.global_relocs); | 48 | gpa.free(mir.global_relocs); |
| 42 | gpa.free(mir.literal_relocs); | 49 | gpa.free(mir.literal_relocs); |
| 43 | mir.* = undefined; | 50 | mir.* = undefined; |
| ... | @@ -119,16 +126,37 @@ pub fn emit( | ... | @@ -119,16 +126,37 @@ pub fn emit( |
| 119 | body_end - Instruction.size * (1 + uav_reloc.reloc.label), | 126 | body_end - Instruction.size * (1 + uav_reloc.reloc.label), |
| 120 | uav_reloc.reloc.addend, | 127 | uav_reloc.reloc.addend, |
| 121 | ); | 128 | ); |
| 129 | for (mir.lazy_relocs) |lazy_reloc| try emitReloc( | ||
| 130 | lf, | ||
| 131 | zcu, | ||
| 132 | func.owner_nav, | ||
| 133 | if (lf.cast(.elf)) |ef| | ||
| 134 | ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_reloc.symbol) catch |err| | ||
| 135 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | ||
| 136 | else if (lf.cast(.macho)) |mf| | ||
| 137 | mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err| | ||
| 138 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | ||
| 139 | else if (lf.cast(.coff)) |cf| | ||
| 140 | if (cf.getOrCreateAtomForLazySymbol(pt, lazy_reloc.symbol)) |atom| | ||
| 141 | cf.getAtom(atom).getSymbolIndex().? | ||
| 142 | else |err| | ||
| 143 | return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)}) | ||
| 144 | else | ||
| 145 | return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), | ||
| 146 | mir.body[lazy_reloc.reloc.label], | ||
| 147 | body_end - Instruction.size * (1 + lazy_reloc.reloc.label), | ||
| 148 | lazy_reloc.reloc.addend, | ||
| 149 | ); | ||
| 122 | for (mir.global_relocs) |global_reloc| try emitReloc( | 150 | for (mir.global_relocs) |global_reloc| try emitReloc( |
| 123 | lf, | 151 | lf, |
| 124 | zcu, | 152 | zcu, |
| 125 | func.owner_nav, | 153 | func.owner_nav, |
| 126 | if (lf.cast(.elf)) |ef| | 154 | if (lf.cast(.elf)) |ef| |
| 127 | try ef.getGlobalSymbol(std.mem.span(global_reloc.global), null) | 155 | try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null) |
| 128 | else if (lf.cast(.macho)) |mf| | 156 | else if (lf.cast(.macho)) |mf| |
| 129 | try mf.getGlobalSymbol(std.mem.span(global_reloc.global), null) | 157 | try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null) |
| 130 | else if (lf.cast(.coff)) |cf| | 158 | else if (lf.cast(.coff)) |cf| |
| 131 | try cf.getGlobalSymbol(std.mem.span(global_reloc.global), "compiler_rt") | 159 | try cf.getGlobalSymbol(std.mem.span(global_reloc.name), "compiler_rt") |
| 132 | else | 160 | else |
| 133 | return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), | 161 | return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}), |
| 134 | mir.body[global_reloc.reloc.label], | 162 | mir.body[global_reloc.reloc.label], |
| ... | @@ -172,35 +200,6 @@ fn emitReloc( | ... | @@ -172,35 +200,6 @@ fn emitReloc( |
| 172 | const gpa = zcu.gpa; | 200 | const gpa = zcu.gpa; |
| 173 | switch (instruction.decode()) { | 201 | switch (instruction.decode()) { |
| 174 | else => unreachable, | 202 | else => unreachable, |
| 175 | .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| { | ||
| 176 | const zo = ef.zigObjectPtr().?; | ||
| 177 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | ||
| 178 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) { | ||
| 179 | .b => .JUMP26, | ||
| 180 | .bl => .CALL26, | ||
| 181 | }; | ||
| 182 | try atom.addReloc(gpa, .{ | ||
| 183 | .r_offset = offset, | ||
| 184 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | ||
| 185 | .r_addend = @bitCast(addend), | ||
| 186 | }, zo); | ||
| 187 | } else if (lf.cast(.macho)) |mf| { | ||
| 188 | const zo = mf.getZigObject().?; | ||
| 189 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | ||
| 190 | try atom.addReloc(mf, .{ | ||
| 191 | .tag = .@"extern", | ||
| 192 | .offset = offset, | ||
| 193 | .target = sym_index, | ||
| 194 | .addend = @bitCast(addend), | ||
| 195 | .type = .branch, | ||
| 196 | .meta = .{ | ||
| 197 | .pcrel = true, | ||
| 198 | .has_subtractor = false, | ||
| 199 | .length = 2, | ||
| 200 | .symbolnum = @intCast(sym_index), | ||
| 201 | }, | ||
| 202 | }); | ||
| 203 | }, | ||
| 204 | .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| { | 203 | .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| { |
| 205 | const zo = ef.zigObjectPtr().?; | 204 | const zo = ef.zigObjectPtr().?; |
| 206 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | 205 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; |
| ... | @@ -259,6 +258,80 @@ fn emitReloc( | ... | @@ -259,6 +258,80 @@ fn emitReloc( |
| 259 | }, | 258 | }, |
| 260 | } | 259 | } |
| 261 | }, | 260 | }, |
| 261 | .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| { | ||
| 262 | const zo = ef.zigObjectPtr().?; | ||
| 263 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | ||
| 264 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) { | ||
| 265 | .b => .JUMP26, | ||
| 266 | .bl => .CALL26, | ||
| 267 | }; | ||
| 268 | try atom.addReloc(gpa, .{ | ||
| 269 | .r_offset = offset, | ||
| 270 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | ||
| 271 | .r_addend = @bitCast(addend), | ||
| 272 | }, zo); | ||
| 273 | } else if (lf.cast(.macho)) |mf| { | ||
| 274 | const zo = mf.getZigObject().?; | ||
| 275 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | ||
| 276 | try atom.addReloc(mf, .{ | ||
| 277 | .tag = .@"extern", | ||
| 278 | .offset = offset, | ||
| 279 | .target = sym_index, | ||
| 280 | .addend = @bitCast(addend), | ||
| 281 | .type = .branch, | ||
| 282 | .meta = .{ | ||
| 283 | .pcrel = true, | ||
| 284 | .has_subtractor = false, | ||
| 285 | .length = 2, | ||
| 286 | .symbolnum = @intCast(sym_index), | ||
| 287 | }, | ||
| 288 | }); | ||
| 289 | }, | ||
| 290 | .load_store => |decoded| if (lf.cast(.elf)) |ef| { | ||
| 291 | const zo = ef.zigObjectPtr().?; | ||
| 292 | const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?; | ||
| 293 | const r_type: std.elf.R_AARCH64 = switch (decoded.decode().register_unsigned_immediate.decode()) { | ||
| 294 | .integer => |integer| switch (integer.decode()) { | ||
| 295 | .unallocated, .prfm => unreachable, | ||
| 296 | .strb, .ldrb, .ldrsb => .LDST8_ABS_LO12_NC, | ||
| 297 | .strh, .ldrh, .ldrsh => .LDST16_ABS_LO12_NC, | ||
| 298 | .ldrsw => .LDST32_ABS_LO12_NC, | ||
| 299 | inline .str, .ldr => |encoded| switch (encoded.sf) { | ||
| 300 | .word => .LDST32_ABS_LO12_NC, | ||
| 301 | .doubleword => .LDST64_ABS_LO12_NC, | ||
| 302 | }, | ||
| 303 | }, | ||
| 304 | .vector => |vector| switch (vector.group.opc1.decode(vector.group.size)) { | ||
| 305 | .byte => .LDST8_ABS_LO12_NC, | ||
| 306 | .half => .LDST16_ABS_LO12_NC, | ||
| 307 | .single => .LDST32_ABS_LO12_NC, | ||
| 308 | .double => .LDST64_ABS_LO12_NC, | ||
| 309 | .quad => .LDST128_ABS_LO12_NC, | ||
| 310 | .scalable, .predicate => unreachable, | ||
| 311 | }, | ||
| 312 | }; | ||
| 313 | try atom.addReloc(gpa, .{ | ||
| 314 | .r_offset = offset, | ||
| 315 | .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type), | ||
| 316 | .r_addend = @bitCast(addend), | ||
| 317 | }, zo); | ||
| 318 | } else if (lf.cast(.macho)) |mf| { | ||
| 319 | const zo = mf.getZigObject().?; | ||
| 320 | const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?; | ||
| 321 | try atom.addReloc(mf, .{ | ||
| 322 | .tag = .@"extern", | ||
| 323 | .offset = offset, | ||
| 324 | .target = sym_index, | ||
| 325 | .addend = @bitCast(addend), | ||
| 326 | .type = .pageoff, | ||
| 327 | .meta = .{ | ||
| 328 | .pcrel = false, | ||
| 329 | .has_subtractor = false, | ||
| 330 | .length = 2, | ||
| 331 | .symbolnum = @intCast(sym_index), | ||
| 332 | }, | ||
| 333 | }); | ||
| 334 | }, | ||
| 262 | } | 335 | } |
| 263 | } | 336 | } |
| 264 | 337 |
src/codegen/aarch64/Select.zig+618-188| ... | @@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction), | ... | @@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction), |
| 22 | literals: std.ArrayListUnmanaged(u32), | 22 | literals: std.ArrayListUnmanaged(u32), |
| 23 | nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav), | 23 | nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav), |
| 24 | uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav), | 24 | uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav), |
| 25 | lazy_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Lazy), | ||
| 25 | global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global), | 26 | global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global), |
| 26 | literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal), | 27 | literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal), |
| 27 | 28 | ||
| ... | @@ -50,11 +51,11 @@ pub const Block = struct { | ... | @@ -50,11 +51,11 @@ pub const Block = struct { |
| 50 | std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type), | 51 | std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type), |
| 51 | ); | 52 | ); |
| 52 | 53 | ||
| 53 | fn branch(block: *const Block, isel: *Select) !void { | 54 | fn branch(target_block: *const Block, isel: *Select) !void { |
| 54 | if (isel.instructions.items.len > block.target_label) { | 55 | if (isel.instructions.items.len > target_block.target_label) { |
| 55 | try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - block.target_label) << 2))); | 56 | try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - target_block.target_label) << 2))); |
| 56 | } | 57 | } |
| 57 | try isel.merge(&block.live_registers, .{}); | 58 | try isel.merge(&target_block.live_registers, .{}); |
| 58 | } | 59 | } |
| 59 | }; | 60 | }; |
| 60 | 61 | ||
| ... | @@ -84,12 +85,12 @@ pub const Loop = struct { | ... | @@ -84,12 +85,12 @@ pub const Loop = struct { |
| 84 | 85 | ||
| 85 | pub const empty_list: u32 = std.math.maxInt(u32); | 86 | pub const empty_list: u32 = std.math.maxInt(u32); |
| 86 | 87 | ||
| 87 | fn branch(loop: *Loop, isel: *Select) !void { | 88 | fn branch(target_loop: *Loop, isel: *Select) !void { |
| 88 | try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1); | 89 | try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1); |
| 89 | const repeat_list_tail = loop.repeat_list; | 90 | const repeat_list_tail = target_loop.repeat_list; |
| 90 | loop.repeat_list = @intCast(isel.instructions.items.len); | 91 | target_loop.repeat_list = @intCast(isel.instructions.items.len); |
| 91 | isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail)); | 92 | isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail)); |
| 92 | try isel.merge(&loop.live_registers, .{}); | 93 | try isel.merge(&target_loop.live_registers, .{}); |
| 93 | } | 94 | } |
| 94 | }; | 95 | }; |
| 95 | 96 | ||
| ... | @@ -108,6 +109,7 @@ pub fn deinit(isel: *Select) void { | ... | @@ -108,6 +109,7 @@ pub fn deinit(isel: *Select) void { |
| 108 | isel.literals.deinit(gpa); | 109 | isel.literals.deinit(gpa); |
| 109 | isel.nav_relocs.deinit(gpa); | 110 | isel.nav_relocs.deinit(gpa); |
| 110 | isel.uav_relocs.deinit(gpa); | 111 | isel.uav_relocs.deinit(gpa); |
| 112 | isel.lazy_relocs.deinit(gpa); | ||
| 111 | isel.global_relocs.deinit(gpa); | 113 | isel.global_relocs.deinit(gpa); |
| 112 | isel.literal_relocs.deinit(gpa); | 114 | isel.literal_relocs.deinit(gpa); |
| 113 | 115 | ||
| ... | @@ -864,7 +866,7 @@ pub fn finishAnalysis(isel: *Select) !void { | ... | @@ -864,7 +866,7 @@ pub fn finishAnalysis(isel: *Select) !void { |
| 864 | } | 866 | } |
| 865 | } | 867 | } |
| 866 | 868 | ||
| 867 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | 869 | pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void { |
| 868 | const zcu = isel.pt.zcu; | 870 | const zcu = isel.pt.zcu; |
| 869 | const ip = &zcu.intern_pool; | 871 | const ip = &zcu.intern_pool; |
| 870 | const gpa = zcu.gpa; | 872 | const gpa = zcu.gpa; |
| ... | @@ -946,7 +948,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -946,7 +948,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 946 | } | 948 | } |
| 947 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 949 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 948 | }, | 950 | }, |
| 949 | .add, .add_optimized, .add_wrap, .sub, .sub_optimized, .sub_wrap => |air_tag| { | 951 | .add, .add_safe, .add_optimized, .add_wrap, .sub, .sub_safe, .sub_optimized, .sub_wrap => |air_tag| { |
| 950 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | 952 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 951 | defer res_vi.value.deref(isel); | 953 | defer res_vi.value.deref(isel); |
| 952 | 954 | ||
| ... | @@ -954,13 +956,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -954,13 +956,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 954 | const ty = isel.air.typeOf(bin_op.lhs, ip); | 956 | const ty = isel.air.typeOf(bin_op.lhs, ip); |
| 955 | if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) { | 957 | if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) { |
| 956 | else => unreachable, | 958 | else => unreachable, |
| 957 | .add, .add_wrap => .add, | 959 | .add, .add_safe, .add_wrap => .add, |
| 958 | .sub, .sub_wrap => .sub, | 960 | .sub, .sub_safe, .sub_wrap => .sub, |
| 959 | }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) { | 961 | }, try isel.use(bin_op.rhs), .{ |
| 960 | else => unreachable, | 962 | .overflow = switch (air_tag) { |
| 961 | .add, .sub => false, | 963 | else => unreachable, |
| 962 | .add_wrap, .sub_wrap => true, | 964 | .add, .sub => .@"unreachable", |
| 963 | } }) else switch (ty.floatBits(isel.target)) { | 965 | .add_safe, .sub_safe => .{ .panic = .integer_overflow }, |
| 966 | .add_wrap, .sub_wrap => .wrap, | ||
| 967 | }, | ||
| 968 | }) else switch (ty.floatBits(isel.target)) { | ||
| 964 | else => unreachable, | 969 | else => unreachable, |
| 965 | 16, 32, 64 => |bits| { | 970 | 16, 32, 64 => |bits| { |
| 966 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | 971 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; |
| ... | @@ -1021,7 +1026,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1021,7 +1026,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1021 | 1026 | ||
| 1022 | try call.prepareCallee(isel); | 1027 | try call.prepareCallee(isel); |
| 1023 | try isel.global_relocs.append(gpa, .{ | 1028 | try isel.global_relocs.append(gpa, .{ |
| 1024 | .global = switch (air_tag) { | 1029 | .name = switch (air_tag) { |
| 1025 | else => unreachable, | 1030 | else => unreachable, |
| 1026 | .add, .add_optimized => switch (bits) { | 1031 | .add, .add_optimized => switch (bits) { |
| 1027 | else => unreachable, | 1032 | else => unreachable, |
| ... | @@ -1336,7 +1341,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1336,7 +1341,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1336 | 1341 | ||
| 1337 | try call.prepareCallee(isel); | 1342 | try call.prepareCallee(isel); |
| 1338 | try isel.global_relocs.append(gpa, .{ | 1343 | try isel.global_relocs.append(gpa, .{ |
| 1339 | .global = switch (bits) { | 1344 | .name = switch (bits) { |
| 1340 | else => unreachable, | 1345 | else => unreachable, |
| 1341 | 16 => "__mulhf3", | 1346 | 16 => "__mulhf3", |
| 1342 | 32 => "__mulsf3", | 1347 | 32 => "__mulsf3", |
| ... | @@ -1379,6 +1384,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1379,6 +1384,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1379 | } | 1384 | } |
| 1380 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 1385 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 1381 | }, | 1386 | }, |
| 1387 | .mul_safe => |air_tag| { | ||
| 1388 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | ||
| 1389 | defer res_vi.value.deref(isel); | ||
| 1390 | |||
| 1391 | const bin_op = air.data(air.inst_index).bin_op; | ||
| 1392 | const ty = isel.air.typeOf(bin_op.lhs, ip); | ||
| 1393 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }); | ||
| 1394 | const int_info = ty.intInfo(zcu); | ||
| 1395 | switch (int_info.signedness) { | ||
| 1396 | .signed => switch (int_info.bits) { | ||
| 1397 | 0 => unreachable, | ||
| 1398 | 1 => { | ||
| 1399 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1400 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1401 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1402 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1403 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1404 | try isel.emit(.orr(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | ||
| 1405 | const skip_label = isel.instructions.items.len; | ||
| 1406 | try isel.emitPanic(.integer_overflow); | ||
| 1407 | try isel.emit(.@"b."( | ||
| 1408 | .invert(.ne), | ||
| 1409 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 1410 | )); | ||
| 1411 | try isel.emit(.ands(.wzr, lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | ||
| 1412 | try rhs_mat.finish(isel); | ||
| 1413 | try lhs_mat.finish(isel); | ||
| 1414 | }, | ||
| 1415 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | ||
| 1416 | }, | ||
| 1417 | .unsigned => switch (int_info.bits) { | ||
| 1418 | 0 => unreachable, | ||
| 1419 | 1 => { | ||
| 1420 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1421 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1422 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1423 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1424 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1425 | try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() })); | ||
| 1426 | try rhs_mat.finish(isel); | ||
| 1427 | try lhs_mat.finish(isel); | ||
| 1428 | }, | ||
| 1429 | 2...16 => |bits| { | ||
| 1430 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1431 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1432 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1433 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1434 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1435 | const skip_label = isel.instructions.items.len; | ||
| 1436 | try isel.emitPanic(.integer_overflow); | ||
| 1437 | try isel.emit(.@"b."( | ||
| 1438 | .eq, | ||
| 1439 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 1440 | )); | ||
| 1441 | try isel.emit(.ands(.wzr, res_ra.w(), .{ .immediate = .{ | ||
| 1442 | .N = .word, | ||
| 1443 | .immr = @intCast(32 - bits), | ||
| 1444 | .imms = @intCast(32 - bits - 1), | ||
| 1445 | } })); | ||
| 1446 | try isel.emit(.madd(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr)); | ||
| 1447 | try rhs_mat.finish(isel); | ||
| 1448 | try lhs_mat.finish(isel); | ||
| 1449 | }, | ||
| 1450 | 17...32 => |bits| { | ||
| 1451 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1452 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1453 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1454 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1455 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1456 | const skip_label = isel.instructions.items.len; | ||
| 1457 | try isel.emitPanic(.integer_overflow); | ||
| 1458 | try isel.emit(.@"b."( | ||
| 1459 | .eq, | ||
| 1460 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 1461 | )); | ||
| 1462 | try isel.emit(.ands(.xzr, res_ra.x(), .{ .immediate = .{ | ||
| 1463 | .N = .doubleword, | ||
| 1464 | .immr = @intCast(64 - bits), | ||
| 1465 | .imms = @intCast(64 - bits - 1), | ||
| 1466 | } })); | ||
| 1467 | try isel.emit(.umaddl(res_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr)); | ||
| 1468 | try rhs_mat.finish(isel); | ||
| 1469 | try lhs_mat.finish(isel); | ||
| 1470 | }, | ||
| 1471 | 33...63 => |bits| { | ||
| 1472 | const lo64_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1473 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1474 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1475 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1476 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1477 | const hi64_ra = hi64_ra: { | ||
| 1478 | const lo64_lock = isel.tryLockReg(lo64_ra); | ||
| 1479 | defer lo64_lock.unlock(isel); | ||
| 1480 | break :hi64_ra try isel.allocIntReg(); | ||
| 1481 | }; | ||
| 1482 | defer isel.freeReg(hi64_ra); | ||
| 1483 | const skip_label = isel.instructions.items.len; | ||
| 1484 | try isel.emitPanic(.integer_overflow); | ||
| 1485 | try isel.emit(.cbz( | ||
| 1486 | hi64_ra.x(), | ||
| 1487 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 1488 | )); | ||
| 1489 | try isel.emit(.orr(hi64_ra.x(), hi64_ra.x(), .{ .shifted_register = .{ | ||
| 1490 | .register = lo64_ra.x(), | ||
| 1491 | .shift = .{ .lsr = @intCast(bits) }, | ||
| 1492 | } })); | ||
| 1493 | try isel.emit(.madd(lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr)); | ||
| 1494 | try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x())); | ||
| 1495 | try rhs_mat.finish(isel); | ||
| 1496 | try lhs_mat.finish(isel); | ||
| 1497 | }, | ||
| 1498 | 64 => { | ||
| 1499 | const res_ra = try res_vi.value.defReg(isel) orelse break :unused; | ||
| 1500 | const lhs_vi = try isel.use(bin_op.lhs); | ||
| 1501 | const rhs_vi = try isel.use(bin_op.rhs); | ||
| 1502 | const lhs_mat = try lhs_vi.matReg(isel); | ||
| 1503 | const rhs_mat = try rhs_vi.matReg(isel); | ||
| 1504 | try isel.emit(.madd(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr)); | ||
| 1505 | const hi64_ra = try isel.allocIntReg(); | ||
| 1506 | defer isel.freeReg(hi64_ra); | ||
| 1507 | const skip_label = isel.instructions.items.len; | ||
| 1508 | try isel.emitPanic(.integer_overflow); | ||
| 1509 | try isel.emit(.cbz( | ||
| 1510 | hi64_ra.x(), | ||
| 1511 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 1512 | )); | ||
| 1513 | try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x())); | ||
| 1514 | try rhs_mat.finish(isel); | ||
| 1515 | try lhs_mat.finish(isel); | ||
| 1516 | }, | ||
| 1517 | 65...128 => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | ||
| 1518 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }), | ||
| 1519 | }, | ||
| 1520 | } | ||
| 1521 | } | ||
| 1522 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 1523 | }, | ||
| 1382 | .mul_sat => |air_tag| { | 1524 | .mul_sat => |air_tag| { |
| 1383 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { | 1525 | if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: { |
| 1384 | defer res_vi.value.deref(isel); | 1526 | defer res_vi.value.deref(isel); |
| ... | @@ -1674,7 +1816,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1674,7 +1816,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1674 | 1816 | ||
| 1675 | try call.prepareCallee(isel); | 1817 | try call.prepareCallee(isel); |
| 1676 | try isel.global_relocs.append(gpa, .{ | 1818 | try isel.global_relocs.append(gpa, .{ |
| 1677 | .global = switch (bits) { | 1819 | .name = switch (bits) { |
| 1678 | else => unreachable, | 1820 | else => unreachable, |
| 1679 | 16 => "__divhf3", | 1821 | 16 => "__divhf3", |
| 1680 | 32 => "__divsf3", | 1822 | 32 => "__divsf3", |
| ... | @@ -1813,7 +1955,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1813,7 +1955,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1813 | 1955 | ||
| 1814 | try call.prepareCallee(isel); | 1956 | try call.prepareCallee(isel); |
| 1815 | try isel.global_relocs.append(gpa, .{ | 1957 | try isel.global_relocs.append(gpa, .{ |
| 1816 | .global = switch (int_info.signedness) { | 1958 | .name = switch (int_info.signedness) { |
| 1817 | .signed => "__divti3", | 1959 | .signed => "__divti3", |
| 1818 | .unsigned => "__udivti3", | 1960 | .unsigned => "__udivti3", |
| 1819 | }, | 1961 | }, |
| ... | @@ -1917,7 +2059,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1917,7 +2059,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1917 | else => unreachable, | 2059 | else => unreachable, |
| 1918 | .div_trunc, .div_trunc_optimized => { | 2060 | .div_trunc, .div_trunc_optimized => { |
| 1919 | try isel.global_relocs.append(gpa, .{ | 2061 | try isel.global_relocs.append(gpa, .{ |
| 1920 | .global = switch (bits) { | 2062 | .name = switch (bits) { |
| 1921 | else => unreachable, | 2063 | else => unreachable, |
| 1922 | 16 => "__trunch", | 2064 | 16 => "__trunch", |
| 1923 | 32 => "truncf", | 2065 | 32 => "truncf", |
| ... | @@ -1931,7 +2073,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1931,7 +2073,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1931 | }, | 2073 | }, |
| 1932 | .div_floor, .div_floor_optimized => { | 2074 | .div_floor, .div_floor_optimized => { |
| 1933 | try isel.global_relocs.append(gpa, .{ | 2075 | try isel.global_relocs.append(gpa, .{ |
| 1934 | .global = switch (bits) { | 2076 | .name = switch (bits) { |
| 1935 | else => unreachable, | 2077 | else => unreachable, |
| 1936 | 16 => "__floorh", | 2078 | 16 => "__floorh", |
| 1937 | 32 => "floorf", | 2079 | 32 => "floorf", |
| ... | @@ -1946,7 +2088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -1946,7 +2088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 1946 | .div_exact, .div_exact_optimized => {}, | 2088 | .div_exact, .div_exact_optimized => {}, |
| 1947 | } | 2089 | } |
| 1948 | try isel.global_relocs.append(gpa, .{ | 2090 | try isel.global_relocs.append(gpa, .{ |
| 1949 | .global = switch (bits) { | 2091 | .name = switch (bits) { |
| 1950 | else => unreachable, | 2092 | else => unreachable, |
| 1951 | 16 => "__divhf3", | 2093 | 16 => "__divhf3", |
| 1952 | 32 => "__divsf3", | 2094 | 32 => "__divsf3", |
| ... | @@ -2046,7 +2188,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -2046,7 +2188,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2046 | 2188 | ||
| 2047 | try call.prepareCallee(isel); | 2189 | try call.prepareCallee(isel); |
| 2048 | try isel.global_relocs.append(gpa, .{ | 2190 | try isel.global_relocs.append(gpa, .{ |
| 2049 | .global = switch (bits) { | 2191 | .name = switch (bits) { |
| 2050 | else => unreachable, | 2192 | else => unreachable, |
| 2051 | 16 => "__fmodh", | 2193 | 16 => "__fmodh", |
| 2052 | 32 => "fmodf", | 2194 | 32 => "fmodf", |
| ... | @@ -2212,7 +2354,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -2212,7 +2354,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2212 | 2354 | ||
| 2213 | try call.prepareCallee(isel); | 2355 | try call.prepareCallee(isel); |
| 2214 | try isel.global_relocs.append(gpa, .{ | 2356 | try isel.global_relocs.append(gpa, .{ |
| 2215 | .global = switch (air_tag) { | 2357 | .name = switch (air_tag) { |
| 2216 | else => unreachable, | 2358 | else => unreachable, |
| 2217 | .max => switch (bits) { | 2359 | .max => switch (bits) { |
| 2218 | else => unreachable, | 2360 | else => unreachable, |
| ... | @@ -2284,7 +2426,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -2284,7 +2426,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 2284 | else => unreachable, | 2426 | else => unreachable, |
| 2285 | .add_with_overflow => .add, | 2427 | .add_with_overflow => .add, |
| 2286 | .sub_with_overflow => .sub, | 2428 | .sub_with_overflow => .sub, |
| 2287 | }, rhs_vi, .{ .wrap = true, .overflow_ra = try overflow_vi.?.defReg(isel) orelse .zr }); | 2429 | }, rhs_vi, .{ |
| 2430 | .overflow = if (try overflow_vi.?.defReg(isel)) |overflow_ra| .{ .ra = overflow_ra } else .wrap, | ||
| 2431 | }); | ||
| 2288 | } | 2432 | } |
| 2289 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 2433 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 2290 | }, | 2434 | }, |
| ... | @@ -3092,7 +3236,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3092,7 +3236,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3092 | 3236 | ||
| 3093 | try call.prepareCallee(isel); | 3237 | try call.prepareCallee(isel); |
| 3094 | try isel.global_relocs.append(gpa, .{ | 3238 | try isel.global_relocs.append(gpa, .{ |
| 3095 | .global = "memcpy", | 3239 | .name = "memcpy", |
| 3096 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 3240 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 3097 | }); | 3241 | }); |
| 3098 | try isel.emit(.bl(0)); | 3242 | try isel.emit(.bl(0)); |
| ... | @@ -3119,7 +3263,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3119,7 +3263,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3119 | 3263 | ||
| 3120 | try call.prepareCallee(isel); | 3264 | try call.prepareCallee(isel); |
| 3121 | try isel.global_relocs.append(gpa, .{ | 3265 | try isel.global_relocs.append(gpa, .{ |
| 3122 | .global = "memcpy", | 3266 | .name = "memcpy", |
| 3123 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 3267 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 3124 | }); | 3268 | }); |
| 3125 | try isel.emit(.bl(0)); | 3269 | try isel.emit(.bl(0)); |
| ... | @@ -3139,19 +3283,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3139,19 +3283,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3139 | .block => { | 3283 | .block => { |
| 3140 | const ty_pl = air.data(air.inst_index).ty_pl; | 3284 | const ty_pl = air.data(air.inst_index).ty_pl; |
| 3141 | const extra = isel.air.extraData(Air.Block, ty_pl.payload); | 3285 | const extra = isel.air.extraData(Air.Block, ty_pl.payload); |
| 3142 | 3286 | try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast( | |
| 3143 | if (ty_pl.ty != .noreturn_type) { | 3287 | isel.air.extra.items[extra.end..][0..extra.data.body_len], |
| 3144 | isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{ | 3288 | )); |
| 3145 | .live_registers = isel.live_registers, | ||
| 3146 | .target_label = @intCast(isel.instructions.items.len), | ||
| 3147 | }); | ||
| 3148 | } | ||
| 3149 | try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len])); | ||
| 3150 | if (ty_pl.ty != .noreturn_type) { | ||
| 3151 | const block_entry = isel.blocks.pop().?; | ||
| 3152 | assert(block_entry.key == air.inst_index); | ||
| 3153 | if (isel.live_values.fetchRemove(air.inst_index)) |result_vi| result_vi.value.deref(isel); | ||
| 3154 | } | ||
| 3155 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3289 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3156 | }, | 3290 | }, |
| 3157 | .loop => { | 3291 | .loop => { |
| ... | @@ -3175,11 +3309,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3175,11 +3309,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3175 | } | 3309 | } |
| 3176 | 3310 | ||
| 3177 | // IT'S DOM TIME!!! | 3311 | // IT'S DOM TIME!!! |
| 3178 | for (isel.blocks.values(), 0..) |*block, dom_index| { | 3312 | for (isel.blocks.values(), 0..) |*dom_block, dom_index| { |
| 3179 | if (@as(u1, @truncate(isel.dom.items[ | 3313 | if (@as(u1, @truncate(isel.dom.items[ |
| 3180 | loop.dom + dom_index / @bitSizeOf(DomInt) | 3314 | loop.dom + dom_index / @bitSizeOf(DomInt) |
| 3181 | ] >> @truncate(dom_index))) == 0) continue; | 3315 | ] >> @truncate(dom_index))) == 0) continue; |
| 3182 | var live_reg_it = block.live_registers.iterator(); | 3316 | var live_reg_it = dom_block.live_registers.iterator(); |
| 3183 | while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) { | 3317 | while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) { |
| 3184 | _ => |live_vi| try live_vi.mat(isel), | 3318 | _ => |live_vi| try live_vi.mat(isel), |
| 3185 | .allocating => unreachable, | 3319 | .allocating => unreachable, |
| ... | @@ -3211,8 +3345,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3211,8 +3345,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3211 | }, | 3345 | }, |
| 3212 | .br => { | 3346 | .br => { |
| 3213 | const br = air.data(air.inst_index).br; | 3347 | const br = air.data(air.inst_index).br; |
| 3214 | const block = isel.blocks.getPtr(br.block_inst).?; | 3348 | try isel.blocks.getPtr(br.block_inst).?.branch(isel); |
| 3215 | try block.branch(isel); | ||
| 3216 | if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand); | 3349 | if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand); |
| 3217 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3350 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3218 | }, | 3351 | }, |
| ... | @@ -3224,6 +3357,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3224,6 +3357,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3224 | try isel.emit(.brk(0xf000)); | 3357 | try isel.emit(.brk(0xf000)); |
| 3225 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 3358 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 3226 | }, | 3359 | }, |
| 3360 | .ret_addr => { | ||
| 3361 | if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: { | ||
| 3362 | defer addr_vi.value.deref(isel); | ||
| 3363 | const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused; | ||
| 3364 | try isel.emit(.ldr(addr_ra.x(), .{ .unsigned_offset = .{ .base = .fp, .offset = 8 } })); | ||
| 3365 | } | ||
| 3366 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 3367 | }, | ||
| 3368 | .frame_addr => { | ||
| 3369 | if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: { | ||
| 3370 | defer addr_vi.value.deref(isel); | ||
| 3371 | const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused; | ||
| 3372 | try isel.emit(.orr(addr_ra.x(), .xzr, .{ .register = .fp })); | ||
| 3373 | } | ||
| 3374 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 3375 | }, | ||
| 3227 | .call => { | 3376 | .call => { |
| 3228 | const pl_op = air.data(air.inst_index).pl_op; | 3377 | const pl_op = air.data(air.inst_index).pl_op; |
| 3229 | const extra = isel.air.extraData(Air.Call, pl_op.payload); | 3378 | const extra = isel.air.extraData(Air.Call, pl_op.payload); |
| ... | @@ -3312,7 +3461,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3312,7 +3461,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3312 | var param_part_it = passed_vi.parts(isel); | 3461 | var param_part_it = passed_vi.parts(isel); |
| 3313 | var arg_part_it = arg_vi.parts(isel); | 3462 | var arg_part_it = arg_vi.parts(isel); |
| 3314 | if (arg_part_it.only()) |_| { | 3463 | if (arg_part_it.only()) |_| { |
| 3315 | try isel.values.ensureUnusedCapacity(isel.pt.zcu.gpa, param_part_it.remaining); | 3464 | try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining); |
| 3316 | arg_vi.setParts(isel, param_part_it.remaining); | 3465 | arg_vi.setParts(isel, param_part_it.remaining); |
| 3317 | while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart( | 3466 | while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart( |
| 3318 | isel, | 3467 | isel, |
| ... | @@ -3659,7 +3808,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3659,7 +3808,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3659 | 3808 | ||
| 3660 | try call.prepareCallee(isel); | 3809 | try call.prepareCallee(isel); |
| 3661 | try isel.global_relocs.append(gpa, .{ | 3810 | try isel.global_relocs.append(gpa, .{ |
| 3662 | .global = switch (air_tag) { | 3811 | .name = switch (air_tag) { |
| 3663 | else => unreachable, | 3812 | else => unreachable, |
| 3664 | .sqrt => switch (bits) { | 3813 | .sqrt => switch (bits) { |
| 3665 | else => unreachable, | 3814 | else => unreachable, |
| ... | @@ -3751,7 +3900,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -3751,7 +3900,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 3751 | 3900 | ||
| 3752 | try call.prepareCallee(isel); | 3901 | try call.prepareCallee(isel); |
| 3753 | try isel.global_relocs.append(gpa, .{ | 3902 | try isel.global_relocs.append(gpa, .{ |
| 3754 | .global = switch (air_tag) { | 3903 | .name = switch (air_tag) { |
| 3755 | else => unreachable, | 3904 | else => unreachable, |
| 3756 | .sin => switch (bits) { | 3905 | .sin => switch (bits) { |
| 3757 | else => unreachable, | 3906 | else => unreachable, |
| ... | @@ -4239,7 +4388,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4239,7 +4388,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4239 | 4388 | ||
| 4240 | try call.prepareCallee(isel); | 4389 | try call.prepareCallee(isel); |
| 4241 | try isel.global_relocs.append(gpa, .{ | 4390 | try isel.global_relocs.append(gpa, .{ |
| 4242 | .global = switch (bits) { | 4391 | .name = switch (bits) { |
| 4243 | else => unreachable, | 4392 | else => unreachable, |
| 4244 | 16 => "__cmphf2", | 4393 | 16 => "__cmphf2", |
| 4245 | 32 => "__cmpsf2", | 4394 | 32 => "__cmpsf2", |
| ... | @@ -4629,6 +4778,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4629,6 +4778,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4629 | try isel.emit(.nop()); | 4778 | try isel.emit(.nop()); |
| 4630 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 4779 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4631 | }, | 4780 | }, |
| 4781 | .dbg_inline_block => { | ||
| 4782 | const ty_pl = air.data(air.inst_index).ty_pl; | ||
| 4783 | const extra = isel.air.extraData(Air.DbgInlineBlock, ty_pl.payload); | ||
| 4784 | try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast( | ||
| 4785 | isel.air.extra.items[extra.end..][0..extra.data.body_len], | ||
| 4786 | )); | ||
| 4787 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 4788 | }, | ||
| 4632 | .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => { | 4789 | .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => { |
| 4633 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 4790 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4634 | }, | 4791 | }, |
| ... | @@ -4724,7 +4881,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4724,7 +4881,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4724 | 4881 | ||
| 4725 | try call.prepareCallee(isel); | 4882 | try call.prepareCallee(isel); |
| 4726 | try isel.global_relocs.append(gpa, .{ | 4883 | try isel.global_relocs.append(gpa, .{ |
| 4727 | .global = "memcpy", | 4884 | .name = "memcpy", |
| 4728 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 4885 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 4729 | }); | 4886 | }); |
| 4730 | try isel.emit(.bl(0)); | 4887 | try isel.emit(.bl(0)); |
| ... | @@ -4816,10 +4973,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4816,10 +4973,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4816 | const ptr_ty = isel.air.typeOf(bin_op.lhs, ip); | 4973 | const ptr_ty = isel.air.typeOf(bin_op.lhs, ip); |
| 4817 | const ptr_info = ptr_ty.ptrInfo(zcu); | 4974 | const ptr_info = ptr_ty.ptrInfo(zcu); |
| 4818 | if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{}); | 4975 | if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{}); |
| 4819 | if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) { | 4976 | if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) |
| 4820 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 4977 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4821 | break :air_tag; | ||
| 4822 | }; | ||
| 4823 | 4978 | ||
| 4824 | const src_vi = try isel.use(bin_op.rhs); | 4979 | const src_vi = try isel.use(bin_op.rhs); |
| 4825 | const size = src_vi.size(isel); | 4980 | const size = src_vi.size(isel); |
| ... | @@ -4833,8 +4988,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4833,8 +4988,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4833 | }); | 4988 | }); |
| 4834 | try ptr_mat.finish(isel); | 4989 | try ptr_mat.finish(isel); |
| 4835 | 4990 | ||
| 4836 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 4991 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 4837 | break :air_tag; | ||
| 4838 | }, | 4992 | }, |
| 4839 | else => {}, | 4993 | else => {}, |
| 4840 | }; | 4994 | }; |
| ... | @@ -4843,7 +4997,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4843,7 +4997,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4843 | 4997 | ||
| 4844 | try call.prepareCallee(isel); | 4998 | try call.prepareCallee(isel); |
| 4845 | try isel.global_relocs.append(gpa, .{ | 4999 | try isel.global_relocs.append(gpa, .{ |
| 4846 | .global = "memcpy", | 5000 | .name = "memcpy", |
| 4847 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 5001 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 4848 | }); | 5002 | }); |
| 4849 | try isel.emit(.bl(0)); | 5003 | try isel.emit(.bl(0)); |
| ... | @@ -4906,7 +5060,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -4906,7 +5060,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 4906 | 5060 | ||
| 4907 | try call.prepareCallee(isel); | 5061 | try call.prepareCallee(isel); |
| 4908 | try isel.global_relocs.append(gpa, .{ | 5062 | try isel.global_relocs.append(gpa, .{ |
| 4909 | .global = switch (dst_bits) { | 5063 | .name = switch (dst_bits) { |
| 4910 | else => unreachable, | 5064 | else => unreachable, |
| 4911 | 16 => switch (src_bits) { | 5065 | 16 => switch (src_bits) { |
| 4912 | else => unreachable, | 5066 | else => unreachable, |
| ... | @@ -5060,6 +5214,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -5060,6 +5214,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5060 | } | 5214 | } |
| 5061 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 5215 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 5062 | }, | 5216 | }, |
| 5217 | .intcast_safe => |air_tag| { | ||
| 5218 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: { | ||
| 5219 | defer dst_vi.value.deref(isel); | ||
| 5220 | |||
| 5221 | const ty_op = air.data(air.inst_index).ty_op; | ||
| 5222 | const dst_ty = ty_op.ty.toType(); | ||
| 5223 | const dst_int_info = dst_ty.intInfo(zcu); | ||
| 5224 | const src_ty = isel.air.typeOf(ty_op.operand, ip); | ||
| 5225 | const src_int_info = src_ty.intInfo(zcu); | ||
| 5226 | const can_be_negative = dst_int_info.signedness == .signed and | ||
| 5227 | src_int_info.signedness == .signed; | ||
| 5228 | const panic_id: Zcu.SimplePanicId = panic_id: switch (dst_ty.zigTypeTag(zcu)) { | ||
| 5229 | else => unreachable, | ||
| 5230 | .int => .integer_out_of_bounds, | ||
| 5231 | .@"enum" => { | ||
| 5232 | if (!dst_ty.isNonexhaustiveEnum(zcu)) { | ||
| 5233 | return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | ||
| 5234 | } | ||
| 5235 | break :panic_id .invalid_enum_value; | ||
| 5236 | }, | ||
| 5237 | }; | ||
| 5238 | if (dst_ty.toIntern() == src_ty.toIntern()) { | ||
| 5239 | try dst_vi.value.move(isel, ty_op.operand); | ||
| 5240 | } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 64) { | ||
| 5241 | const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused; | ||
| 5242 | const src_vi = try isel.use(ty_op.operand); | ||
| 5243 | const dst_active_bits = dst_int_info.bits - @intFromBool(dst_int_info.signedness == .signed); | ||
| 5244 | const src_active_bits = src_int_info.bits - @intFromBool(src_int_info.signedness == .signed); | ||
| 5245 | if ((dst_int_info.signedness != .unsigned or src_int_info.signedness != .signed) and dst_active_bits >= src_active_bits) { | ||
| 5246 | const src_mat = try src_vi.matReg(isel); | ||
| 5247 | try isel.emit(if (can_be_negative and dst_active_bits > 32 and src_active_bits <= 32) | ||
| 5248 | .sbfm(dst_ra.x(), src_mat.ra.x(), .{ | ||
| 5249 | .N = .doubleword, | ||
| 5250 | .immr = 0, | ||
| 5251 | .imms = @intCast(src_int_info.bits - 1), | ||
| 5252 | }) | ||
| 5253 | else switch (src_int_info.bits) { | ||
| 5254 | else => unreachable, | ||
| 5255 | 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }), | ||
| 5256 | 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }), | ||
| 5257 | }); | ||
| 5258 | try src_mat.finish(isel); | ||
| 5259 | } else { | ||
| 5260 | const skip_label = isel.instructions.items.len; | ||
| 5261 | try isel.emitPanic(panic_id); | ||
| 5262 | try isel.emit(.@"b."( | ||
| 5263 | .eq, | ||
| 5264 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 5265 | )); | ||
| 5266 | if (can_be_negative) { | ||
| 5267 | const src_mat = src_mat: { | ||
| 5268 | const dst_lock = isel.lockReg(dst_ra); | ||
| 5269 | defer dst_lock.unlock(isel); | ||
| 5270 | break :src_mat try src_vi.matReg(isel); | ||
| 5271 | }; | ||
| 5272 | try isel.emit(switch (src_int_info.bits) { | ||
| 5273 | else => unreachable, | ||
| 5274 | 1...32 => .subs(.wzr, dst_ra.w(), .{ .register = src_mat.ra.w() }), | ||
| 5275 | 33...64 => .subs(.xzr, dst_ra.x(), .{ .register = src_mat.ra.x() }), | ||
| 5276 | }); | ||
| 5277 | try isel.emit(switch (@max(dst_int_info.bits, src_int_info.bits)) { | ||
| 5278 | else => unreachable, | ||
| 5279 | 1...32 => .sbfm(dst_ra.w(), src_mat.ra.w(), .{ | ||
| 5280 | .N = .word, | ||
| 5281 | .immr = 0, | ||
| 5282 | .imms = @intCast(dst_int_info.bits - 1), | ||
| 5283 | }), | ||
| 5284 | 33...64 => .sbfm(dst_ra.x(), src_mat.ra.x(), .{ | ||
| 5285 | .N = .doubleword, | ||
| 5286 | .immr = 0, | ||
| 5287 | .imms = @intCast(dst_int_info.bits - 1), | ||
| 5288 | }), | ||
| 5289 | }); | ||
| 5290 | try src_mat.finish(isel); | ||
| 5291 | } else { | ||
| 5292 | const src_mat = try src_vi.matReg(isel); | ||
| 5293 | try isel.emit(switch (@min(dst_int_info.bits, src_int_info.bits)) { | ||
| 5294 | else => unreachable, | ||
| 5295 | 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }), | ||
| 5296 | 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }), | ||
| 5297 | }); | ||
| 5298 | const active_bits = @min(dst_active_bits, src_active_bits); | ||
| 5299 | try isel.emit(switch (src_int_info.bits) { | ||
| 5300 | else => unreachable, | ||
| 5301 | 1...32 => .ands(.wzr, src_mat.ra.w(), .{ .immediate = .{ | ||
| 5302 | .N = .word, | ||
| 5303 | .immr = @intCast(32 - active_bits), | ||
| 5304 | .imms = @intCast(32 - active_bits - 1), | ||
| 5305 | } }), | ||
| 5306 | 33...64 => .ands(.xzr, src_mat.ra.x(), .{ .immediate = .{ | ||
| 5307 | .N = .doubleword, | ||
| 5308 | .immr = @intCast(64 - active_bits), | ||
| 5309 | .imms = @intCast(64 - active_bits - 1), | ||
| 5310 | } }), | ||
| 5311 | }); | ||
| 5312 | try src_mat.finish(isel); | ||
| 5313 | } | ||
| 5314 | } | ||
| 5315 | } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) }); | ||
| 5316 | } | ||
| 5317 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 5318 | }, | ||
| 5063 | .trunc => |air_tag| { | 5319 | .trunc => |air_tag| { |
| 5064 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: { | 5320 | if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: { |
| 5065 | defer dst_vi.value.deref(isel); | 5321 | defer dst_vi.value.deref(isel); |
| ... | @@ -5832,7 +6088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -5832,7 +6088,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5832 | 6088 | ||
| 5833 | try call.prepareCallee(isel); | 6089 | try call.prepareCallee(isel); |
| 5834 | try isel.global_relocs.append(gpa, .{ | 6090 | try isel.global_relocs.append(gpa, .{ |
| 5835 | .global = switch (dst_int_info.bits) { | 6091 | .name = switch (dst_int_info.bits) { |
| 5836 | else => unreachable, | 6092 | else => unreachable, |
| 5837 | 1...32 => switch (dst_int_info.signedness) { | 6093 | 1...32 => switch (dst_int_info.signedness) { |
| 5838 | .signed => switch (src_bits) { | 6094 | .signed => switch (src_bits) { |
| ... | @@ -5972,7 +6228,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -5972,7 +6228,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 5972 | 6228 | ||
| 5973 | try call.prepareCallee(isel); | 6229 | try call.prepareCallee(isel); |
| 5974 | try isel.global_relocs.append(gpa, .{ | 6230 | try isel.global_relocs.append(gpa, .{ |
| 5975 | .global = switch (src_int_info.bits) { | 6231 | .name = switch (src_int_info.bits) { |
| 5976 | else => unreachable, | 6232 | else => unreachable, |
| 5977 | 1...32 => switch (src_int_info.signedness) { | 6233 | 1...32 => switch (src_int_info.signedness) { |
| 5978 | .signed => switch (dst_bits) { | 6234 | .signed => switch (dst_bits) { |
| ... | @@ -6055,14 +6311,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6055,14 +6311,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6055 | } | 6311 | } |
| 6056 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6312 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6057 | }, | 6313 | }, |
| 6058 | .memset => |air_tag| { | 6314 | .memset, .memset_safe => |air_tag| { |
| 6059 | const bin_op = air.data(air.inst_index).bin_op; | 6315 | const bin_op = air.data(air.inst_index).bin_op; |
| 6060 | const dst_ty = isel.air.typeOf(bin_op.lhs, ip); | 6316 | const dst_ty = isel.air.typeOf(bin_op.lhs, ip); |
| 6061 | const dst_info = dst_ty.ptrInfo(zcu); | 6317 | const dst_info = dst_ty.ptrInfo(zcu); |
| 6062 | const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: { | 6318 | const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: { |
| 6063 | if (bin_op.rhs.toInterned()) |fill_val| | 6319 | if (bin_op.rhs.toInterned()) |fill_val| { |
| 6320 | if (ip.isUndef(fill_val)) switch (air_tag) { | ||
| 6321 | else => unreachable, | ||
| 6322 | .memset => break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag, | ||
| 6323 | .memset_safe => break :fill_byte .{ .constant = 0xaa }, | ||
| 6324 | }; | ||
| 6064 | if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| | 6325 | if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte| |
| 6065 | break :fill_byte .{ .constant = fill_byte }; | 6326 | break :fill_byte .{ .constant = fill_byte }; |
| 6327 | } | ||
| 6066 | switch (dst_ty.elemType2(zcu).abiSize(zcu)) { | 6328 | switch (dst_ty.elemType2(zcu).abiSize(zcu)) { |
| 6067 | 0 => unreachable, | 6329 | 0 => unreachable, |
| 6068 | 1 => break :fill_byte .{ .value = bin_op.rhs }, | 6330 | 1 => break :fill_byte .{ .value = bin_op.rhs }, |
| ... | @@ -6121,8 +6383,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6121,8 +6383,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6121 | .c => unreachable, | 6383 | .c => unreachable, |
| 6122 | } | 6384 | } |
| 6123 | 6385 | ||
| 6124 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6386 | break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6125 | break :air_tag; | ||
| 6126 | }, | 6387 | }, |
| 6127 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }), | 6388 | else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }), |
| 6128 | } | 6389 | } |
| ... | @@ -6133,7 +6394,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6133,7 +6394,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6133 | 6394 | ||
| 6134 | try call.prepareCallee(isel); | 6395 | try call.prepareCallee(isel); |
| 6135 | try isel.global_relocs.append(gpa, .{ | 6396 | try isel.global_relocs.append(gpa, .{ |
| 6136 | .global = "memset", | 6397 | .name = "memset", |
| 6137 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6398 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6138 | }); | 6399 | }); |
| 6139 | try isel.emit(.bl(0)); | 6400 | try isel.emit(.bl(0)); |
| ... | @@ -6179,7 +6440,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6179,7 +6440,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6179 | 6440 | ||
| 6180 | try call.prepareCallee(isel); | 6441 | try call.prepareCallee(isel); |
| 6181 | try isel.global_relocs.append(gpa, .{ | 6442 | try isel.global_relocs.append(gpa, .{ |
| 6182 | .global = @tagName(air_tag), | 6443 | .name = @tagName(air_tag), |
| 6183 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6444 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6184 | }); | 6445 | }); |
| 6185 | try isel.emit(.bl(0)); | 6446 | try isel.emit(.bl(0)); |
| ... | @@ -6268,6 +6529,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6268,6 +6529,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6268 | 6529 | ||
| 6269 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6530 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6270 | }, | 6531 | }, |
| 6532 | .error_name => { | ||
| 6533 | if (isel.live_values.fetchRemove(air.inst_index)) |name_vi| unused: { | ||
| 6534 | defer name_vi.value.deref(isel); | ||
| 6535 | var ptr_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 0, 8); | ||
| 6536 | const ptr_part_vi = try ptr_part_it.only(isel); | ||
| 6537 | const ptr_part_ra = try ptr_part_vi.?.defReg(isel); | ||
| 6538 | var len_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 8, 8); | ||
| 6539 | const len_part_vi = try len_part_it.only(isel); | ||
| 6540 | const len_part_ra = try len_part_vi.?.defReg(isel); | ||
| 6541 | if (ptr_part_ra == null and len_part_ra == null) break :unused; | ||
| 6542 | |||
| 6543 | const un_op = air.data(air.inst_index).un_op; | ||
| 6544 | const err_vi = try isel.use(un_op); | ||
| 6545 | const err_mat = try err_vi.matReg(isel); | ||
| 6546 | const ptr_ra = try isel.allocIntReg(); | ||
| 6547 | defer isel.freeReg(ptr_ra); | ||
| 6548 | const start_ra, const end_ra = range_ras: { | ||
| 6549 | const name_lock: RegLock = if (len_part_ra != null) if (ptr_part_ra) |name_ptr_ra| | ||
| 6550 | isel.tryLockReg(name_ptr_ra) | ||
| 6551 | else | ||
| 6552 | .empty else .empty; | ||
| 6553 | defer name_lock.unlock(isel); | ||
| 6554 | break :range_ras .{ try isel.allocIntReg(), try isel.allocIntReg() }; | ||
| 6555 | }; | ||
| 6556 | defer { | ||
| 6557 | isel.freeReg(start_ra); | ||
| 6558 | isel.freeReg(end_ra); | ||
| 6559 | } | ||
| 6560 | if (len_part_ra) |name_len_ra| try isel.emit(.sub( | ||
| 6561 | name_len_ra.w(), | ||
| 6562 | end_ra.w(), | ||
| 6563 | .{ .register = start_ra.w() }, | ||
| 6564 | )); | ||
| 6565 | if (ptr_part_ra) |name_ptr_ra| try isel.emit(.add( | ||
| 6566 | name_ptr_ra.x(), | ||
| 6567 | ptr_ra.x(), | ||
| 6568 | .{ .extended_register = .{ | ||
| 6569 | .register = start_ra.w(), | ||
| 6570 | .extend = .{ .uxtw = 0 }, | ||
| 6571 | } }, | ||
| 6572 | )); | ||
| 6573 | if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 })); | ||
| 6574 | try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() })); | ||
| 6575 | try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{ | ||
| 6576 | .register = err_mat.ra.w(), | ||
| 6577 | .extend = switch (zcu.errorSetBits()) { | ||
| 6578 | else => unreachable, | ||
| 6579 | 1...8 => .{ .uxtb = 2 }, | ||
| 6580 | 9...16 => .{ .uxth = 2 }, | ||
| 6581 | 17...32 => .{ .uxtw = 2 }, | ||
| 6582 | }, | ||
| 6583 | } })); | ||
| 6584 | try isel.lazy_relocs.append(gpa, .{ | ||
| 6585 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | ||
| 6586 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | ||
| 6587 | }); | ||
| 6588 | try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 })); | ||
| 6589 | try isel.lazy_relocs.append(gpa, .{ | ||
| 6590 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | ||
| 6591 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | ||
| 6592 | }); | ||
| 6593 | try isel.emit(.adrp(ptr_ra.x(), 0)); | ||
| 6594 | try err_mat.finish(isel); | ||
| 6595 | } | ||
| 6596 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 6597 | }, | ||
| 6271 | .aggregate_init => { | 6598 | .aggregate_init => { |
| 6272 | if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| { | 6599 | if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| { |
| 6273 | defer agg_vi.value.deref(isel); | 6600 | defer agg_vi.value.deref(isel); |
| ... | @@ -6362,7 +6689,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6362,7 +6689,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6362 | 6689 | ||
| 6363 | try call.prepareCallee(isel); | 6690 | try call.prepareCallee(isel); |
| 6364 | try isel.global_relocs.append(gpa, .{ | 6691 | try isel.global_relocs.append(gpa, .{ |
| 6365 | .global = "memcpy", | 6692 | .name = "memcpy", |
| 6366 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6693 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6367 | }); | 6694 | }); |
| 6368 | try isel.emit(.bl(0)); | 6695 | try isel.emit(.bl(0)); |
| ... | @@ -6478,7 +6805,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6478,7 +6805,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6478 | 6805 | ||
| 6479 | try call.prepareCallee(isel); | 6806 | try call.prepareCallee(isel); |
| 6480 | try isel.global_relocs.append(gpa, .{ | 6807 | try isel.global_relocs.append(gpa, .{ |
| 6481 | .global = switch (bits) { | 6808 | .name = switch (bits) { |
| 6482 | else => unreachable, | 6809 | else => unreachable, |
| 6483 | 16 => "__fmah", | 6810 | 16 => "__fmah", |
| 6484 | 32 => "fmaf", | 6811 | 32 => "fmaf", |
| ... | @@ -6559,6 +6886,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6559,6 +6886,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6559 | } | 6886 | } |
| 6560 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6887 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6561 | }, | 6888 | }, |
| 6889 | .cmp_lt_errors_len => { | ||
| 6890 | if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: { | ||
| 6891 | defer is_vi.value.deref(isel); | ||
| 6892 | const is_ra = try is_vi.value.defReg(isel) orelse break :unused; | ||
| 6893 | try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls))); | ||
| 6894 | |||
| 6895 | const un_op = air.data(air.inst_index).un_op; | ||
| 6896 | const err_vi = try isel.use(un_op); | ||
| 6897 | const err_mat = try err_vi.matReg(isel); | ||
| 6898 | const ptr_ra = try isel.allocIntReg(); | ||
| 6899 | defer isel.freeReg(ptr_ra); | ||
| 6900 | try isel.emit(.subs(.wzr, err_mat.ra.w(), .{ .register = ptr_ra.w() })); | ||
| 6901 | try isel.lazy_relocs.append(gpa, .{ | ||
| 6902 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | ||
| 6903 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | ||
| 6904 | }); | ||
| 6905 | try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() })); | ||
| 6906 | try isel.lazy_relocs.append(gpa, .{ | ||
| 6907 | .symbol = .{ .kind = .const_data, .ty = .anyerror_type }, | ||
| 6908 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | ||
| 6909 | }); | ||
| 6910 | try isel.emit(.adrp(ptr_ra.x(), 0)); | ||
| 6911 | try err_mat.finish(isel); | ||
| 6912 | } | ||
| 6913 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | ||
| 6914 | }, | ||
| 6562 | .runtime_nav_ptr => { | 6915 | .runtime_nav_ptr => { |
| 6563 | if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: { | 6916 | if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: { |
| 6564 | defer ptr_vi.value.deref(isel); | 6917 | defer ptr_vi.value.deref(isel); |
| ... | @@ -6567,19 +6920,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6567,19 +6920,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6567 | const ty_nav = air.data(air.inst_index).ty_nav; | 6920 | const ty_nav = air.data(air.inst_index).ty_nav; |
| 6568 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { | 6921 | if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) { |
| 6569 | false => { | 6922 | false => { |
| 6570 | try isel.nav_relocs.append(zcu.gpa, .{ | 6923 | try isel.nav_relocs.append(gpa, .{ |
| 6571 | .nav = ty_nav.nav, | 6924 | .nav = ty_nav.nav, |
| 6572 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6925 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6573 | }); | 6926 | }); |
| 6574 | try isel.emit(.adr(ptr_ra.x(), 0)); | 6927 | try isel.emit(.adr(ptr_ra.x(), 0)); |
| 6575 | }, | 6928 | }, |
| 6576 | true => { | 6929 | true => { |
| 6577 | try isel.nav_relocs.append(zcu.gpa, .{ | 6930 | try isel.nav_relocs.append(gpa, .{ |
| 6578 | .nav = ty_nav.nav, | 6931 | .nav = ty_nav.nav, |
| 6579 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6932 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6580 | }); | 6933 | }); |
| 6581 | try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 })); | 6934 | try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 })); |
| 6582 | try isel.nav_relocs.append(zcu.gpa, .{ | 6935 | try isel.nav_relocs.append(gpa, .{ |
| 6583 | .nav = ty_nav.nav, | 6936 | .nav = ty_nav.nav, |
| 6584 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | 6937 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 6585 | }); | 6938 | }); |
| ... | @@ -6589,9 +6942,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { | ... | @@ -6589,9 +6942,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void { |
| 6589 | } | 6942 | } |
| 6590 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; | 6943 | if (air.next()) |next_air_tag| continue :air_tag next_air_tag; |
| 6591 | }, | 6944 | }, |
| 6592 | .add_safe, | ||
| 6593 | .sub_safe, | ||
| 6594 | .mul_safe, | ||
| 6595 | .inferred_alloc, | 6945 | .inferred_alloc, |
| 6596 | .inferred_alloc_comptime, | 6946 | .inferred_alloc_comptime, |
| 6597 | .int_from_float_safe, | 6947 | .int_from_float_safe, |
| ... | @@ -6822,6 +7172,9 @@ pub fn layout( | ... | @@ -6822,6 +7172,9 @@ pub fn layout( |
| 6822 | saves_len += 1; | 7172 | saves_len += 1; |
| 6823 | saves_size += 8; | 7173 | saves_size += 8; |
| 6824 | deferred_gr = null; | 7174 | deferred_gr = null; |
| 7175 | } else switch (@as(u1, @truncate(saved_gra_len))) { | ||
| 7176 | 0 => {}, | ||
| 7177 | 1 => saves_size += 8, | ||
| 6825 | } | 7178 | } |
| 6826 | save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start; | 7179 | save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start; |
| 6827 | while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) { | 7180 | while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) { |
| ... | @@ -6844,42 +7197,42 @@ pub fn layout( | ... | @@ -6844,42 +7197,42 @@ pub fn layout( |
| 6844 | { | 7197 | { |
| 6845 | wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)}); | 7198 | wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)}); |
| 6846 | var save_index: usize = 0; | 7199 | var save_index: usize = 0; |
| 6847 | while (save_index < saves.len) { | 7200 | while (save_index < saves.len) if (save_index + 2 <= saves.len and |
| 6848 | if (save_index + 2 <= saves.len and saves[save_index + 0].class == saves[save_index + 1].class and | 7201 | saves[save_index + 0].class == saves[save_index + 1].class and |
| 6849 | saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset) | 7202 | saves[save_index + 0].size == saves[save_index + 1].size and |
| 6850 | { | 7203 | saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset) |
| 6851 | try isel.emit(.stp( | 7204 | { |
| 6852 | saves[save_index + 0].register, | 7205 | try isel.emit(.stp( |
| 6853 | saves[save_index + 1].register, | 7206 | saves[save_index + 0].register, |
| 6854 | switch (saves[save_index + 0].offset) { | 7207 | saves[save_index + 1].register, |
| 6855 | 0 => .{ .pre_index = .{ | 7208 | switch (saves[save_index + 0].offset) { |
| 6856 | .base = .sp, | 7209 | 0 => .{ .pre_index = .{ |
| 6857 | .index = @intCast(-@as(i11, saves_size)), | 7210 | .base = .sp, |
| 6858 | } }, | 7211 | .index = @intCast(-@as(i11, saves_size)), |
| 6859 | else => |offset| .{ .signed_offset = .{ | 7212 | } }, |
| 6860 | .base = .sp, | 7213 | else => |offset| .{ .signed_offset = .{ |
| 6861 | .offset = @intCast(offset), | 7214 | .base = .sp, |
| 6862 | } }, | 7215 | .offset = @intCast(offset), |
| 6863 | }, | 7216 | } }, |
| 6864 | )); | 7217 | }, |
| 6865 | save_index += 2; | 7218 | )); |
| 6866 | } else { | 7219 | save_index += 2; |
| 6867 | try isel.emit(.str( | 7220 | } else { |
| 6868 | saves[save_index].register, | 7221 | try isel.emit(.str( |
| 6869 | switch (saves[save_index].offset) { | 7222 | saves[save_index].register, |
| 6870 | 0 => .{ .pre_index = .{ | 7223 | switch (saves[save_index].offset) { |
| 6871 | .base = .sp, | 7224 | 0 => .{ .pre_index = .{ |
| 6872 | .index = @intCast(-@as(i11, saves_size)), | 7225 | .base = .sp, |
| 6873 | } }, | 7226 | .index = @intCast(-@as(i11, saves_size)), |
| 6874 | else => |offset| .{ .unsigned_offset = .{ | 7227 | } }, |
| 6875 | .base = .sp, | 7228 | else => |offset| .{ .unsigned_offset = .{ |
| 6876 | .offset = @intCast(offset), | 7229 | .base = .sp, |
| 6877 | } }, | 7230 | .offset = @intCast(offset), |
| 6878 | }, | 7231 | } }, |
| 6879 | )); | 7232 | }, |
| 6880 | save_index += 1; | 7233 | )); |
| 6881 | } | 7234 | save_index += 1; |
| 6882 | } | 7235 | }; |
| 6883 | 7236 | ||
| 6884 | try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset })); | 7237 | try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset })); |
| 6885 | const scratch_reg: Register = if (isel.stack_align == .@"16") | 7238 | const scratch_reg: Register = if (isel.stack_align == .@"16") |
| ... | @@ -7053,11 +7406,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt | ... | @@ -7053,11 +7406,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt |
| 7053 | return constant.fmtValue(isel.pt); | 7406 | return constant.fmtValue(isel.pt); |
| 7054 | } | 7407 | } |
| 7055 | 7408 | ||
| 7409 | fn block( | ||
| 7410 | isel: *Select, | ||
| 7411 | air_inst_index: Air.Inst.Index, | ||
| 7412 | res_ty: ZigType, | ||
| 7413 | air_body: []const Air.Inst.Index, | ||
| 7414 | ) !void { | ||
| 7415 | if (res_ty.toIntern() != .noreturn_type) { | ||
| 7416 | isel.blocks.putAssumeCapacityNoClobber(air_inst_index, .{ | ||
| 7417 | .live_registers = isel.live_registers, | ||
| 7418 | .target_label = @intCast(isel.instructions.items.len), | ||
| 7419 | }); | ||
| 7420 | } | ||
| 7421 | try isel.body(air_body); | ||
| 7422 | if (res_ty.toIntern() != .noreturn_type) { | ||
| 7423 | const block_entry = isel.blocks.pop().?; | ||
| 7424 | assert(block_entry.key == air_inst_index); | ||
| 7425 | if (isel.live_values.fetchRemove(air_inst_index)) |result_vi| result_vi.value.deref(isel); | ||
| 7426 | } | ||
| 7427 | } | ||
| 7428 | |||
| 7056 | fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void { | 7429 | fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void { |
| 7057 | wip_mir_log.debug(" | {f}", .{instruction}); | 7430 | wip_mir_log.debug(" | {f}", .{instruction}); |
| 7058 | try isel.instructions.append(isel.pt.zcu.gpa, instruction); | 7431 | try isel.instructions.append(isel.pt.zcu.gpa, instruction); |
| 7059 | } | 7432 | } |
| 7060 | 7433 | ||
| 7434 | fn emitPanic(isel: *Select, panic_id: Zcu.SimplePanicId) !void { | ||
| 7435 | const zcu = isel.pt.zcu; | ||
| 7436 | try isel.nav_relocs.append(zcu.gpa, .{ | ||
| 7437 | .nav = switch (zcu.intern_pool.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) { | ||
| 7438 | else => unreachable, | ||
| 7439 | inline .@"extern", .func => |func| func.owner_nav, | ||
| 7440 | }, | ||
| 7441 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, | ||
| 7442 | }); | ||
| 7443 | try isel.emit(.bl(0)); | ||
| 7444 | } | ||
| 7445 | |||
| 7061 | fn emitLiteral(isel: *Select, bytes: []const u8) !void { | 7446 | fn emitLiteral(isel: *Select, bytes: []const u8) !void { |
| 7062 | const words: []align(1) const u32 = @ptrCast(bytes); | 7447 | const words: []align(1) const u32 = @ptrCast(bytes); |
| 7063 | const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len); | 7448 | const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len); |
| ... | @@ -8104,6 +8489,32 @@ pub const Value = struct { | ... | @@ -8104,6 +8489,32 @@ pub const Value = struct { |
| 8104 | } | 8489 | } |
| 8105 | } | 8490 | } |
| 8106 | 8491 | ||
| 8492 | const AddOrSubtractOptions = struct { | ||
| 8493 | overflow: Overflow, | ||
| 8494 | |||
| 8495 | const Overflow = union(enum) { | ||
| 8496 | @"unreachable", | ||
| 8497 | panic: Zcu.SimplePanicId, | ||
| 8498 | wrap, | ||
| 8499 | ra: Register.Alias, | ||
| 8500 | |||
| 8501 | fn defCond(overflow: Overflow, isel: *Select, cond: codegen.aarch64.encoding.ConditionCode) !void { | ||
| 8502 | switch (overflow) { | ||
| 8503 | .@"unreachable" => unreachable, | ||
| 8504 | .panic => |panic_id| { | ||
| 8505 | const skip_label = isel.instructions.items.len; | ||
| 8506 | try isel.emitPanic(panic_id); | ||
| 8507 | try isel.emit(.@"b."( | ||
| 8508 | cond.invert(), | ||
| 8509 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 8510 | )); | ||
| 8511 | }, | ||
| 8512 | .wrap => {}, | ||
| 8513 | .ra => |overflow_ra| try isel.emit(.csinc(overflow_ra.w(), .wzr, .wzr, cond.invert())), | ||
| 8514 | } | ||
| 8515 | } | ||
| 8516 | }; | ||
| 8517 | }; | ||
| 8107 | fn addOrSubtract( | 8518 | fn addOrSubtract( |
| 8108 | res_vi: Value.Index, | 8519 | res_vi: Value.Index, |
| 8109 | isel: *Select, | 8520 | isel: *Select, |
| ... | @@ -8111,19 +8522,21 @@ pub const Value = struct { | ... | @@ -8111,19 +8522,21 @@ pub const Value = struct { |
| 8111 | lhs_vi: Value.Index, | 8522 | lhs_vi: Value.Index, |
| 8112 | op: codegen.aarch64.encoding.Instruction.AddSubtractOp, | 8523 | op: codegen.aarch64.encoding.Instruction.AddSubtractOp, |
| 8113 | rhs_vi: Value.Index, | 8524 | rhs_vi: Value.Index, |
| 8114 | opts: struct { | 8525 | opts: AddOrSubtractOptions, |
| 8115 | wrap: bool, | ||
| 8116 | overflow_ra: Register.Alias = .zr, | ||
| 8117 | }, | ||
| 8118 | ) !void { | 8526 | ) !void { |
| 8119 | assert(opts.wrap or opts.overflow_ra == .zr); | ||
| 8120 | const zcu = isel.pt.zcu; | 8527 | const zcu = isel.pt.zcu; |
| 8121 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); | 8528 | if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); |
| 8122 | const int_info = ty.intInfo(zcu); | 8529 | const int_info = ty.intInfo(zcu); |
| 8123 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); | 8530 | if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) }); |
| 8124 | var part_offset = res_vi.size(isel); | 8531 | var part_offset = res_vi.size(isel); |
| 8125 | var need_wrap = opts.wrap; | 8532 | var need_wrap = switch (opts.overflow) { |
| 8126 | var need_carry = opts.overflow_ra != .zr; | 8533 | .@"unreachable" => false, |
| 8534 | .panic, .wrap, .ra => true, | ||
| 8535 | }; | ||
| 8536 | var need_carry = switch (opts.overflow) { | ||
| 8537 | .@"unreachable", .wrap => false, | ||
| 8538 | .panic, .ra => true, | ||
| 8539 | }; | ||
| 8127 | while (part_offset > 0) : (need_wrap = false) { | 8540 | while (part_offset > 0) : (need_wrap = false) { |
| 8128 | const part_size = @min(part_offset, 8); | 8541 | const part_size = @min(part_offset, 8); |
| 8129 | part_offset -= part_size; | 8542 | part_offset -= part_size; |
| ... | @@ -8133,48 +8546,87 @@ pub const Value = struct { | ... | @@ -8133,48 +8546,87 @@ pub const Value = struct { |
| 8133 | const unwrapped_res_part_ra = unwrapped_res_part_ra: { | 8546 | const unwrapped_res_part_ra = unwrapped_res_part_ra: { |
| 8134 | if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra; | 8547 | if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra; |
| 8135 | if (int_info.bits % 32 == 0) { | 8548 | if (int_info.bits % 32 == 0) { |
| 8136 | if (opts.overflow_ra != .zr) try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(switch (int_info.signedness) { | 8549 | try opts.overflow.defCond(isel, switch (int_info.signedness) { |
| 8137 | .signed => .vs, | 8550 | .signed => .vs, |
| 8138 | .unsigned => switch (op) { | 8551 | .unsigned => switch (op) { |
| 8139 | .add => .cs, | 8552 | .add => .cs, |
| 8140 | .sub => .cc, | 8553 | .sub => .cc, |
| 8141 | }, | 8554 | }, |
| 8142 | }))); | 8555 | }); |
| 8143 | break :unwrapped_res_part_ra wrapped_res_part_ra; | 8556 | break :unwrapped_res_part_ra wrapped_res_part_ra; |
| 8144 | } | 8557 | } |
| 8145 | const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: { | 8558 | need_carry = false; |
| 8146 | switch (op) { | 8559 | const wrapped_part_ra, const unwrapped_part_ra = part_ra: switch (opts.overflow) { |
| 8147 | .add => {}, | 8560 | .@"unreachable" => unreachable, |
| 8148 | .sub => switch (int_info.signedness) { | 8561 | .panic, .ra => switch (int_info.signedness) { |
| 8149 | .signed => {}, | 8562 | .signed => { |
| 8150 | .unsigned => { | 8563 | try opts.overflow.defCond(isel, .ne); |
| 8151 | try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc))); | 8564 | const wrapped_part_ra = switch (wrapped_res_part_ra) { |
| 8152 | break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra }; | 8565 | else => |res_part_ra| res_part_ra, |
| 8153 | }, | 8566 | .zr => try isel.allocIntReg(), |
| 8567 | }; | ||
| 8568 | errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); | ||
| 8569 | const unwrapped_part_ra = unwrapped_part_ra: { | ||
| 8570 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { | ||
| 8571 | else => |res_part_ra| isel.lockReg(res_part_ra), | ||
| 8572 | .zr => .empty, | ||
| 8573 | }; | ||
| 8574 | defer wrapped_res_part_lock.unlock(isel); | ||
| 8575 | break :unwrapped_part_ra try isel.allocIntReg(); | ||
| 8576 | }; | ||
| 8577 | errdefer isel.freeReg(unwrapped_part_ra); | ||
| 8578 | switch (part_size) { | ||
| 8579 | else => unreachable, | ||
| 8580 | 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })), | ||
| 8581 | 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })), | ||
| 8582 | } | ||
| 8583 | break :part_ra .{ wrapped_part_ra, unwrapped_part_ra }; | ||
| 8154 | }, | 8584 | }, |
| 8155 | } | 8585 | .unsigned => { |
| 8156 | try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne))); | 8586 | const unwrapped_part_ra = unwrapped_part_ra: { |
| 8157 | const wrapped_part_ra = switch (wrapped_res_part_ra) { | 8587 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { |
| 8158 | else => |res_part_ra| res_part_ra, | 8588 | else => |res_part_ra| isel.lockReg(res_part_ra), |
| 8159 | .zr => try isel.allocIntReg(), | 8589 | .zr => .empty, |
| 8160 | }; | 8590 | }; |
| 8161 | errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); | 8591 | defer wrapped_res_part_lock.unlock(isel); |
| 8162 | const unwrapped_part_ra = unwrapped_part_ra: { | 8592 | break :unwrapped_part_ra try isel.allocIntReg(); |
| 8163 | const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) { | 8593 | }; |
| 8164 | else => |res_part_ra| isel.lockReg(res_part_ra), | 8594 | errdefer isel.freeReg(unwrapped_part_ra); |
| 8165 | .zr => .empty, | 8595 | const bit: u6 = @truncate(int_info.bits); |
| 8166 | }; | 8596 | switch (opts.overflow) { |
| 8167 | defer wrapped_res_part_lock.unlock(isel); | 8597 | .@"unreachable", .wrap => unreachable, |
| 8168 | break :unwrapped_part_ra try isel.allocIntReg(); | 8598 | .panic => |panic_id| { |
| 8169 | }; | 8599 | const skip_label = isel.instructions.items.len; |
| 8170 | errdefer isel.freeReg(unwrapped_part_ra); | 8600 | try isel.emitPanic(panic_id); |
| 8171 | switch (part_size) { | 8601 | try isel.emit(.tbz( |
| 8172 | else => unreachable, | 8602 | switch (bit) { |
| 8173 | 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })), | 8603 | 0, 32 => unreachable, |
| 8174 | 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })), | 8604 | 1...31 => unwrapped_part_ra.w(), |
| 8175 | } | 8605 | 33...63 => unwrapped_part_ra.x(), |
| 8176 | break :part_ra .{ wrapped_part_ra, unwrapped_part_ra }; | 8606 | }, |
| 8177 | } else .{ wrapped_res_part_ra, wrapped_res_part_ra }; | 8607 | bit, |
| 8608 | @intCast((isel.instructions.items.len + 1 - skip_label) << 2), | ||
| 8609 | )); | ||
| 8610 | }, | ||
| 8611 | .ra => |overflow_ra| try isel.emit(switch (bit) { | ||
| 8612 | 0, 32 => unreachable, | ||
| 8613 | 1...31 => .ubfm(overflow_ra.w(), unwrapped_part_ra.w(), .{ | ||
| 8614 | .N = .word, | ||
| 8615 | .immr = bit, | ||
| 8616 | .imms = bit, | ||
| 8617 | }), | ||
| 8618 | 33...63 => .ubfm(overflow_ra.x(), unwrapped_part_ra.x(), .{ | ||
| 8619 | .N = .doubleword, | ||
| 8620 | .immr = bit, | ||
| 8621 | .imms = bit, | ||
| 8622 | }), | ||
| 8623 | }), | ||
| 8624 | } | ||
| 8625 | break :part_ra .{ wrapped_res_part_ra, unwrapped_part_ra }; | ||
| 8626 | }, | ||
| 8627 | }, | ||
| 8628 | .wrap => .{ wrapped_res_part_ra, wrapped_res_part_ra }, | ||
| 8629 | }; | ||
| 8178 | defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); | 8630 | defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra); |
| 8179 | errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra); | 8631 | errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra); |
| 8180 | if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) { | 8632 | if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) { |
| ... | @@ -8650,41 +9102,15 @@ pub const Value = struct { | ... | @@ -8650,41 +9102,15 @@ pub const Value = struct { |
| 8650 | expected_live_registers: *const LiveRegisters, | 9102 | expected_live_registers: *const LiveRegisters, |
| 8651 | ) !void { | 9103 | ) !void { |
| 8652 | try vi.liveIn(isel, src_ra, expected_live_registers); | 9104 | try vi.liveIn(isel, src_ra, expected_live_registers); |
| 8653 | const offset_from_parent: i65, const parent_vi = vi.valueParent(isel); | 9105 | const offset_from_parent, const parent_vi = vi.valueParent(isel); |
| 8654 | switch (parent_vi.parent(isel)) { | 9106 | switch (parent_vi.parent(isel)) { |
| 8655 | .unallocated => {}, | 9107 | .unallocated => {}, |
| 8656 | .stack_slot => |stack_slot| { | 9108 | .stack_slot => |stack_slot| if (stack_slot.base != Register.Alias.fp) try isel.storeReg( |
| 8657 | const offset = stack_slot.offset + offset_from_parent; | 9109 | src_ra, |
| 8658 | try isel.emit(switch (vi.size(isel)) { | 9110 | vi.size(isel), |
| 8659 | else => unreachable, | 9111 | stack_slot.base, |
| 8660 | 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{ | 9112 | @as(i65, stack_slot.offset) + offset_from_parent, |
| 8661 | .base = stack_slot.base.x(), | 9113 | ), |
| 8662 | .offset = @intCast(offset), | ||
| 8663 | } }) else .strb(src_ra.w(), .{ .unsigned_offset = .{ | ||
| 8664 | .base = stack_slot.base.x(), | ||
| 8665 | .offset = @intCast(offset), | ||
| 8666 | } }), | ||
| 8667 | 2 => if (src_ra.isVector()) .str(src_ra.h(), .{ .unsigned_offset = .{ | ||
| 8668 | .base = stack_slot.base.x(), | ||
| 8669 | .offset = @intCast(offset), | ||
| 8670 | } }) else .strh(src_ra.w(), .{ .unsigned_offset = .{ | ||
| 8671 | .base = stack_slot.base.x(), | ||
| 8672 | .offset = @intCast(offset), | ||
| 8673 | } }), | ||
| 8674 | 4 => .str(if (src_ra.isVector()) src_ra.s() else src_ra.w(), .{ .unsigned_offset = .{ | ||
| 8675 | .base = stack_slot.base.x(), | ||
| 8676 | .offset = @intCast(offset), | ||
| 8677 | } }), | ||
| 8678 | 8 => .str(if (src_ra.isVector()) src_ra.d() else src_ra.x(), .{ .unsigned_offset = .{ | ||
| 8679 | .base = stack_slot.base.x(), | ||
| 8680 | .offset = @intCast(offset), | ||
| 8681 | } }), | ||
| 8682 | 16 => .str(src_ra.q(), .{ .unsigned_offset = .{ | ||
| 8683 | .base = stack_slot.base.x(), | ||
| 8684 | .offset = @intCast(offset), | ||
| 8685 | } }), | ||
| 8686 | }); | ||
| 8687 | }, | ||
| 8688 | else => unreachable, | 9114 | else => unreachable, |
| 8689 | } | 9115 | } |
| 8690 | try vi.spillReg(isel, src_ra, 0, expected_live_registers); | 9116 | try vi.spillReg(isel, src_ra, 0, expected_live_registers); |
| ... | @@ -9631,14 +10057,18 @@ pub const Value = struct { | ... | @@ -9631,14 +10057,18 @@ pub const Value = struct { |
| 9631 | var base_ptr = ip.indexToKey(base).ptr; | 10057 | var base_ptr = ip.indexToKey(base).ptr; |
| 9632 | const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child; | 10058 | const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child; |
| 9633 | const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type; | 10059 | const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type; |
| 9634 | base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu); | 10060 | base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu) + ptr.byte_offset; |
| 10061 | continue :constant_key .{ .ptr = base_ptr }; | ||
| 10062 | }, | ||
| 10063 | .opt_payload => |base| { | ||
| 10064 | var base_ptr = ip.indexToKey(base).ptr; | ||
| 10065 | base_ptr.byte_offset += ptr.byte_offset; | ||
| 9635 | continue :constant_key .{ .ptr = base_ptr }; | 10066 | continue :constant_key .{ .ptr = base_ptr }; |
| 9636 | }, | 10067 | }, |
| 9637 | .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr }, | ||
| 9638 | .field => |field| { | 10068 | .field => |field| { |
| 9639 | var base_ptr = ip.indexToKey(field.base).ptr; | 10069 | var base_ptr = ip.indexToKey(field.base).ptr; |
| 9640 | const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child); | 10070 | const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child); |
| 9641 | base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu); | 10071 | base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset; |
| 9642 | continue :constant_key .{ .ptr = base_ptr }; | 10072 | continue :constant_key .{ .ptr = base_ptr }; |
| 9643 | }, | 10073 | }, |
| 9644 | .comptime_alloc, .comptime_field, .arr_elem => unreachable, | 10074 | .comptime_alloc, .comptime_field, .arr_elem => unreachable, |
src/codegen/aarch64/instructions.zon+190| ... | @@ -213,6 +213,63 @@ | ... | @@ -213,6 +213,63 @@ |
| 213 | }, | 213 | }, |
| 214 | .encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } }, | 214 | .encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } }, |
| 215 | }, | 215 | }, |
| 216 | // C6.2.16 ASR (register) | ||
| 217 | .{ | ||
| 218 | .pattern = "ASR <Wd>, <Wn>, <Wm>", | ||
| 219 | .symbols = .{ | ||
| 220 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 221 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 222 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 223 | }, | ||
| 224 | .encode = .{ .asrv, .Wd, .Wn, .Wm }, | ||
| 225 | }, | ||
| 226 | .{ | ||
| 227 | .pattern = "ASR <Xd>, <Xn>, <Xm>", | ||
| 228 | .symbols = .{ | ||
| 229 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 230 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 231 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 232 | }, | ||
| 233 | .encode = .{ .asrv, .Xd, .Xn, .Xm }, | ||
| 234 | }, | ||
| 235 | // C6.2.17 ASR (immediate) | ||
| 236 | .{ | ||
| 237 | .pattern = "ASR <Wd>, <Wn>, #<shift>", | ||
| 238 | .symbols = .{ | ||
| 239 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 240 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 241 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } }, | ||
| 242 | }, | ||
| 243 | .encode = .{ .sbfm, .Wd, .Wn, .{ .N = .word, .immr = .shift, .imms = 31 } }, | ||
| 244 | }, | ||
| 245 | .{ | ||
| 246 | .pattern = "ASR <Xd>, <Xn>, #<shift>", | ||
| 247 | .symbols = .{ | ||
| 248 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 249 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 250 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } }, | ||
| 251 | }, | ||
| 252 | .encode = .{ .sbfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .shift, .imms = 63 } }, | ||
| 253 | }, | ||
| 254 | // C6.2.18 ASRV | ||
| 255 | .{ | ||
| 256 | .pattern = "ASRV <Wd>, <Wn>, <Wm>", | ||
| 257 | .symbols = .{ | ||
| 258 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 259 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 260 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 261 | }, | ||
| 262 | .encode = .{ .asrv, .Wd, .Wn, .Wm }, | ||
| 263 | }, | ||
| 264 | .{ | ||
| 265 | .pattern = "ASRV <Xd>, <Xn>, <Xm>", | ||
| 266 | .symbols = .{ | ||
| 267 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 268 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 269 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 270 | }, | ||
| 271 | .encode = .{ .asrv, .Xd, .Xn, .Xm }, | ||
| 272 | }, | ||
| 216 | // C6.2.35 BLR | 273 | // C6.2.35 BLR |
| 217 | .{ | 274 | .{ |
| 218 | .pattern = "BLR <Xn>", | 275 | .pattern = "BLR <Xn>", |
| ... | @@ -681,6 +738,82 @@ | ... | @@ -681,6 +738,82 @@ |
| 681 | }, | 738 | }, |
| 682 | .encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } }, | 739 | .encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } }, |
| 683 | }, | 740 | }, |
| 741 | // C6.2.212 LSL (register) | ||
| 742 | .{ | ||
| 743 | .pattern = "LSL <Wd>, <Wn>, <Wm>", | ||
| 744 | .symbols = .{ | ||
| 745 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 746 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 747 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 748 | }, | ||
| 749 | .encode = .{ .lslv, .Wd, .Wn, .Wm }, | ||
| 750 | }, | ||
| 751 | .{ | ||
| 752 | .pattern = "LSL <Xd>, <Xn>, <Xm>", | ||
| 753 | .symbols = .{ | ||
| 754 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 755 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 756 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 757 | }, | ||
| 758 | .encode = .{ .lslv, .Xd, .Xn, .Xm }, | ||
| 759 | }, | ||
| 760 | // C6.2.214 LSLV | ||
| 761 | .{ | ||
| 762 | .pattern = "LSLV <Wd>, <Wn>, <Wm>", | ||
| 763 | .symbols = .{ | ||
| 764 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 765 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 766 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 767 | }, | ||
| 768 | .encode = .{ .lslv, .Wd, .Wn, .Wm }, | ||
| 769 | }, | ||
| 770 | .{ | ||
| 771 | .pattern = "LSLV <Xd>, <Xn>, <Xm>", | ||
| 772 | .symbols = .{ | ||
| 773 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 774 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 775 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 776 | }, | ||
| 777 | .encode = .{ .lslv, .Xd, .Xn, .Xm }, | ||
| 778 | }, | ||
| 779 | // C6.2.215 LSR (register) | ||
| 780 | .{ | ||
| 781 | .pattern = "LSR <Wd>, <Wn>, <Wm>", | ||
| 782 | .symbols = .{ | ||
| 783 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 784 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 785 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 786 | }, | ||
| 787 | .encode = .{ .lsrv, .Wd, .Wn, .Wm }, | ||
| 788 | }, | ||
| 789 | .{ | ||
| 790 | .pattern = "LSR <Xd>, <Xn>, <Xm>", | ||
| 791 | .symbols = .{ | ||
| 792 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 793 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 794 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 795 | }, | ||
| 796 | .encode = .{ .lsrv, .Xd, .Xn, .Xm }, | ||
| 797 | }, | ||
| 798 | // C6.2.217 LSRV | ||
| 799 | .{ | ||
| 800 | .pattern = "LSRV <Wd>, <Wn>, <Wm>", | ||
| 801 | .symbols = .{ | ||
| 802 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 803 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 804 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 805 | }, | ||
| 806 | .encode = .{ .lsrv, .Wd, .Wn, .Wm }, | ||
| 807 | }, | ||
| 808 | .{ | ||
| 809 | .pattern = "LSRV <Xd>, <Xn>, <Xm>", | ||
| 810 | .symbols = .{ | ||
| 811 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 812 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 813 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 814 | }, | ||
| 815 | .encode = .{ .lsrv, .Xd, .Xn, .Xm }, | ||
| 816 | }, | ||
| 684 | // C6.2.220 MOV (to/from SP) | 817 | // C6.2.220 MOV (to/from SP) |
| 685 | .{ | 818 | .{ |
| 686 | .pattern = "MOV WSP, <Wn|WSP>", | 819 | .pattern = "MOV WSP, <Wn|WSP>", |
| ... | @@ -964,6 +1097,63 @@ | ... | @@ -964,6 +1097,63 @@ |
| 964 | }, | 1097 | }, |
| 965 | .encode = .{ .ret, .Xn }, | 1098 | .encode = .{ .ret, .Xn }, |
| 966 | }, | 1099 | }, |
| 1100 | // C6.2.261 ROR (immediate) | ||
| 1101 | .{ | ||
| 1102 | .pattern = "ROR <Wd>, <Ws>, #<shift>", | ||
| 1103 | .symbols = .{ | ||
| 1104 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1105 | .Ws = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1106 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } }, | ||
| 1107 | }, | ||
| 1108 | .encode = .{ .extr, .Wd, .Ws, .Ws, .shift }, | ||
| 1109 | }, | ||
| 1110 | .{ | ||
| 1111 | .pattern = "ROR <Xd>, <Xs>, #<shift>", | ||
| 1112 | .symbols = .{ | ||
| 1113 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1114 | .Xs = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1115 | .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } }, | ||
| 1116 | }, | ||
| 1117 | .encode = .{ .extr, .Xd, .Xs, .Xs, .shift }, | ||
| 1118 | }, | ||
| 1119 | // C6.2.262 ROR (register) | ||
| 1120 | .{ | ||
| 1121 | .pattern = "ROR <Wd>, <Wn>, <Wm>", | ||
| 1122 | .symbols = .{ | ||
| 1123 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1124 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1125 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1126 | }, | ||
| 1127 | .encode = .{ .rorv, .Wd, .Wn, .Wm }, | ||
| 1128 | }, | ||
| 1129 | .{ | ||
| 1130 | .pattern = "ROR <Xd>, <Xn>, <Xm>", | ||
| 1131 | .symbols = .{ | ||
| 1132 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1133 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1134 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1135 | }, | ||
| 1136 | .encode = .{ .rorv, .Xd, .Xn, .Xm }, | ||
| 1137 | }, | ||
| 1138 | // C6.2.263 RORV | ||
| 1139 | .{ | ||
| 1140 | .pattern = "RORV <Wd>, <Wn>, <Wm>", | ||
| 1141 | .symbols = .{ | ||
| 1142 | .Wd = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1143 | .Wn = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1144 | .Wm = .{ .reg = .{ .format = .{ .integer = .word } } }, | ||
| 1145 | }, | ||
| 1146 | .encode = .{ .rorv, .Wd, .Wn, .Wm }, | ||
| 1147 | }, | ||
| 1148 | .{ | ||
| 1149 | .pattern = "RORV <Xd>, <Xn>, <Xm>", | ||
| 1150 | .symbols = .{ | ||
| 1151 | .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1152 | .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1153 | .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } }, | ||
| 1154 | }, | ||
| 1155 | .encode = .{ .rorv, .Xd, .Xn, .Xm }, | ||
| 1156 | }, | ||
| 967 | // C6.2.268 SBFM | 1157 | // C6.2.268 SBFM |
| 968 | .{ | 1158 | .{ |
| 969 | .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>", | 1159 | .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>", |
src/target.zig+4-2| ... | @@ -351,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti | ... | @@ -351,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti |
| 351 | } | 351 | } |
| 352 | } | 352 | } |
| 353 | 353 | ||
| 354 | pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool { | 354 | pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool { |
| 355 | switch (target.os.tag) { | 355 | switch (target.os.tag) { |
| 356 | .plan9 => return false, | 356 | .plan9 => return false, |
| 357 | else => {}, | 357 | else => {}, |
| ... | @@ -373,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime | ... | @@ -373,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime |
| 373 | }; | 373 | }; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool { | 376 | pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool { |
| 377 | switch (target.cpu.arch) { | 377 | switch (target.cpu.arch) { |
| 378 | .spirv32, .spirv64 => return false, | 378 | .spirv32, .spirv64 => return false, |
| 379 | // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed | 379 | // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed |
| ... | @@ -382,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha | ... | @@ -382,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha |
| 382 | } | 382 | } |
| 383 | return switch (zigBackend(target, use_llvm)) { | 383 | return switch (zigBackend(target, use_llvm)) { |
| 384 | .stage2_llvm => true, | 384 | .stage2_llvm => true, |
| 385 | .stage2_wasm => false, | ||
| 385 | .stage2_x86_64 => switch (target.ofmt) { | 386 | .stage2_x86_64 => switch (target.ofmt) { |
| 386 | .elf, .macho => true, | 387 | .elf, .macho => true, |
| 387 | else => have_llvm, | 388 | else => have_llvm, |
| ... | @@ -860,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile | ... | @@ -860,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile |
| 860 | pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool { | 861 | pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool { |
| 861 | return switch (feature) { | 862 | return switch (feature) { |
| 862 | .panic_fn => switch (backend) { | 863 | .panic_fn => switch (backend) { |
| 864 | .stage2_aarch64, | ||
| 863 | .stage2_c, | 865 | .stage2_c, |
| 864 | .stage2_llvm, | 866 | .stage2_llvm, |
| 865 | .stage2_x86_64, | 867 | .stage2_x86_64, |
test/behavior/error.zig-3| ... | @@ -590,7 +590,6 @@ test "error union comptime caching" { | ... | @@ -590,7 +590,6 @@ test "error union comptime caching" { |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | test "@errorName" { | 592 | test "@errorName" { |
| 593 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 594 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 593 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 595 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 594 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 596 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 595 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | @@ -605,7 +604,6 @@ fn gimmeItBroke() anyerror { | ... | @@ -605,7 +604,6 @@ fn gimmeItBroke() anyerror { |
| 605 | } | 604 | } |
| 606 | 605 | ||
| 607 | test "@errorName sentinel length matches slice length" { | 606 | test "@errorName sentinel length matches slice length" { |
| 608 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 609 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 607 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 610 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 608 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 611 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 609 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | @@ -883,7 +881,6 @@ test "catch within a function that calls no errorable functions" { | ... | @@ -883,7 +881,6 @@ test "catch within a function that calls no errorable functions" { |
| 883 | } | 881 | } |
| 884 | 882 | ||
| 885 | test "error from comptime string" { | 883 | test "error from comptime string" { |
| 886 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 887 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 884 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 888 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 885 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 889 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 886 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/return_address.zig-1| ... | @@ -6,7 +6,6 @@ fn retAddr() usize { | ... | @@ -6,7 +6,6 @@ fn retAddr() usize { |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | test "return address" { | 8 | test "return address" { |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | ||
| 10 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 11 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; | 11 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/cases/array_in_anon_struct.zig+1-1| ... | @@ -19,4 +19,4 @@ pub fn main() !void { | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | ||
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux,aarch64-linux |
test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig+2-2| ... | @@ -7,5 +7,5 @@ export fn entry3() callconv(.avr_interrupt) void {} | ... | @@ -7,5 +7,5 @@ export fn entry3() callconv(.avr_interrupt) void {} |
| 7 | // target=aarch64-linux-none | 7 | // target=aarch64-linux-none |
| 8 | // | 8 | // |
| 9 | // :1:30: error: calling convention 'x86_64_interrupt' only available on architectures 'x86_64' | 9 | // :1:30: error: calling convention 'x86_64_interrupt' only available on architectures 'x86_64' |
| 10 | // :1:30: error: calling convention 'x86_interrupt' only available on architectures 'x86' | 10 | // :2:30: error: calling convention 'x86_interrupt' only available on architectures 'x86' |
| 11 | // :1:30: error: calling convention 'avr_interrupt' only available on architectures 'avr' | 11 | // :3:30: error: calling convention 'avr_interrupt' only available on architectures 'avr' |
test/cases/compile_errors/error_set_membership.zig+1-1| ... | @@ -25,7 +25,7 @@ pub fn main() Error!void { | ... | @@ -25,7 +25,7 @@ pub fn main() Error!void { |
| 25 | 25 | ||
| 26 | // error | 26 | // error |
| 27 | // backend=stage2 | 27 | // backend=stage2 |
| 28 | // target=native | 28 | // target=x86_64-linux |
| 29 | // | 29 | // |
| 30 | // :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' | 30 | // :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set' |
| 31 | // :23:29: note: 'error.InvalidDirection' not a member of destination error set | 31 | // :23:29: note: 'error.InvalidDirection' not a member of destination error set |
test/cases/compile_errors/function_ptr_alignment.zig+1-1| ... | @@ -10,7 +10,7 @@ comptime { | ... | @@ -10,7 +10,7 @@ comptime { |
| 10 | 10 | ||
| 11 | // error | 11 | // error |
| 12 | // backend=stage2 | 12 | // backend=stage2 |
| 13 | // target=native | 13 | // target=x86_64-linux |
| 14 | // | 14 | // |
| 15 | // :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' | 15 | // :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void' |
| 16 | // :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' | 16 | // :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2' |
test/cases/compile_errors/issue_15572_break_on_inline_while.zig+1-1| ... | @@ -15,6 +15,6 @@ pub fn main() void { | ... | @@ -15,6 +15,6 @@ pub fn main() void { |
| 15 | 15 | ||
| 16 | // error | 16 | // error |
| 17 | // backend=stage2 | 17 | // backend=stage2 |
| 18 | // target=native | 18 | // target=x86_64-linux |
| 19 | // | 19 | // |
| 20 | // :9:28: error: incompatible types: 'builtin.Type.EnumField' and 'void' | 20 | // :9:28: error: incompatible types: 'builtin.Type.EnumField' and 'void' |
test/cases/compile_errors/switch_on_non_err_union.zig+1-1| ... | @@ -6,6 +6,6 @@ pub fn main() void { | ... | @@ -6,6 +6,6 @@ pub fn main() void { |
| 6 | 6 | ||
| 7 | // error | 7 | // error |
| 8 | // backend=stage2 | 8 | // backend=stage2 |
| 9 | // target=native | 9 | // target=x86_64-linux |
| 10 | // | 10 | // |
| 11 | // :2:23: error: expected error union type, found 'bool' | 11 | // :2:23: error: expected error union type, found 'bool' |
test/cases/pic_freestanding.zig+1-1| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | 3 | ||
| 4 | fn _start() callconv(.naked) void {} | 4 | pub fn _start() callconv(.naked) void {} |
| 5 | 5 | ||
| 6 | comptime { | 6 | comptime { |
| 7 | @export(&_start, .{ .name = if (builtin.cpu.arch.isMIPS()) "__start" else "_start" }); | 7 | @export(&_start, .{ .name = if (builtin.cpu.arch.isMIPS()) "__start" else "_start" }); |
test/cases/safety/@alignCast misaligned.zig	+1-1| ... | @@ -22,4 +22,4 @@ fn foo(bytes: []u8) u32 { | ... | @@ -22,4 +22,4 @@ fn foo(bytes: []u8) u32 { |
| 22 | } | 22 | } |
| 23 | // run | 23 | // run |
| 24 | // backend=stage2,llvm | 24 | // backend=stage2,llvm |
| 25 | // target=native | 25 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@enumFromInt - no matching tag value.zig	+1-1| ... | @@ -23,4 +23,4 @@ fn baz(_: Foo) void {} | ... | @@ -23,4 +23,4 @@ fn baz(_: Foo) void {} |
| 23 | 23 | ||
| 24 | // run | 24 | // run |
| 25 | // backend=stage2,llvm | 25 | // backend=stage2,llvm |
| 26 | // target=native | 26 | // target=x86_64-linux |
test/cases/safety/@enumFromInt truncated bits - exhaustive.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() u8 { | ... | @@ -20,4 +20,4 @@ pub fn main() u8 { |
| 20 | 20 | ||
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux |
test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() u8 { | ... | @@ -20,4 +20,4 @@ pub fn main() u8 { |
| 20 | 20 | ||
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux |
test/cases/safety/@errorCast error not present in destination.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn foo(set1: Set1) Set2 { | ... | @@ -18,4 +18,4 @@ fn foo(set1: Set1) Set2 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/@errorCast error union casted to disjoint set.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn foo() anyerror!i32 { | ... | @@ -17,4 +17,4 @@ fn foo() anyerror!i32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/@intCast to u0.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn bar(one: u1, not_zero: i32) void { | ... | @@ -19,4 +19,4 @@ fn bar(one: u1, not_zero: i32) void { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - negative out of range.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn bar(a: f32) i8 { | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) i8 { |
| 17 | fn baz(_: i8) void {} | 17 | fn baz(_: i8) void {} |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { |
| 17 | fn baz(_: u8) void {} | 17 | fn baz(_: u8) void {} |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/@intFromFloat cannot fit - positive out of range.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { | ... | @@ -17,4 +17,4 @@ fn bar(a: f32) u8 { |
| 17 | fn baz(_: u8) void {} | 17 | fn baz(_: u8) void {} |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@ptrFromInt with misaligned address.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/@tagName on corrupted enum value.zig	+1-1| ... | @@ -23,4 +23,4 @@ pub fn main() !void { | ... | @@ -23,4 +23,4 @@ pub fn main() !void { |
| 23 | 23 | ||
| 24 | // run | 24 | // run |
| 25 | // backend=stage2,llvm | 25 | // backend=stage2,llvm |
| 26 | // target=native | 26 | // target=x86_64-linux |
test/cases/safety/@tagName on corrupted union value.zig	+1-1| ... | @@ -24,4 +24,4 @@ pub fn main() !void { | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=native | 27 | // target=x86_64-linux |
test/cases/safety/array slice sentinel mismatch vector.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux |
test/cases/safety/array slice sentinel mismatch.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/bad union field access.zig	+1-1| ... | @@ -24,4 +24,4 @@ fn bar(f: *Foo) void { | ... | @@ -24,4 +24,4 @@ fn bar(f: *Foo) void { |
| 24 | } | 24 | } |
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=native | 27 | // target=x86_64-linux |
test/cases/safety/calling panic.zig	+1-1| ... | @@ -13,4 +13,4 @@ pub fn main() !void { | ... | @@ -13,4 +13,4 @@ pub fn main() !void { |
| 13 | } | 13 | } |
| 14 | // run | 14 | // run |
| 15 | // backend=stage2,llvm | 15 | // backend=stage2,llvm |
| 16 | // target=native | 16 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/cast []u8 to bigger slice of wrong size.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { | ... | @@ -18,4 +18,4 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/cast integer to global error and no code matches.zig	+1-1| ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { | ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/empty slice with sentinel out of bounds.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/exact division failure - vectors.zig	+1-1| ... | @@ -20,4 +20,4 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ... | @@ -20,4 +20,4 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 20 | } | 20 | } |
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux |
test/cases/safety/exact division failure.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn divExact(a: i32, b: i32) i32 { | ... | @@ -18,4 +18,4 @@ fn divExact(a: i32, b: i32) i32 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/for_len_mismatch.zig+1-1| ... | @@ -22,4 +22,4 @@ pub fn main() !void { | ... | @@ -22,4 +22,4 @@ pub fn main() !void { |
| 22 | } | 22 | } |
| 23 | // run | 23 | // run |
| 24 | // backend=stage2,llvm | 24 | // backend=stage2,llvm |
| 25 | // target=native | 25 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/for_len_mismatch_three.zig+1-1| ... | @@ -21,4 +21,4 @@ pub fn main() !void { | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | } | 21 | } |
| 22 | // run | 22 | // run |
| 23 | // backend=stage2,llvm | 23 | // backend=stage2,llvm |
| 24 | // target=native | 24 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/ignored expression integer overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/integer addition overflow.zig	+1-1| ... | @@ -20,4 +20,4 @@ fn add(a: u16, b: u16) u16 { | ... | @@ -20,4 +20,4 @@ fn add(a: u16, b: u16) u16 { |
| 20 | 20 | ||
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer division by zero - vectors.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ... | @@ -19,4 +19,4 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux |
test/cases/safety/integer division by zero.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn div0(a: i32, b: i32) i32 { | ... | @@ -17,4 +17,4 @@ fn div0(a: i32, b: i32) i32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer multiplication overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn mul(a: u16, b: u16) u16 { | ... | @@ -18,4 +18,4 @@ fn mul(a: u16, b: u16) u16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer negation overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn neg(a: i16) i16 { | ... | @@ -18,4 +18,4 @@ fn neg(a: i16) i16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/integer subtraction overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn sub(a: u16, b: u16) u16 { | ... | @@ -18,4 +18,4 @@ fn sub(a: u16, b: u16) u16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memcpy_alias.zig+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memcpy_len_mismatch.zig+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memmove_len_mismatch.zig+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_array_undefined_bytes.zig+1-1| ... | @@ -15,4 +15,4 @@ pub fn main() !void { | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | } | 15 | } |
| 16 | // run | 16 | // run |
| 17 | // backend=stage2,llvm | 17 | // backend=stage2,llvm |
| 18 | // target=native | 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_array_undefined_large.zig+1-1| ... | @@ -15,4 +15,4 @@ pub fn main() !void { | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | } | 15 | } |
| 16 | // run | 16 | // run |
| 17 | // backend=stage2,llvm | 17 | // backend=stage2,llvm |
| 18 | // target=native | 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_slice_undefined_bytes.zig+1-1| ... | @@ -17,4 +17,4 @@ pub fn main() !void { | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/memset_slice_undefined_large.zig+1-1| ... | @@ -17,4 +17,4 @@ pub fn main() !void { | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/modrem by zero.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn div0(a: u32, b: u32) u32 { | ... | @@ -17,4 +17,4 @@ fn div0(a: u32, b: u32) u32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/modulus by zero.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn mod0(a: i32, b: i32) i32 { | ... | @@ -17,4 +17,4 @@ fn mod0(a: i32, b: i32) i32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/noreturn returned.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() void { | ... | @@ -20,4 +20,4 @@ pub fn main() void { |
| 20 | } | 20 | } |
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional unwrap operator on C pointer.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional unwrap operator on null pointer.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/optional_empty_error_set.zig+1-1| ... | @@ -19,4 +19,4 @@ fn foo() !void { | ... | @@ -19,4 +19,4 @@ fn foo() !void { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/out of bounds array slice by length.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn foo(a: u32) u32 { | ... | @@ -17,4 +17,4 @@ fn foo(a: u32) u32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/out of bounds slice access.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn bar(a: []const i32) i32 { | ... | @@ -18,4 +18,4 @@ fn bar(a: []const i32) i32 { |
| 18 | fn baz(_: i32) void {} | 18 | fn baz(_: i32) void {} |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer casting null to non-optional pointer.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer casting to null function pointer.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() !void { | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | 20 | ||
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/pointer slice sentinel mismatch.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/remainder division by zero.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn rem0(a: i32, b: i32) i32 { | ... | @@ -17,4 +17,4 @@ fn rem0(a: i32, b: i32) i32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/shift left by huge amount.zig	+1-1| ... | @@ -19,4 +19,4 @@ pub fn main() !void { | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | ||
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/shift right by huge amount.zig	+1-1| ... | @@ -19,4 +19,4 @@ pub fn main() !void { | ... | @@ -19,4 +19,4 @@ pub fn main() !void { |
| 19 | 19 | ||
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed integer division overflow - vectors.zig	+1-1| ... | @@ -20,4 +20,4 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) { | ... | @@ -20,4 +20,4 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) { |
| 20 | } | 20 | } |
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux |
test/cases/safety/signed integer division overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn div(a: i16, b: i16) i16 { | ... | @@ -18,4 +18,4 @@ fn div(a: i16, b: i16) i16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux |
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig	+1-1| ... | @@ -17,4 +17,4 @@ fn unsigned_cast(x: i32) u32 { | ... | @@ -17,4 +17,4 @@ fn unsigned_cast(x: i32) u32 { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed shift left overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shl(a: i16, b: u4) i16 { | ... | @@ -18,4 +18,4 @@ fn shl(a: i16, b: u4) i16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/signed shift right overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shr(a: i16, b: u4) i16 { | ... | @@ -18,4 +18,4 @@ fn shr(a: i16, b: u4) i16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/signed-unsigned vector cast.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/slice by length sentinel mismatch on lhs.zig	+1-1| ... | @@ -15,4 +15,4 @@ pub fn main() !void { | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | } | 15 | } |
| 16 | // run | 16 | // run |
| 17 | // backend=stage2,llvm | 17 | // backend=stage2,llvm |
| 18 | // target=native | 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice by length sentinel mismatch on rhs.zig	+1-1| ... | @@ -15,4 +15,4 @@ pub fn main() !void { | ... | @@ -15,4 +15,4 @@ pub fn main() !void { |
| 15 | } | 15 | } |
| 16 | // run | 16 | // run |
| 17 | // backend=stage2,llvm | 17 | // backend=stage2,llvm |
| 18 | // target=native | 18 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice sentinel mismatch - floats.zig	+1-1| ... | @@ -17,4 +17,4 @@ pub fn main() !void { | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | ||
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux |
test/cases/safety/slice sentinel mismatch - optional pointers.zig	+1-1| ... | @@ -17,4 +17,4 @@ pub fn main() !void { | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | 17 | ||
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice slice sentinel mismatch.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice start index greater than end index.zig	+1-1| ... | @@ -21,4 +21,4 @@ pub fn main() !void { | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | 21 | ||
| 22 | // run | 22 | // run |
| 23 | // backend=stage2,llvm | 23 | // backend=stage2,llvm |
| 24 | // target=native | 24 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice with sentinel out of bounds - runtime len.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() !void { | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | 20 | ||
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice with sentinel out of bounds.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_0.zig+1-1| ... | @@ -24,4 +24,4 @@ const std = @import("std"); | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_1.zig+1-1| ... | @@ -24,4 +24,4 @@ const std = @import("std"); | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slice_cast_change_len_2.zig+1-1| ... | @@ -24,4 +24,4 @@ const std = @import("std"); | ... | @@ -24,4 +24,4 @@ const std = @import("std"); |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=x86_64-linux | 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slicing null C pointer - runtime len.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/slicing null C pointer.zig	+1-1| ... | @@ -17,4 +17,4 @@ pub fn main() !void { | ... | @@ -17,4 +17,4 @@ pub fn main() !void { |
| 17 | } | 17 | } |
| 18 | // run | 18 | // run |
| 19 | // backend=stage2,llvm | 19 | // backend=stage2,llvm |
| 20 | // target=native | 20 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/switch else on corrupt enum value - one prong.zig	+1-1| ... | @@ -21,4 +21,4 @@ pub fn main() !void { | ... | @@ -21,4 +21,4 @@ pub fn main() !void { |
| 21 | } | 21 | } |
| 22 | // run | 22 | // run |
| 23 | // backend=stage2,llvm | 23 | // backend=stage2,llvm |
| 24 | // target=native | 24 | // target=x86_64-linux |
test/cases/safety/switch else on corrupt enum value - union.zig	+1-1| ... | @@ -26,4 +26,4 @@ pub fn main() !void { | ... | @@ -26,4 +26,4 @@ pub fn main() !void { |
| 26 | } | 26 | } |
| 27 | // run | 27 | // run |
| 28 | // backend=stage2,llvm | 28 | // backend=stage2,llvm |
| 29 | // target=native | 29 | // target=x86_64-linux |
test/cases/safety/switch else on corrupt enum value.zig	+1-1| ... | @@ -20,4 +20,4 @@ pub fn main() !void { | ... | @@ -20,4 +20,4 @@ pub fn main() !void { |
| 20 | } | 20 | } |
| 21 | // run | 21 | // run |
| 22 | // backend=stage2,llvm | 22 | // backend=stage2,llvm |
| 23 | // target=native | 23 | // target=x86_64-linux |
test/cases/safety/switch on corrupted enum value.zig	+1-1| ... | @@ -24,4 +24,4 @@ pub fn main() !void { | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=native | 27 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/switch on corrupted union value.zig	+1-1| ... | @@ -24,4 +24,4 @@ pub fn main() !void { | ... | @@ -24,4 +24,4 @@ pub fn main() !void { |
| 24 | 24 | ||
| 25 | // run | 25 | // run |
| 26 | // backend=stage2,llvm | 26 | // backend=stage2,llvm |
| 27 | // target=native | 27 | // target=x86_64-linux |
test/cases/safety/truncating vector cast.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/unreachable.zig+1-1| ... | @@ -12,4 +12,4 @@ pub fn main() !void { | ... | @@ -12,4 +12,4 @@ pub fn main() !void { |
| 12 | } | 12 | } |
| 13 | // run | 13 | // run |
| 14 | // backend=stage2,llvm | 14 | // backend=stage2,llvm |
| 15 | // target=native | 15 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig	+1-1| ... | @@ -16,4 +16,4 @@ pub fn main() !void { | ... | @@ -16,4 +16,4 @@ pub fn main() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux |
test/cases/safety/unsigned shift left overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shl(a: u16, b: u4) u16 { | ... | @@ -18,4 +18,4 @@ fn shl(a: u16, b: u4) u16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/unsigned shift right overflow.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shr(a: u16, b: u4) u16 { | ... | @@ -18,4 +18,4 @@ fn shr(a: u16, b: u4) u16 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unsigned-signed vector cast.zig	+1-1| ... | @@ -18,4 +18,4 @@ pub fn main() !void { | ... | @@ -18,4 +18,4 @@ pub fn main() !void { |
| 18 | 18 | ||
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux |
test/cases/safety/unwrap error switch.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn bar() !void { | ... | @@ -18,4 +18,4 @@ fn bar() !void { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/unwrap error.zig	+1-1| ... | @@ -16,4 +16,4 @@ fn bar() !void { | ... | @@ -16,4 +16,4 @@ fn bar() !void { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/value does not fit in shortening cast - u0.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: u8) u0 { | ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: u8) u0 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/value does not fit in shortening cast.zig	+1-1| ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: i32) i8 { | ... | @@ -18,4 +18,4 @@ fn shorten_cast(x: i32) i8 { |
| 18 | } | 18 | } |
| 19 | // run | 19 | // run |
| 20 | // backend=stage2,llvm | 20 | // backend=stage2,llvm |
| 21 | // target=native | 21 | // target=x86_64-linux,aarch64-linux |
test/cases/safety/vector integer addition overflow.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { | ... | @@ -19,4 +19,4 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux |
test/cases/safety/vector integer multiplication overflow.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { | ... | @@ -19,4 +19,4 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux |
test/cases/safety/vector integer negation overflow.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) { | ... | @@ -19,4 +19,4 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux |
test/cases/safety/vector integer subtraction overflow.zig	+1-1| ... | @@ -19,4 +19,4 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { | ... | @@ -19,4 +19,4 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) { |
| 19 | } | 19 | } |
| 20 | // run | 20 | // run |
| 21 | // backend=stage2,llvm | 21 | // backend=stage2,llvm |
| 22 | // target=native | 22 | // target=x86_64-linux |
test/cases/safety/zero casted to error.zig	+1-1| ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { | ... | @@ -16,4 +16,4 @@ fn bar(x: u16) anyerror { |
| 16 | } | 16 | } |
| 17 | // run | 17 | // run |
| 18 | // backend=stage2,llvm | 18 | // backend=stage2,llvm |
| 19 | // target=native | 19 | // target=x86_64-linux,aarch64-linux |
test/cases/taking_pointer_of_global_tagged_union.zig+1-1| ... | @@ -23,4 +23,4 @@ pub fn main() !void { | ... | @@ -23,4 +23,4 @@ pub fn main() !void { |
| 23 | 23 | ||
| 24 | // run | 24 | // run |
| 25 | // backend=stage2,llvm | 25 | // backend=stage2,llvm |
| 26 | // target=native | 26 | // target=x86_64-linux |
test/src/Cases.zig+1-5| ... | @@ -436,7 +436,7 @@ fn addFromDirInner( | ... | @@ -436,7 +436,7 @@ fn addFromDirInner( |
| 436 | const target = &resolved_target.result; | 436 | const target = &resolved_target.result; |
| 437 | for (backends) |backend| { | 437 | for (backends) |backend| { |
| 438 | if (backend == .stage2 and | 438 | if (backend == .stage2 and |
| 439 | target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) | 439 | target.cpu.arch != .aarch64 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64) |
| 440 | { | 440 | { |
| 441 | // Other backends don't support new liveness format | 441 | // Other backends don't support new liveness format |
| 442 | continue; | 442 | continue; |
| ... | @@ -447,10 +447,6 @@ fn addFromDirInner( | ... | @@ -447,10 +447,6 @@ fn addFromDirInner( |
| 447 | // Rosetta has issues with ZLD | 447 | // Rosetta has issues with ZLD |
| 448 | continue; | 448 | continue; |
| 449 | } | 449 | } |
| 450 | if (backend == .stage2 and target.ofmt == .coff) { | ||
| 451 | // COFF linker has bitrotted | ||
| 452 | continue; | ||
| 453 | } | ||
| 454 | 450 | ||
| 455 | const next = ctx.cases.items.len; | 451 | const next = ctx.cases.items.len; |
| 456 | try ctx.cases.append(.{ | 452 | try ctx.cases.append(.{ |