authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-26 03:09:55-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-07-26 17:31:04-04:00
log69abc945e45af3f447f9ee07d426d1ec40cf3f15
tree457a9ee76f91135cf7a71192a09c317a63c05961
parent1274254c48ee105623c513dfc01451fee2912c5b

aarch64: implement some safety checks

Closes #24553

124 files changed, 1078 insertions(+), 365 deletions(-)

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