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 {
240240 _ = @import("compiler_rt/udivmodti4.zig");
241241
242242 // extra
243 if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");
243 _ = @import("compiler_rt/os_version_check.zig");
244244 _ = @import("compiler_rt/emutls.zig");
245245 _ = @import("compiler_rt/arm.zig");
246246 _ = @import("compiler_rt/aulldiv.zig");
src/Compilation.zig+6-4
......@@ -1816,10 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18161816 if (options.skip_linker_dependencies) break :s .none;
18171817 const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;
18181818 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)) {
18201820 if (output_mode == .Obj) break :s .zcu;
1821 if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64)
1822 break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
1821 if (switch (target_util.zigBackend(target, use_llvm)) {
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;
18231825 }
18241826 if (is_exe_or_dyn_lib) break :s .lib;
18251827 break :s .obj;
......@@ -1854,7 +1856,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
18541856 const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib);
18551857 if (!want_ubsan_rt) break :s .none;
18561858 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;
18581860 if (is_exe_or_dyn_lib) break :s .lib;
18591861 break :s .obj;
18601862 };
src/Package/Module.zig+1-1
......@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
250250 };
251251
252252 const stack_check = b: {
253 if (!target_util.supportsStackProbing(target)) {
253 if (!target_util.supportsStackProbing(target, zig_backend)) {
254254 if (options.inherited.stack_check == true)
255255 return error.StackCheckUnsupportedByTarget;
256256 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 {
168137168137 .unused,
168138168138 .unused,
168139168139 },
168140 .dst_temps = .{ .{ .cc = .b }, .unused },
168140 .dst_temps = .{ .{ .cc = .be }, .unused },
168141168141 .clobbers = .{ .eflags = true },
168142168142 .each = .{ .once = &.{
168143168143 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
......@@ -168161,7 +168161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168161168161 .unused,
168162168162 .unused,
168163168163 },
168164 .dst_temps = .{ .{ .cc = .b }, .unused },
168164 .dst_temps = .{ .{ .cc = .be }, .unused },
168165168165 .clobbers = .{ .eflags = true },
168166168166 .each = .{ .once = &.{
168167168167 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
......@@ -168185,7 +168185,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
168185168185 .unused,
168186168186 .unused,
168187168187 },
168188 .dst_temps = .{ .{ .cc = .b }, .unused },
168188 .dst_temps = .{ .{ .cc = .be }, .unused },
168189168189 .clobbers = .{ .eflags = true },
168190168190 .each = .{ .once = &.{
168191168191 .{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
src/arch/x86_64/Emit.zig+6-5
......@@ -168,11 +168,12 @@ pub fn emitMir(emit: *Emit) Error!void {
168168 else if (emit.bin_file.cast(.macho)) |macho_file|
169169 macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
170170 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
171 else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: {
172 const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
173 return emit.fail("{s} creating lazy symbol", .{@errorName(err)});
174 break :sym_index coff_file.getAtom(atom).getSymbolIndex().?;
175 } else if (emit.bin_file.cast(.plan9)) |p9_file|
171 else if (emit.bin_file.cast(.coff)) |coff_file|
172 if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom|
173 coff_file.getAtom(atom).getSymbolIndex().?
174 else |err|
175 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
176 else if (emit.bin_file.cast(.plan9)) |p9_file|
176177 p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
177178 return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
178179 else
src/codegen/aarch64.zig+5-2
......@@ -47,6 +47,7 @@ pub fn generate(
4747 .literals = .empty,
4848 .nav_relocs = .empty,
4949 .uav_relocs = .empty,
50 .lazy_relocs = .empty,
5051 .global_relocs = .empty,
5152 .literal_relocs = .empty,
5253
......@@ -101,8 +102,8 @@ pub fn generate(
101102 };
102103 switch (passed_vi.parent(&isel)) {
103104 .unallocated => if (!mod.strip) {
104 var part_it = arg_vi.parts(&isel);
105 const first_passed_part_vi = part_it.next() orelse passed_vi;
105 var part_it = passed_vi.parts(&isel);
106 const first_passed_part_vi = part_it.next().?;
106107 const hint_ra = first_passed_part_vi.hint(&isel).?;
107108 passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector())
108109 isel.va_list.__vr_top.withOffset(@as(i8, -16) *
......@@ -167,6 +168,7 @@ pub fn generate(
167168 .literals = &.{},
168169 .nav_relocs = &.{},
169170 .uav_relocs = &.{},
171 .lazy_relocs = &.{},
170172 .global_relocs = &.{},
171173 .literal_relocs = &.{},
172174 };
......@@ -174,6 +176,7 @@ pub fn generate(
174176 mir.literals = try isel.literals.toOwnedSlice(gpa);
175177 mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa);
176178 mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa);
179 mir.lazy_relocs = try isel.lazy_relocs.toOwnedSlice(gpa);
177180 mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa);
178181 mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa);
179182 return mir;
src/codegen/aarch64/Assemble.zig+26-6
......@@ -6,14 +6,19 @@ pub const Operand = union(enum) {
66};
77
88pub fn nextInstruction(as: *Assemble) !?Instruction {
9 @setEvalBranchQuota(37_000);
9 @setEvalBranchQuota(42_000);
1010 comptime var ct_token_buf: [token_buf_len]u8 = undefined;
1111 var token_buf: [token_buf_len]u8 = undefined;
1212 const original_source = while (true) {
1313 const original_source = as.source;
1414 const source_token = try as.nextToken(&token_buf, .{});
15 if (source_token.len == 0) return null;
16 if (source_token[0] != '\n') break original_source;
15 switch (source_token.len) {
16 0 => return null,
17 else => switch (source_token[0]) {
18 else => break original_source,
19 '\n', ';' => {},
20 },
21 }
1722 };
1823 log.debug(
1924 \\.
......@@ -52,7 +57,13 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
5257 std.zig.fmtString(source_token),
5358 });
5459 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 }
5667 const encode = @field(Instruction, @tagName(instruction.encode[0]));
5768 const Encode = @TypeOf(encode);
5869 var args: std.meta.ArgsTuple(Encode) = undefined;
......@@ -65,7 +76,7 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
6576 const symbol = &@field(symbols, symbol_name);
6677 symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern;
6778 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;
6980 }
7081 }
7182 log.debug("'{s}' not matched...", .{instruction.pattern});
......@@ -125,6 +136,15 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
125136 }
126137}
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
128148const token_buf_len = "v31.b[15]".len;
129149fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
130150 operands: bool = false,
......@@ -134,7 +154,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
134154 while (true) c: switch (as.source[0]) {
135155 0 => return as.source[0..0],
136156 '\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..],
137 '\n', '!', '#', ',', '[', ']' => {
157 '\n', '!', '#', ',', ';', '[', ']' => {
138158 defer as.source = as.source[1..];
139159 return as.source[0..1];
140160 },
src/codegen/aarch64/Mir.zig+106-33
......@@ -4,6 +4,7 @@ epilogue: []const Instruction,
44literals: []const u32,
55nav_relocs: []const Reloc.Nav,
66uav_relocs: []const Reloc.Uav,
7lazy_relocs: []const Reloc.Lazy,
78global_relocs: []const Reloc.Global,
89literal_relocs: []const Reloc.Literal,
910
......@@ -21,8 +22,13 @@ pub const Reloc = struct {
2122 reloc: Reloc,
2223 };
2324
25 pub const Lazy = struct {
26 symbol: link.File.LazySymbol,
27 reloc: Reloc,
28 };
29
2430 pub const Global = struct {
25 global: [*:0]const u8,
31 name: [*:0]const u8,
2632 reloc: Reloc,
2733 };
2834
......@@ -38,6 +44,7 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
3844 gpa.free(mir.literals);
3945 gpa.free(mir.nav_relocs);
4046 gpa.free(mir.uav_relocs);
47 gpa.free(mir.lazy_relocs);
4148 gpa.free(mir.global_relocs);
4249 gpa.free(mir.literal_relocs);
4350 mir.* = undefined;
......@@ -119,16 +126,37 @@ pub fn emit(
119126 body_end - Instruction.size * (1 + uav_reloc.reloc.label),
120127 uav_reloc.reloc.addend,
121128 );
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 );
122150 for (mir.global_relocs) |global_reloc| try emitReloc(
123151 lf,
124152 zcu,
125153 func.owner_nav,
126154 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)
128156 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)
130158 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")
132160 else
133161 return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
134162 mir.body[global_reloc.reloc.label],
......@@ -172,35 +200,6 @@ fn emitReloc(
172200 const gpa = zcu.gpa;
173201 switch (instruction.decode()) {
174202 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 },
204203 .data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| {
205204 const zo = ef.zigObjectPtr().?;
206205 const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
......@@ -259,6 +258,80 @@ fn emitReloc(
259258 },
260259 }
261260 },
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 },
262335 }
263336}
264337
src/codegen/aarch64/Select.zig+1119-301
......@@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction),
2222literals: std.ArrayListUnmanaged(u32),
2323nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav),
2424uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav),
25lazy_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Lazy),
2526global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global),
2627literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),
2728
......@@ -50,11 +51,11 @@ pub const Block = struct {
5051 std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type),
5152 );
5253
53 fn branch(block: *const Block, isel: *Select) !void {
54 if (isel.instructions.items.len > block.target_label) {
55 try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - block.target_label) << 2)));
54 fn branch(target_block: *const Block, isel: *Select) !void {
55 if (isel.instructions.items.len > target_block.target_label) {
56 try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - target_block.target_label) << 2)));
5657 }
57 try isel.merge(&block.live_registers, .{});
58 try isel.merge(&target_block.live_registers, .{});
5859 }
5960};
6061
......@@ -84,12 +85,12 @@ pub const Loop = struct {
8485
8586 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 {
8889 try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1);
89 const repeat_list_tail = loop.repeat_list;
90 loop.repeat_list = @intCast(isel.instructions.items.len);
90 const repeat_list_tail = target_loop.repeat_list;
91 target_loop.repeat_list = @intCast(isel.instructions.items.len);
9192 isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail));
92 try isel.merge(&loop.live_registers, .{});
93 try isel.merge(&target_loop.live_registers, .{});
9394 }
9495};
9596
......@@ -108,6 +109,7 @@ pub fn deinit(isel: *Select) void {
108109 isel.literals.deinit(gpa);
109110 isel.nav_relocs.deinit(gpa);
110111 isel.uav_relocs.deinit(gpa);
112 isel.lazy_relocs.deinit(gpa);
111113 isel.global_relocs.deinit(gpa);
112114 isel.literal_relocs.deinit(gpa);
113115
......@@ -582,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
582584
583585 air_body_index += 1;
584586 },
585 .@"try", .try_cold, .try_ptr, .try_ptr_cold => {
587 .@"try", .try_cold => {
586588 const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
587589 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 {
594596 air_inst_index = air_body[air_body_index];
595597 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
596598 },
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 },
597611 .ret, .ret_safe, .ret_load => {
598612 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
599613 isel.returns = true;
......@@ -864,7 +878,7 @@ pub fn finishAnalysis(isel: *Select) !void {
864878 }
865879}
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 {
868882 const zcu = isel.pt.zcu;
869883 const ip = &zcu.intern_pool;
870884 const gpa = zcu.gpa;
......@@ -946,7 +960,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
946960 }
947961 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
948962 },
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| {
950964 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
951965 defer res_vi.value.deref(isel);
952966
......@@ -954,13 +968,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
954968 const ty = isel.air.typeOf(bin_op.lhs, ip);
955969 if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) {
956970 else => unreachable,
957 .add, .add_wrap => .add,
958 .sub, .sub_wrap => .sub,
959 }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) {
960 else => unreachable,
961 .add, .sub => false,
962 .add_wrap, .sub_wrap => true,
963 } }) else switch (ty.floatBits(isel.target)) {
971 .add, .add_safe, .add_wrap => .add,
972 .sub, .sub_safe, .sub_wrap => .sub,
973 }, try isel.use(bin_op.rhs), .{
974 .overflow = switch (air_tag) {
975 else => unreachable,
976 .add, .sub => .@"unreachable",
977 .add_safe, .sub_safe => .{ .panic = .integer_overflow },
978 .add_wrap, .sub_wrap => .wrap,
979 },
980 }) else switch (ty.floatBits(isel.target)) {
964981 else => unreachable,
965982 16, 32, 64 => |bits| {
966983 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 {
10211038
10221039 try call.prepareCallee(isel);
10231040 try isel.global_relocs.append(gpa, .{
1024 .global = switch (air_tag) {
1041 .name = switch (air_tag) {
10251042 else => unreachable,
10261043 .add, .add_optimized => switch (bits) {
10271044 else => unreachable,
......@@ -1336,7 +1353,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
13361353
13371354 try call.prepareCallee(isel);
13381355 try isel.global_relocs.append(gpa, .{
1339 .global = switch (bits) {
1356 .name = switch (bits) {
13401357 else => unreachable,
13411358 16 => "__mulhf3",
13421359 32 => "__mulsf3",
......@@ -1379,6 +1396,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
13791396 }
13801397 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
13811398 },
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 },
13821536 .mul_sat => |air_tag| {
13831537 if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
13841538 defer res_vi.value.deref(isel);
......@@ -1674,7 +1828,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
16741828
16751829 try call.prepareCallee(isel);
16761830 try isel.global_relocs.append(gpa, .{
1677 .global = switch (bits) {
1831 .name = switch (bits) {
16781832 else => unreachable,
16791833 16 => "__divhf3",
16801834 32 => "__divsf3",
......@@ -1813,7 +1967,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
18131967
18141968 try call.prepareCallee(isel);
18151969 try isel.global_relocs.append(gpa, .{
1816 .global = switch (int_info.signedness) {
1970 .name = switch (int_info.signedness) {
18171971 .signed => "__divti3",
18181972 .unsigned => "__udivti3",
18191973 },
......@@ -1917,7 +2071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
19172071 else => unreachable,
19182072 .div_trunc, .div_trunc_optimized => {
19192073 try isel.global_relocs.append(gpa, .{
1920 .global = switch (bits) {
2074 .name = switch (bits) {
19212075 else => unreachable,
19222076 16 => "__trunch",
19232077 32 => "truncf",
......@@ -1931,7 +2085,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
19312085 },
19322086 .div_floor, .div_floor_optimized => {
19332087 try isel.global_relocs.append(gpa, .{
1934 .global = switch (bits) {
2088 .name = switch (bits) {
19352089 else => unreachable,
19362090 16 => "__floorh",
19372091 32 => "floorf",
......@@ -1946,7 +2100,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
19462100 .div_exact, .div_exact_optimized => {},
19472101 }
19482102 try isel.global_relocs.append(gpa, .{
1949 .global = switch (bits) {
2103 .name = switch (bits) {
19502104 else => unreachable,
19512105 16 => "__divhf3",
19522106 32 => "__divsf3",
......@@ -2046,7 +2200,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
20462200
20472201 try call.prepareCallee(isel);
20482202 try isel.global_relocs.append(gpa, .{
2049 .global = switch (bits) {
2203 .name = switch (bits) {
20502204 else => unreachable,
20512205 16 => "__fmodh",
20522206 32 => "fmodf",
......@@ -2212,7 +2366,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
22122366
22132367 try call.prepareCallee(isel);
22142368 try isel.global_relocs.append(gpa, .{
2215 .global = switch (air_tag) {
2369 .name = switch (air_tag) {
22162370 else => unreachable,
22172371 .max => switch (bits) {
22182372 else => unreachable,
......@@ -2284,7 +2438,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
22842438 else => unreachable,
22852439 .add_with_overflow => .add,
22862440 .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 });
22882444 }
22892445 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
22902446 },
......@@ -3092,7 +3248,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
30923248
30933249 try call.prepareCallee(isel);
30943250 try isel.global_relocs.append(gpa, .{
3095 .global = "memcpy",
3251 .name = "memcpy",
30963252 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
30973253 });
30983254 try isel.emit(.bl(0));
......@@ -3119,7 +3275,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
31193275
31203276 try call.prepareCallee(isel);
31213277 try isel.global_relocs.append(gpa, .{
3122 .global = "memcpy",
3278 .name = "memcpy",
31233279 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
31243280 });
31253281 try isel.emit(.bl(0));
......@@ -3139,19 +3295,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
31393295 .block => {
31403296 const ty_pl = air.data(air.inst_index).ty_pl;
31413297 const extra = isel.air.extraData(Air.Block, ty_pl.payload);
3142
3143 if (ty_pl.ty != .noreturn_type) {
3144 isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{
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 }
3298 try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast(
3299 isel.air.extra.items[extra.end..][0..extra.data.body_len],
3300 ));
31553301 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
31563302 },
31573303 .loop => {
......@@ -3175,11 +3321,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
31753321 }
31763322
31773323 // IT'S DOM TIME!!!
3178 for (isel.blocks.values(), 0..) |*block, dom_index| {
3324 for (isel.blocks.values(), 0..) |*dom_block, dom_index| {
31793325 if (@as(u1, @truncate(isel.dom.items[
31803326 loop.dom + dom_index / @bitSizeOf(DomInt)
31813327 ] >> @truncate(dom_index))) == 0) continue;
3182 var live_reg_it = block.live_registers.iterator();
3328 var live_reg_it = dom_block.live_registers.iterator();
31833329 while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
31843330 _ => |live_vi| try live_vi.mat(isel),
31853331 .allocating => unreachable,
......@@ -3211,8 +3357,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
32113357 },
32123358 .br => {
32133359 const br = air.data(air.inst_index).br;
3214 const block = isel.blocks.getPtr(br.block_inst).?;
3215 try block.branch(isel);
3360 try isel.blocks.getPtr(br.block_inst).?.branch(isel);
32163361 if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand);
32173362 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
32183363 },
......@@ -3224,6 +3369,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
32243369 try isel.emit(.brk(0xf000));
32253370 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
32263371 },
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 },
32273388 .call => {
32283389 const pl_op = air.data(air.inst_index).pl_op;
32293390 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 {
33123473 var param_part_it = passed_vi.parts(isel);
33133474 var arg_part_it = arg_vi.parts(isel);
33143475 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);
33163477 arg_vi.setParts(isel, param_part_it.remaining);
33173478 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
33183479 isel,
......@@ -3659,7 +3820,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
36593820
36603821 try call.prepareCallee(isel);
36613822 try isel.global_relocs.append(gpa, .{
3662 .global = switch (air_tag) {
3823 .name = switch (air_tag) {
36633824 else => unreachable,
36643825 .sqrt => switch (bits) {
36653826 else => unreachable,
......@@ -3751,7 +3912,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
37513912
37523913 try call.prepareCallee(isel);
37533914 try isel.global_relocs.append(gpa, .{
3754 .global = switch (air_tag) {
3915 .name = switch (air_tag) {
37553916 else => unreachable,
37563917 .sin => switch (bits) {
37573918 else => unreachable,
......@@ -4239,7 +4400,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
42394400
42404401 try call.prepareCallee(isel);
42414402 try isel.global_relocs.append(gpa, .{
4242 .global = switch (bits) {
4403 .name = switch (bits) {
42434404 else => unreachable,
42444405 16 => "__cmphf2",
42454406 32 => "__cmpsf2",
......@@ -4328,7 +4489,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
43284489 };
43294490 var cond_mat: ?Value.Materialize = null;
43304491 var cond_reg: Register = undefined;
4331 var temp_reg: Register = undefined;
43324492 var cases_it = switch_br.iterateCases();
43334493 while (cases_it.next()) |case| {
43344494 const next_label = isel.instructions.items.len;
......@@ -4342,11 +4502,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
43424502 if (cond_mat == null) {
43434503 var cond_vi = try isel.use(switch_br.operand);
43444504 cond_mat = try cond_vi.matReg(isel);
4345 const temp_ra = try isel.allocIntReg();
4346 cond_reg, temp_reg = switch (cond_int_info.bits) {
4505 cond_reg = switch (cond_int_info.bits) {
43474506 else => unreachable,
4348 1...32 => .{ cond_mat.?.ra.w(), temp_ra.w() },
4349 33...64 => .{ cond_mat.?.ra.x(), temp_ra.x() },
4507 1...32 => cond_mat.?.ra.w(),
4508 33...64 => cond_mat.?.ra.x(),
43504509 };
43514510 }
43524511 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 {
43874546 ) else high_bigint.toInt(i64) catch
43884547 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 };
43904559 const delta_int = high_int -% low_int;
4391 if (case_range_index > 0) {
4392 return isel.fail("case range", .{});
4393 } else if (case.items.len > 0) {
4394 return isel.fail("case range", .{});
4560 if (case_range_index | case.items.len > 0) {
4561 if (std.math.cast(u5, delta_int)) |pos_imm| try isel.emit(.ccmp(
4562 adjusted_reg,
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 }
43954587 } else {
4396 const adjusted_reg = switch (low_int) {
4397 0 => cond_reg,
4398 else => temp_reg,
4399 };
4400
44014588 if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs(
44024589 zero_reg,
44034590 adjusted_reg,
......@@ -4421,41 +4608,55 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
44214608 adjusted_reg,
44224609 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
44234610 )) else {
4424 try isel.movImmediate(temp_reg, @bitCast(delta_int));
4425 try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = temp_reg }));
4611 const imm_ra = try isel.allocIntReg();
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));
44264620 }
4621 }
44274622
4428 switch (low_int) {
4429 0 => {},
4430 else => {
4431 if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
4432 adjusted_reg,
4433 cond_reg,
4434 .{ .immediate = pos_imm },
4435 )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
4436 adjusted_reg,
4437 cond_reg,
4438 .{ .immediate = neg_imm },
4439 )) else if (if (@as(i12, @truncate(low_int)) == 0)
4440 std.math.cast(u12, low_int >> 12)
4441 else
4442 null) |pos_imm_lsr_12| try isel.emit(.sub(
4443 adjusted_reg,
4444 cond_reg,
4445 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4446 )) else if (if (@as(i12, @truncate(-low_int)) == 0)
4447 std.math.cast(u12, -low_int >> 12)
4448 else
4449 null) |neg_imm_lsr_12| try isel.emit(.add(
4450 adjusted_reg,
4451 cond_reg,
4452 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4453 )) else {
4454 try isel.movImmediate(temp_reg, @bitCast(low_int));
4455 try isel.emit(.subs(adjusted_reg, cond_reg, .{ .register = temp_reg }));
4456 }
4457 },
4458 }
4623 switch (low_int) {
4624 0 => {},
4625 else => {
4626 if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
4627 adjusted_reg,
4628 cond_reg,
4629 .{ .immediate = pos_imm },
4630 )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
4631 adjusted_reg,
4632 cond_reg,
4633 .{ .immediate = neg_imm },
4634 )) else if (if (@as(i12, @truncate(low_int)) == 0)
4635 std.math.cast(u12, low_int >> 12)
4636 else
4637 null) |pos_imm_lsr_12| try isel.emit(.sub(
4638 adjusted_reg,
4639 cond_reg,
4640 .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
4641 )) else if (if (@as(i12, @truncate(-low_int)) == 0)
4642 std.math.cast(u12, -low_int >> 12)
4643 else
4644 null) |neg_imm_lsr_12| try isel.emit(.add(
4645 adjusted_reg,
4646 cond_reg,
4647 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
4648 )) else {
4649 const imm_ra = try isel.allocIntReg();
4650 defer isel.freeReg(imm_ra);
4651 const imm_reg = switch (cond_int_info.bits) {
4652 else => unreachable,
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 },
44594660 }
44604661 }
44614662 var case_item_index = case.items.len;
......@@ -4483,13 +4684,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
44834684 .{ .n = false, .z = true, .c = false, .v = false },
44844685 .ne,
44854686 )) 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 };
44874694 try isel.emit(.ccmp(
44884695 cond_reg,
4489 .{ .register = temp_reg },
4696 .{ .register = imm_reg },
44904697 .{ .n = false, .z = true, .c = false, .v = false },
44914698 .ne,
44924699 ));
4700 try isel.movImmediate(imm_reg, @bitCast(item_int));
44934701 }
44944702 } else {
44954703 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 {
45154723 cond_reg,
45164724 .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
45174725 )) else {
4518 try isel.movImmediate(temp_reg, @bitCast(item_int));
4519 try isel.emit(.subs(zero_reg, cond_reg, .{ .register = temp_reg }));
4726 const imm_ra = try isel.allocIntReg();
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));
45204735 }
45214736 }
45224737 }
45234738 }
4524 if (cond_mat) |mat| {
4525 try mat.finish(isel);
4526 isel.freeReg(temp_reg.alias);
4527 }
4739 if (cond_mat) |mat| try mat.finish(isel);
45284740 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
45294741 },
45304742 .@"try", .try_cold => {
......@@ -4560,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
45604772 const error_set_part_vi = try error_set_part_it.only(isel);
45614773 const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
45624774 try isel.emit(.cbz(
4563 switch (error_set_part_vi.?.size(isel)) {
4564 else => unreachable,
4565 1...4 => error_set_part_mat.ra.w(),
4566 5...8 => error_set_part_mat.ra.x(),
4567 },
4775 error_set_part_mat.ra.w(),
45684776 @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
45694777 ));
45704778 try error_set_part_mat.finish(isel);
45714779
45724780 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
45734781 },
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 },
45744831 .dbg_stmt => {
45754832 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
45764833 },
......@@ -4578,6 +4835,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
45784835 try isel.emit(.nop());
45794836 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
45804837 },
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 },
45814846 .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => {
45824847 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
45834848 },
......@@ -4673,7 +4938,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
46734938
46744939 try call.prepareCallee(isel);
46754940 try isel.global_relocs.append(gpa, .{
4676 .global = "memcpy",
4941 .name = "memcpy",
46774942 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
46784943 });
46794944 try isel.emit(.bl(0));
......@@ -4765,10 +5030,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
47655030 const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
47665031 const ptr_info = ptr_ty.ptrInfo(zcu);
47675032 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)) {
4769 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4770 break :air_tag;
4771 };
5033 if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val))
5034 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
47725035
47735036 const src_vi = try isel.use(bin_op.rhs);
47745037 const size = src_vi.size(isel);
......@@ -4782,8 +5045,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
47825045 });
47835046 try ptr_mat.finish(isel);
47845047
4785 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4786 break :air_tag;
5048 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
47875049 },
47885050 else => {},
47895051 };
......@@ -4792,7 +5054,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
47925054
47935055 try call.prepareCallee(isel);
47945056 try isel.global_relocs.append(gpa, .{
4795 .global = "memcpy",
5057 .name = "memcpy",
47965058 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
47975059 });
47985060 try isel.emit(.bl(0));
......@@ -4855,7 +5117,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
48555117
48565118 try call.prepareCallee(isel);
48575119 try isel.global_relocs.append(gpa, .{
4858 .global = switch (dst_bits) {
5120 .name = switch (dst_bits) {
48595121 else => unreachable,
48605122 16 => switch (src_bits) {
48615123 else => unreachable,
......@@ -5009,6 +5271,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
50095271 }
50105272 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
50115273 },
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 },
50125376 .trunc => |air_tag| {
50135377 if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
50145378 defer dst_vi.value.deref(isel);
......@@ -5096,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
50965460 }
50975461 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
50985462 },
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 },
51075463 .optional_payload => {
51085464 if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
51095465 defer payload_vi.value.deref(isel);
......@@ -5122,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
51225478 }
51235479 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
51245480 },
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 },
51255512 .wrap_optional => {
51265513 if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
51275514 defer opt_vi.value.deref(isel);
......@@ -5161,21 +5548,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
51615548 }
51625549 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
51635550 },
5164 .unwrap_errunion_err => {
5165 if (isel.live_values.fetchRemove(air.inst_index)) |error_set_vi| {
5166 defer error_set_vi.value.deref(isel);
5167
5551 .unwrap_errunion_err => {
5552 if (isel.live_values.fetchRemove(air.inst_index)) |error_set_vi| {
5553 defer error_set_vi.value.deref(isel);
5554
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);
51685623 const ty_op = air.data(air.inst_index).ty_op;
5169 const error_union_ty = isel.air.typeOf(ty_op.operand, ip);
5170
5171 const error_union_vi = try isel.use(ty_op.operand);
5172 var error_set_part_it = error_union_vi.field(
5173 error_union_ty,
5174 codegen.errUnionErrorOffset(error_union_ty.errorUnionPayload(zcu), zcu),
5175 error_set_vi.value.size(isel),
5624 const payload_ty = ty_op.ty.toType().childType(zcu);
5625 const error_union_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
5626 const error_set_size = error_union_ty.errorUnionSet(zcu).abiSize(zcu);
5627 const error_union_ptr_vi = try isel.use(ty_op.operand);
5628 const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
5629 if (error_set_size > 0) try isel.storeReg(
5630 .zr,
5631 error_set_size,
5632 error_union_ptr_mat.ra,
5633 codegen.errUnionErrorOffset(payload_ty, zcu),
51765634 );
5177 const error_set_part_vi = try error_set_part_it.only(isel);
5178 try error_set_vi.value.copy(isel, ty_op.ty.toType(), error_set_part_vi.?);
5635 switch (codegen.errUnionPayloadOffset(payload_ty, zcu)) {
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 }
51795653 }
51805654 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
51815655 },
......@@ -5365,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
53655839 }
53665840 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
53675841 },
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 },
53685868 .slice => {
53695869 if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
53705870 defer slice_vi.value.deref(isel);
......@@ -5781,7 +6281,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
57816281
57826282 try call.prepareCallee(isel);
57836283 try isel.global_relocs.append(gpa, .{
5784 .global = switch (dst_int_info.bits) {
6284 .name = switch (dst_int_info.bits) {
57856285 else => unreachable,
57866286 1...32 => switch (dst_int_info.signedness) {
57876287 .signed => switch (src_bits) {
......@@ -5921,7 +6421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
59216421
59226422 try call.prepareCallee(isel);
59236423 try isel.global_relocs.append(gpa, .{
5924 .global = switch (src_int_info.bits) {
6424 .name = switch (src_int_info.bits) {
59256425 else => unreachable,
59266426 1...32 => switch (src_int_info.signedness) {
59276427 .signed => switch (dst_bits) {
......@@ -6004,14 +6504,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
60046504 }
60056505 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
60066506 },
6007 .memset => |air_tag| {
6507 .memset, .memset_safe => |air_tag| {
60086508 const bin_op = air.data(air.inst_index).bin_op;
60096509 const dst_ty = isel.air.typeOf(bin_op.lhs, ip);
60106510 const dst_info = dst_ty.ptrInfo(zcu);
60116511 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 };
60136518 if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|
60146519 break :fill_byte .{ .constant = fill_byte };
6520 }
60156521 switch (dst_ty.elemType2(zcu).abiSize(zcu)) {
60166522 0 => unreachable,
60176523 1 => break :fill_byte .{ .value = bin_op.rhs },
......@@ -6070,8 +6576,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
60706576 .c => unreachable,
60716577 }
60726578
6073 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
6074 break :air_tag;
6579 break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
60756580 },
60766581 else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }),
60776582 }
......@@ -6082,7 +6587,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
60826587
60836588 try call.prepareCallee(isel);
60846589 try isel.global_relocs.append(gpa, .{
6085 .global = "memset",
6590 .name = "memset",
60866591 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
60876592 });
60886593 try isel.emit(.bl(0));
......@@ -6128,7 +6633,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
61286633
61296634 try call.prepareCallee(isel);
61306635 try isel.global_relocs.append(gpa, .{
6131 .global = @tagName(air_tag),
6636 .name = @tagName(air_tag),
61326637 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
61336638 });
61346639 try isel.emit(.bl(0));
......@@ -6217,6 +6722,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
62176722
62186723 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
62196724 },
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 },
62206791 .aggregate_init => {
62216792 if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| {
62226793 defer agg_vi.value.deref(isel);
......@@ -6311,7 +6882,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
63116882
63126883 try call.prepareCallee(isel);
63136884 try isel.global_relocs.append(gpa, .{
6314 .global = "memcpy",
6885 .name = "memcpy",
63156886 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
63166887 });
63176888 try isel.emit(.bl(0));
......@@ -6427,7 +6998,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
64276998
64286999 try call.prepareCallee(isel);
64297000 try isel.global_relocs.append(gpa, .{
6430 .global = switch (bits) {
7001 .name = switch (bits) {
64317002 else => unreachable,
64327003 16 => "__fmah",
64337004 32 => "fmaf",
......@@ -6508,6 +7079,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
65087079 }
65097080 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
65107081 },
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 },
65117108 .runtime_nav_ptr => {
65127109 if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {
65137110 defer ptr_vi.value.deref(isel);
......@@ -6516,19 +7113,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
65167113 const ty_nav = air.data(air.inst_index).ty_nav;
65177114 if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {
65187115 false => {
6519 try isel.nav_relocs.append(zcu.gpa, .{
7116 try isel.nav_relocs.append(gpa, .{
65207117 .nav = ty_nav.nav,
65217118 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
65227119 });
65237120 try isel.emit(.adr(ptr_ra.x(), 0));
65247121 },
65257122 true => {
6526 try isel.nav_relocs.append(zcu.gpa, .{
7123 try isel.nav_relocs.append(gpa, .{
65277124 .nav = ty_nav.nav,
65287125 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
65297126 });
65307127 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, .{
65327129 .nav = ty_nav.nav,
65337130 .reloc = .{ .label = @intCast(isel.instructions.items.len) },
65347131 });
......@@ -6538,9 +7135,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
65387135 }
65397136 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
65407137 },
6541 .add_safe,
6542 .sub_safe,
6543 .mul_safe,
65447138 .inferred_alloc,
65457139 .inferred_alloc_comptime,
65467140 .int_from_float_safe,
......@@ -6642,8 +7236,8 @@ pub fn layout(
66427236 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
66437237
66447238 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
6645 const stack_size_low: u12 = @truncate(stack_size >> 0);
6646 const stack_size_high: u12 = @truncate(stack_size >> 12);
7239 const stack_size_lo: u12 = @truncate(stack_size >> 0);
7240 const stack_size_hi: u12 = @truncate(stack_size >> 12);
66477241
66487242 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
66497243 class: enum { integer, vector },
......@@ -6771,6 +7365,9 @@ pub fn layout(
67717365 saves_len += 1;
67727366 saves_size += 8;
67737367 deferred_gr = null;
7368 } else switch (@as(u1, @truncate(saved_gra_len))) {
7369 0 => {},
7370 1 => saves_size += 8,
67747371 }
67757372 save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;
67767373 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(
67937390 {
67947391 wip_mir_log.debug("{f}<prologue>:", .{nav.fqn.fmt(ip)});
67957392 var save_index: usize = 0;
6796 while (save_index < saves.len) {
6797 if (save_index + 2 <= saves.len and 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)
6799 {
6800 try isel.emit(.stp(
6801 saves[save_index + 0].register,
6802 saves[save_index + 1].register,
6803 switch (saves[save_index + 0].offset) {
6804 0 => .{ .pre_index = .{
6805 .base = .sp,
6806 .index = @intCast(-@as(i11, saves_size)),
6807 } },
6808 else => |offset| .{ .signed_offset = .{
6809 .base = .sp,
6810 .offset = @intCast(offset),
6811 } },
6812 },
6813 ));
6814 save_index += 2;
6815 } else {
6816 try isel.emit(.str(
6817 saves[save_index].register,
6818 switch (saves[save_index].offset) {
6819 0 => .{ .pre_index = .{
6820 .base = .sp,
6821 .index = @intCast(-@as(i11, saves_size)),
6822 } },
6823 else => |offset| .{ .unsigned_offset = .{
6824 .base = .sp,
6825 .offset = @intCast(offset),
6826 } },
6827 },
6828 ));
6829 save_index += 1;
6830 }
6831 }
7393 while (save_index < saves.len) if (save_index + 2 <= saves.len and
7394 saves[save_index + 0].class == saves[save_index + 1].class and
7395 saves[save_index + 0].size == saves[save_index + 1].size and
7396 saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
7397 {
7398 try isel.emit(.stp(
7399 saves[save_index + 0].register,
7400 saves[save_index + 1].register,
7401 switch (saves[save_index + 0].offset) {
7402 0 => .{ .pre_index = .{
7403 .base = .sp,
7404 .index = @intCast(-@as(i11, saves_size)),
7405 } },
7406 else => |offset| .{ .signed_offset = .{
7407 .base = .sp,
7408 .offset = @intCast(offset),
7409 } },
7410 },
7411 ));
7412 save_index += 2;
7413 } else {
7414 try isel.emit(.str(
7415 saves[save_index].register,
7416 switch (saves[save_index].offset) {
7417 0 => .{ .pre_index = .{
7418 .base = .sp,
7419 .index = @intCast(-@as(i11, saves_size)),
7420 } },
7421 else => |offset| .{ .unsigned_offset = .{
7422 .base = .sp,
7423 .offset = @intCast(offset),
7424 } },
7425 },
7426 ));
7427 save_index += 1;
7428 };
68327429
7430 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
68337431 const scratch_reg: Register = if (isel.stack_align == .@"16")
68347432 .sp
6835 else if (stack_size == 0)
7433 else if (stack_size == 0 and frame_record_offset == 0)
68367434 .fp
68377435 else
6838 .x9;
6839 try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
6840 if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{
6841 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
6842 }));
6843 if (stack_size_low > 0) try isel.emit(.sub(
6844 scratch_reg,
6845 if (stack_size_high > 0) scratch_reg else .sp,
6846 .{ .immediate = stack_size_low },
6847 ));
6848 if (isel.stack_align != .@"16") {
6849 try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
6850 .N = .doubleword,
6851 .immr = -%isel.stack_align.toLog2Units(),
6852 .imms = ~isel.stack_align.toLog2Units(),
6853 } }));
7436 .ip0;
7437 if (mod.stack_check) {
7438 if (stack_size_hi > 2) {
7439 try isel.movImmediate(.ip1, stack_size_hi);
7440 const loop_label = isel.instructions.items.len;
7441 try isel.emit(.sub(.sp, .sp, .{
7442 .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
7443 }));
7444 try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
7445 try isel.emit(.ldr(.xzr, .{ .base = .sp }));
7446 try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
7447 (isel.instructions.items.len - loop_label) << 2,
7448 ))));
7449 } else for (0..stack_size_hi) |_| {
7450 try isel.emit(.sub(.sp, .sp, .{
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 }));
68547471 }
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 } }));
68557477 wip_mir_log.debug("", .{});
68567478 }
68577479
......@@ -6896,17 +7518,17 @@ pub fn layout(
68967518 save_index += 1;
68977519 } else save_index += 1;
68987520 }
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)) {
69007522 try isel.emit(switch (frame_record_offset) {
69017523 0 => .add(.sp, .fp, .{ .immediate = 0 }),
69027524 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
69037525 });
69047526 } else {
6905 if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{
6906 .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
7527 if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
7528 .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
69077529 }));
6908 if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{
6909 .immediate = stack_size_low,
7530 if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
7531 .immediate = stack_size_lo,
69107532 }));
69117533 }
69127534 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
69777599 return constant.fmtValue(isel.pt);
69787600}
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
69807622fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void {
69817623 wip_mir_log.debug(" | {f}", .{instruction});
69827624 try isel.instructions.append(isel.pt.zcu.gpa, instruction);
69837625}
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
69857639fn emitLiteral(isel: *Select, bytes: []const u8) !void {
69867640 const words: []align(1) const u32 = @ptrCast(bytes);
69877641 const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len);
......@@ -8028,6 +8682,32 @@ pub const Value = struct {
80288682 }
80298683 }
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 };
80318711 fn addOrSubtract(
80328712 res_vi: Value.Index,
80338713 isel: *Select,
......@@ -8035,19 +8715,21 @@ pub const Value = struct {
80358715 lhs_vi: Value.Index,
80368716 op: codegen.aarch64.encoding.Instruction.AddSubtractOp,
80378717 rhs_vi: Value.Index,
8038 opts: struct {
8039 wrap: bool,
8040 overflow_ra: Register.Alias = .zr,
8041 },
8718 opts: AddOrSubtractOptions,
80428719 ) !void {
8043 assert(opts.wrap or opts.overflow_ra == .zr);
80448720 const zcu = isel.pt.zcu;
80458721 if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
80468722 const int_info = ty.intInfo(zcu);
80478723 if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
80488724 var part_offset = res_vi.size(isel);
8049 var need_wrap = opts.wrap;
8050 var need_carry = opts.overflow_ra != .zr;
8725 var need_wrap = switch (opts.overflow) {
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 };
80518733 while (part_offset > 0) : (need_wrap = false) {
80528734 const part_size = @min(part_offset, 8);
80538735 part_offset -= part_size;
......@@ -8057,48 +8739,87 @@ pub const Value = struct {
80578739 const unwrapped_res_part_ra = unwrapped_res_part_ra: {
80588740 if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra;
80598741 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) {
80618743 .signed => .vs,
80628744 .unsigned => switch (op) {
80638745 .add => .cs,
80648746 .sub => .cc,
80658747 },
8066 })));
8748 });
80678749 break :unwrapped_res_part_ra wrapped_res_part_ra;
80688750 }
8069 const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: {
8070 switch (op) {
8071 .add => {},
8072 .sub => switch (int_info.signedness) {
8073 .signed => {},
8074 .unsigned => {
8075 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc)));
8076 break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra };
8077 },
8751 need_carry = false;
8752 const wrapped_part_ra, const unwrapped_part_ra = part_ra: switch (opts.overflow) {
8753 .@"unreachable" => unreachable,
8754 .panic, .ra => switch (int_info.signedness) {
8755 .signed => {
8756 try opts.overflow.defCond(isel, .ne);
8757 const wrapped_part_ra = switch (wrapped_res_part_ra) {
8758 else => |res_part_ra| res_part_ra,
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 };
80788777 },
8079 }
8080 try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne)));
8081 const wrapped_part_ra = switch (wrapped_res_part_ra) {
8082 else => |res_part_ra| res_part_ra,
8083 .zr => try isel.allocIntReg(),
8084 };
8085 errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
8086 const unwrapped_part_ra = unwrapped_part_ra: {
8087 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
8088 else => |res_part_ra| isel.lockReg(res_part_ra),
8089 .zr => .empty,
8090 };
8091 defer wrapped_res_part_lock.unlock(isel);
8092 break :unwrapped_part_ra try isel.allocIntReg();
8093 };
8094 errdefer isel.freeReg(unwrapped_part_ra);
8095 switch (part_size) {
8096 else => unreachable,
8097 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),
8098 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),
8099 }
8100 break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };
8101 } else .{ wrapped_res_part_ra, wrapped_res_part_ra };
8778 .unsigned => {
8779 const unwrapped_part_ra = unwrapped_part_ra: {
8780 const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
8781 else => |res_part_ra| isel.lockReg(res_part_ra),
8782 .zr => .empty,
8783 };
8784 defer wrapped_res_part_lock.unlock(isel);
8785 break :unwrapped_part_ra try isel.allocIntReg();
8786 };
8787 errdefer isel.freeReg(unwrapped_part_ra);
8788 const bit: u6 = @truncate(int_info.bits);
8789 switch (opts.overflow) {
8790 .@"unreachable", .wrap => unreachable,
8791 .panic => |panic_id| {
8792 const skip_label = isel.instructions.items.len;
8793 try isel.emitPanic(panic_id);
8794 try isel.emit(.tbz(
8795 switch (bit) {
8796 0, 32 => unreachable,
8797 1...31 => unwrapped_part_ra.w(),
8798 33...63 => unwrapped_part_ra.x(),
8799 },
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 };
81028823 defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
81038824 errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra);
81048825 if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) {
......@@ -8574,41 +9295,15 @@ pub const Value = struct {
85749295 expected_live_registers: *const LiveRegisters,
85759296 ) !void {
85769297 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);
85789299 switch (parent_vi.parent(isel)) {
85799300 .unallocated => {},
8580 .stack_slot => |stack_slot| {
8581 const offset = stack_slot.offset + offset_from_parent;
8582 try isel.emit(switch (vi.size(isel)) {
8583 else => unreachable,
8584 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{
8585 .base = stack_slot.base.x(),
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 },
9301 .stack_slot => |stack_slot| if (stack_slot.base != Register.Alias.fp) try isel.storeReg(
9302 src_ra,
9303 vi.size(isel),
9304 stack_slot.base,
9305 @as(i65, stack_slot.offset) + offset_from_parent,
9306 ),
86129307 else => unreachable,
86139308 }
86149309 try vi.spillReg(isel, src_ra, 0, expected_live_registers);
......@@ -9027,8 +9722,14 @@ pub const Value = struct {
90279722 } },
90289723 },
90299724 .struct_type => {
9030 const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
90319725 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;
90329733 if (loaded_struct.field_types.len > Value.max_parts and
90339734 (std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
90349735 return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
......@@ -9136,6 +9837,77 @@ pub const Value = struct {
91369837 if (part.is_vector) subpart_vi.setIsVector(isel);
91379838 }
91389839 },
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 },
91399911 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
91409912 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
91419913 .error_set_type,
......@@ -9555,21 +10327,29 @@ pub const Value = struct {
955510327 var base_ptr = ip.indexToKey(base).ptr;
955610328 const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child;
955710329 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;
955910336 continue :constant_key .{ .ptr = base_ptr };
956010337 },
9561 .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr },
956210338 .field => |field| {
956310339 var base_ptr = ip.indexToKey(field.base).ptr;
956410340 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;
956610342 continue :constant_key .{ .ptr = base_ptr };
956710343 },
956810344 .comptime_alloc, .comptime_field, .arr_elem => unreachable,
956910345 };
957010346 },
957110347 .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 },
957310353 else => {
957410354 assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
957510355 offset = 0;
......@@ -10622,16 +11402,14 @@ pub const CallAbiIterator = struct {
1062211402 {
1062311403 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
1062411404 const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
10625 const size = error_set_ty.abiSize(zcu);
10626 const end = offset % 8 + size;
11405 const end = offset % 8 + error_set_ty.abiSize(zcu);
1062711406 const part_index: usize = @intCast(offset / 8);
1062811407 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
1062911408 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
1063011409 }
1063111410 {
1063211411 const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
10633 const size = payload_ty.abiSize(zcu);
10634 const end = offset % 8 + size;
11412 const end = offset % 8 + payload_ty.abiSize(zcu);
1063511413 const part_index: usize = @intCast(offset / 8);
1063611414 sizes[part_index] = @max(sizes[part_index], @min(end, 8));
1063711415 if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
......@@ -10675,8 +11453,14 @@ pub const CallAbiIterator = struct {
1067511453 => unreachable,
1067611454 },
1067711455 .struct_type => {
10678 const size = wip_vi.size(isel);
1067911456 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);
1068011464 if (size <= 16 * 4) homogeneous_aggregate: {
1068111465 const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
1068211466 const parts_len = @shrExact(size, fdt.log2Size());
......@@ -10761,6 +11545,40 @@ pub const CallAbiIterator = struct {
1076111545 else => it.indirect(isel, wip_vi),
1076211546 }
1076311547 },
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 },
1076411582 .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
1076511583 .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
1076611584 .error_set_type,
src/codegen/aarch64/encoding.zig+2
......@@ -151,6 +151,7 @@ pub const Register = struct {
151151 pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
152152 pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
153153
154 pub const ip = x16;
154155 pub const ip0 = x16;
155156 pub const ip1 = x17;
156157 pub const fp = x29;
......@@ -774,6 +775,7 @@ pub const Register = struct {
774775
775776 ffr,
776777
778 pub const ip: Alias = .r16;
777779 pub const ip0: Alias = .r16;
778780 pub const ip1: Alias = .r17;
779781 pub const fp: Alias = .r29;
src/codegen/aarch64/instructions.zon+190
......@@ -213,6 +213,63 @@
213213 },
214214 .encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
215215 },
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 },
216273 // C6.2.35 BLR
217274 .{
218275 .pattern = "BLR <Xn>",
......@@ -681,6 +738,82 @@
681738 },
682739 .encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
683740 },
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 },
684817 // C6.2.220 MOV (to/from SP)
685818 .{
686819 .pattern = "MOV WSP, <Wn|WSP>",
......@@ -964,6 +1097,63 @@
9641097 },
9651098 .encode = .{ .ret, .Xn },
9661099 },
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 },
9671157 // C6.2.268 SBFM
9681158 .{
9691159 .pattern = "SBFM <Wd>, <Wn>, #<immr>, #<imms>",
src/target.zig+11-5
......@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
248248 return false;
249249}
250250
251pub fn supportsStackProbing(target: *const std.Target) bool {
252 return target.os.tag != .windows and target.os.tag != .uefi and
253 (target.cpu.arch == .x86 or target.cpu.arch == .x86_64);
251pub fn supportsStackProbing(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
252 return switch (backend) {
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 };
254258}
255259
256260pub 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
347351 }
348352}
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 {
351355 switch (target.os.tag) {
352356 .plan9 => return false,
353357 else => {},
......@@ -369,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime
369373 };
370374}
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 {
373377 switch (target.cpu.arch) {
374378 .spirv32, .spirv64 => return false,
375379 // 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
378382 }
379383 return switch (zigBackend(target, use_llvm)) {
380384 .stage2_llvm => true,
385 .stage2_wasm => false,
381386 .stage2_x86_64 => switch (target.ofmt) {
382387 .elf, .macho => true,
383388 else => have_llvm,
......@@ -856,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile
856861pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool {
857862 return switch (feature) {
858863 .panic_fn => switch (backend) {
864 .stage2_aarch64,
859865 .stage2_c,
860866 .stage2_llvm,
861867 .stage2_x86_64,
test/behavior/decl_literals.zig-2
......@@ -33,7 +33,6 @@ test "decl literal with pointer" {
3333}
3434
3535test "call decl literal with optional" {
36 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3736 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
3837 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3938 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -74,7 +73,6 @@ test "call decl literal" {
7473}
7574
7675test "call decl literal with error union" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7876 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
7977
8078 const S = struct {
test/behavior/error.zig-4
......@@ -590,7 +590,6 @@ test "error union comptime caching" {
590590}
591591
592592test "@errorName" {
593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
594593 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
595594 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
596595 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -605,7 +604,6 @@ fn gimmeItBroke() anyerror {
605604}
606605
607606test "@errorName sentinel length matches slice length" {
608 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
609607 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
610608 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
611609 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -883,7 +881,6 @@ test "catch within a function that calls no errorable functions" {
883881}
884882
885883test "error from comptime string" {
886 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
887884 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
888885 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
889886 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -946,7 +943,6 @@ test "optional error set function parameter" {
946943}
947944
948945test "returning an error union containing a type with no runtime bits" {
949 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
950946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
951947 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" {
587587}
588588
589589test "@fieldParentPtr unaligned packed struct" {
590 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
591590 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
592591 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
593592 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {
726725}
727726
728727test "@fieldParentPtr aligned packed struct" {
729 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
730728 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
731729 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
732730 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/inline_switch.zig-2
......@@ -43,7 +43,6 @@ test "inline switch enums" {
4343
4444const U = union(E) { a: void, b: u2, c: u3, d: u4 };
4545test "inline switch unions" {
46 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
4746 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
4847 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
4948
......@@ -105,7 +104,6 @@ test "inline else enum" {
105104}
106105
107106test "inline else int with gaps" {
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109107 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
110108 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" {
319319}
320320
321321test "coerce an anon struct literal to optional struct" {
322 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
323322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
324323 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
325324 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {
447446}
448447
449448test "optional pointer to zero bit error union payload" {
450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
451449 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
452450 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
453451 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/return_address.zig-1
......@@ -6,7 +6,6 @@ fn retAddr() usize {
66}
77
88test "return address" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1211 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" {
797797}
798798
799799test "non-packed struct with u128 entry in union" {
800 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
801800 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
802801 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
803802 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {
10261025}
10271026
10281027test "for loop over pointers to struct, getting field from struct pointer" {
1029 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10301028 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
10311029 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10321030 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {
10931091}
10941092
10951093test "anon init through optional" {
1096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10971094 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10981095 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
10991096 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1113,7 +1110,6 @@ test "anon init through optional" {
11131110}
11141111
11151112test "anon init through error union" {
1116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11171113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11181114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11191115 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -1398,7 +1394,6 @@ test "struct has only one reference" {
13981394}
13991395
14001396test "no dependency loop on pointer to optional struct" {
1401 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14021397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14031398 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
14041399
test/behavior/switch.zig-5
......@@ -8,7 +8,6 @@ const minInt = std.math.minInt;
88const maxInt = std.math.maxInt;
99
1010test "switch with numbers" {
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1211 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1312 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1413
......@@ -300,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
300299}
301300
302301test "switch on enum using pointer capture" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
305303 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306304
......@@ -361,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
361359}
362360
363361test "switch on union with some prongs capturing" {
364 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
365362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
366363 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
367364
......@@ -976,8 +973,6 @@ test "switch prong captures range" {
976973}
977974
978975test "prong with inline call to unreachable" {
979 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
980
981976 const U = union(enum) {
982977 void: void,
983978 bool: bool,
test/behavior/switch_on_captured_error.zig-1
......@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
66const builtin = @import("builtin");
77
88test "switch on error union catch capture" {
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
1110 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" {
160160}
161161
162162test "constant tagged union with payload" {
163 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
164163 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
165164 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
166165
......@@ -263,7 +262,6 @@ fn testComparison() !void {
263262}
264263
265264test "comparison between union and enum literal" {
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
268266 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
269267 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {
279277 C: i32,
280278};
281279test "cast union to tag type of union" {
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283280 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
284281 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
285282
......@@ -300,7 +297,6 @@ test "union field access gives the enum values" {
300297}
301298
302299test "cast tag type of union to union" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304300 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305301 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
306302
......@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {
316312};
317313
318314test "implicit cast union to its tag type" {
319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
320315 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
321316 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
322317
......@@ -495,7 +490,6 @@ test "initialize global array of union" {
495490}
496491
497492test "update the tag value for zero-sized unions" {
498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
499493 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
500494 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
734728}
735729
736730test "@intFromEnum works on unions" {
737 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
738731 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739732 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
740733
......@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {
848841}
849842
850843test "@unionInit can modify a union type" {
851 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852844 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
853845 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
854846
......@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {
871863}
872864
873865test "@unionInit can modify a pointer value" {
874 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
875866 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
876867 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" {
990981}
991982
992983test "switching on non exhaustive union" {
993 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
994984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
995985 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
996986
......@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {
11761166}
11771167
11781168test "union tag is set when initiated as a temporary value at runtime" {
1179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11801169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11811170 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11821171 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {
12161205}
12171206
12181207test "return an extern union from C calling convention" {
1219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12201208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12211209 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12221210 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
......@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {
12481236}
12491237
12501238test "noreturn field in union" {
1251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12521239 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12531240 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12541241
......@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {
14811468}
14821469
14831470test "access the tag of a global tagged union" {
1484 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1485
14861471 const U = union(enum) {
14871472 a,
14881473 b: u8,
......@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {
21112096}
21122097
21132098test "copied union field doesn't alias source" {
2114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
21152099 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
21162100 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
21172101 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -2334,8 +2318,6 @@ test "assign global tagged union" {
23342318}
23352319
23362320test "set mutable union by switching on same union" {
2337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2338
23392321 const U = union(enum) {
23402322 foo,
23412323 bar: usize,
test/behavior/union_with_members.zig-1
......@@ -17,7 +17,6 @@ const ET = union(enum) {
1717};
1818
1919test "enum with members" {
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
2322 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/while.zig-1
......@@ -344,7 +344,6 @@ test "else continue outer while" {
344344}
345345
346346test "try terminating an infinite loop" {
347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
348347 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
349348 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 {
1919
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux,aarch64-linux
test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig+2-2
......@@ -7,5 +7,5 @@ export fn entry3() callconv(.avr_interrupt) void {}
77// target=aarch64-linux-none
88//
99// :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'
11// :1:30: error: calling convention 'avr_interrupt' only available on architectures 'avr'
10// :2:30: error: calling convention 'x86_interrupt' only available on architectures 'x86'
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 {
2525
2626// error
2727// backend=stage2
28// target=native
28// target=x86_64-linux
2929//
3030// :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set'
3131// :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 {
1010
1111// error
1212// backend=stage2
13// target=native
13// target=x86_64-linux
1414//
1515// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void'
1616// :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 {
1515
1616// error
1717// backend=stage2
18// target=native
18// target=x86_64-linux
1919//
2020// :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 {
66
77// error
88// backend=stage2
9// target=native
9// target=x86_64-linux
1010//
1111// :2:23: error: expected error union type, found 'bool'
test/cases/pic_freestanding.zig+1-1
......@@ -1,7 +1,7 @@
11const builtin = @import("builtin");
22const std = @import("std");
33
4fn _start() callconv(.naked) void {}
4pub fn _start() callconv(.naked) void {}
55
66comptime {
77 @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 {
2222}
2323// run
2424// backend=stage2,llvm
25// target=native
25// target=x86_64-linux,aarch64-linux
test/cases/safety/@enumFromInt - no matching tag value.zig +1-1
......@@ -23,4 +23,4 @@ fn baz(_: Foo) void {}
2323
2424// run
2525// backend=stage2,llvm
26// target=native
26// target=x86_64-linux
test/cases/safety/@enumFromInt truncated bits - exhaustive.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() u8 {
2020
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux
test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() u8 {
2020
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux
test/cases/safety/@errorCast error not present in destination.zig +1-1
......@@ -18,4 +18,4 @@ fn foo(set1: Set1) Set2 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/@errorCast error union casted to disjoint set.zig +1-1
......@@ -17,4 +17,4 @@ fn foo() anyerror!i32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/@intCast to u0.zig +1-1
......@@ -19,4 +19,4 @@ fn bar(one: u1, not_zero: i32) void {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux,aarch64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux,aarch64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux,aarch64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux,aarch64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux,aarch64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - negative out of range.zig +1-1
......@@ -17,4 +17,4 @@ fn bar(a: f32) i8 {
1717fn baz(_: i8) void {}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig +1-1
......@@ -17,4 +17,4 @@ fn bar(a: f32) u8 {
1717fn baz(_: u8) void {}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/@intFromFloat cannot fit - positive out of range.zig +1-1
......@@ -17,4 +17,4 @@ fn bar(a: f32) u8 {
1717fn baz(_: u8) void {}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/@ptrFromInt with misaligned address.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/@tagName on corrupted enum value.zig +1-1
......@@ -23,4 +23,4 @@ pub fn main() !void {
2323
2424// run
2525// backend=stage2,llvm
26// target=native
26// target=x86_64-linux
test/cases/safety/@tagName on corrupted union value.zig +1-1
......@@ -24,4 +24,4 @@ pub fn main() !void {
2424
2525// run
2626// backend=stage2,llvm
27// target=native
27// target=x86_64-linux
test/cases/safety/array slice sentinel mismatch vector.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux
test/cases/safety/array slice sentinel mismatch.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/bad union field access.zig +1-1
......@@ -24,4 +24,4 @@ fn bar(f: *Foo) void {
2424}
2525// run
2626// backend=stage2,llvm
27// target=native
27// target=x86_64-linux
test/cases/safety/calling panic.zig +1-1
......@@ -13,4 +13,4 @@ pub fn main() !void {
1313}
1414// run
1515// backend=stage2,llvm
16// target=native
16// target=x86_64-linux,aarch64-linux
test/cases/safety/cast []u8 to bigger slice of wrong size.zig +1-1
......@@ -18,4 +18,4 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/cast integer to global error and no code matches.zig +1-1
......@@ -16,4 +16,4 @@ fn bar(x: u16) anyerror {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/empty slice with sentinel out of bounds.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/exact division failure - vectors.zig +1-1
......@@ -20,4 +20,4 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
2020}
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux
test/cases/safety/exact division failure.zig +1-1
......@@ -18,4 +18,4 @@ fn divExact(a: i32, b: i32) i32 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/for_len_mismatch.zig+1-1
......@@ -22,4 +22,4 @@ pub fn main() !void {
2222}
2323// run
2424// backend=stage2,llvm
25// target=native
25// target=x86_64-linux,aarch64-linux
test/cases/safety/for_len_mismatch_three.zig+1-1
......@@ -21,4 +21,4 @@ pub fn main() !void {
2121}
2222// run
2323// backend=stage2,llvm
24// target=native
24// target=x86_64-linux,aarch64-linux
test/cases/safety/ignored expression integer overflow.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/integer addition overflow.zig +1-1
......@@ -20,4 +20,4 @@ fn add(a: u16, b: u16) u16 {
2020
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux,aarch64-linux
test/cases/safety/integer division by zero - vectors.zig +1-1
......@@ -19,4 +19,4 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux
test/cases/safety/integer division by zero.zig +1-1
......@@ -17,4 +17,4 @@ fn div0(a: i32, b: i32) i32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/integer multiplication overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn mul(a: u16, b: u16) u16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/integer negation overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn neg(a: i16) i16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/integer subtraction overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn sub(a: u16, b: u16) u16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/memcpy_alias.zig+1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/memcpy_len_mismatch.zig+1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/memmove_len_mismatch.zig+1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/memset_array_undefined_bytes.zig+1-1
......@@ -15,4 +15,4 @@ pub fn main() !void {
1515}
1616// run
1717// backend=stage2,llvm
18// target=native
18// target=x86_64-linux,aarch64-linux
test/cases/safety/memset_array_undefined_large.zig+1-1
......@@ -15,4 +15,4 @@ pub fn main() !void {
1515}
1616// run
1717// backend=stage2,llvm
18// target=native
18// target=x86_64-linux,aarch64-linux
test/cases/safety/memset_slice_undefined_bytes.zig+1-1
......@@ -17,4 +17,4 @@ pub fn main() !void {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/memset_slice_undefined_large.zig+1-1
......@@ -17,4 +17,4 @@ pub fn main() !void {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/modrem by zero.zig +1-1
......@@ -17,4 +17,4 @@ fn div0(a: u32, b: u32) u32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/modulus by zero.zig +1-1
......@@ -17,4 +17,4 @@ fn mod0(a: i32, b: i32) i32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/noreturn returned.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() void {
2020}
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux,aarch64-linux
test/cases/safety/optional unwrap operator on C pointer.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/optional unwrap operator on null pointer.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/optional_empty_error_set.zig+1-1
......@@ -19,4 +19,4 @@ fn foo() !void {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux,aarch64-linux
test/cases/safety/out of bounds array slice by length.zig +1-1
......@@ -17,4 +17,4 @@ fn foo(a: u32) u32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/out of bounds slice access.zig +1-1
......@@ -18,4 +18,4 @@ fn bar(a: []const i32) i32 {
1818fn baz(_: i32) void {}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/pointer casting null to non-optional pointer.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/pointer casting to null function pointer.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() !void {
2020
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux,aarch64-linux
test/cases/safety/pointer slice sentinel mismatch.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/remainder division by zero.zig +1-1
......@@ -17,4 +17,4 @@ fn rem0(a: i32, b: i32) i32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/shift left by huge amount.zig +1-1
......@@ -19,4 +19,4 @@ pub fn main() !void {
1919
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux,aarch64-linux
test/cases/safety/shift right by huge amount.zig +1-1
......@@ -19,4 +19,4 @@ pub fn main() !void {
1919
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux,aarch64-linux
test/cases/safety/signed integer division overflow - vectors.zig +1-1
......@@ -20,4 +20,4 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
2020}
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux
test/cases/safety/signed integer division overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn div(a: i16, b: i16) i16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig +1-1
......@@ -17,4 +17,4 @@ fn unsigned_cast(x: i32) u32 {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/signed shift left overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn shl(a: i16, b: u4) i16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/signed shift right overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn shr(a: i16, b: u4) i16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/signed-unsigned vector cast.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/slice by length sentinel mismatch on lhs.zig +1-1
......@@ -15,4 +15,4 @@ pub fn main() !void {
1515}
1616// run
1717// backend=stage2,llvm
18// target=native
18// target=x86_64-linux,aarch64-linux
test/cases/safety/slice by length sentinel mismatch on rhs.zig +1-1
......@@ -15,4 +15,4 @@ pub fn main() !void {
1515}
1616// run
1717// backend=stage2,llvm
18// target=native
18// target=x86_64-linux,aarch64-linux
test/cases/safety/slice sentinel mismatch - floats.zig +1-1
......@@ -17,4 +17,4 @@ pub fn main() !void {
1717
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux
test/cases/safety/slice sentinel mismatch - optional pointers.zig +1-1
......@@ -17,4 +17,4 @@ pub fn main() !void {
1717
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/slice slice sentinel mismatch.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/slice start index greater than end index.zig +1-1
......@@ -21,4 +21,4 @@ pub fn main() !void {
2121
2222// run
2323// backend=stage2,llvm
24// target=native
24// target=x86_64-linux,aarch64-linux
test/cases/safety/slice with sentinel out of bounds - runtime len.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() !void {
2020
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux,aarch64-linux
test/cases/safety/slice with sentinel out of bounds.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/slice_cast_change_len_0.zig+1-1
......@@ -24,4 +24,4 @@ const std = @import("std");
2424
2525// run
2626// backend=stage2,llvm
27// target=x86_64-linux
27// target=x86_64-linux,aarch64-linux
test/cases/safety/slice_cast_change_len_1.zig+1-1
......@@ -24,4 +24,4 @@ const std = @import("std");
2424
2525// run
2626// backend=stage2,llvm
27// target=x86_64-linux
27// target=x86_64-linux,aarch64-linux
test/cases/safety/slice_cast_change_len_2.zig+1-1
......@@ -24,4 +24,4 @@ const std = @import("std");
2424
2525// run
2626// backend=stage2,llvm
27// target=x86_64-linux
27// target=x86_64-linux,aarch64-linux
test/cases/safety/slicing null C pointer - runtime len.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/slicing null C pointer.zig +1-1
......@@ -17,4 +17,4 @@ pub fn main() !void {
1717}
1818// run
1919// backend=stage2,llvm
20// target=native
20// target=x86_64-linux,aarch64-linux
test/cases/safety/switch else on corrupt enum value - one prong.zig +1-1
......@@ -21,4 +21,4 @@ pub fn main() !void {
2121}
2222// run
2323// backend=stage2,llvm
24// target=native
24// target=x86_64-linux
test/cases/safety/switch else on corrupt enum value - union.zig +1-1
......@@ -26,4 +26,4 @@ pub fn main() !void {
2626}
2727// run
2828// backend=stage2,llvm
29// target=native
29// target=x86_64-linux
test/cases/safety/switch else on corrupt enum value.zig +1-1
......@@ -20,4 +20,4 @@ pub fn main() !void {
2020}
2121// run
2222// backend=stage2,llvm
23// target=native
23// target=x86_64-linux
test/cases/safety/switch on corrupted enum value.zig +1-1
......@@ -24,4 +24,4 @@ pub fn main() !void {
2424
2525// run
2626// backend=stage2,llvm
27// target=native
27// target=x86_64-linux,aarch64-linux
test/cases/safety/switch on corrupted union value.zig +1-1
......@@ -24,4 +24,4 @@ pub fn main() !void {
2424
2525// run
2626// backend=stage2,llvm
27// target=native
27// target=x86_64-linux
test/cases/safety/truncating vector cast.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/unreachable.zig+1-1
......@@ -12,4 +12,4 @@ pub fn main() !void {
1212}
1313// run
1414// backend=stage2,llvm
15// target=native
15// target=x86_64-linux,aarch64-linux
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig +1-1
......@@ -16,4 +16,4 @@ pub fn main() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux
test/cases/safety/unsigned shift left overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn shl(a: u16, b: u4) u16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/unsigned shift right overflow.zig +1-1
......@@ -18,4 +18,4 @@ fn shr(a: u16, b: u4) u16 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/unsigned-signed vector cast.zig +1-1
......@@ -18,4 +18,4 @@ pub fn main() !void {
1818
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux
test/cases/safety/unwrap error switch.zig +1-1
......@@ -18,4 +18,4 @@ fn bar() !void {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/unwrap error.zig +1-1
......@@ -16,4 +16,4 @@ fn bar() !void {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/safety/value does not fit in shortening cast - u0.zig +1-1
......@@ -18,4 +18,4 @@ fn shorten_cast(x: u8) u0 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/value does not fit in shortening cast.zig +1-1
......@@ -18,4 +18,4 @@ fn shorten_cast(x: i32) i8 {
1818}
1919// run
2020// backend=stage2,llvm
21// target=native
21// target=x86_64-linux,aarch64-linux
test/cases/safety/vector integer addition overflow.zig +1-1
......@@ -19,4 +19,4 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux
test/cases/safety/vector integer multiplication overflow.zig +1-1
......@@ -19,4 +19,4 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux
test/cases/safety/vector integer negation overflow.zig +1-1
......@@ -19,4 +19,4 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux
test/cases/safety/vector integer subtraction overflow.zig +1-1
......@@ -19,4 +19,4 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
1919}
2020// run
2121// backend=stage2,llvm
22// target=native
22// target=x86_64-linux
test/cases/safety/zero casted to error.zig +1-1
......@@ -16,4 +16,4 @@ fn bar(x: u16) anyerror {
1616}
1717// run
1818// backend=stage2,llvm
19// target=native
19// target=x86_64-linux,aarch64-linux
test/cases/taking_pointer_of_global_tagged_union.zig+1-1
......@@ -23,4 +23,4 @@ pub fn main() !void {
2323
2424// run
2525// backend=stage2,llvm
26// target=native
26// target=x86_64-linux
test/src/Cases.zig+1-5
......@@ -436,7 +436,7 @@ fn addFromDirInner(
436436 const target = &resolved_target.result;
437437 for (backends) |backend| {
438438 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)
440440 {
441441 // Other backends don't support new liveness format
442442 continue;
......@@ -447,10 +447,6 @@ fn addFromDirInner(
447447 // Rosetta has issues with ZLD
448448 continue;
449449 }
450 if (backend == .stage2 and target.ofmt == .coff) {
451 // COFF linker has bitrotted
452 continue;
453 }
454450
455451 const next = ctx.cases.items.len;
456452 try ctx.cases.append(.{