authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-27 00:17:19-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-27 00:17:19-07:00
logda408bd6fce9e07daccd35f9257e6819f58fc767
tree512a3e0977ea38602c407f5730bb90a8fa6fcfa7
parente12dc4947c411d25c4c56d887e62d0e2b9addcb8
parent7894703ee74a915206143f0b3efea082f999bb86
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24585 from jacobly0/aarch64

aarch64: more progress

137 files changed, 1590 insertions(+), 523 deletions(-)

lib/compiler_rt.zig+1-1
...@@ -240,7 +240,7 @@ comptime {...@@ -240,7 +240,7 @@ comptime {
240 _ = @import("compiler_rt/udivmodti4.zig");240 _ = @import("compiler_rt/udivmodti4.zig");
241241
242 // extra242 // extra
243 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");243 _ = @import("compiler_rt/os_version_check.zig");
244 _ = @import("compiler_rt/emutls.zig");244 _ = @import("compiler_rt/emutls.zig");
245 _ = @import("compiler_rt/arm.zig");245 _ = @import("compiler_rt/arm.zig");
246 _ = @import("compiler_rt/aulldiv.zig");246 _ = @import("compiler_rt/aulldiv.zig");
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/Package/Module.zig+1-1
...@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {...@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
250 };250 };
251251
252 const stack_check = b: {252 const stack_check = b: {
253 if (!target_util.supportsStackProbing(target)) {253 if (!target_util.supportsStackProbing(target, zig_backend)) {
254 if (options.inherited.stack_check == true)254 if (options.inherited.stack_check == true)
255 return error.StackCheckUnsupportedByTarget;255 return error.StackCheckUnsupportedByTarget;
256 break :b false;256 break :b false;
src/arch/x86_64/CodeGen.zig+3-3
...@@ -168137,7 +168137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168137,7 +168137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168137 .unused,168137 .unused,
168138 .unused,168138 .unused,
168139 },168139 },
168140 .dst_temps = .{ .{ .cc = .b }, .unused },168140 .dst_temps = .{ .{ .cc = .be }, .unused },
168141 .clobbers = .{ .eflags = true },168141 .clobbers = .{ .eflags = true },
168142 .each = .{ .once = &.{168142 .each = .{ .once = &.{
168143 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },168143 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
...@@ -168161,7 +168161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168161,7 +168161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168161 .unused,168161 .unused,
168162 .unused,168162 .unused,
168163 },168163 },
168164 .dst_temps = .{ .{ .cc = .b }, .unused },168164 .dst_temps = .{ .{ .cc = .be }, .unused },
168165 .clobbers = .{ .eflags = true },168165 .clobbers = .{ .eflags = true },
168166 .each = .{ .once = &.{168166 .each = .{ .once = &.{
168167 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },168167 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
...@@ -168185,7 +168185,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {...@@ -168185,7 +168185,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168185 .unused,168185 .unused,
168186 .unused,168186 .unused,
168187 },168187 },
168188 .dst_temps = .{ .{ .cc = .b }, .unused },168188 .dst_temps = .{ .{ .cc = .be }, .unused },
168189 .clobbers = .{ .eflags = true },168189 .clobbers = .{ .eflags = true },
168190 .each = .{ .once = &.{168190 .each = .{ .once = &.{
168191 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },168191 .{ ._, ._, .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 else179 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,
5253
...@@ -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};
77
8pub fn nextInstruction(as: *Assemble) !?Instruction {8pub 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}
127138
139fn 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
128const token_buf_len = "v31.b[15]".len;148const token_buf_len = "v31.b[15]".len;
129fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {149fn 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,
4literals: []const u32,4literals: []const u32,
5nav_relocs: []const Reloc.Nav,5nav_relocs: []const Reloc.Nav,
6uav_relocs: []const Reloc.Uav,6uav_relocs: []const Reloc.Uav,
7lazy_relocs: []const Reloc.Lazy,
7global_relocs: []const Reloc.Global,8global_relocs: []const Reloc.Global,
8literal_relocs: []const Reloc.Literal,9literal_relocs: []const Reloc.Literal,
910
...@@ -21,8 +22,13 @@ pub const Reloc = struct {...@@ -21,8 +22,13 @@ pub const Reloc = struct {
21 reloc: Reloc,22 reloc: Reloc,
22 };23 };
2324
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 };
2834
...@@ -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 else160 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}
264337
src/codegen/aarch64/Select.zig+1119-301
...@@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction),...@@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction),
22literals: std.ArrayListUnmanaged(u32),22literals: std.ArrayListUnmanaged(u32),
23nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav),23nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav),
24uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav),24uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav),
25lazy_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Lazy),
25global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global),26global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global),
26literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),27literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),
2728
...@@ -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 );
5253
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};
6061
...@@ -84,12 +85,12 @@ pub const Loop = struct {...@@ -84,12 +85,12 @@ pub const Loop = struct {
8485
85 pub const empty_list: u32 = std.math.maxInt(u32);86 pub const empty_list: u32 = std.math.maxInt(u32);
8687
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};
9596
...@@ -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);
113115
...@@ -582,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -582,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
582584
583 air_body_index += 1;585 air_body_index += 1;
584 },586 },
585 .@"try", .try_cold, .try_ptr, .try_ptr_cold => {587 .@"try", .try_cold => {
586 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;588 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
587 const extra = isel.air.extraData(Air.Try, pl_op.payload);589 const extra = isel.air.extraData(Air.Try, pl_op.payload);
588590
...@@ -594,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -594,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
594 air_inst_index = air_body[air_body_index];596 air_inst_index = air_body[air_body_index];
595 continue :air_tag air_tags[@intFromEnum(air_inst_index)];597 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
596 },598 },
599 .try_ptr, .try_ptr_cold => {
600 const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
601 const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
602
603 try isel.analyzeUse(extra.data.ptr);
604 try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
605 try isel.def_order.putNoClobber(gpa, air_inst_index, {});
606
607 air_body_index += 1;
608 air_inst_index = air_body[air_body_index];
609 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
610 },
597 .ret, .ret_safe, .ret_load => {611 .ret, .ret_safe, .ret_load => {
598 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;612 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
599 isel.returns = true;613 isel.returns = true;
...@@ -864,7 +878,7 @@ pub fn finishAnalysis(isel: *Select) !void {...@@ -864,7 +878,7 @@ pub fn finishAnalysis(isel: *Select) !void {
864 }878 }
865}879}
866880
867pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {881pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {
868 const zcu = isel.pt.zcu;882 const zcu = isel.pt.zcu;
869 const ip = &zcu.intern_pool;883 const ip = &zcu.intern_pool;
870 const gpa = zcu.gpa;884 const gpa = zcu.gpa;
...@@ -946,7 +960,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -946,7 +960,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
946 }960 }
947 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;961 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
948 },962 },
949 .add, .add_optimized, .add_wrap, .sub, .sub_optimized, .sub_wrap => |air_tag| {963 .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: {964 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
951 defer res_vi.value.deref(isel);965 defer res_vi.value.deref(isel);
952966
...@@ -954,13 +968,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -954,13 +968,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
954 const ty = isel.air.typeOf(bin_op.lhs, ip);968 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) {969 if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) {
956 else => unreachable,970 else => unreachable,
957 .add, .add_wrap => .add,971 .add, .add_safe, .add_wrap => .add,
958 .sub, .sub_wrap => .sub,972 .sub, .sub_safe, .sub_wrap => .sub,
959 }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) {973 }, try isel.use(bin_op.rhs), .{
960 else => unreachable,974 .overflow = switch (air_tag) {
961 .add, .sub => false,975 else => unreachable,
962 .add_wrap, .sub_wrap => true,976 .add, .sub => .@"unreachable",
963 } }) else switch (ty.floatBits(isel.target)) {977 .add_safe, .sub_safe => .{ .panic = .integer_overflow },
978 .add_wrap, .sub_wrap => .wrap,
979 },
980 }) else switch (ty.floatBits(isel.target)) {
964 else => unreachable,981 else => unreachable,
965 16, 32, 64 => |bits| {982 16, 32, 64 => |bits| {
966 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;983 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
...@@ -1021,7 +1038,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1021,7 +1038,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
10211038
1022 try call.prepareCallee(isel);1039 try call.prepareCallee(isel);
1023 try isel.global_relocs.append(gpa, .{1040 try isel.global_relocs.append(gpa, .{
1024 .global = switch (air_tag) {1041 .name = switch (air_tag) {
1025 else => unreachable,1042 else => unreachable,
1026 .add, .add_optimized => switch (bits) {1043 .add, .add_optimized => switch (bits) {
1027 else => unreachable,1044 else => unreachable,
...@@ -1336,7 +1353,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1336,7 +1353,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
13361353
1337 try call.prepareCallee(isel);1354 try call.prepareCallee(isel);
1338 try isel.global_relocs.append(gpa, .{1355 try isel.global_relocs.append(gpa, .{
1339 .global = switch (bits) {1356 .name = switch (bits) {
1340 else => unreachable,1357 else => unreachable,
1341 16 => "__mulhf3",1358 16 => "__mulhf3",
1342 32 => "__mulsf3",1359 32 => "__mulsf3",
...@@ -1379,6 +1396,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1379,6 +1396,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
1379 }1396 }
1380 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;1397 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1381 },1398 },
1399 .mul_safe => |air_tag| {
1400 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1401 defer res_vi.value.deref(isel);
1402
1403 const bin_op = air.data(air.inst_index).bin_op;
1404 const ty = isel.air.typeOf(bin_op.lhs, ip);
1405 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
1406 const int_info = ty.intInfo(zcu);
1407 switch (int_info.signedness) {
1408 .signed => switch (int_info.bits) {
1409 0 => unreachable,
1410 1 => {
1411 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1412 const lhs_vi = try isel.use(bin_op.lhs);
1413 const rhs_vi = try isel.use(bin_op.rhs);
1414 const lhs_mat = try lhs_vi.matReg(isel);
1415 const rhs_mat = try rhs_vi.matReg(isel);
1416 try isel.emit(.orr(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1417 const skip_label = isel.instructions.items.len;
1418 try isel.emitPanic(.integer_overflow);
1419 try isel.emit(.@"b."(
1420 .invert(.ne),
1421 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
1422 ));
1423 try isel.emit(.ands(.wzr, lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1424 try rhs_mat.finish(isel);
1425 try lhs_mat.finish(isel);
1426 },
1427 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1428 },
1429 .unsigned => switch (int_info.bits) {
1430 0 => unreachable,
1431 1 => {
1432 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1433 const lhs_vi = try isel.use(bin_op.lhs);
1434 const rhs_vi = try isel.use(bin_op.rhs);
1435 const lhs_mat = try lhs_vi.matReg(isel);
1436 const rhs_mat = try rhs_vi.matReg(isel);
1437 try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
1438 try rhs_mat.finish(isel);
1439 try lhs_mat.finish(isel);
1440 },
1441 2...16 => |bits| {
1442 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1443 const lhs_vi = try isel.use(bin_op.lhs);
1444 const rhs_vi = try isel.use(bin_op.rhs);
1445 const lhs_mat = try lhs_vi.matReg(isel);
1446 const rhs_mat = try rhs_vi.matReg(isel);
1447 const skip_label = isel.instructions.items.len;
1448 try isel.emitPanic(.integer_overflow);
1449 try isel.emit(.@"b."(
1450 .eq,
1451 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
1452 ));
1453 try isel.emit(.ands(.wzr, res_ra.w(), .{ .immediate = .{
1454 .N = .word,
1455 .immr = @intCast(32 - bits),
1456 .imms = @intCast(32 - bits - 1),
1457 } }));
1458 try isel.emit(.madd(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr));
1459 try rhs_mat.finish(isel);
1460 try lhs_mat.finish(isel);
1461 },
1462 17...32 => |bits| {
1463 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1464 const lhs_vi = try isel.use(bin_op.lhs);
1465 const rhs_vi = try isel.use(bin_op.rhs);
1466 const lhs_mat = try lhs_vi.matReg(isel);
1467 const rhs_mat = try rhs_vi.matReg(isel);
1468 const skip_label = isel.instructions.items.len;
1469 try isel.emitPanic(.integer_overflow);
1470 try isel.emit(.@"b."(
1471 .eq,
1472 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
1473 ));
1474 try isel.emit(.ands(.xzr, res_ra.x(), .{ .immediate = .{
1475 .N = .doubleword,
1476 .immr = @intCast(64 - bits),
1477 .imms = @intCast(64 - bits - 1),
1478 } }));
1479 try isel.emit(.umaddl(res_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr));
1480 try rhs_mat.finish(isel);
1481 try lhs_mat.finish(isel);
1482 },
1483 33...63 => |bits| {
1484 const lo64_ra = try res_vi.value.defReg(isel) orelse break :unused;
1485 const lhs_vi = try isel.use(bin_op.lhs);
1486 const rhs_vi = try isel.use(bin_op.rhs);
1487 const lhs_mat = try lhs_vi.matReg(isel);
1488 const rhs_mat = try rhs_vi.matReg(isel);
1489 const hi64_ra = hi64_ra: {
1490 const lo64_lock = isel.tryLockReg(lo64_ra);
1491 defer lo64_lock.unlock(isel);
1492 break :hi64_ra try isel.allocIntReg();
1493 };
1494 defer isel.freeReg(hi64_ra);
1495 const skip_label = isel.instructions.items.len;
1496 try isel.emitPanic(.integer_overflow);
1497 try isel.emit(.cbz(
1498 hi64_ra.x(),
1499 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
1500 ));
1501 try isel.emit(.orr(hi64_ra.x(), hi64_ra.x(), .{ .shifted_register = .{
1502 .register = lo64_ra.x(),
1503 .shift = .{ .lsr = @intCast(bits) },
1504 } }));
1505 try isel.emit(.madd(lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
1506 try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
1507 try rhs_mat.finish(isel);
1508 try lhs_mat.finish(isel);
1509 },
1510 64 => {
1511 const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
1512 const lhs_vi = try isel.use(bin_op.lhs);
1513 const rhs_vi = try isel.use(bin_op.rhs);
1514 const lhs_mat = try lhs_vi.matReg(isel);
1515 const rhs_mat = try rhs_vi.matReg(isel);
1516 try isel.emit(.madd(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
1517 const hi64_ra = try isel.allocIntReg();
1518 defer isel.freeReg(hi64_ra);
1519 const skip_label = isel.instructions.items.len;
1520 try isel.emitPanic(.integer_overflow);
1521 try isel.emit(.cbz(
1522 hi64_ra.x(),
1523 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
1524 ));
1525 try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
1526 try rhs_mat.finish(isel);
1527 try lhs_mat.finish(isel);
1528 },
1529 65...128 => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1530 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
1531 },
1532 }
1533 }
1534 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
1535 },
1382 .mul_sat => |air_tag| {1536 .mul_sat => |air_tag| {
1383 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {1537 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
1384 defer res_vi.value.deref(isel);1538 defer res_vi.value.deref(isel);
...@@ -1674,7 +1828,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1674,7 +1828,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
16741828
1675 try call.prepareCallee(isel);1829 try call.prepareCallee(isel);
1676 try isel.global_relocs.append(gpa, .{1830 try isel.global_relocs.append(gpa, .{
1677 .global = switch (bits) {1831 .name = switch (bits) {
1678 else => unreachable,1832 else => unreachable,
1679 16 => "__divhf3",1833 16 => "__divhf3",
1680 32 => "__divsf3",1834 32 => "__divsf3",
...@@ -1813,7 +1967,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1813,7 +1967,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
18131967
1814 try call.prepareCallee(isel);1968 try call.prepareCallee(isel);
1815 try isel.global_relocs.append(gpa, .{1969 try isel.global_relocs.append(gpa, .{
1816 .global = switch (int_info.signedness) {1970 .name = switch (int_info.signedness) {
1817 .signed => "__divti3",1971 .signed => "__divti3",
1818 .unsigned => "__udivti3",1972 .unsigned => "__udivti3",
1819 },1973 },
...@@ -1917,7 +2071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1917,7 +2071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
1917 else => unreachable,2071 else => unreachable,
1918 .div_trunc, .div_trunc_optimized => {2072 .div_trunc, .div_trunc_optimized => {
1919 try isel.global_relocs.append(gpa, .{2073 try isel.global_relocs.append(gpa, .{
1920 .global = switch (bits) {2074 .name = switch (bits) {
1921 else => unreachable,2075 else => unreachable,
1922 16 => "__trunch",2076 16 => "__trunch",
1923 32 => "truncf",2077 32 => "truncf",
...@@ -1931,7 +2085,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1931,7 +2085,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
1931 },2085 },
1932 .div_floor, .div_floor_optimized => {2086 .div_floor, .div_floor_optimized => {
1933 try isel.global_relocs.append(gpa, .{2087 try isel.global_relocs.append(gpa, .{
1934 .global = switch (bits) {2088 .name = switch (bits) {
1935 else => unreachable,2089 else => unreachable,
1936 16 => "__floorh",2090 16 => "__floorh",
1937 32 => "floorf",2091 32 => "floorf",
...@@ -1946,7 +2100,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -1946,7 +2100,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
1946 .div_exact, .div_exact_optimized => {},2100 .div_exact, .div_exact_optimized => {},
1947 }2101 }
1948 try isel.global_relocs.append(gpa, .{2102 try isel.global_relocs.append(gpa, .{
1949 .global = switch (bits) {2103 .name = switch (bits) {
1950 else => unreachable,2104 else => unreachable,
1951 16 => "__divhf3",2105 16 => "__divhf3",
1952 32 => "__divsf3",2106 32 => "__divsf3",
...@@ -2046,7 +2200,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -2046,7 +2200,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
20462200
2047 try call.prepareCallee(isel);2201 try call.prepareCallee(isel);
2048 try isel.global_relocs.append(gpa, .{2202 try isel.global_relocs.append(gpa, .{
2049 .global = switch (bits) {2203 .name = switch (bits) {
2050 else => unreachable,2204 else => unreachable,
2051 16 => "__fmodh",2205 16 => "__fmodh",
2052 32 => "fmodf",2206 32 => "fmodf",
...@@ -2212,7 +2366,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -2212,7 +2366,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
22122366
2213 try call.prepareCallee(isel);2367 try call.prepareCallee(isel);
2214 try isel.global_relocs.append(gpa, .{2368 try isel.global_relocs.append(gpa, .{
2215 .global = switch (air_tag) {2369 .name = switch (air_tag) {
2216 else => unreachable,2370 else => unreachable,
2217 .max => switch (bits) {2371 .max => switch (bits) {
2218 else => unreachable,2372 else => unreachable,
...@@ -2284,7 +2438,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -2284,7 +2438,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
2284 else => unreachable,2438 else => unreachable,
2285 .add_with_overflow => .add,2439 .add_with_overflow => .add,
2286 .sub_with_overflow => .sub,2440 .sub_with_overflow => .sub,
2287 }, rhs_vi, .{ .wrap = true, .overflow_ra = try overflow_vi.?.defReg(isel) orelse .zr });2441 }, rhs_vi, .{
2442 .overflow = if (try overflow_vi.?.defReg(isel)) |overflow_ra| .{ .ra = overflow_ra } else .wrap,
2443 });
2288 }2444 }
2289 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;2445 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
2290 },2446 },
...@@ -3092,7 +3248,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3092,7 +3248,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
30923248
3093 try call.prepareCallee(isel);3249 try call.prepareCallee(isel);
3094 try isel.global_relocs.append(gpa, .{3250 try isel.global_relocs.append(gpa, .{
3095 .global = "memcpy",3251 .name = "memcpy",
3096 .reloc = .{ .label = @intCast(isel.instructions.items.len) },3252 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3097 });3253 });
3098 try isel.emit(.bl(0));3254 try isel.emit(.bl(0));
...@@ -3119,7 +3275,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3119,7 +3275,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
31193275
3120 try call.prepareCallee(isel);3276 try call.prepareCallee(isel);
3121 try isel.global_relocs.append(gpa, .{3277 try isel.global_relocs.append(gpa, .{
3122 .global = "memcpy",3278 .name = "memcpy",
3123 .reloc = .{ .label = @intCast(isel.instructions.items.len) },3279 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
3124 });3280 });
3125 try isel.emit(.bl(0));3281 try isel.emit(.bl(0));
...@@ -3139,19 +3295,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3139,19 +3295,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
3139 .block => {3295 .block => {
3140 const ty_pl = air.data(air.inst_index).ty_pl;3296 const ty_pl = air.data(air.inst_index).ty_pl;
3141 const extra = isel.air.extraData(Air.Block, ty_pl.payload);3297 const extra = isel.air.extraData(Air.Block, ty_pl.payload);
31423298 try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast(
3143 if (ty_pl.ty != .noreturn_type) {3299 isel.air.extra.items[extra.end..][0..extra.data.body_len],
3144 isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{3300 ));
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;3301 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3156 },3302 },
3157 .loop => {3303 .loop => {
...@@ -3175,11 +3321,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3175,11 +3321,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
3175 }3321 }
31763322
3177 // IT'S DOM TIME!!!3323 // IT'S DOM TIME!!!
3178 for (isel.blocks.values(), 0..) |*block, dom_index| {3324 for (isel.blocks.values(), 0..) |*dom_block, dom_index| {
3179 if (@as(u1, @truncate(isel.dom.items[3325 if (@as(u1, @truncate(isel.dom.items[
3180 loop.dom + dom_index / @bitSizeOf(DomInt)3326 loop.dom + dom_index / @bitSizeOf(DomInt)
3181 ] >> @truncate(dom_index))) == 0) continue;3327 ] >> @truncate(dom_index))) == 0) continue;
3182 var live_reg_it = block.live_registers.iterator();3328 var live_reg_it = dom_block.live_registers.iterator();
3183 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {3329 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
3184 _ => |live_vi| try live_vi.mat(isel),3330 _ => |live_vi| try live_vi.mat(isel),
3185 .allocating => unreachable,3331 .allocating => unreachable,
...@@ -3211,8 +3357,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3211,8 +3357,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
3211 },3357 },
3212 .br => {3358 .br => {
3213 const br = air.data(air.inst_index).br;3359 const br = air.data(air.inst_index).br;
3214 const block = isel.blocks.getPtr(br.block_inst).?;3360 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);3361 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;3362 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3218 },3363 },
...@@ -3224,6 +3369,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3224,6 +3369,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
3224 try isel.emit(.brk(0xf000));3369 try isel.emit(.brk(0xf000));
3225 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;3370 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3226 },3371 },
3372 .ret_addr => {
3373 if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: {
3374 defer addr_vi.value.deref(isel);
3375 const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused;
3376 try isel.emit(.ldr(addr_ra.x(), .{ .unsigned_offset = .{ .base = .fp, .offset = 8 } }));
3377 }
3378 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3379 },
3380 .frame_addr => {
3381 if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: {
3382 defer addr_vi.value.deref(isel);
3383 const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused;
3384 try isel.emit(.orr(addr_ra.x(), .xzr, .{ .register = .fp }));
3385 }
3386 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
3387 },
3227 .call => {3388 .call => {
3228 const pl_op = air.data(air.inst_index).pl_op;3389 const pl_op = air.data(air.inst_index).pl_op;
3229 const extra = isel.air.extraData(Air.Call, pl_op.payload);3390 const extra = isel.air.extraData(Air.Call, pl_op.payload);
...@@ -3312,7 +3473,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3312,7 +3473,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
3312 var param_part_it = passed_vi.parts(isel);3473 var param_part_it = passed_vi.parts(isel);
3313 var arg_part_it = arg_vi.parts(isel);3474 var arg_part_it = arg_vi.parts(isel);
3314 if (arg_part_it.only()) |_| {3475 if (arg_part_it.only()) |_| {
3315 try isel.values.ensureUnusedCapacity(isel.pt.zcu.gpa, param_part_it.remaining);3476 try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining);
3316 arg_vi.setParts(isel, param_part_it.remaining);3477 arg_vi.setParts(isel, param_part_it.remaining);
3317 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(3478 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
3318 isel,3479 isel,
...@@ -3659,7 +3820,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3659,7 +3820,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
36593820
3660 try call.prepareCallee(isel);3821 try call.prepareCallee(isel);
3661 try isel.global_relocs.append(gpa, .{3822 try isel.global_relocs.append(gpa, .{
3662 .global = switch (air_tag) {3823 .name = switch (air_tag) {
3663 else => unreachable,3824 else => unreachable,
3664 .sqrt => switch (bits) {3825 .sqrt => switch (bits) {
3665 else => unreachable,3826 else => unreachable,
...@@ -3751,7 +3912,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -3751,7 +3912,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
37513912
3752 try call.prepareCallee(isel);3913 try call.prepareCallee(isel);
3753 try isel.global_relocs.append(gpa, .{3914 try isel.global_relocs.append(gpa, .{
3754 .global = switch (air_tag) {3915 .name = switch (air_tag) {
3755 else => unreachable,3916 else => unreachable,
3756 .sin => switch (bits) {3917 .sin => switch (bits) {
3757 else => unreachable,3918 else => unreachable,
...@@ -4239,7 +4400,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4239,7 +4400,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
42394400
4240 try call.prepareCallee(isel);4401 try call.prepareCallee(isel);
4241 try isel.global_relocs.append(gpa, .{4402 try isel.global_relocs.append(gpa, .{
4242 .global = switch (bits) {4403 .name = switch (bits) {
4243 else => unreachable,4404 else => unreachable,
4244 16 => "__cmphf2",4405 16 => "__cmphf2",
4245 32 => "__cmpsf2",4406 32 => "__cmpsf2",
...@@ -4328,7 +4489,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4328,7 +4489,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4328 };4489 };
4329 var cond_mat: ?Value.Materialize = null;4490 var cond_mat: ?Value.Materialize = null;
4330 var cond_reg: Register = undefined;4491 var cond_reg: Register = undefined;
4331 var temp_reg: Register = undefined;
4332 var cases_it = switch_br.iterateCases();4492 var cases_it = switch_br.iterateCases();
4333 while (cases_it.next()) |case| {4493 while (cases_it.next()) |case| {
4334 const next_label = isel.instructions.items.len;4494 const next_label = isel.instructions.items.len;
...@@ -4342,11 +4502,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4342,11 +4502,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4342 if (cond_mat == null) {4502 if (cond_mat == null) {
4343 var cond_vi = try isel.use(switch_br.operand);4503 var cond_vi = try isel.use(switch_br.operand);
4344 cond_mat = try cond_vi.matReg(isel);4504 cond_mat = try cond_vi.matReg(isel);
4345 const temp_ra = try isel.allocIntReg();4505 cond_reg = switch (cond_int_info.bits) {
4346 cond_reg, temp_reg = switch (cond_int_info.bits) {
4347 else => unreachable,4506 else => unreachable,
4348 1...32 => .{ cond_mat.?.ra.w(), temp_ra.w() },4507 1...32 => cond_mat.?.ra.w(),
4349 33...64 => .{ cond_mat.?.ra.x(), temp_ra.x() },4508 33...64 => cond_mat.?.ra.x(),
4350 };4509 };
4351 }4510 }
4352 if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned(4511 if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned(
...@@ -4387,17 +4546,45 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4387,17 +4546,45 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4387 ) else high_bigint.toInt(i64) catch4546 ) else high_bigint.toInt(i64) catch
4388 return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)});4547 return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)});
43894548
4549 const adjusted_ra = switch (low_int) {
4550 0 => cond_mat.?.ra,
4551 else => try isel.allocIntReg(),
4552 };
4553 defer if (adjusted_ra != cond_mat.?.ra) isel.freeReg(adjusted_ra);
4554 const adjusted_reg = switch (cond_int_info.bits) {
4555 else => unreachable,
4556 1...32 => adjusted_ra.w(),
4557 33...64 => adjusted_ra.x(),
4558 };
4390 const delta_int = high_int -% low_int;4559 const delta_int = high_int -% low_int;
4391 if (case_range_index > 0) {4560 if (case_range_index | case.items.len > 0) {
4392 return isel.fail("case range", .{});4561 if (std.math.cast(u5, delta_int)) |pos_imm| try isel.emit(.ccmp(
4393 } else if (case.items.len > 0) {4562 adjusted_reg,
4394 return isel.fail("case range", .{});4563 .{ .immediate = pos_imm },
4564 .{ .n = false, .z = true, .c = false, .v = false },
4565 if (case_range_index > 0) .hi else .ne,
4566 )) else if (std.math.cast(u5, -delta_int)) |neg_imm| try isel.emit(.ccmn(
4567 adjusted_reg,
4568 .{ .immediate = neg_imm },
4569 .{ .n = false, .z = true, .c = false, .v = false },
4570 if (case_range_index > 0) .hi else .ne,
4571 )) else {
4572 const imm_ra = try isel.allocIntReg();
4573 defer isel.freeReg(imm_ra);
4574 const imm_reg = switch (cond_int_info.bits) {
4575 else => unreachable,
4576 1...32 => imm_ra.w(),
4577 33...64 => imm_ra.x(),
4578 };
4579 try isel.emit(.ccmp(
4580 cond_reg,
4581 .{ .register = imm_reg },
4582 .{ .n = false, .z = true, .c = false, .v = false },
4583 if (case_range_index > 0) .hi else .ne,
4584 ));
4585 try isel.movImmediate(imm_reg, @bitCast(delta_int));
4586 }
4395 } else {4587 } else {
4396 const adjusted_reg = switch (low_int) {
4397 0 => cond_reg,
4398 else => temp_reg,
4399 };
4400
4401 if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs(4588 if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs(
4402 zero_reg,4589 zero_reg,
4403 adjusted_reg,4590 adjusted_reg,
...@@ -4421,41 +4608,55 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4421,41 +4608,55 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4421 adjusted_reg,4608 adjusted_reg,
4422 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },4609 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4423 )) else {4610 )) else {
4424 try isel.movImmediate(temp_reg, @bitCast(delta_int));4611 const imm_ra = try isel.allocIntReg();
4425 try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = temp_reg }));4612 defer isel.freeReg(imm_ra);
4613 const imm_reg = switch (cond_int_info.bits) {
4614 else => unreachable,
4615 1...32 => imm_ra.w(),
4616 33...64 => imm_ra.x(),
4617 };
4618 try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = imm_reg }));
4619 try isel.movImmediate(imm_reg, @bitCast(delta_int));
4426 }4620 }
4621 }
44274622
4428 switch (low_int) {4623 switch (low_int) {
4429 0 => {},4624 0 => {},
4430 else => {4625 else => {
4431 if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(4626 if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
4432 adjusted_reg,4627 adjusted_reg,
4433 cond_reg,4628 cond_reg,
4434 .{ .immediate = pos_imm },4629 .{ .immediate = pos_imm },
4435 )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(4630 )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
4436 adjusted_reg,4631 adjusted_reg,
4437 cond_reg,4632 cond_reg,
4438 .{ .immediate = neg_imm },4633 .{ .immediate = neg_imm },
4439 )) else if (if (@as(i12, @truncate(low_int)) == 0)4634 )) else if (if (@as(i12, @truncate(low_int)) == 0)
4440 std.math.cast(u12, low_int >> 12)4635 std.math.cast(u12, low_int >> 12)
4441 else4636 else
4442 null) |pos_imm_lsr_12| try isel.emit(.sub(4637 null) |pos_imm_lsr_12| try isel.emit(.sub(
4443 adjusted_reg,4638 adjusted_reg,
4444 cond_reg,4639 cond_reg,
4445 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },4640 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4446 )) else if (if (@as(i12, @truncate(-low_int)) == 0)4641 )) else if (if (@as(i12, @truncate(-low_int)) == 0)
4447 std.math.cast(u12, -low_int >> 12)4642 std.math.cast(u12, -low_int >> 12)
4448 else4643 else
4449 null) |neg_imm_lsr_12| try isel.emit(.add(4644 null) |neg_imm_lsr_12| try isel.emit(.add(
4450 adjusted_reg,4645 adjusted_reg,
4451 cond_reg,4646 cond_reg,
4452 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },4647 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4453 )) else {4648 )) else {
4454 try isel.movImmediate(temp_reg, @bitCast(low_int));4649 const imm_ra = try isel.allocIntReg();
4455 try isel.emit(.subs(adjusted_reg, cond_reg, .{ .register = temp_reg }));4650 defer isel.freeReg(imm_ra);
4456 }4651 const imm_reg = switch (cond_int_info.bits) {
4457 },4652 else => unreachable,
4458 }4653 1...32 => imm_ra.w(),
4654 33...64 => imm_ra.x(),
4655 };
4656 try isel.emit(.sub(adjusted_reg, cond_reg, .{ .register = imm_reg }));
4657 try isel.movImmediate(imm_reg, @bitCast(low_int));
4658 }
4659 },
4459 }4660 }
4460 }4661 }
4461 var case_item_index = case.items.len;4662 var case_item_index = case.items.len;
...@@ -4483,13 +4684,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4483,13 +4684,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4483 .{ .n = false, .z = true, .c = false, .v = false },4684 .{ .n = false, .z = true, .c = false, .v = false },
4484 .ne,4685 .ne,
4485 )) else {4686 )) else {
4486 try isel.movImmediate(temp_reg, @bitCast(item_int));4687 const imm_ra = try isel.allocIntReg();
4688 defer isel.freeReg(imm_ra);
4689 const imm_reg = switch (cond_int_info.bits) {
4690 else => unreachable,
4691 1...32 => imm_ra.w(),
4692 33...64 => imm_ra.x(),
4693 };
4487 try isel.emit(.ccmp(4694 try isel.emit(.ccmp(
4488 cond_reg,4695 cond_reg,
4489 .{ .register = temp_reg },4696 .{ .register = imm_reg },
4490 .{ .n = false, .z = true, .c = false, .v = false },4697 .{ .n = false, .z = true, .c = false, .v = false },
4491 .ne,4698 .ne,
4492 ));4699 ));
4700 try isel.movImmediate(imm_reg, @bitCast(item_int));
4493 }4701 }
4494 } else {4702 } else {
4495 if (std.math.cast(u12, item_int)) |pos_imm| try isel.emit(.subs(4703 if (std.math.cast(u12, item_int)) |pos_imm| try isel.emit(.subs(
...@@ -4515,16 +4723,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4515,16 +4723,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4515 cond_reg,4723 cond_reg,
4516 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },4724 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4517 )) else {4725 )) else {
4518 try isel.movImmediate(temp_reg, @bitCast(item_int));4726 const imm_ra = try isel.allocIntReg();
4519 try isel.emit(.subs(zero_reg, cond_reg, .{ .register = temp_reg }));4727 defer isel.freeReg(imm_ra);
4728 const imm_reg = switch (cond_int_info.bits) {
4729 else => unreachable,
4730 1...32 => imm_ra.w(),
4731 33...64 => imm_ra.x(),
4732 };
4733 try isel.emit(.subs(zero_reg, cond_reg, .{ .register = imm_reg }));
4734 try isel.movImmediate(imm_reg, @bitCast(item_int));
4520 }4735 }
4521 }4736 }
4522 }4737 }
4523 }4738 }
4524 if (cond_mat) |mat| {4739 if (cond_mat) |mat| try mat.finish(isel);
4525 try mat.finish(isel);
4526 isel.freeReg(temp_reg.alias);
4527 }
4528 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4740 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4529 },4741 },
4530 .@"try", .try_cold => {4742 .@"try", .try_cold => {
...@@ -4560,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4560,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4560 const error_set_part_vi = try error_set_part_it.only(isel);4772 const error_set_part_vi = try error_set_part_it.only(isel);
4561 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);4773 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
4562 try isel.emit(.cbz(4774 try isel.emit(.cbz(
4563 switch (error_set_part_vi.?.size(isel)) {4775 error_set_part_mat.ra.w(),
4564 else => unreachable,
4565 1...4 => error_set_part_mat.ra.w(),
4566 5...8 => error_set_part_mat.ra.x(),
4567 },
4568 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),4776 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
4569 ));4777 ));
4570 try error_set_part_mat.finish(isel);4778 try error_set_part_mat.finish(isel);
45714779
4572 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4780 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4573 },4781 },
4782 .try_ptr, .try_ptr_cold => {
4783 const ty_pl = air.data(air.inst_index).ty_pl;
4784 const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
4785 const error_union_ty = isel.air.typeOf(extra.data.ptr, ip).childType(zcu);
4786 const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
4787 const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
4788
4789 const error_union_ptr_vi = try isel.use(extra.data.ptr);
4790 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
4791 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
4792 defer payload_ptr_vi.value.deref(isel);
4793 switch (codegen.errUnionPayloadOffset(ty_pl.ty.toType().childType(zcu), zcu)) {
4794 0 => try payload_ptr_vi.value.move(isel, extra.data.ptr),
4795 else => |payload_offset| {
4796 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
4797 const lo12: u12 = @truncate(payload_offset >> 0);
4798 const hi12: u12 = @intCast(payload_offset >> 12);
4799 if (hi12 > 0) try isel.emit(.add(
4800 payload_ptr_ra.x(),
4801 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
4802 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
4803 ));
4804 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
4805 },
4806 }
4807 }
4808
4809 const cont_label = isel.instructions.items.len;
4810 const cont_live_registers = isel.live_registers;
4811 try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
4812 try isel.merge(&cont_live_registers, .{});
4813
4814 const error_set_ra = try isel.allocIntReg();
4815 defer isel.freeReg(error_set_ra);
4816 try isel.loadReg(
4817 error_set_ra,
4818 ZigType.fromInterned(error_union_info.error_set_type).abiSize(zcu),
4819 .unsigned,
4820 error_union_ptr_mat.ra,
4821 codegen.errUnionErrorOffset(payload_ty, zcu),
4822 );
4823 try error_union_ptr_mat.finish(isel);
4824 try isel.emit(.cbz(
4825 error_set_ra.w(),
4826 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
4827 ));
4828
4829 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4830 },
4574 .dbg_stmt => {4831 .dbg_stmt => {
4575 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4832 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4576 },4833 },
...@@ -4578,6 +4835,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4578,6 +4835,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4578 try isel.emit(.nop());4835 try isel.emit(.nop());
4579 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4836 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4580 },4837 },
4838 .dbg_inline_block => {
4839 const ty_pl = air.data(air.inst_index).ty_pl;
4840 const extra = isel.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
4841 try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast(
4842 isel.air.extra.items[extra.end..][0..extra.data.body_len],
4843 ));
4844 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4845 },
4581 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => {4846 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => {
4582 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;4847 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4583 },4848 },
...@@ -4673,7 +4938,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4673,7 +4938,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
46734938
4674 try call.prepareCallee(isel);4939 try call.prepareCallee(isel);
4675 try isel.global_relocs.append(gpa, .{4940 try isel.global_relocs.append(gpa, .{
4676 .global = "memcpy",4941 .name = "memcpy",
4677 .reloc = .{ .label = @intCast(isel.instructions.items.len) },4942 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4678 });4943 });
4679 try isel.emit(.bl(0));4944 try isel.emit(.bl(0));
...@@ -4765,10 +5030,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4765,10 +5030,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4765 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);5030 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
4766 const ptr_info = ptr_ty.ptrInfo(zcu);5031 const ptr_info = ptr_ty.ptrInfo(zcu);
4767 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{});5032 if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{});
4768 if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) {5033 if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val))
4769 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5034 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4770 break :air_tag;
4771 };
47725035
4773 const src_vi = try isel.use(bin_op.rhs);5036 const src_vi = try isel.use(bin_op.rhs);
4774 const size = src_vi.size(isel);5037 const size = src_vi.size(isel);
...@@ -4782,8 +5045,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4782,8 +5045,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
4782 });5045 });
4783 try ptr_mat.finish(isel);5046 try ptr_mat.finish(isel);
47845047
4785 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5048 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4786 break :air_tag;
4787 },5049 },
4788 else => {},5050 else => {},
4789 };5051 };
...@@ -4792,7 +5054,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4792,7 +5054,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
47925054
4793 try call.prepareCallee(isel);5055 try call.prepareCallee(isel);
4794 try isel.global_relocs.append(gpa, .{5056 try isel.global_relocs.append(gpa, .{
4795 .global = "memcpy",5057 .name = "memcpy",
4796 .reloc = .{ .label = @intCast(isel.instructions.items.len) },5058 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
4797 });5059 });
4798 try isel.emit(.bl(0));5060 try isel.emit(.bl(0));
...@@ -4855,7 +5117,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -4855,7 +5117,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
48555117
4856 try call.prepareCallee(isel);5118 try call.prepareCallee(isel);
4857 try isel.global_relocs.append(gpa, .{5119 try isel.global_relocs.append(gpa, .{
4858 .global = switch (dst_bits) {5120 .name = switch (dst_bits) {
4859 else => unreachable,5121 else => unreachable,
4860 16 => switch (src_bits) {5122 16 => switch (src_bits) {
4861 else => unreachable,5123 else => unreachable,
...@@ -5009,6 +5271,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5009,6 +5271,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5009 }5271 }
5010 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5272 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5011 },5273 },
5274 .intcast_safe => |air_tag| {
5275 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5276 defer dst_vi.value.deref(isel);
5277
5278 const ty_op = air.data(air.inst_index).ty_op;
5279 const dst_ty = ty_op.ty.toType();
5280 const dst_int_info = dst_ty.intInfo(zcu);
5281 const src_ty = isel.air.typeOf(ty_op.operand, ip);
5282 const src_int_info = src_ty.intInfo(zcu);
5283 const can_be_negative = dst_int_info.signedness == .signed and
5284 src_int_info.signedness == .signed;
5285 const panic_id: Zcu.SimplePanicId = panic_id: switch (dst_ty.zigTypeTag(zcu)) {
5286 else => unreachable,
5287 .int => .integer_out_of_bounds,
5288 .@"enum" => {
5289 if (!dst_ty.isNonexhaustiveEnum(zcu)) {
5290 return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5291 }
5292 break :panic_id .invalid_enum_value;
5293 },
5294 };
5295 if (dst_ty.toIntern() == src_ty.toIntern()) {
5296 try dst_vi.value.move(isel, ty_op.operand);
5297 } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 64) {
5298 const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
5299 const src_vi = try isel.use(ty_op.operand);
5300 const dst_active_bits = dst_int_info.bits - @intFromBool(dst_int_info.signedness == .signed);
5301 const src_active_bits = src_int_info.bits - @intFromBool(src_int_info.signedness == .signed);
5302 if ((dst_int_info.signedness != .unsigned or src_int_info.signedness != .signed) and dst_active_bits >= src_active_bits) {
5303 const src_mat = try src_vi.matReg(isel);
5304 try isel.emit(if (can_be_negative and dst_active_bits > 32 and src_active_bits <= 32)
5305 .sbfm(dst_ra.x(), src_mat.ra.x(), .{
5306 .N = .doubleword,
5307 .immr = 0,
5308 .imms = @intCast(src_int_info.bits - 1),
5309 })
5310 else switch (src_int_info.bits) {
5311 else => unreachable,
5312 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }),
5313 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }),
5314 });
5315 try src_mat.finish(isel);
5316 } else {
5317 const skip_label = isel.instructions.items.len;
5318 try isel.emitPanic(panic_id);
5319 try isel.emit(.@"b."(
5320 .eq,
5321 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
5322 ));
5323 if (can_be_negative) {
5324 const src_mat = src_mat: {
5325 const dst_lock = isel.lockReg(dst_ra);
5326 defer dst_lock.unlock(isel);
5327 break :src_mat try src_vi.matReg(isel);
5328 };
5329 try isel.emit(switch (src_int_info.bits) {
5330 else => unreachable,
5331 1...32 => .subs(.wzr, dst_ra.w(), .{ .register = src_mat.ra.w() }),
5332 33...64 => .subs(.xzr, dst_ra.x(), .{ .register = src_mat.ra.x() }),
5333 });
5334 try isel.emit(switch (@max(dst_int_info.bits, src_int_info.bits)) {
5335 else => unreachable,
5336 1...32 => .sbfm(dst_ra.w(), src_mat.ra.w(), .{
5337 .N = .word,
5338 .immr = 0,
5339 .imms = @intCast(dst_int_info.bits - 1),
5340 }),
5341 33...64 => .sbfm(dst_ra.x(), src_mat.ra.x(), .{
5342 .N = .doubleword,
5343 .immr = 0,
5344 .imms = @intCast(dst_int_info.bits - 1),
5345 }),
5346 });
5347 try src_mat.finish(isel);
5348 } else {
5349 const src_mat = try src_vi.matReg(isel);
5350 try isel.emit(switch (@min(dst_int_info.bits, src_int_info.bits)) {
5351 else => unreachable,
5352 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }),
5353 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }),
5354 });
5355 const active_bits = @min(dst_active_bits, src_active_bits);
5356 try isel.emit(switch (src_int_info.bits) {
5357 else => unreachable,
5358 1...32 => .ands(.wzr, src_mat.ra.w(), .{ .immediate = .{
5359 .N = .word,
5360 .immr = @intCast(32 - active_bits),
5361 .imms = @intCast(32 - active_bits - 1),
5362 } }),
5363 33...64 => .ands(.xzr, src_mat.ra.x(), .{ .immediate = .{
5364 .N = .doubleword,
5365 .immr = @intCast(64 - active_bits),
5366 .imms = @intCast(64 - active_bits - 1),
5367 } }),
5368 });
5369 try src_mat.finish(isel);
5370 }
5371 }
5372 } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
5373 }
5374 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5375 },
5012 .trunc => |air_tag| {5376 .trunc => |air_tag| {
5013 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {5377 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
5014 defer dst_vi.value.deref(isel);5378 defer dst_vi.value.deref(isel);
...@@ -5096,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5096,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5096 }5460 }
5097 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5461 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5098 },5462 },
5099 .optional_payload_ptr => {
5100 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
5101 defer dst_vi.value.deref(isel);
5102 const ty_op = air.data(air.inst_index).ty_op;
5103 try dst_vi.value.move(isel, ty_op.operand);
5104 }
5105 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5106 },
5107 .optional_payload => {5463 .optional_payload => {
5108 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {5464 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
5109 defer payload_vi.value.deref(isel);5465 defer payload_vi.value.deref(isel);
...@@ -5122,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5122,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5122 }5478 }
5123 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5479 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5124 },5480 },
5481 .optional_payload_ptr => {
5482 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
5483 defer payload_ptr_vi.value.deref(isel);
5484 const ty_op = air.data(air.inst_index).ty_op;
5485 try payload_ptr_vi.value.move(isel, ty_op.operand);
5486 }
5487 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5488 },
5489 .optional_payload_ptr_set => {
5490 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
5491 defer payload_ptr_vi.value.deref(isel);
5492 const ty_op = air.data(air.inst_index).ty_op;
5493 const opt_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
5494 if (!opt_ty.optionalReprIsPayload(zcu)) {
5495 const opt_ptr_vi = try isel.use(ty_op.operand);
5496 const opt_ptr_mat = try opt_ptr_vi.matReg(isel);
5497 const has_value_ra = try isel.allocIntReg();
5498 defer isel.freeReg(has_value_ra);
5499 try isel.storeReg(
5500 has_value_ra,
5501 1,
5502 opt_ptr_mat.ra,
5503 opt_ty.optionalChild(zcu).abiSize(zcu),
5504 );
5505 try opt_ptr_mat.finish(isel);
5506 try isel.emit(.movz(has_value_ra.w(), 1, .{ .lsl = .@"0" }));
5507 }
5508 try payload_ptr_vi.value.move(isel, ty_op.operand);
5509 }
5510 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5511 },
5125 .wrap_optional => {5512 .wrap_optional => {
5126 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {5513 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
5127 defer opt_vi.value.deref(isel);5514 defer opt_vi.value.deref(isel);
...@@ -5161,21 +5548,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5161,21 +5548,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5161 }5548 }
5162 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5549 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5163 },5550 },
5164 .unwrap_errunion_err => {5551 .unwrap_errunion_err => {
5165 if (isel.live_values.fetchRemove(air.inst_index)) |error_set_vi| {5552 if (isel.live_values.fetchRemove(air.inst_index)) |error_set_vi| {
5166 defer error_set_vi.value.deref(isel);5553 defer error_set_vi.value.deref(isel);
51675554
5555 const ty_op = air.data(air.inst_index).ty_op;
5556 const error_union_ty = isel.air.typeOf(ty_op.operand, ip);
5557
5558 const error_union_vi = try isel.use(ty_op.operand);
5559 var error_set_part_it = error_union_vi.field(
5560 error_union_ty,
5561 codegen.errUnionErrorOffset(error_union_ty.errorUnionPayload(zcu), zcu),
5562 error_set_vi.value.size(isel),
5563 );
5564 const error_set_part_vi = try error_set_part_it.only(isel);
5565 try error_set_vi.value.copy(isel, ty_op.ty.toType(), error_set_part_vi.?);
5566 }
5567 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5568 },
5569 .unwrap_errunion_payload_ptr => {
5570 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
5571 defer payload_ptr_vi.value.deref(isel);
5572 const ty_op = air.data(air.inst_index).ty_op;
5573 switch (codegen.errUnionPayloadOffset(ty_op.ty.toType().childType(zcu), zcu)) {
5574 0 => try payload_ptr_vi.value.move(isel, ty_op.operand),
5575 else => |payload_offset| {
5576 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
5577 const error_union_ptr_vi = try isel.use(ty_op.operand);
5578 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5579 const lo12: u12 = @truncate(payload_offset >> 0);
5580 const hi12: u12 = @intCast(payload_offset >> 12);
5581 if (hi12 > 0) try isel.emit(.add(
5582 payload_ptr_ra.x(),
5583 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5584 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5585 ));
5586 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5587 try error_union_ptr_mat.finish(isel);
5588 },
5589 }
5590 }
5591 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5592 },
5593 .unwrap_errunion_err_ptr => {
5594 if (isel.live_values.fetchRemove(air.inst_index)) |error_ptr_vi| unused: {
5595 defer error_ptr_vi.value.deref(isel);
5596 const ty_op = air.data(air.inst_index).ty_op;
5597 switch (codegen.errUnionErrorOffset(
5598 isel.air.typeOf(ty_op.operand, ip).childType(zcu).errorUnionPayload(zcu),
5599 zcu,
5600 )) {
5601 0 => try error_ptr_vi.value.move(isel, ty_op.operand),
5602 else => |error_offset| {
5603 const error_ptr_ra = try error_ptr_vi.value.defReg(isel) orelse break :unused;
5604 const error_union_ptr_vi = try isel.use(ty_op.operand);
5605 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5606 const lo12: u12 = @truncate(error_offset >> 0);
5607 const hi12: u12 = @intCast(error_offset >> 12);
5608 if (hi12 > 0) try isel.emit(.add(
5609 error_ptr_ra.x(),
5610 if (lo12 > 0) error_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5611 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5612 ));
5613 if (lo12 > 0) try isel.emit(.add(error_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5614 try error_union_ptr_mat.finish(isel);
5615 },
5616 }
5617 }
5618 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5619 },
5620 .errunion_payload_ptr_set => {
5621 if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
5622 defer payload_ptr_vi.value.deref(isel);
5168 const ty_op = air.data(air.inst_index).ty_op;5623 const ty_op = air.data(air.inst_index).ty_op;
5169 const error_union_ty = isel.air.typeOf(ty_op.operand, ip);5624 const payload_ty = ty_op.ty.toType().childType(zcu);
51705625 const error_union_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
5171 const error_union_vi = try isel.use(ty_op.operand);5626 const error_set_size = error_union_ty.errorUnionSet(zcu).abiSize(zcu);
5172 var error_set_part_it = error_union_vi.field(5627 const error_union_ptr_vi = try isel.use(ty_op.operand);
5173 error_union_ty,5628 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5174 codegen.errUnionErrorOffset(error_union_ty.errorUnionPayload(zcu), zcu),5629 if (error_set_size > 0) try isel.storeReg(
5175 error_set_vi.value.size(isel),5630 .zr,
5631 error_set_size,
5632 error_union_ptr_mat.ra,
5633 codegen.errUnionErrorOffset(payload_ty, zcu),
5176 );5634 );
5177 const error_set_part_vi = try error_set_part_it.only(isel);5635 switch (codegen.errUnionPayloadOffset(payload_ty, zcu)) {
5178 try error_set_vi.value.copy(isel, ty_op.ty.toType(), error_set_part_vi.?);5636 0 => {
5637 try error_union_ptr_mat.finish(isel);
5638 try payload_ptr_vi.value.move(isel, ty_op.operand);
5639 },
5640 else => |payload_offset| {
5641 const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
5642 const lo12: u12 = @truncate(payload_offset >> 0);
5643 const hi12: u12 = @intCast(payload_offset >> 12);
5644 if (hi12 > 0) try isel.emit(.add(
5645 payload_ptr_ra.x(),
5646 if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
5647 .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
5648 ));
5649 if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
5650 try error_union_ptr_mat.finish(isel);
5651 },
5652 }
5179 }5653 }
5180 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5654 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5181 },5655 },
...@@ -5365,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5365,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
5365 }5839 }
5366 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;5840 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5367 },5841 },
5842 .set_union_tag => {
5843 const bin_op = air.data(air.inst_index).bin_op;
5844 const union_ty = isel.air.typeOf(bin_op.lhs, ip).childType(zcu);
5845 const union_layout = union_ty.unionGetLayout(zcu);
5846 const tag_vi = try isel.use(bin_op.rhs);
5847 const union_ptr_vi = try isel.use(bin_op.lhs);
5848 const union_ptr_mat = try union_ptr_vi.matReg(isel);
5849 try tag_vi.store(isel, isel.air.typeOf(bin_op.rhs, ip), union_ptr_mat.ra, .{
5850 .offset = union_layout.tagOffset(),
5851 });
5852 try union_ptr_mat.finish(isel);
5853 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5854 },
5855 .get_union_tag => {
5856 if (isel.live_values.fetchRemove(air.inst_index)) |tag_vi| {
5857 defer tag_vi.value.deref(isel);
5858 const ty_op = air.data(air.inst_index).ty_op;
5859 const union_ty = isel.air.typeOf(ty_op.operand, ip);
5860 const union_layout = union_ty.unionGetLayout(zcu);
5861 const union_vi = try isel.use(ty_op.operand);
5862 var tag_part_it = union_vi.field(union_ty, union_layout.tagOffset(), union_layout.tag_size);
5863 const tag_part_vi = try tag_part_it.only(isel);
5864 try tag_vi.value.copy(isel, ty_op.ty.toType(), tag_part_vi.?);
5865 }
5866 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
5867 },
5368 .slice => {5868 .slice => {
5369 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {5869 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
5370 defer slice_vi.value.deref(isel);5870 defer slice_vi.value.deref(isel);
...@@ -5781,7 +6281,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5781,7 +6281,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
57816281
5782 try call.prepareCallee(isel);6282 try call.prepareCallee(isel);
5783 try isel.global_relocs.append(gpa, .{6283 try isel.global_relocs.append(gpa, .{
5784 .global = switch (dst_int_info.bits) {6284 .name = switch (dst_int_info.bits) {
5785 else => unreachable,6285 else => unreachable,
5786 1...32 => switch (dst_int_info.signedness) {6286 1...32 => switch (dst_int_info.signedness) {
5787 .signed => switch (src_bits) {6287 .signed => switch (src_bits) {
...@@ -5921,7 +6421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -5921,7 +6421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
59216421
5922 try call.prepareCallee(isel);6422 try call.prepareCallee(isel);
5923 try isel.global_relocs.append(gpa, .{6423 try isel.global_relocs.append(gpa, .{
5924 .global = switch (src_int_info.bits) {6424 .name = switch (src_int_info.bits) {
5925 else => unreachable,6425 else => unreachable,
5926 1...32 => switch (src_int_info.signedness) {6426 1...32 => switch (src_int_info.signedness) {
5927 .signed => switch (dst_bits) {6427 .signed => switch (dst_bits) {
...@@ -6004,14 +6504,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6004,14 +6504,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6004 }6504 }
6005 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;6505 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6006 },6506 },
6007 .memset => |air_tag| {6507 .memset, .memset_safe => |air_tag| {
6008 const bin_op = air.data(air.inst_index).bin_op;6508 const bin_op = air.data(air.inst_index).bin_op;
6009 const dst_ty = isel.air.typeOf(bin_op.lhs, ip);6509 const dst_ty = isel.air.typeOf(bin_op.lhs, ip);
6010 const dst_info = dst_ty.ptrInfo(zcu);6510 const dst_info = dst_ty.ptrInfo(zcu);
6011 const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: {6511 const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: {
6012 if (bin_op.rhs.toInterned()) |fill_val|6512 if (bin_op.rhs.toInterned()) |fill_val| {
6513 if (ip.isUndef(fill_val)) switch (air_tag) {
6514 else => unreachable,
6515 .memset => break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag,
6516 .memset_safe => break :fill_byte .{ .constant = 0xaa },
6517 };
6013 if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|6518 if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|
6014 break :fill_byte .{ .constant = fill_byte };6519 break :fill_byte .{ .constant = fill_byte };
6520 }
6015 switch (dst_ty.elemType2(zcu).abiSize(zcu)) {6521 switch (dst_ty.elemType2(zcu).abiSize(zcu)) {
6016 0 => unreachable,6522 0 => unreachable,
6017 1 => break :fill_byte .{ .value = bin_op.rhs },6523 1 => break :fill_byte .{ .value = bin_op.rhs },
...@@ -6070,8 +6576,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6070,8 +6576,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6070 .c => unreachable,6576 .c => unreachable,
6071 }6577 }
60726578
6073 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;6579 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6074 break :air_tag;
6075 },6580 },
6076 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }),6581 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }),
6077 }6582 }
...@@ -6082,7 +6587,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6082,7 +6587,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
60826587
6083 try call.prepareCallee(isel);6588 try call.prepareCallee(isel);
6084 try isel.global_relocs.append(gpa, .{6589 try isel.global_relocs.append(gpa, .{
6085 .global = "memset",6590 .name = "memset",
6086 .reloc = .{ .label = @intCast(isel.instructions.items.len) },6591 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6087 });6592 });
6088 try isel.emit(.bl(0));6593 try isel.emit(.bl(0));
...@@ -6128,7 +6633,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6128,7 +6633,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
61286633
6129 try call.prepareCallee(isel);6634 try call.prepareCallee(isel);
6130 try isel.global_relocs.append(gpa, .{6635 try isel.global_relocs.append(gpa, .{
6131 .global = @tagName(air_tag),6636 .name = @tagName(air_tag),
6132 .reloc = .{ .label = @intCast(isel.instructions.items.len) },6637 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6133 });6638 });
6134 try isel.emit(.bl(0));6639 try isel.emit(.bl(0));
...@@ -6217,6 +6722,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6217,6 +6722,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
62176722
6218 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;6723 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6219 },6724 },
6725 .error_name => {
6726 if (isel.live_values.fetchRemove(air.inst_index)) |name_vi| unused: {
6727 defer name_vi.value.deref(isel);
6728 var ptr_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 0, 8);
6729 const ptr_part_vi = try ptr_part_it.only(isel);
6730 const ptr_part_ra = try ptr_part_vi.?.defReg(isel);
6731 var len_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 8, 8);
6732 const len_part_vi = try len_part_it.only(isel);
6733 const len_part_ra = try len_part_vi.?.defReg(isel);
6734 if (ptr_part_ra == null and len_part_ra == null) break :unused;
6735
6736 const un_op = air.data(air.inst_index).un_op;
6737 const error_vi = try isel.use(un_op);
6738 const error_mat = try error_vi.matReg(isel);
6739 const ptr_ra = try isel.allocIntReg();
6740 defer isel.freeReg(ptr_ra);
6741 const start_ra, const end_ra = range_ras: {
6742 const name_lock: RegLock = if (len_part_ra != null) if (ptr_part_ra) |name_ptr_ra|
6743 isel.tryLockReg(name_ptr_ra)
6744 else
6745 .empty else .empty;
6746 defer name_lock.unlock(isel);
6747 break :range_ras .{ try isel.allocIntReg(), try isel.allocIntReg() };
6748 };
6749 defer {
6750 isel.freeReg(start_ra);
6751 isel.freeReg(end_ra);
6752 }
6753 if (len_part_ra) |name_len_ra| try isel.emit(.sub(
6754 name_len_ra.w(),
6755 end_ra.w(),
6756 .{ .register = start_ra.w() },
6757 ));
6758 if (ptr_part_ra) |name_ptr_ra| try isel.emit(.add(
6759 name_ptr_ra.x(),
6760 ptr_ra.x(),
6761 .{ .extended_register = .{
6762 .register = start_ra.w(),
6763 .extend = .{ .uxtw = 0 },
6764 } },
6765 ));
6766 if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 }));
6767 try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() }));
6768 try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{
6769 .register = error_mat.ra.w(),
6770 .extend = switch (zcu.errorSetBits()) {
6771 else => unreachable,
6772 1...8 => .{ .uxtb = 2 },
6773 9...16 => .{ .uxth = 2 },
6774 17...32 => .{ .uxtw = 2 },
6775 },
6776 } }));
6777 try isel.lazy_relocs.append(gpa, .{
6778 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
6779 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6780 });
6781 try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
6782 try isel.lazy_relocs.append(gpa, .{
6783 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
6784 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6785 });
6786 try isel.emit(.adrp(ptr_ra.x(), 0));
6787 try error_mat.finish(isel);
6788 }
6789 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6790 },
6220 .aggregate_init => {6791 .aggregate_init => {
6221 if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| {6792 if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| {
6222 defer agg_vi.value.deref(isel);6793 defer agg_vi.value.deref(isel);
...@@ -6311,7 +6882,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6311,7 +6882,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
63116882
6312 try call.prepareCallee(isel);6883 try call.prepareCallee(isel);
6313 try isel.global_relocs.append(gpa, .{6884 try isel.global_relocs.append(gpa, .{
6314 .global = "memcpy",6885 .name = "memcpy",
6315 .reloc = .{ .label = @intCast(isel.instructions.items.len) },6886 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6316 });6887 });
6317 try isel.emit(.bl(0));6888 try isel.emit(.bl(0));
...@@ -6427,7 +6998,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6427,7 +6998,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
64276998
6428 try call.prepareCallee(isel);6999 try call.prepareCallee(isel);
6429 try isel.global_relocs.append(gpa, .{7000 try isel.global_relocs.append(gpa, .{
6430 .global = switch (bits) {7001 .name = switch (bits) {
6431 else => unreachable,7002 else => unreachable,
6432 16 => "__fmah",7003 16 => "__fmah",
6433 32 => "fmaf",7004 32 => "fmaf",
...@@ -6508,6 +7079,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6508,6 +7079,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6508 }7079 }
6509 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;7080 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6510 },7081 },
7082 .cmp_lt_errors_len => {
7083 if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: {
7084 defer is_vi.value.deref(isel);
7085 const is_ra = try is_vi.value.defReg(isel) orelse break :unused;
7086 try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls)));
7087
7088 const un_op = air.data(air.inst_index).un_op;
7089 const error_vi = try isel.use(un_op);
7090 const error_mat = try error_vi.matReg(isel);
7091 const ptr_ra = try isel.allocIntReg();
7092 defer isel.freeReg(ptr_ra);
7093 try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
7094 try isel.lazy_relocs.append(gpa, .{
7095 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
7096 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
7097 });
7098 try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() }));
7099 try isel.lazy_relocs.append(gpa, .{
7100 .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
7101 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
7102 });
7103 try isel.emit(.adrp(ptr_ra.x(), 0));
7104 try error_mat.finish(isel);
7105 }
7106 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
7107 },
6511 .runtime_nav_ptr => {7108 .runtime_nav_ptr => {
6512 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {7109 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {
6513 defer ptr_vi.value.deref(isel);7110 defer ptr_vi.value.deref(isel);
...@@ -6516,19 +7113,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6516,19 +7113,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6516 const ty_nav = air.data(air.inst_index).ty_nav;7113 const ty_nav = air.data(air.inst_index).ty_nav;
6517 if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {7114 if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {
6518 false => {7115 false => {
6519 try isel.nav_relocs.append(zcu.gpa, .{7116 try isel.nav_relocs.append(gpa, .{
6520 .nav = ty_nav.nav,7117 .nav = ty_nav.nav,
6521 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6522 });7119 });
6523 try isel.emit(.adr(ptr_ra.x(), 0));7120 try isel.emit(.adr(ptr_ra.x(), 0));
6524 },7121 },
6525 true => {7122 true => {
6526 try isel.nav_relocs.append(zcu.gpa, .{7123 try isel.nav_relocs.append(gpa, .{
6527 .nav = ty_nav.nav,7124 .nav = ty_nav.nav,
6528 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7125 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6529 });7126 });
6530 try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));7127 try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
6531 try isel.nav_relocs.append(zcu.gpa, .{7128 try isel.nav_relocs.append(gpa, .{
6532 .nav = ty_nav.nav,7129 .nav = ty_nav.nav,
6533 .reloc = .{ .label = @intCast(isel.instructions.items.len) },7130 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
6534 });7131 });
...@@ -6538,9 +7135,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {...@@ -6538,9 +7135,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
6538 }7135 }
6539 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;7136 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6540 },7137 },
6541 .add_safe,
6542 .sub_safe,
6543 .mul_safe,
6544 .inferred_alloc,7138 .inferred_alloc,
6545 .inferred_alloc_comptime,7139 .inferred_alloc_comptime,
6546 .int_from_float_safe,7140 .int_from_float_safe,
...@@ -6642,8 +7236,8 @@ pub fn layout(...@@ -6642,8 +7236,8 @@ pub fn layout(
6642 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});7236 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
66437237
6644 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));7238 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
6645 const stack_size_low: u12 = @truncate(stack_size >> 0);7239 const stack_size_lo: u12 = @truncate(stack_size >> 0);
6646 const stack_size_high: u12 = @truncate(stack_size >> 12);7240 const stack_size_hi: u12 = @truncate(stack_size >> 12);
66477241
6648 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {7242 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
6649 class: enum { integer, vector },7243 class: enum { integer, vector },
...@@ -6771,6 +7365,9 @@ pub fn layout(...@@ -6771,6 +7365,9 @@ pub fn layout(
6771 saves_len += 1;7365 saves_len += 1;
6772 saves_size += 8;7366 saves_size += 8;
6773 deferred_gr = null;7367 deferred_gr = null;
7368 } else switch (@as(u1, @truncate(saved_gra_len))) {
7369 0 => {},
7370 1 => saves_size += 8,
6774 }7371 }
6775 save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;7372 save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;
6776 while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {7373 while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
...@@ -6793,65 +7390,90 @@ pub fn layout(...@@ -6793,65 +7390,90 @@ pub fn layout(
6793 {7390 {
6794 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});7391 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});
6795 var save_index: usize = 0;7392 var save_index: usize = 0;
6796 while (save_index < saves.len) {7393 while (save_index < saves.len) if (save_index + 2 <= saves.len and
6797 if (save_index + 2 <= saves.len and saves[save_index + 0].class == saves[save_index + 1].class and7394 saves[save_index + 0].class == saves[save_index + 1].class and
6798 saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)7395 saves[save_index + 0].size == saves[save_index + 1].size and
6799 {7396 saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
6800 try isel.emit(.stp(7397 {
6801 saves[save_index + 0].register,7398 try isel.emit(.stp(
6802 saves[save_index + 1].register,7399 saves[save_index + 0].register,
6803 switch (saves[save_index + 0].offset) {7400 saves[save_index + 1].register,
6804 0 => .{ .pre_index = .{7401 switch (saves[save_index + 0].offset) {
6805 .base = .sp,7402 0 => .{ .pre_index = .{
6806 .index = @intCast(-@as(i11, saves_size)),7403 .base = .sp,
6807 } },7404 .index = @intCast(-@as(i11, saves_size)),
6808 else => |offset| .{ .signed_offset = .{7405 } },
6809 .base = .sp,7406 else => |offset| .{ .signed_offset = .{
6810 .offset = @intCast(offset),7407 .base = .sp,
6811 } },7408 .offset = @intCast(offset),
6812 },7409 } },
6813 ));7410 },
6814 save_index += 2;7411 ));
6815 } else {7412 save_index += 2;
6816 try isel.emit(.str(7413 } else {
6817 saves[save_index].register,7414 try isel.emit(.str(
6818 switch (saves[save_index].offset) {7415 saves[save_index].register,
6819 0 => .{ .pre_index = .{7416 switch (saves[save_index].offset) {
6820 .base = .sp,7417 0 => .{ .pre_index = .{
6821 .index = @intCast(-@as(i11, saves_size)),7418 .base = .sp,
6822 } },7419 .index = @intCast(-@as(i11, saves_size)),
6823 else => |offset| .{ .unsigned_offset = .{7420 } },
6824 .base = .sp,7421 else => |offset| .{ .unsigned_offset = .{
6825 .offset = @intCast(offset),7422 .base = .sp,
6826 } },7423 .offset = @intCast(offset),
6827 },7424 } },
6828 ));7425 },
6829 save_index += 1;7426 ));
6830 }7427 save_index += 1;
6831 }7428 };
68327429
7430 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
6833 const scratch_reg: Register = if (isel.stack_align == .@"16")7431 const scratch_reg: Register = if (isel.stack_align == .@"16")
6834 .sp7432 .sp
6835 else if (stack_size == 0)7433 else if (stack_size == 0 and frame_record_offset == 0)
6836 .fp7434 .fp
6837 else7435 else
6838 .x9;7436 .ip0;
6839 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));7437 if (mod.stack_check) {
6840 if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{7438 if (stack_size_hi > 2) {
6841 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },7439 try isel.movImmediate(.ip1, stack_size_hi);
6842 }));7440 const loop_label = isel.instructions.items.len;
6843 if (stack_size_low > 0) try isel.emit(.sub(7441 try isel.emit(.sub(.sp, .sp, .{
6844 scratch_reg,7442 .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
6845 if (stack_size_high > 0) scratch_reg else .sp,7443 }));
6846 .{ .immediate = stack_size_low },7444 try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
6847 ));7445 try isel.emit(.ldr(.xzr, .{ .base = .sp }));
6848 if (isel.stack_align != .@"16") {7446 try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
6849 try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{7447 (isel.instructions.items.len - loop_label) << 2,
6850 .N = .doubleword,7448 ))));
6851 .immr = -%isel.stack_align.toLog2Units(),7449 } else for (0..stack_size_hi) |_| {
6852 .imms = ~isel.stack_align.toLog2Units(),7450 try isel.emit(.sub(.sp, .sp, .{
6853 } }));7451 .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
7452 }));
7453 try isel.emit(.ldr(.xzr, .{ .base = .sp }));
7454 }
7455 if (stack_size_lo > 0) try isel.emit(.sub(
7456 scratch_reg,
7457 .sp,
7458 .{ .immediate = stack_size_lo },
7459 )) else if (scratch_reg.alias == Register.Alias.ip0)
7460 try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
7461 } else {
7462 if (stack_size_hi > 0) try isel.emit(.sub(scratch_reg, .sp, .{
7463 .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
7464 }));
7465 if (stack_size_lo > 0) try isel.emit(.sub(
7466 scratch_reg,
7467 if (stack_size_hi > 0) scratch_reg else .sp,
7468 .{ .immediate = stack_size_lo },
7469 )) else if (scratch_reg.alias == Register.Alias.ip0 and stack_size_hi == 0)
7470 try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
6854 }7471 }
7472 if (isel.stack_align != .@"16") try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
7473 .N = .doubleword,
7474 .immr = -%isel.stack_align.toLog2Units(),
7475 .imms = ~isel.stack_align.toLog2Units(),
7476 } }));
6855 wip_mir_log.debug("", .{});7477 wip_mir_log.debug("", .{});
6856 }7478 }
68577479
...@@ -6896,17 +7518,17 @@ pub fn layout(...@@ -6896,17 +7518,17 @@ pub fn layout(
6896 save_index += 1;7518 save_index += 1;
6897 } else save_index += 1;7519 } else save_index += 1;
6898 }7520 }
6899 if (isel.stack_align != .@"16" or (stack_size_low > 0 and stack_size_high > 0)) {7521 if (isel.stack_align != .@"16" or (stack_size_lo > 0 and stack_size_hi > 0)) {
6900 try isel.emit(switch (frame_record_offset) {7522 try isel.emit(switch (frame_record_offset) {
6901 0 => .add(.sp, .fp, .{ .immediate = 0 }),7523 0 => .add(.sp, .fp, .{ .immediate = 0 }),
6902 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),7524 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
6903 });7525 });
6904 } else {7526 } else {
6905 if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{7527 if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
6906 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },7528 .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
6907 }));7529 }));
6908 if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{7530 if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
6909 .immediate = stack_size_low,7531 .immediate = stack_size_lo,
6910 }));7532 }));
6911 }7533 }
6912 wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});7534 wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});
...@@ -6977,11 +7599,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt...@@ -6977,11 +7599,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt
6977 return constant.fmtValue(isel.pt);7599 return constant.fmtValue(isel.pt);
6978}7600}
69797601
7602fn block(
7603 isel: *Select,
7604 air_inst_index: Air.Inst.Index,
7605 res_ty: ZigType,
7606 air_body: []const Air.Inst.Index,
7607) !void {
7608 if (res_ty.toIntern() != .noreturn_type) {
7609 isel.blocks.putAssumeCapacityNoClobber(air_inst_index, .{
7610 .live_registers = isel.live_registers,
7611 .target_label = @intCast(isel.instructions.items.len),
7612 });
7613 }
7614 try isel.body(air_body);
7615 if (res_ty.toIntern() != .noreturn_type) {
7616 const block_entry = isel.blocks.pop().?;
7617 assert(block_entry.key == air_inst_index);
7618 if (isel.live_values.fetchRemove(air_inst_index)) |result_vi| result_vi.value.deref(isel);
7619 }
7620}
7621
6980fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void {7622fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void {
6981 wip_mir_log.debug(" | {f}", .{instruction});7623 wip_mir_log.debug(" | {f}", .{instruction});
6982 try isel.instructions.append(isel.pt.zcu.gpa, instruction);7624 try isel.instructions.append(isel.pt.zcu.gpa, instruction);
6983}7625}
69847626
7627fn emitPanic(isel: *Select, panic_id: Zcu.SimplePanicId) !void {
7628 const zcu = isel.pt.zcu;
7629 try isel.nav_relocs.append(zcu.gpa, .{
7630 .nav = switch (zcu.intern_pool.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) {
7631 else => unreachable,
7632 inline .@"extern", .func => |func| func.owner_nav,
7633 },
7634 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
7635 });
7636 try isel.emit(.bl(0));
7637}
7638
6985fn emitLiteral(isel: *Select, bytes: []const u8) !void {7639fn emitLiteral(isel: *Select, bytes: []const u8) !void {
6986 const words: []align(1) const u32 = @ptrCast(bytes);7640 const words: []align(1) const u32 = @ptrCast(bytes);
6987 const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len);7641 const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len);
...@@ -8028,6 +8682,32 @@ pub const Value = struct {...@@ -8028,6 +8682,32 @@ pub const Value = struct {
8028 }8682 }
8029 }8683 }
80308684
8685 const AddOrSubtractOptions = struct {
8686 overflow: Overflow,
8687
8688 const Overflow = union(enum) {
8689 @"unreachable",
8690 panic: Zcu.SimplePanicId,
8691 wrap,
8692 ra: Register.Alias,
8693
8694 fn defCond(overflow: Overflow, isel: *Select, cond: codegen.aarch64.encoding.ConditionCode) !void {
8695 switch (overflow) {
8696 .@"unreachable" => unreachable,
8697 .panic => |panic_id| {
8698 const skip_label = isel.instructions.items.len;
8699 try isel.emitPanic(panic_id);
8700 try isel.emit(.@"b."(
8701 cond.invert(),
8702 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
8703 ));
8704 },
8705 .wrap => {},
8706 .ra => |overflow_ra| try isel.emit(.csinc(overflow_ra.w(), .wzr, .wzr, cond.invert())),
8707 }
8708 }
8709 };
8710 };
8031 fn addOrSubtract(8711 fn addOrSubtract(
8032 res_vi: Value.Index,8712 res_vi: Value.Index,
8033 isel: *Select,8713 isel: *Select,
...@@ -8035,19 +8715,21 @@ pub const Value = struct {...@@ -8035,19 +8715,21 @@ pub const Value = struct {
8035 lhs_vi: Value.Index,8715 lhs_vi: Value.Index,
8036 op: codegen.aarch64.encoding.Instruction.AddSubtractOp,8716 op: codegen.aarch64.encoding.Instruction.AddSubtractOp,
8037 rhs_vi: Value.Index,8717 rhs_vi: Value.Index,
8038 opts: struct {8718 opts: AddOrSubtractOptions,
8039 wrap: bool,
8040 overflow_ra: Register.Alias = .zr,
8041 },
8042 ) !void {8719 ) !void {
8043 assert(opts.wrap or opts.overflow_ra == .zr);
8044 const zcu = isel.pt.zcu;8720 const zcu = isel.pt.zcu;
8045 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) });8721 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
8046 const int_info = ty.intInfo(zcu);8722 const int_info = ty.intInfo(zcu);
8047 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) });8723 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
8048 var part_offset = res_vi.size(isel);8724 var part_offset = res_vi.size(isel);
8049 var need_wrap = opts.wrap;8725 var need_wrap = switch (opts.overflow) {
8050 var need_carry = opts.overflow_ra != .zr;8726 .@"unreachable" => false,
8727 .panic, .wrap, .ra => true,
8728 };
8729 var need_carry = switch (opts.overflow) {
8730 .@"unreachable", .wrap => false,
8731 .panic, .ra => true,
8732 };
8051 while (part_offset > 0) : (need_wrap = false) {8733 while (part_offset > 0) : (need_wrap = false) {
8052 const part_size = @min(part_offset, 8);8734 const part_size = @min(part_offset, 8);
8053 part_offset -= part_size;8735 part_offset -= part_size;
...@@ -8057,48 +8739,87 @@ pub const Value = struct {...@@ -8057,48 +8739,87 @@ pub const Value = struct {
8057 const unwrapped_res_part_ra = unwrapped_res_part_ra: {8739 const unwrapped_res_part_ra = unwrapped_res_part_ra: {
8058 if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra;8740 if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra;
8059 if (int_info.bits % 32 == 0) {8741 if (int_info.bits % 32 == 0) {
8060 if (opts.overflow_ra != .zr) try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(switch (int_info.signedness) {8742 try opts.overflow.defCond(isel, switch (int_info.signedness) {
8061 .signed => .vs,8743 .signed => .vs,
8062 .unsigned => switch (op) {8744 .unsigned => switch (op) {
8063 .add => .cs,8745 .add => .cs,
8064 .sub => .cc,8746 .sub => .cc,
8065 },8747 },
8066 })));8748 });
8067 break :unwrapped_res_part_ra wrapped_res_part_ra;8749 break :unwrapped_res_part_ra wrapped_res_part_ra;
8068 }8750 }
8069 const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: {8751 need_carry = false;
8070 switch (op) {8752 const wrapped_part_ra, const unwrapped_part_ra = part_ra: switch (opts.overflow) {
8071 .add => {},8753 .@"unreachable" => unreachable,
8072 .sub => switch (int_info.signedness) {8754 .panic, .ra => switch (int_info.signedness) {
8073 .signed => {},8755 .signed => {
8074 .unsigned => {8756 try opts.overflow.defCond(isel, .ne);
8075 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc)));8757 const wrapped_part_ra = switch (wrapped_res_part_ra) {
8076 break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra };8758 else => |res_part_ra| res_part_ra,
8077 },8759 .zr => try isel.allocIntReg(),
8760 };
8761 errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
8762 const unwrapped_part_ra = unwrapped_part_ra: {
8763 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
8764 else => |res_part_ra| isel.lockReg(res_part_ra),
8765 .zr => .empty,
8766 };
8767 defer wrapped_res_part_lock.unlock(isel);
8768 break :unwrapped_part_ra try isel.allocIntReg();
8769 };
8770 errdefer isel.freeReg(unwrapped_part_ra);
8771 switch (part_size) {
8772 else => unreachable,
8773 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),
8774 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),
8775 }
8776 break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };
8078 },8777 },
8079 }8778 .unsigned => {
8080 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne)));8779 const unwrapped_part_ra = unwrapped_part_ra: {
8081 const wrapped_part_ra = switch (wrapped_res_part_ra) {8780 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
8082 else => |res_part_ra| res_part_ra,8781 else => |res_part_ra| isel.lockReg(res_part_ra),
8083 .zr => try isel.allocIntReg(),8782 .zr => .empty,
8084 };8783 };
8085 errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);8784 defer wrapped_res_part_lock.unlock(isel);
8086 const unwrapped_part_ra = unwrapped_part_ra: {8785 break :unwrapped_part_ra try isel.allocIntReg();
8087 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {8786 };
8088 else => |res_part_ra| isel.lockReg(res_part_ra),8787 errdefer isel.freeReg(unwrapped_part_ra);
8089 .zr => .empty,8788 const bit: u6 = @truncate(int_info.bits);
8090 };8789 switch (opts.overflow) {
8091 defer wrapped_res_part_lock.unlock(isel);8790 .@"unreachable", .wrap => unreachable,
8092 break :unwrapped_part_ra try isel.allocIntReg();8791 .panic => |panic_id| {
8093 };8792 const skip_label = isel.instructions.items.len;
8094 errdefer isel.freeReg(unwrapped_part_ra);8793 try isel.emitPanic(panic_id);
8095 switch (part_size) {8794 try isel.emit(.tbz(
8096 else => unreachable,8795 switch (bit) {
8097 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),8796 0, 32 => unreachable,
8098 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),8797 1...31 => unwrapped_part_ra.w(),
8099 }8798 33...63 => unwrapped_part_ra.x(),
8100 break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };8799 },
8101 } else .{ wrapped_res_part_ra, wrapped_res_part_ra };8800 bit,
8801 @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
8802 ));
8803 },
8804 .ra => |overflow_ra| try isel.emit(switch (bit) {
8805 0, 32 => unreachable,
8806 1...31 => .ubfm(overflow_ra.w(), unwrapped_part_ra.w(), .{
8807 .N = .word,
8808 .immr = bit,
8809 .imms = bit,
8810 }),
8811 33...63 => .ubfm(overflow_ra.x(), unwrapped_part_ra.x(), .{
8812 .N = .doubleword,
8813 .immr = bit,
8814 .imms = bit,
8815 }),
8816 }),
8817 }
8818 break :part_ra .{ wrapped_res_part_ra, unwrapped_part_ra };
8819 },
8820 },
8821 .wrap => .{ wrapped_res_part_ra, wrapped_res_part_ra },
8822 };
8102 defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);8823 defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
8103 errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra);8824 errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra);
8104 if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) {8825 if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) {
...@@ -8574,41 +9295,15 @@ pub const Value = struct {...@@ -8574,41 +9295,15 @@ pub const Value = struct {
8574 expected_live_registers: *const LiveRegisters,9295 expected_live_registers: *const LiveRegisters,
8575 ) !void {9296 ) !void {
8576 try vi.liveIn(isel, src_ra, expected_live_registers);9297 try vi.liveIn(isel, src_ra, expected_live_registers);
8577 const offset_from_parent: i65, const parent_vi = vi.valueParent(isel);9298 const offset_from_parent, const parent_vi = vi.valueParent(isel);
8578 switch (parent_vi.parent(isel)) {9299 switch (parent_vi.parent(isel)) {
8579 .unallocated => {},9300 .unallocated => {},
8580 .stack_slot => |stack_slot| {9301 .stack_slot => |stack_slot| if (stack_slot.base != Register.Alias.fp) try isel.storeReg(
8581 const offset = stack_slot.offset + offset_from_parent;9302 src_ra,
8582 try isel.emit(switch (vi.size(isel)) {9303 vi.size(isel),
8583 else => unreachable,9304 stack_slot.base,
8584 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{9305 @as(i65, stack_slot.offset) + offset_from_parent,
8585 .base = stack_slot.base.x(),9306 ),
8586 .offset = @intCast(offset),
8587 } }) else .strb(src_ra.w(), .{ .unsigned_offset = .{
8588 .base = stack_slot.base.x(),
8589 .offset = @intCast(offset),
8590 } }),
8591 2 => if (src_ra.isVector()) .str(src_ra.h(), .{ .unsigned_offset = .{
8592 .base = stack_slot.base.x(),
8593 .offset = @intCast(offset),
8594 } }) else .strh(src_ra.w(), .{ .unsigned_offset = .{
8595 .base = stack_slot.base.x(),
8596 .offset = @intCast(offset),
8597 } }),
8598 4 => .str(if (src_ra.isVector()) src_ra.s() else src_ra.w(), .{ .unsigned_offset = .{
8599 .base = stack_slot.base.x(),
8600 .offset = @intCast(offset),
8601 } }),
8602 8 => .str(if (src_ra.isVector()) src_ra.d() else src_ra.x(), .{ .unsigned_offset = .{
8603 .base = stack_slot.base.x(),
8604 .offset = @intCast(offset),
8605 } }),
8606 16 => .str(src_ra.q(), .{ .unsigned_offset = .{
8607 .base = stack_slot.base.x(),
8608 .offset = @intCast(offset),
8609 } }),
8610 });
8611 },
8612 else => unreachable,9307 else => unreachable,
8613 }9308 }
8614 try vi.spillReg(isel, src_ra, 0, expected_live_registers);9309 try vi.spillReg(isel, src_ra, 0, expected_live_registers);
...@@ -9027,8 +9722,14 @@ pub const Value = struct {...@@ -9027,8 +9722,14 @@ pub const Value = struct {
9027 } },9722 } },
9028 },9723 },
9029 .struct_type => {9724 .struct_type => {
9030 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9031 const loaded_struct = ip.loadStructType(ty.toIntern());9725 const loaded_struct = ip.loadStructType(ty.toIntern());
9726 switch (loaded_struct.layout) {
9727 .auto, .@"extern" => {},
9728 .@"packed" => continue :type_key .{
9729 .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
9730 },
9731 }
9732 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9032 if (loaded_struct.field_types.len > Value.max_parts and9733 if (loaded_struct.field_types.len > Value.max_parts and
9033 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)9734 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
9034 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});9735 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
...@@ -9136,6 +9837,77 @@ pub const Value = struct {...@@ -9136,6 +9837,77 @@ pub const Value = struct {
9136 if (part.is_vector) subpart_vi.setIsVector(isel);9837 if (part.is_vector) subpart_vi.setIsVector(isel);
9137 }9838 }
9138 },9839 },
9840 .union_type => {
9841 const loaded_union = ip.loadUnionType(ty.toIntern());
9842 switch (loaded_union.flagsUnordered(ip).layout) {
9843 .auto, .@"extern" => {},
9844 .@"packed" => continue :type_key .{ .int_type = .{
9845 .signedness = .unsigned,
9846 .bits = @intCast(ty.bitSize(zcu)),
9847 } },
9848 }
9849 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
9850 if ((std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
9851 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
9852 const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
9853 const alignment = vi.alignment(isel);
9854 const tag_offset = union_layout.tagOffset();
9855 const payload_offset = union_layout.payloadOffset();
9856 const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness };
9857 var parts: [2]Part = undefined;
9858 var parts_len: Value.PartsLen = 0;
9859 var field_end: u64 = 0;
9860 for (0..2) |field_index| {
9861 const field: enum { tag, payload } = switch (field_index) {
9862 0 => if (tag_offset < payload_offset) .tag else .payload,
9863 1 => if (tag_offset < payload_offset) .payload else .tag,
9864 else => unreachable,
9865 };
9866 const field_size, const field_begin = switch (field) {
9867 .tag => .{ union_layout.tag_size, tag_offset },
9868 .payload => .{ union_layout.payload_size, payload_offset },
9869 };
9870 if (field_begin >= offset + size) break;
9871 if (field_size == 0) continue;
9872 field_end = field_begin + field_size;
9873 if (field_end <= offset) continue;
9874 const field_signedness = field_signedness: switch (field) {
9875 .tag => {
9876 if (offset >= field_begin and offset + size <= field_begin + field_size) {
9877 ty = .fromInterned(loaded_union.enum_tag_ty);
9878 ty_size = field_size;
9879 offset -= field_begin;
9880 continue :type_key ip.indexToKey(loaded_union.enum_tag_ty);
9881 }
9882 break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness;
9883 },
9884 .payload => null,
9885 };
9886 if (parts_len > 0) combine: {
9887 const prev_part = &parts[parts_len - 1];
9888 const combined_size = field_end - prev_part.offset;
9889 if (combined_size > @as(u64, 1) << @min(
9890 min_part_log2_stride,
9891 alignment.toLog2Units(),
9892 @ctz(prev_part.offset),
9893 )) break :combine;
9894 prev_part.size = combined_size;
9895 prev_part.signedness = null;
9896 continue;
9897 }
9898 parts[parts_len] = .{
9899 .offset = field_begin,
9900 .size = field_size,
9901 .signedness = field_signedness,
9902 };
9903 parts_len += 1;
9904 }
9905 vi.setParts(isel, parts_len);
9906 for (parts[0..parts_len]) |part| {
9907 const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
9908 if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
9909 }
9910 },
9139 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },9911 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
9140 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),9912 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
9141 .error_set_type,9913 .error_set_type,
...@@ -9555,21 +10327,29 @@ pub const Value = struct {...@@ -9555,21 +10327,29 @@ pub const Value = struct {
9555 var base_ptr = ip.indexToKey(base).ptr;10327 var base_ptr = ip.indexToKey(base).ptr;
9556 const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child;10328 const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child;
9557 const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type;10329 const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type;
9558 base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu);10330 base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu) + ptr.byte_offset;
10331 continue :constant_key .{ .ptr = base_ptr };
10332 },
10333 .opt_payload => |base| {
10334 var base_ptr = ip.indexToKey(base).ptr;
10335 base_ptr.byte_offset += ptr.byte_offset;
9559 continue :constant_key .{ .ptr = base_ptr };10336 continue :constant_key .{ .ptr = base_ptr };
9560 },10337 },
9561 .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr },
9562 .field => |field| {10338 .field => |field| {
9563 var base_ptr = ip.indexToKey(field.base).ptr;10339 var base_ptr = ip.indexToKey(field.base).ptr;
9564 const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child);10340 const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child);
9565 base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu);10341 base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset;
9566 continue :constant_key .{ .ptr = base_ptr };10342 continue :constant_key .{ .ptr = base_ptr };
9567 },10343 },
9568 .comptime_alloc, .comptime_field, .arr_elem => unreachable,10344 .comptime_alloc, .comptime_field, .arr_elem => unreachable,
9569 };10345 };
9570 },10346 },
9571 .slice => |slice| switch (offset) {10347 .slice => |slice| switch (offset) {
9572 0 => continue :constant_key .{ .ptr = ip.indexToKey(slice.ptr).ptr },10348 0 => continue :constant_key switch (ip.indexToKey(slice.ptr)) {
10349 else => unreachable,
10350 .undef => |undef| .{ .undef = undef },
10351 .ptr => |ptr| .{ .ptr = ptr },
10352 },
9573 else => {10353 else => {
9574 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));10354 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
9575 offset = 0;10355 offset = 0;
...@@ -10622,16 +11402,14 @@ pub const CallAbiIterator = struct {...@@ -10622,16 +11402,14 @@ pub const CallAbiIterator = struct {
10622 {11402 {
10623 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);11403 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
10624 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);11404 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
10625 const size = error_set_ty.abiSize(zcu);11405 const end = offset % 8 + error_set_ty.abiSize(zcu);
10626 const end = offset % 8 + size;
10627 const part_index: usize = @intCast(offset / 8);11406 const part_index: usize = @intCast(offset / 8);
10628 sizes[part_index] = @max(sizes[part_index], @min(end, 8));11407 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
10629 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);11408 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
10630 }11409 }
10631 {11410 {
10632 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);11411 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
10633 const size = payload_ty.abiSize(zcu);11412 const end = offset % 8 + payload_ty.abiSize(zcu);
10634 const end = offset % 8 + size;
10635 const part_index: usize = @intCast(offset / 8);11413 const part_index: usize = @intCast(offset / 8);
10636 sizes[part_index] = @max(sizes[part_index], @min(end, 8));11414 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
10637 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);11415 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
...@@ -10675,8 +11453,14 @@ pub const CallAbiIterator = struct {...@@ -10675,8 +11453,14 @@ pub const CallAbiIterator = struct {
10675 => unreachable,11453 => unreachable,
10676 },11454 },
10677 .struct_type => {11455 .struct_type => {
10678 const size = wip_vi.size(isel);
10679 const loaded_struct = ip.loadStructType(ty.toIntern());11456 const loaded_struct = ip.loadStructType(ty.toIntern());
11457 switch (loaded_struct.layout) {
11458 .auto, .@"extern" => {},
11459 .@"packed" => continue :type_key .{
11460 .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
11461 },
11462 }
11463 const size = wip_vi.size(isel);
10680 if (size <= 16 * 4) homogeneous_aggregate: {11464 if (size <= 16 * 4) homogeneous_aggregate: {
10681 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;11465 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
10682 const parts_len = @shrExact(size, fdt.log2Size());11466 const parts_len = @shrExact(size, fdt.log2Size());
...@@ -10761,6 +11545,40 @@ pub const CallAbiIterator = struct {...@@ -10761,6 +11545,40 @@ pub const CallAbiIterator = struct {
10761 else => it.indirect(isel, wip_vi),11545 else => it.indirect(isel, wip_vi),
10762 }11546 }
10763 },11547 },
11548 .union_type => {
11549 const loaded_union = ip.loadUnionType(ty.toIntern());
11550 switch (loaded_union.flagsUnordered(ip).layout) {
11551 .auto, .@"extern" => {},
11552 .@"packed" => continue :type_key .{ .int_type = .{
11553 .signedness = .unsigned,
11554 .bits = @intCast(ty.bitSize(zcu)),
11555 } },
11556 }
11557 switch (wip_vi.size(isel)) {
11558 0 => unreachable,
11559 1...8 => it.integer(isel, wip_vi),
11560 9...16 => {
11561 const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
11562 var sizes: [2]u64 = @splat(0);
11563 {
11564 const offset = union_layout.tagOffset();
11565 const end = offset % 8 + union_layout.tag_size;
11566 const part_index: usize = @intCast(offset / 8);
11567 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11568 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
11569 }
11570 {
11571 const offset = union_layout.payloadOffset();
11572 const end = offset % 8 + union_layout.payload_size;
11573 const part_index: usize = @intCast(offset / 8);
11574 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
11575 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
11576 }
11577 it.integers(isel, wip_vi, sizes);
11578 },
11579 else => it.indirect(isel, wip_vi),
11580 }
11581 },
10764 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },11582 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
10765 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),11583 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
10766 .error_set_type,11584 .error_set_type,
src/codegen/aarch64/encoding.zig+2
...@@ -151,6 +151,7 @@ pub const Register = struct {...@@ -151,6 +151,7 @@ pub const Register = struct {
151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
153153
154 pub const ip = x16;
154 pub const ip0 = x16;155 pub const ip0 = x16;
155 pub const ip1 = x17;156 pub const ip1 = x17;
156 pub const fp = x29;157 pub const fp = x29;
...@@ -774,6 +775,7 @@ pub const Register = struct {...@@ -774,6 +775,7 @@ pub const Register = struct {
774775
775 ffr,776 ffr,
776777
778 pub const ip: Alias = .r16;
777 pub const ip0: Alias = .r16;779 pub const ip0: Alias = .r16;
778 pub const ip1: Alias = .r17;780 pub const ip1: Alias = .r17;
779 pub const fp: Alias = .r29;781 pub const fp: Alias = .r29;
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 BLR273 // 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 SBFM1157 // C6.2.268 SBFM
968 .{1158 .{
969 .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",1159 .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",
src/target.zig+11-5
...@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {...@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
248 return false;248 return false;
249}249}
250250
251pub fn supportsStackProbing(target: *const std.Target) bool {251pub fn supportsStackProbing(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
252 return target.os.tag != .windows and target.os.tag != .uefi and252 return switch (backend) {
253 (target.cpu.arch == .x86 or target.cpu.arch == .x86_64);253 .stage2_aarch64, .stage2_x86_64 => true,
254 .stage2_llvm => target.os.tag != .windows and target.os.tag != .uefi and
255 (target.cpu.arch == .x86 or target.cpu.arch == .x86_64),
256 else => false,
257 };
254}258}
255259
256pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {260pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
...@@ -347,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti...@@ -347,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti
347 }351 }
348}352}
349353
350pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {354pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
351 switch (target.os.tag) {355 switch (target.os.tag) {
352 .plan9 => return false,356 .plan9 => return false,
353 else => {},357 else => {},
...@@ -369,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime...@@ -369,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime
369 };373 };
370}374}
371375
372pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {376pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
373 switch (target.cpu.arch) {377 switch (target.cpu.arch) {
374 .spirv32, .spirv64 => return false,378 .spirv32, .spirv64 => return false,
375 // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed379 // Remove this once https://github.com/ziglang/zig/issues/23715 is fixed
...@@ -378,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha...@@ -378,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha
378 }382 }
379 return switch (zigBackend(target, use_llvm)) {383 return switch (zigBackend(target, use_llvm)) {
380 .stage2_llvm => true,384 .stage2_llvm => true,
385 .stage2_wasm => false,
381 .stage2_x86_64 => switch (target.ofmt) {386 .stage2_x86_64 => switch (target.ofmt) {
382 .elf, .macho => true,387 .elf, .macho => true,
383 else => have_llvm,388 else => have_llvm,
...@@ -856,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile...@@ -856,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile
856pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool {861pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool {
857 return switch (feature) {862 return switch (feature) {
858 .panic_fn => switch (backend) {863 .panic_fn => switch (backend) {
864 .stage2_aarch64,
859 .stage2_c,865 .stage2_c,
860 .stage2_llvm,866 .stage2_llvm,
861 .stage2_x86_64,867 .stage2_x86_64,
test/behavior/decl_literals.zig-2
...@@ -33,7 +33,6 @@ test "decl literal with pointer" {...@@ -33,7 +33,6 @@ test "decl literal with pointer" {
33}33}
3434
35test "call decl literal with optional" {35test "call decl literal with optional" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
37 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -74,7 +73,6 @@ test "call decl literal" {...@@ -74,7 +73,6 @@ test "call decl literal" {
74}73}
7574
76test "call decl literal with error union" {75test "call decl literal with error union" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
78 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
7977
80 const S = struct {78 const S = struct {
test/behavior/error.zig-4
...@@ -590,7 +590,6 @@ test "error union comptime caching" {...@@ -590,7 +590,6 @@ test "error union comptime caching" {
590}590}
591591
592test "@errorName" {592test "@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; // TODO594 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}
606605
607test "@errorName sentinel length matches slice length" {606test "@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; // TODO608 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}
884882
885test "error from comptime string" {883test "error from comptime string" {
886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO884 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
888 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO885 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;
...@@ -946,7 +943,6 @@ test "optional error set function parameter" {...@@ -946,7 +943,6 @@ test "optional error set function parameter" {
946}943}
947944
948test "returning an error union containing a type with no runtime bits" {945test "returning an error union containing a type with no runtime bits" {
949 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
950 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
951 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;947 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
952948
test/behavior/field_parent_ptr.zig-2
...@@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {...@@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
587}587}
588588
589test "@fieldParentPtr unaligned packed struct" {589test "@fieldParentPtr unaligned packed struct" {
590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
591 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;590 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
592 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;591 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
593 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;592 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {...@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {
726}725}
727726
728test "@fieldParentPtr aligned packed struct" {727test "@fieldParentPtr aligned packed struct" {
729 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
731 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;729 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
732 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/inline_switch.zig-2
...@@ -43,7 +43,6 @@ test "inline switch enums" {...@@ -43,7 +43,6 @@ test "inline switch enums" {
4343
44const U = union(E) { a: void, b: u2, c: u3, d: u4 };44const U = union(E) { a: void, b: u2, c: u3, d: u4 };
45test "inline switch unions" {45test "inline switch unions" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
48 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO47 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4948
...@@ -105,7 +104,6 @@ test "inline else enum" {...@@ -105,7 +104,6 @@ test "inline else enum" {
105}104}
106105
107test "inline else int with gaps" {106test "inline else int with gaps" {
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
110 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO108 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
111109
test/behavior/optional.zig-2
...@@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {...@@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {
319}319}
320320
321test "coerce an anon struct literal to optional struct" {321test "coerce an anon struct literal to optional struct" {
322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
324 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;324 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {...@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {
447}446}
448447
449test "optional pointer to zero bit error union payload" {448test "optional pointer to zero bit error union payload" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;451 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}
77
8test "return address" {8test "return address" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO10 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/behavior/struct.zig-5
...@@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {...@@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {
797}797}
798798
799test "non-packed struct with u128 entry in union" {799test "non-packed struct with u128 entry in union" {
800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
801 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO800 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;802 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {...@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {
1026}1025}
10271026
1028test "for loop over pointers to struct, getting field from struct pointer" {1027test "for loop over pointers to struct, getting field from struct pointer" {
1029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1030 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1028 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1031 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1032 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1030 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {...@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {
1093}1091}
10941092
1095test "anon init through optional" {1093test "anon init through optional" {
1096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1097 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1094 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1098 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1095 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1099 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1096 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1113,7 +1110,6 @@ test "anon init through optional" {...@@ -1113,7 +1110,6 @@ test "anon init through optional" {
1113}1110}
11141111
1115test "anon init through error union" {1112test "anon init through error union" {
1116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1118 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1119 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1115 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -1398,7 +1394,6 @@ test "struct has only one reference" {...@@ -1398,7 +1394,6 @@ test "struct has only one reference" {
1398}1394}
13991395
1400test "no dependency loop on pointer to optional struct" {1396test "no dependency loop on pointer to optional struct" {
1401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1402 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1403 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;1398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14041399
test/behavior/switch.zig-5
...@@ -8,7 +8,6 @@ const minInt = std.math.minInt;...@@ -8,7 +8,6 @@ const minInt = std.math.minInt;
8const maxInt = std.math.maxInt;8const maxInt = std.math.maxInt;
99
10test "switch with numbers" {10test "switch with numbers" {
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO11 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;12 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1413
...@@ -300,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {...@@ -300,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
300}299}
301300
302test "switch on enum using pointer capture" {301test "switch on enum using pointer capture" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306304
...@@ -361,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {...@@ -361,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
361}359}
362360
363test "switch on union with some prongs capturing" {361test "switch on union with some prongs capturing" {
364 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
366 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
367364
...@@ -976,8 +973,6 @@ test "switch prong captures range" {...@@ -976,8 +973,6 @@ test "switch prong captures range" {
976}973}
977974
978test "prong with inline call to unreachable" {975test "prong with inline call to unreachable" {
979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
980
981 const U = union(enum) {976 const U = union(enum) {
982 void: void,977 void: void,
983 bool: bool,978 bool: bool,
test/behavior/switch_on_captured_error.zig-1
...@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;...@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8test "switch on error union catch capture" {8test "switch on error union catch capture" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;9 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;10 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
1211
test/behavior/union.zig-18
...@@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {...@@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {
160}160}
161161
162test "constant tagged union with payload" {162test "constant tagged union with payload" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
165 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166165
...@@ -263,7 +262,6 @@ fn testComparison() !void {...@@ -263,7 +262,6 @@ fn testComparison() !void {
263}262}
264263
265test "comparison between union and enum literal" {264test "comparison between union and enum literal" {
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
269 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {...@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {
279 C: i32,277 C: i32,
280};278};
281test "cast union to tag type of union" {279test "cast union to tag type of union" {
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
284 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285282
...@@ -300,7 +297,6 @@ test "union field access gives the enum values" {...@@ -300,7 +297,6 @@ test "union field access gives the enum values" {
300}297}
301298
302test "cast tag type of union to union" {299test "cast tag type of union to union" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306302
...@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {...@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {
316};312};
317313
318test "implicit cast union to its tag type" {314test "implicit cast union to its tag type" {
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322317
...@@ -495,7 +490,6 @@ test "initialize global array of union" {...@@ -495,7 +490,6 @@ test "initialize global array of union" {
495}490}
496491
497test "update the tag value for zero-sized unions" {492test "update the tag value for zero-sized unions" {
498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
499 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
500 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO494 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
501495
...@@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci...@@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci
734}728}
735729
736test "@intFromEnum works on unions" {730test "@intFromEnum works on unions" {
737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
738 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
740733
...@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {...@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {
848}841}
849842
850test "@unionInit can modify a union type" {843test "@unionInit can modify a union type" {
851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
853 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
854846
...@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {...@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {
871}863}
872864
873test "@unionInit can modify a pointer value" {865test "@unionInit can modify a pointer value" {
874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO866 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO867 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
877868
...@@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {...@@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {
990}981}
991982
992test "switching on non exhaustive union" {983test "switching on non exhaustive union" {
993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO985 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
996986
...@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {...@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {
1176}1166}
11771167
1178test "union tag is set when initiated as a temporary value at runtime" {1168test "union tag is set when initiated as a temporary value at runtime" {
1179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1181 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1182 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {...@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {
1216}1205}
12171206
1218test "return an extern union from C calling convention" {1207test "return an extern union from C calling convention" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1222 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;1210 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
...@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {...@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {
1248}1236}
12491237
1250test "noreturn field in union" {1238test "noreturn field in union" {
1251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1239 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1253 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12541241
...@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {...@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {
1481}1468}
14821469
1483test "access the tag of a global tagged union" {1470test "access the tag of a global tagged union" {
1484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1485
1486 const U = union(enum) {1471 const U = union(enum) {
1487 a,1472 a,
1488 b: u8,1473 b: u8,
...@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {...@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {
2111}2096}
21122097
2113test "copied union field doesn't alias source" {2098test "copied union field doesn't alias source" {
2114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO2099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2116 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO2100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2117 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;2101 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
...@@ -2334,8 +2318,6 @@ test "assign global tagged union" {...@@ -2334,8 +2318,6 @@ test "assign global tagged union" {
2334}2318}
23352319
2336test "set mutable union by switching on same union" {2320test "set mutable union by switching on same union" {
2337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2338
2339 const U = union(enum) {2321 const U = union(enum) {
2340 foo,2322 foo,
2341 bar: usize,2323 bar: usize,
test/behavior/union_with_members.zig-1
...@@ -17,7 +17,6 @@ const ET = union(enum) {...@@ -17,7 +17,6 @@ const ET = union(enum) {
17};17};
1818
19test "enum with members" {19test "enum with members" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/while.zig-1
...@@ -344,7 +344,6 @@ test "else continue outer while" {...@@ -344,7 +344,6 @@ test "else continue outer while" {
344}344}
345345
346test "try terminating an infinite loop" {346test "try terminating an infinite loop" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
349 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;348 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
350349
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 {
1919
20// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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-none7// 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 {
2525
26// error26// error
27// backend=stage227// backend=stage2
28// target=native28// 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 set31// :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 {
1010
11// error11// error
12// backend=stage212// backend=stage2
13// target=native13// 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 {
1515
16// error16// error
17// backend=stage217// backend=stage2
18// target=native18// 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 {
66
7// error7// error
8// backend=stage28// backend=stage2
9// target=native9// 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 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");2const std = @import("std");
33
4fn _start() callconv(.naked) void {}4pub fn _start() callconv(.naked) void {}
55
6comptime {6comptime {
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// run23// run
24// backend=stage2,llvm24// backend=stage2,llvm
25// target=native25// 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 {}
2323
24// run24// run
25// backend=stage2,llvm25// backend=stage2,llvm
26// target=native26// 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 {
2020
21// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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 {
2020
21// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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 {
17fn baz(_: i8) void {}17fn baz(_: i8) void {}
18// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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 {
17fn baz(_: u8) void {}17fn baz(_: u8) void {}
18// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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 {
17fn baz(_: u8) void {}17fn baz(_: u8) void {}
18// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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 {
2323
24// run24// run
25// backend=stage2,llvm25// backend=stage2,llvm
26// target=native26// 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 {
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=native27// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=native27// 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// run14// run
15// backend=stage2,llvm15// backend=stage2,llvm
16// target=native16// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run23// run
24// backend=stage2,llvm24// backend=stage2,llvm
25// target=native25// 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// run22// run
23// backend=stage2,llvm23// backend=stage2,llvm
24// target=native24// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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 {
2020
21// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run16// run
17// backend=stage2,llvm17// backend=stage2,llvm
18// target=native18// 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// run16// run
17// backend=stage2,llvm17// backend=stage2,llvm
18// target=native18// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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 {
18fn baz(_: i32) void {}18fn baz(_: i32) void {}
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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 {
2020
21// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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 {
1919
20// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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 {
1919
20// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run16// run
17// backend=stage2,llvm17// backend=stage2,llvm
18// target=native18// 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// run16// run
17// backend=stage2,llvm17// backend=stage2,llvm
18// target=native18// 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 {
1717
18// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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 {
1717
18// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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 {
2121
22// run22// run
23// backend=stage2,llvm23// backend=stage2,llvm
24// target=native24// 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 {
2020
21// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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");
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=x86_64-linux27// 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");
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=x86_64-linux27// 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");
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=x86_64-linux27// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run18// run
19// backend=stage2,llvm19// backend=stage2,llvm
20// target=native20// 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// run22// run
23// backend=stage2,llvm23// backend=stage2,llvm
24// target=native24// 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// run27// run
28// backend=stage2,llvm28// backend=stage2,llvm
29// target=native29// 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// run21// run
22// backend=stage2,llvm22// backend=stage2,llvm
23// target=native23// 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 {
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=native27// 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 {
2424
25// run25// run
26// backend=stage2,llvm26// backend=stage2,llvm
27// target=native27// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run13// run
14// backend=stage2,llvm14// backend=stage2,llvm
15// target=native15// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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 {
1818
19// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run19// run
20// backend=stage2,llvm20// backend=stage2,llvm
21// target=native21// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run20// run
21// backend=stage2,llvm21// backend=stage2,llvm
22// target=native22// 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// run17// run
18// backend=stage2,llvm18// backend=stage2,llvm
19// target=native19// 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 {
2323
24// run24// run
25// backend=stage2,llvm25// backend=stage2,llvm
26// target=native26// 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 and438 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 format441 // 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 ZLD447 // 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 }
454450
455 const next = ctx.cases.items.len;451 const next = ctx.cases.items.len;
456 try ctx.cases.append(.{452 try ctx.cases.append(.{