diff --git a/lib/compiler_rt.zig b/lib/compiler_rt.zig
index 17e9e04da7..b8723c56ee 100644
--- a/lib/compiler_rt.zig
+++ b/lib/compiler_rt.zig
@@ -240,7 +240,7 @@ comptime {
_ = @import("compiler_rt/udivmodti4.zig");
// extra
- if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/os_version_check.zig");
+ _ = @import("compiler_rt/os_version_check.zig");
_ = @import("compiler_rt/emutls.zig");
_ = @import("compiler_rt/arm.zig");
_ = @import("compiler_rt/aulldiv.zig");
diff --git a/src/Compilation.zig b/src/Compilation.zig
index 4ed2e8c0ca..3796ed6acc 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1816,10 +1816,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
if (options.skip_linker_dependencies) break :s .none;
const want = options.want_compiler_rt orelse is_exe_or_dyn_lib;
if (!want) break :s .none;
- if (have_zcu) {
+ if (have_zcu and target_util.canBuildLibCompilerRt(target, use_llvm, build_options.have_llvm and use_llvm)) {
if (output_mode == .Obj) break :s .zcu;
- if (target.ofmt == .coff and target_util.zigBackend(target, use_llvm) == .stage2_x86_64)
- break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
+ if (switch (target_util.zigBackend(target, use_llvm)) {
+ else => false,
+ .stage2_aarch64, .stage2_x86_64 => target.ofmt == .coff,
+ }) break :s if (is_exe_or_dyn_lib) .dyn_lib else .zcu;
}
if (is_exe_or_dyn_lib) break :s .lib;
break :s .obj;
@@ -1854,7 +1856,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
const want_ubsan_rt = options.want_ubsan_rt orelse (can_build_ubsan_rt and any_sanitize_c == .full and is_exe_or_dyn_lib);
if (!want_ubsan_rt) break :s .none;
if (options.skip_linker_dependencies) break :s .none;
- if (have_zcu) break :s .zcu;
+ if (have_zcu and target_util.canBuildLibUbsanRt(target, use_llvm, build_options.have_llvm and use_llvm)) break :s .zcu;
if (is_exe_or_dyn_lib) break :s .lib;
break :s .obj;
};
diff --git a/src/Package/Module.zig b/src/Package/Module.zig
index d829b397ba..1c941f51f4 100644
--- a/src/Package/Module.zig
+++ b/src/Package/Module.zig
@@ -250,7 +250,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
};
const stack_check = b: {
- if (!target_util.supportsStackProbing(target)) {
+ if (!target_util.supportsStackProbing(target, zig_backend)) {
if (options.inherited.stack_check == true)
return error.StackCheckUnsupportedByTarget;
break :b false;
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index d100070294..ad2d1b580f 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -168137,7 +168137,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.unused,
.unused,
},
- .dst_temps = .{ .{ .cc = .b }, .unused },
+ .dst_temps = .{ .{ .cc = .be }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
@@ -168161,7 +168161,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.unused,
.unused,
},
- .dst_temps = .{ .{ .cc = .b }, .unused },
+ .dst_temps = .{ .{ .cc = .be }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
@@ -168185,7 +168185,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
.unused,
.unused,
},
- .dst_temps = .{ .{ .cc = .b }, .unused },
+ .dst_temps = .{ .{ .cc = .be }, .unused },
.clobbers = .{ .eflags = true },
.each = .{ .once = &.{
.{ ._, ._, .lea, .tmp1p, .lea(.tmp0), ._, ._ },
diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig
index da15dc6bfb..49c67620d5 100644
--- a/src/arch/x86_64/Emit.zig
+++ b/src/arch/x86_64/Emit.zig
@@ -168,11 +168,12 @@ pub fn emitMir(emit: *Emit) Error!void {
else if (emit.bin_file.cast(.macho)) |macho_file|
macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, emit.pt, lazy_sym) catch |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
- else if (emit.bin_file.cast(.coff)) |coff_file| sym_index: {
- const atom = coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
- return emit.fail("{s} creating lazy symbol", .{@errorName(err)});
- break :sym_index coff_file.getAtom(atom).getSymbolIndex().?;
- } else if (emit.bin_file.cast(.plan9)) |p9_file|
+ else if (emit.bin_file.cast(.coff)) |coff_file|
+ if (coff_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym)) |atom|
+ coff_file.getAtom(atom).getSymbolIndex().?
+ else |err|
+ return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
+ else if (emit.bin_file.cast(.plan9)) |p9_file|
p9_file.getOrCreateAtomForLazySymbol(emit.pt, lazy_sym) catch |err|
return emit.fail("{s} creating lazy symbol", .{@errorName(err)})
else
diff --git a/src/codegen/aarch64.zig b/src/codegen/aarch64.zig
index f4b02a13c8..4cb3e8ecc8 100644
--- a/src/codegen/aarch64.zig
+++ b/src/codegen/aarch64.zig
@@ -47,6 +47,7 @@ pub fn generate(
.literals = .empty,
.nav_relocs = .empty,
.uav_relocs = .empty,
+ .lazy_relocs = .empty,
.global_relocs = .empty,
.literal_relocs = .empty,
@@ -101,8 +102,8 @@ pub fn generate(
};
switch (passed_vi.parent(&isel)) {
.unallocated => if (!mod.strip) {
- var part_it = arg_vi.parts(&isel);
- const first_passed_part_vi = part_it.next() orelse passed_vi;
+ var part_it = passed_vi.parts(&isel);
+ const first_passed_part_vi = part_it.next().?;
const hint_ra = first_passed_part_vi.hint(&isel).?;
passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector())
isel.va_list.__vr_top.withOffset(@as(i8, -16) *
@@ -167,6 +168,7 @@ pub fn generate(
.literals = &.{},
.nav_relocs = &.{},
.uav_relocs = &.{},
+ .lazy_relocs = &.{},
.global_relocs = &.{},
.literal_relocs = &.{},
};
@@ -174,6 +176,7 @@ pub fn generate(
mir.literals = try isel.literals.toOwnedSlice(gpa);
mir.nav_relocs = try isel.nav_relocs.toOwnedSlice(gpa);
mir.uav_relocs = try isel.uav_relocs.toOwnedSlice(gpa);
+ mir.lazy_relocs = try isel.lazy_relocs.toOwnedSlice(gpa);
mir.global_relocs = try isel.global_relocs.toOwnedSlice(gpa);
mir.literal_relocs = try isel.literal_relocs.toOwnedSlice(gpa);
return mir;
diff --git a/src/codegen/aarch64/Assemble.zig b/src/codegen/aarch64/Assemble.zig
index 080df667d7..494e012d80 100644
--- a/src/codegen/aarch64/Assemble.zig
+++ b/src/codegen/aarch64/Assemble.zig
@@ -6,14 +6,19 @@ pub const Operand = union(enum) {
};
pub fn nextInstruction(as: *Assemble) !?Instruction {
- @setEvalBranchQuota(37_000);
+ @setEvalBranchQuota(42_000);
comptime var ct_token_buf: [token_buf_len]u8 = undefined;
var token_buf: [token_buf_len]u8 = undefined;
const original_source = while (true) {
const original_source = as.source;
const source_token = try as.nextToken(&token_buf, .{});
- if (source_token.len == 0) return null;
- if (source_token[0] != '\n') break original_source;
+ switch (source_token.len) {
+ 0 => return null,
+ else => switch (source_token[0]) {
+ else => break original_source,
+ '\n', ';' => {},
+ },
+ }
};
log.debug(
\\.
@@ -52,7 +57,13 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
std.zig.fmtString(source_token),
});
if (pattern_token.len == 0) {
- if (source_token.len > 0 and source_token[0] != '\n') break :next_pattern;
+ switch (source_token.len) {
+ 0 => {},
+ else => switch (source_token[0]) {
+ else => break :next_pattern,
+ '\n', ';' => {},
+ },
+ }
const encode = @field(Instruction, @tagName(instruction.encode[0]));
const Encode = @TypeOf(encode);
var args: std.meta.ArgsTuple(Encode) = undefined;
@@ -65,7 +76,7 @@ pub fn nextInstruction(as: *Assemble) !?Instruction {
const symbol = &@field(symbols, symbol_name);
symbol.* = zonCast(SymbolSpec, @field(instruction.symbols, symbol_name), .{}).parse(source_token) orelse break :next_pattern;
log.debug("{s} = {any}", .{ symbol_name, symbol.* });
- } else if (!std.ascii.eqlIgnoreCase(pattern_token, source_token)) break :next_pattern;
+ } else if (!toUpperEqlAssertUpper(source_token, pattern_token)) break :next_pattern;
}
}
log.debug("'{s}' not matched...", .{instruction.pattern});
@@ -125,6 +136,15 @@ fn zonCast(comptime Result: type, zon_value: anytype, symbols: anytype) Result {
}
}
+fn toUpperEqlAssertUpper(lhs: []const u8, rhs: []const u8) bool {
+ if (lhs.len != rhs.len) return false;
+ for (lhs, rhs) |l, r| {
+ assert(!std.ascii.isLower(r));
+ if (std.ascii.toUpper(l) != r) return false;
+ }
+ return true;
+}
+
const token_buf_len = "v31.b[15]".len;
fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
operands: bool = false,
@@ -134,7 +154,7 @@ fn nextToken(as: *Assemble, buf: *[token_buf_len]u8, comptime opts: struct {
while (true) c: switch (as.source[0]) {
0 => return as.source[0..0],
'\t', '\n' + 1...'\r', ' ' => as.source = as.source[1..],
- '\n', '!', '#', ',', '[', ']' => {
+ '\n', '!', '#', ',', ';', '[', ']' => {
defer as.source = as.source[1..];
return as.source[0..1];
},
diff --git a/src/codegen/aarch64/Mir.zig b/src/codegen/aarch64/Mir.zig
index 1446238888..b6598b7ea7 100644
--- a/src/codegen/aarch64/Mir.zig
+++ b/src/codegen/aarch64/Mir.zig
@@ -4,6 +4,7 @@ epilogue: []const Instruction,
literals: []const u32,
nav_relocs: []const Reloc.Nav,
uav_relocs: []const Reloc.Uav,
+lazy_relocs: []const Reloc.Lazy,
global_relocs: []const Reloc.Global,
literal_relocs: []const Reloc.Literal,
@@ -21,8 +22,13 @@ pub const Reloc = struct {
reloc: Reloc,
};
+ pub const Lazy = struct {
+ symbol: link.File.LazySymbol,
+ reloc: Reloc,
+ };
+
pub const Global = struct {
- global: [*:0]const u8,
+ name: [*:0]const u8,
reloc: Reloc,
};
@@ -38,6 +44,7 @@ pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
gpa.free(mir.literals);
gpa.free(mir.nav_relocs);
gpa.free(mir.uav_relocs);
+ gpa.free(mir.lazy_relocs);
gpa.free(mir.global_relocs);
gpa.free(mir.literal_relocs);
mir.* = undefined;
@@ -119,16 +126,37 @@ pub fn emit(
body_end - Instruction.size * (1 + uav_reloc.reloc.label),
uav_reloc.reloc.addend,
);
+ for (mir.lazy_relocs) |lazy_reloc| try emitReloc(
+ lf,
+ zcu,
+ func.owner_nav,
+ if (lf.cast(.elf)) |ef|
+ ef.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(ef, pt, lazy_reloc.symbol) catch |err|
+ return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
+ else if (lf.cast(.macho)) |mf|
+ mf.getZigObject().?.getOrCreateMetadataForLazySymbol(mf, pt, lazy_reloc.symbol) catch |err|
+ return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
+ else if (lf.cast(.coff)) |cf|
+ if (cf.getOrCreateAtomForLazySymbol(pt, lazy_reloc.symbol)) |atom|
+ cf.getAtom(atom).getSymbolIndex().?
+ else |err|
+ return zcu.codegenFail(func.owner_nav, "{s} creating lazy symbol", .{@errorName(err)})
+ else
+ return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
+ mir.body[lazy_reloc.reloc.label],
+ body_end - Instruction.size * (1 + lazy_reloc.reloc.label),
+ lazy_reloc.reloc.addend,
+ );
for (mir.global_relocs) |global_reloc| try emitReloc(
lf,
zcu,
func.owner_nav,
if (lf.cast(.elf)) |ef|
- try ef.getGlobalSymbol(std.mem.span(global_reloc.global), null)
+ try ef.getGlobalSymbol(std.mem.span(global_reloc.name), null)
else if (lf.cast(.macho)) |mf|
- try mf.getGlobalSymbol(std.mem.span(global_reloc.global), null)
+ try mf.getGlobalSymbol(std.mem.span(global_reloc.name), null)
else if (lf.cast(.coff)) |cf|
- try cf.getGlobalSymbol(std.mem.span(global_reloc.global), "compiler_rt")
+ try cf.getGlobalSymbol(std.mem.span(global_reloc.name), "compiler_rt")
else
return zcu.codegenFail(func.owner_nav, "external symbols unimplemented for {s}", .{@tagName(lf.tag)}),
mir.body[global_reloc.reloc.label],
@@ -172,35 +200,6 @@ fn emitReloc(
const gpa = zcu.gpa;
switch (instruction.decode()) {
else => unreachable,
- .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| {
- const zo = ef.zigObjectPtr().?;
- const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
- const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) {
- .b => .JUMP26,
- .bl => .CALL26,
- };
- try atom.addReloc(gpa, .{
- .r_offset = offset,
- .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type),
- .r_addend = @bitCast(addend),
- }, zo);
- } else if (lf.cast(.macho)) |mf| {
- const zo = mf.getZigObject().?;
- const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?;
- try atom.addReloc(mf, .{
- .tag = .@"extern",
- .offset = offset,
- .target = sym_index,
- .addend = @bitCast(addend),
- .type = .branch,
- .meta = .{
- .pcrel = true,
- .has_subtractor = false,
- .length = 2,
- .symbolnum = @intCast(sym_index),
- },
- });
- },
.data_processing_immediate => |decoded| if (lf.cast(.elf)) |ef| {
const zo = ef.zigObjectPtr().?;
const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
@@ -259,6 +258,80 @@ fn emitReloc(
},
}
},
+ .branch_exception_generating_system => |decoded| if (lf.cast(.elf)) |ef| {
+ const zo = ef.zigObjectPtr().?;
+ const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
+ const r_type: std.elf.R_AARCH64 = switch (decoded.decode().unconditional_branch_immediate.group.op) {
+ .b => .JUMP26,
+ .bl => .CALL26,
+ };
+ try atom.addReloc(gpa, .{
+ .r_offset = offset,
+ .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type),
+ .r_addend = @bitCast(addend),
+ }, zo);
+ } else if (lf.cast(.macho)) |mf| {
+ const zo = mf.getZigObject().?;
+ const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?;
+ try atom.addReloc(mf, .{
+ .tag = .@"extern",
+ .offset = offset,
+ .target = sym_index,
+ .addend = @bitCast(addend),
+ .type = .branch,
+ .meta = .{
+ .pcrel = true,
+ .has_subtractor = false,
+ .length = 2,
+ .symbolnum = @intCast(sym_index),
+ },
+ });
+ },
+ .load_store => |decoded| if (lf.cast(.elf)) |ef| {
+ const zo = ef.zigObjectPtr().?;
+ const atom = zo.symbol(try zo.getOrCreateMetadataForNav(zcu, owner_nav)).atom(ef).?;
+ const r_type: std.elf.R_AARCH64 = switch (decoded.decode().register_unsigned_immediate.decode()) {
+ .integer => |integer| switch (integer.decode()) {
+ .unallocated, .prfm => unreachable,
+ .strb, .ldrb, .ldrsb => .LDST8_ABS_LO12_NC,
+ .strh, .ldrh, .ldrsh => .LDST16_ABS_LO12_NC,
+ .ldrsw => .LDST32_ABS_LO12_NC,
+ inline .str, .ldr => |encoded| switch (encoded.sf) {
+ .word => .LDST32_ABS_LO12_NC,
+ .doubleword => .LDST64_ABS_LO12_NC,
+ },
+ },
+ .vector => |vector| switch (vector.group.opc1.decode(vector.group.size)) {
+ .byte => .LDST8_ABS_LO12_NC,
+ .half => .LDST16_ABS_LO12_NC,
+ .single => .LDST32_ABS_LO12_NC,
+ .double => .LDST64_ABS_LO12_NC,
+ .quad => .LDST128_ABS_LO12_NC,
+ .scalable, .predicate => unreachable,
+ },
+ };
+ try atom.addReloc(gpa, .{
+ .r_offset = offset,
+ .r_info = @as(u64, sym_index) << 32 | @intFromEnum(r_type),
+ .r_addend = @bitCast(addend),
+ }, zo);
+ } else if (lf.cast(.macho)) |mf| {
+ const zo = mf.getZigObject().?;
+ const atom = zo.symbols.items[try zo.getOrCreateMetadataForNav(mf, owner_nav)].getAtom(mf).?;
+ try atom.addReloc(mf, .{
+ .tag = .@"extern",
+ .offset = offset,
+ .target = sym_index,
+ .addend = @bitCast(addend),
+ .type = .pageoff,
+ .meta = .{
+ .pcrel = false,
+ .has_subtractor = false,
+ .length = 2,
+ .symbolnum = @intCast(sym_index),
+ },
+ });
+ },
}
}
diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig
index f7da48d847..f84088624a 100644
--- a/src/codegen/aarch64/Select.zig
+++ b/src/codegen/aarch64/Select.zig
@@ -22,6 +22,7 @@ instructions: std.ArrayListUnmanaged(codegen.aarch64.encoding.Instruction),
literals: std.ArrayListUnmanaged(u32),
nav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Nav),
uav_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Uav),
+lazy_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Lazy),
global_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Global),
literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),
@@ -50,11 +51,11 @@ pub const Block = struct {
std.math.maxInt(@typeInfo(Air.Inst.Index).@"enum".tag_type),
);
- fn branch(block: *const Block, isel: *Select) !void {
- if (isel.instructions.items.len > block.target_label) {
- try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - block.target_label) << 2)));
+ fn branch(target_block: *const Block, isel: *Select) !void {
+ if (isel.instructions.items.len > target_block.target_label) {
+ try isel.emit(.b(@intCast((isel.instructions.items.len + 1 - target_block.target_label) << 2)));
}
- try isel.merge(&block.live_registers, .{});
+ try isel.merge(&target_block.live_registers, .{});
}
};
@@ -84,12 +85,12 @@ pub const Loop = struct {
pub const empty_list: u32 = std.math.maxInt(u32);
- fn branch(loop: *Loop, isel: *Select) !void {
+ fn branch(target_loop: *Loop, isel: *Select) !void {
try isel.instructions.ensureUnusedCapacity(isel.pt.zcu.gpa, 1);
- const repeat_list_tail = loop.repeat_list;
- loop.repeat_list = @intCast(isel.instructions.items.len);
+ const repeat_list_tail = target_loop.repeat_list;
+ target_loop.repeat_list = @intCast(isel.instructions.items.len);
isel.instructions.appendAssumeCapacity(@bitCast(repeat_list_tail));
- try isel.merge(&loop.live_registers, .{});
+ try isel.merge(&target_loop.live_registers, .{});
}
};
@@ -108,6 +109,7 @@ pub fn deinit(isel: *Select) void {
isel.literals.deinit(gpa);
isel.nav_relocs.deinit(gpa);
isel.uav_relocs.deinit(gpa);
+ isel.lazy_relocs.deinit(gpa);
isel.global_relocs.deinit(gpa);
isel.literal_relocs.deinit(gpa);
@@ -582,7 +584,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
air_body_index += 1;
},
- .@"try", .try_cold, .try_ptr, .try_ptr_cold => {
+ .@"try", .try_cold => {
const pl_op = air_data[@intFromEnum(air_inst_index)].pl_op;
const extra = isel.air.extraData(Air.Try, pl_op.payload);
@@ -594,6 +596,18 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
air_inst_index = air_body[air_body_index];
continue :air_tag air_tags[@intFromEnum(air_inst_index)];
},
+ .try_ptr, .try_ptr_cold => {
+ const ty_pl = air_data[@intFromEnum(air_inst_index)].ty_pl;
+ const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
+
+ try isel.analyzeUse(extra.data.ptr);
+ try isel.analyze(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
+ try isel.def_order.putNoClobber(gpa, air_inst_index, {});
+
+ air_body_index += 1;
+ air_inst_index = air_body[air_body_index];
+ continue :air_tag air_tags[@intFromEnum(air_inst_index)];
+ },
.ret, .ret_safe, .ret_load => {
const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
isel.returns = true;
@@ -864,7 +878,7 @@ pub fn finishAnalysis(isel: *Select) !void {
}
}
-pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
+pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, CodegenFail }!void {
const zcu = isel.pt.zcu;
const ip = &zcu.intern_pool;
const gpa = zcu.gpa;
@@ -946,7 +960,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .add, .add_optimized, .add_wrap, .sub, .sub_optimized, .sub_wrap => |air_tag| {
+ .add, .add_safe, .add_optimized, .add_wrap, .sub, .sub_safe, .sub_optimized, .sub_wrap => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
defer res_vi.value.deref(isel);
@@ -954,13 +968,16 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
const ty = isel.air.typeOf(bin_op.lhs, ip);
if (!ty.isRuntimeFloat()) try res_vi.value.addOrSubtract(isel, ty, try isel.use(bin_op.lhs), switch (air_tag) {
else => unreachable,
- .add, .add_wrap => .add,
- .sub, .sub_wrap => .sub,
- }, try isel.use(bin_op.rhs), .{ .wrap = switch (air_tag) {
- else => unreachable,
- .add, .sub => false,
- .add_wrap, .sub_wrap => true,
- } }) else switch (ty.floatBits(isel.target)) {
+ .add, .add_safe, .add_wrap => .add,
+ .sub, .sub_safe, .sub_wrap => .sub,
+ }, try isel.use(bin_op.rhs), .{
+ .overflow = switch (air_tag) {
+ else => unreachable,
+ .add, .sub => .@"unreachable",
+ .add_safe, .sub_safe => .{ .panic = .integer_overflow },
+ .add_wrap, .sub_wrap => .wrap,
+ },
+ }) else switch (ty.floatBits(isel.target)) {
else => unreachable,
16, 32, 64 => |bits| {
const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
@@ -1021,7 +1038,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (air_tag) {
+ .name = switch (air_tag) {
else => unreachable,
.add, .add_optimized => switch (bits) {
else => unreachable,
@@ -1336,7 +1353,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__mulhf3",
32 => "__mulsf3",
@@ -1379,6 +1396,143 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .mul_safe => |air_tag| {
+ if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
+ defer res_vi.value.deref(isel);
+
+ const bin_op = air.data(air.inst_index).bin_op;
+ const ty = isel.air.typeOf(bin_op.lhs, ip);
+ if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) });
+ const int_info = ty.intInfo(zcu);
+ switch (int_info.signedness) {
+ .signed => switch (int_info.bits) {
+ 0 => unreachable,
+ 1 => {
+ const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ try isel.emit(.orr(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(.integer_overflow);
+ try isel.emit(.@"b."(
+ .invert(.ne),
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ try isel.emit(.ands(.wzr, lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
+ },
+ .unsigned => switch (int_info.bits) {
+ 0 => unreachable,
+ 1 => {
+ const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ try isel.emit(.@"and"(res_ra.w(), lhs_mat.ra.w(), .{ .register = rhs_mat.ra.w() }));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ 2...16 => |bits| {
+ const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(.integer_overflow);
+ try isel.emit(.@"b."(
+ .eq,
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ try isel.emit(.ands(.wzr, res_ra.w(), .{ .immediate = .{
+ .N = .word,
+ .immr = @intCast(32 - bits),
+ .imms = @intCast(32 - bits - 1),
+ } }));
+ try isel.emit(.madd(res_ra.w(), lhs_mat.ra.w(), rhs_mat.ra.w(), .wzr));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ 17...32 => |bits| {
+ const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(.integer_overflow);
+ try isel.emit(.@"b."(
+ .eq,
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ try isel.emit(.ands(.xzr, res_ra.x(), .{ .immediate = .{
+ .N = .doubleword,
+ .immr = @intCast(64 - bits),
+ .imms = @intCast(64 - bits - 1),
+ } }));
+ try isel.emit(.umaddl(res_ra.x(), lhs_mat.ra.w(), rhs_mat.ra.w(), .xzr));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ 33...63 => |bits| {
+ const lo64_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ const hi64_ra = hi64_ra: {
+ const lo64_lock = isel.tryLockReg(lo64_ra);
+ defer lo64_lock.unlock(isel);
+ break :hi64_ra try isel.allocIntReg();
+ };
+ defer isel.freeReg(hi64_ra);
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(.integer_overflow);
+ try isel.emit(.cbz(
+ hi64_ra.x(),
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ try isel.emit(.orr(hi64_ra.x(), hi64_ra.x(), .{ .shifted_register = .{
+ .register = lo64_ra.x(),
+ .shift = .{ .lsr = @intCast(bits) },
+ } }));
+ try isel.emit(.madd(lo64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
+ try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ 64 => {
+ const res_ra = try res_vi.value.defReg(isel) orelse break :unused;
+ const lhs_vi = try isel.use(bin_op.lhs);
+ const rhs_vi = try isel.use(bin_op.rhs);
+ const lhs_mat = try lhs_vi.matReg(isel);
+ const rhs_mat = try rhs_vi.matReg(isel);
+ try isel.emit(.madd(res_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x(), .xzr));
+ const hi64_ra = try isel.allocIntReg();
+ defer isel.freeReg(hi64_ra);
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(.integer_overflow);
+ try isel.emit(.cbz(
+ hi64_ra.x(),
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ try isel.emit(.umulh(hi64_ra.x(), lhs_mat.ra.x(), rhs_mat.ra.x()));
+ try rhs_mat.finish(isel);
+ try lhs_mat.finish(isel);
+ },
+ 65...128 => return isel.fail("bad {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
+ else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(ty) }),
+ },
+ }
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.mul_sat => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |res_vi| unused: {
defer res_vi.value.deref(isel);
@@ -1674,7 +1828,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__divhf3",
32 => "__divsf3",
@@ -1813,7 +1967,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (int_info.signedness) {
+ .name = switch (int_info.signedness) {
.signed => "__divti3",
.unsigned => "__udivti3",
},
@@ -1917,7 +2071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
else => unreachable,
.div_trunc, .div_trunc_optimized => {
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__trunch",
32 => "truncf",
@@ -1931,7 +2085,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
},
.div_floor, .div_floor_optimized => {
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__floorh",
32 => "floorf",
@@ -1946,7 +2100,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
.div_exact, .div_exact_optimized => {},
}
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__divhf3",
32 => "__divsf3",
@@ -2046,7 +2200,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__fmodh",
32 => "fmodf",
@@ -2212,7 +2366,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (air_tag) {
+ .name = switch (air_tag) {
else => unreachable,
.max => switch (bits) {
else => unreachable,
@@ -2284,7 +2438,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
else => unreachable,
.add_with_overflow => .add,
.sub_with_overflow => .sub,
- }, rhs_vi, .{ .wrap = true, .overflow_ra = try overflow_vi.?.defReg(isel) orelse .zr });
+ }, rhs_vi, .{
+ .overflow = if (try overflow_vi.?.defReg(isel)) |overflow_ra| .{ .ra = overflow_ra } else .wrap,
+ });
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
@@ -3092,7 +3248,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memcpy",
+ .name = "memcpy",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -3119,7 +3275,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memcpy",
+ .name = "memcpy",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -3139,19 +3295,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
.block => {
const ty_pl = air.data(air.inst_index).ty_pl;
const extra = isel.air.extraData(Air.Block, ty_pl.payload);
-
- if (ty_pl.ty != .noreturn_type) {
- isel.blocks.putAssumeCapacityNoClobber(air.inst_index, .{
- .live_registers = isel.live_registers,
- .target_label = @intCast(isel.instructions.items.len),
- });
- }
- try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
- if (ty_pl.ty != .noreturn_type) {
- const block_entry = isel.blocks.pop().?;
- assert(block_entry.key == air.inst_index);
- if (isel.live_values.fetchRemove(air.inst_index)) |result_vi| result_vi.value.deref(isel);
- }
+ try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast(
+ isel.air.extra.items[extra.end..][0..extra.data.body_len],
+ ));
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
.loop => {
@@ -3175,11 +3321,11 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
// IT'S DOM TIME!!!
- for (isel.blocks.values(), 0..) |*block, dom_index| {
+ for (isel.blocks.values(), 0..) |*dom_block, dom_index| {
if (@as(u1, @truncate(isel.dom.items[
loop.dom + dom_index / @bitSizeOf(DomInt)
] >> @truncate(dom_index))) == 0) continue;
- var live_reg_it = block.live_registers.iterator();
+ var live_reg_it = dom_block.live_registers.iterator();
while (live_reg_it.next()) |live_reg_entry| switch (live_reg_entry.value.*) {
_ => |live_vi| try live_vi.mat(isel),
.allocating => unreachable,
@@ -3211,8 +3357,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
},
.br => {
const br = air.data(air.inst_index).br;
- const block = isel.blocks.getPtr(br.block_inst).?;
- try block.branch(isel);
+ try isel.blocks.getPtr(br.block_inst).?.branch(isel);
if (isel.live_values.get(br.block_inst)) |dst_vi| try dst_vi.move(isel, br.operand);
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
@@ -3224,6 +3369,22 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try isel.emit(.brk(0xf000));
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .ret_addr => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: {
+ defer addr_vi.value.deref(isel);
+ const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused;
+ try isel.emit(.ldr(addr_ra.x(), .{ .unsigned_offset = .{ .base = .fp, .offset = 8 } }));
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
+ .frame_addr => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |addr_vi| unused: {
+ defer addr_vi.value.deref(isel);
+ const addr_ra = try addr_vi.value.defReg(isel) orelse break :unused;
+ try isel.emit(.orr(addr_ra.x(), .xzr, .{ .register = .fp }));
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.call => {
const pl_op = air.data(air.inst_index).pl_op;
const extra = isel.air.extraData(Air.Call, pl_op.payload);
@@ -3312,7 +3473,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
var param_part_it = passed_vi.parts(isel);
var arg_part_it = arg_vi.parts(isel);
if (arg_part_it.only()) |_| {
- try isel.values.ensureUnusedCapacity(isel.pt.zcu.gpa, param_part_it.remaining);
+ try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining);
arg_vi.setParts(isel, param_part_it.remaining);
while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
isel,
@@ -3659,7 +3820,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (air_tag) {
+ .name = switch (air_tag) {
else => unreachable,
.sqrt => switch (bits) {
else => unreachable,
@@ -3751,7 +3912,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (air_tag) {
+ .name = switch (air_tag) {
else => unreachable,
.sin => switch (bits) {
else => unreachable,
@@ -4239,7 +4400,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__cmphf2",
32 => "__cmpsf2",
@@ -4328,7 +4489,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
};
var cond_mat: ?Value.Materialize = null;
var cond_reg: Register = undefined;
- var temp_reg: Register = undefined;
var cases_it = switch_br.iterateCases();
while (cases_it.next()) |case| {
const next_label = isel.instructions.items.len;
@@ -4342,11 +4502,10 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
if (cond_mat == null) {
var cond_vi = try isel.use(switch_br.operand);
cond_mat = try cond_vi.matReg(isel);
- const temp_ra = try isel.allocIntReg();
- cond_reg, temp_reg = switch (cond_int_info.bits) {
+ cond_reg = switch (cond_int_info.bits) {
else => unreachable,
- 1...32 => .{ cond_mat.?.ra.w(), temp_ra.w() },
- 33...64 => .{ cond_mat.?.ra.x(), temp_ra.x() },
+ 1...32 => cond_mat.?.ra.w(),
+ 33...64 => cond_mat.?.ra.x(),
};
}
if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned(
@@ -4387,17 +4546,45 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
) else high_bigint.toInt(i64) catch
return isel.fail("too big case range end: {f}", .{isel.fmtConstant(high_val)});
+ const adjusted_ra = switch (low_int) {
+ 0 => cond_mat.?.ra,
+ else => try isel.allocIntReg(),
+ };
+ defer if (adjusted_ra != cond_mat.?.ra) isel.freeReg(adjusted_ra);
+ const adjusted_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => adjusted_ra.w(),
+ 33...64 => adjusted_ra.x(),
+ };
const delta_int = high_int -% low_int;
- if (case_range_index > 0) {
- return isel.fail("case range", .{});
- } else if (case.items.len > 0) {
- return isel.fail("case range", .{});
+ if (case_range_index | case.items.len > 0) {
+ if (std.math.cast(u5, delta_int)) |pos_imm| try isel.emit(.ccmp(
+ adjusted_reg,
+ .{ .immediate = pos_imm },
+ .{ .n = false, .z = true, .c = false, .v = false },
+ if (case_range_index > 0) .hi else .ne,
+ )) else if (std.math.cast(u5, -delta_int)) |neg_imm| try isel.emit(.ccmn(
+ adjusted_reg,
+ .{ .immediate = neg_imm },
+ .{ .n = false, .z = true, .c = false, .v = false },
+ if (case_range_index > 0) .hi else .ne,
+ )) else {
+ const imm_ra = try isel.allocIntReg();
+ defer isel.freeReg(imm_ra);
+ const imm_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => imm_ra.w(),
+ 33...64 => imm_ra.x(),
+ };
+ try isel.emit(.ccmp(
+ cond_reg,
+ .{ .register = imm_reg },
+ .{ .n = false, .z = true, .c = false, .v = false },
+ if (case_range_index > 0) .hi else .ne,
+ ));
+ try isel.movImmediate(imm_reg, @bitCast(delta_int));
+ }
} else {
- const adjusted_reg = switch (low_int) {
- 0 => cond_reg,
- else => temp_reg,
- };
-
if (std.math.cast(u12, delta_int)) |pos_imm| try isel.emit(.subs(
zero_reg,
adjusted_reg,
@@ -4421,41 +4608,55 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
adjusted_reg,
.{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
)) else {
- try isel.movImmediate(temp_reg, @bitCast(delta_int));
- try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = temp_reg }));
+ const imm_ra = try isel.allocIntReg();
+ defer isel.freeReg(imm_ra);
+ const imm_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => imm_ra.w(),
+ 33...64 => imm_ra.x(),
+ };
+ try isel.emit(.subs(zero_reg, adjusted_reg, .{ .register = imm_reg }));
+ try isel.movImmediate(imm_reg, @bitCast(delta_int));
}
+ }
- switch (low_int) {
- 0 => {},
- else => {
- if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
- adjusted_reg,
- cond_reg,
- .{ .immediate = pos_imm },
- )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
- adjusted_reg,
- cond_reg,
- .{ .immediate = neg_imm },
- )) else if (if (@as(i12, @truncate(low_int)) == 0)
- std.math.cast(u12, low_int >> 12)
- else
- null) |pos_imm_lsr_12| try isel.emit(.sub(
- adjusted_reg,
- cond_reg,
- .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
- )) else if (if (@as(i12, @truncate(-low_int)) == 0)
- std.math.cast(u12, -low_int >> 12)
- else
- null) |neg_imm_lsr_12| try isel.emit(.add(
- adjusted_reg,
- cond_reg,
- .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
- )) else {
- try isel.movImmediate(temp_reg, @bitCast(low_int));
- try isel.emit(.subs(adjusted_reg, cond_reg, .{ .register = temp_reg }));
- }
- },
- }
+ switch (low_int) {
+ 0 => {},
+ else => {
+ if (std.math.cast(u12, low_int)) |pos_imm| try isel.emit(.sub(
+ adjusted_reg,
+ cond_reg,
+ .{ .immediate = pos_imm },
+ )) else if (std.math.cast(u12, -low_int)) |neg_imm| try isel.emit(.add(
+ adjusted_reg,
+ cond_reg,
+ .{ .immediate = neg_imm },
+ )) else if (if (@as(i12, @truncate(low_int)) == 0)
+ std.math.cast(u12, low_int >> 12)
+ else
+ null) |pos_imm_lsr_12| try isel.emit(.sub(
+ adjusted_reg,
+ cond_reg,
+ .{ .shifted_immediate = .{ .immediate = pos_imm_lsr_12, .lsl = .@"12" } },
+ )) else if (if (@as(i12, @truncate(-low_int)) == 0)
+ std.math.cast(u12, -low_int >> 12)
+ else
+ null) |neg_imm_lsr_12| try isel.emit(.add(
+ adjusted_reg,
+ cond_reg,
+ .{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
+ )) else {
+ const imm_ra = try isel.allocIntReg();
+ defer isel.freeReg(imm_ra);
+ const imm_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => imm_ra.w(),
+ 33...64 => imm_ra.x(),
+ };
+ try isel.emit(.sub(adjusted_reg, cond_reg, .{ .register = imm_reg }));
+ try isel.movImmediate(imm_reg, @bitCast(low_int));
+ }
+ },
}
}
var case_item_index = case.items.len;
@@ -4483,13 +4684,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
.{ .n = false, .z = true, .c = false, .v = false },
.ne,
)) else {
- try isel.movImmediate(temp_reg, @bitCast(item_int));
+ const imm_ra = try isel.allocIntReg();
+ defer isel.freeReg(imm_ra);
+ const imm_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => imm_ra.w(),
+ 33...64 => imm_ra.x(),
+ };
try isel.emit(.ccmp(
cond_reg,
- .{ .register = temp_reg },
+ .{ .register = imm_reg },
.{ .n = false, .z = true, .c = false, .v = false },
.ne,
));
+ try isel.movImmediate(imm_reg, @bitCast(item_int));
}
} else {
if (std.math.cast(u12, item_int)) |pos_imm| try isel.emit(.subs(
@@ -4515,16 +4723,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
cond_reg,
.{ .shifted_immediate = .{ .immediate = neg_imm_lsr_12, .lsl = .@"12" } },
)) else {
- try isel.movImmediate(temp_reg, @bitCast(item_int));
- try isel.emit(.subs(zero_reg, cond_reg, .{ .register = temp_reg }));
+ const imm_ra = try isel.allocIntReg();
+ defer isel.freeReg(imm_ra);
+ const imm_reg = switch (cond_int_info.bits) {
+ else => unreachable,
+ 1...32 => imm_ra.w(),
+ 33...64 => imm_ra.x(),
+ };
+ try isel.emit(.subs(zero_reg, cond_reg, .{ .register = imm_reg }));
+ try isel.movImmediate(imm_reg, @bitCast(item_int));
}
}
}
}
- if (cond_mat) |mat| {
- try mat.finish(isel);
- isel.freeReg(temp_reg.alias);
- }
+ if (cond_mat) |mat| try mat.finish(isel);
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
.@"try", .try_cold => {
@@ -4560,17 +4772,62 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
const error_set_part_vi = try error_set_part_it.only(isel);
const error_set_part_mat = try error_set_part_vi.?.matReg(isel);
try isel.emit(.cbz(
- switch (error_set_part_vi.?.size(isel)) {
- else => unreachable,
- 1...4 => error_set_part_mat.ra.w(),
- 5...8 => error_set_part_mat.ra.x(),
- },
+ error_set_part_mat.ra.w(),
@intCast((isel.instructions.items.len + 1 - cont_label) << 2),
));
try error_set_part_mat.finish(isel);
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .try_ptr, .try_ptr_cold => {
+ const ty_pl = air.data(air.inst_index).ty_pl;
+ const extra = isel.air.extraData(Air.TryPtr, ty_pl.payload);
+ const error_union_ty = isel.air.typeOf(extra.data.ptr, ip).childType(zcu);
+ const error_union_info = ip.indexToKey(error_union_ty.toIntern()).error_union_type;
+ const payload_ty: ZigType = .fromInterned(error_union_info.payload_type);
+
+ const error_union_ptr_vi = try isel.use(extra.data.ptr);
+ const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
+ if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
+ defer payload_ptr_vi.value.deref(isel);
+ switch (codegen.errUnionPayloadOffset(ty_pl.ty.toType().childType(zcu), zcu)) {
+ 0 => try payload_ptr_vi.value.move(isel, extra.data.ptr),
+ else => |payload_offset| {
+ const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
+ const lo12: u12 = @truncate(payload_offset >> 0);
+ const hi12: u12 = @intCast(payload_offset >> 12);
+ if (hi12 > 0) try isel.emit(.add(
+ payload_ptr_ra.x(),
+ if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
+ .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
+ ));
+ if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
+ },
+ }
+ }
+
+ const cont_label = isel.instructions.items.len;
+ const cont_live_registers = isel.live_registers;
+ try isel.body(@ptrCast(isel.air.extra.items[extra.end..][0..extra.data.body_len]));
+ try isel.merge(&cont_live_registers, .{});
+
+ const error_set_ra = try isel.allocIntReg();
+ defer isel.freeReg(error_set_ra);
+ try isel.loadReg(
+ error_set_ra,
+ ZigType.fromInterned(error_union_info.error_set_type).abiSize(zcu),
+ .unsigned,
+ error_union_ptr_mat.ra,
+ codegen.errUnionErrorOffset(payload_ty, zcu),
+ );
+ try error_union_ptr_mat.finish(isel);
+ try isel.emit(.cbz(
+ error_set_ra.w(),
+ @intCast((isel.instructions.items.len + 1 - cont_label) << 2),
+ ));
+
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.dbg_stmt => {
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
@@ -4578,6 +4835,14 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try isel.emit(.nop());
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .dbg_inline_block => {
+ const ty_pl = air.data(air.inst_index).ty_pl;
+ const extra = isel.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
+ try isel.block(air.inst_index, ty_pl.ty.toType(), @ptrCast(
+ isel.air.extra.items[extra.end..][0..extra.data.body_len],
+ ));
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => {
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
@@ -4673,7 +4938,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memcpy",
+ .name = "memcpy",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -4765,10 +5030,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
const ptr_ty = isel.air.typeOf(bin_op.lhs, ip);
const ptr_info = ptr_ty.ptrInfo(zcu);
if (ptr_info.packed_offset.host_size > 0) return isel.fail("packed store", .{});
- if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val)) {
- if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
- break :air_tag;
- };
+ if (bin_op.rhs.toInterned()) |rhs_val| if (ip.isUndef(rhs_val))
+ break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
const src_vi = try isel.use(bin_op.rhs);
const size = src_vi.size(isel);
@@ -4782,8 +5045,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
});
try ptr_mat.finish(isel);
- if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
- break :air_tag;
+ break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
else => {},
};
@@ -4792,7 +5054,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memcpy",
+ .name = "memcpy",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -4855,7 +5117,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (dst_bits) {
+ .name = switch (dst_bits) {
else => unreachable,
16 => switch (src_bits) {
else => unreachable,
@@ -5009,6 +5271,108 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .intcast_safe => |air_tag| {
+ if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
+ defer dst_vi.value.deref(isel);
+
+ const ty_op = air.data(air.inst_index).ty_op;
+ const dst_ty = ty_op.ty.toType();
+ const dst_int_info = dst_ty.intInfo(zcu);
+ const src_ty = isel.air.typeOf(ty_op.operand, ip);
+ const src_int_info = src_ty.intInfo(zcu);
+ const can_be_negative = dst_int_info.signedness == .signed and
+ src_int_info.signedness == .signed;
+ const panic_id: Zcu.SimplePanicId = panic_id: switch (dst_ty.zigTypeTag(zcu)) {
+ else => unreachable,
+ .int => .integer_out_of_bounds,
+ .@"enum" => {
+ if (!dst_ty.isNonexhaustiveEnum(zcu)) {
+ return isel.fail("bad {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
+ }
+ break :panic_id .invalid_enum_value;
+ },
+ };
+ if (dst_ty.toIntern() == src_ty.toIntern()) {
+ try dst_vi.value.move(isel, ty_op.operand);
+ } else if (dst_int_info.bits <= 64 and src_int_info.bits <= 64) {
+ const dst_ra = try dst_vi.value.defReg(isel) orelse break :unused;
+ const src_vi = try isel.use(ty_op.operand);
+ const dst_active_bits = dst_int_info.bits - @intFromBool(dst_int_info.signedness == .signed);
+ const src_active_bits = src_int_info.bits - @intFromBool(src_int_info.signedness == .signed);
+ if ((dst_int_info.signedness != .unsigned or src_int_info.signedness != .signed) and dst_active_bits >= src_active_bits) {
+ const src_mat = try src_vi.matReg(isel);
+ try isel.emit(if (can_be_negative and dst_active_bits > 32 and src_active_bits <= 32)
+ .sbfm(dst_ra.x(), src_mat.ra.x(), .{
+ .N = .doubleword,
+ .immr = 0,
+ .imms = @intCast(src_int_info.bits - 1),
+ })
+ else switch (src_int_info.bits) {
+ else => unreachable,
+ 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }),
+ 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }),
+ });
+ try src_mat.finish(isel);
+ } else {
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(panic_id);
+ try isel.emit(.@"b."(
+ .eq,
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ if (can_be_negative) {
+ const src_mat = src_mat: {
+ const dst_lock = isel.lockReg(dst_ra);
+ defer dst_lock.unlock(isel);
+ break :src_mat try src_vi.matReg(isel);
+ };
+ try isel.emit(switch (src_int_info.bits) {
+ else => unreachable,
+ 1...32 => .subs(.wzr, dst_ra.w(), .{ .register = src_mat.ra.w() }),
+ 33...64 => .subs(.xzr, dst_ra.x(), .{ .register = src_mat.ra.x() }),
+ });
+ try isel.emit(switch (@max(dst_int_info.bits, src_int_info.bits)) {
+ else => unreachable,
+ 1...32 => .sbfm(dst_ra.w(), src_mat.ra.w(), .{
+ .N = .word,
+ .immr = 0,
+ .imms = @intCast(dst_int_info.bits - 1),
+ }),
+ 33...64 => .sbfm(dst_ra.x(), src_mat.ra.x(), .{
+ .N = .doubleword,
+ .immr = 0,
+ .imms = @intCast(dst_int_info.bits - 1),
+ }),
+ });
+ try src_mat.finish(isel);
+ } else {
+ const src_mat = try src_vi.matReg(isel);
+ try isel.emit(switch (@min(dst_int_info.bits, src_int_info.bits)) {
+ else => unreachable,
+ 1...32 => .orr(dst_ra.w(), .wzr, .{ .register = src_mat.ra.w() }),
+ 33...64 => .orr(dst_ra.x(), .xzr, .{ .register = src_mat.ra.x() }),
+ });
+ const active_bits = @min(dst_active_bits, src_active_bits);
+ try isel.emit(switch (src_int_info.bits) {
+ else => unreachable,
+ 1...32 => .ands(.wzr, src_mat.ra.w(), .{ .immediate = .{
+ .N = .word,
+ .immr = @intCast(32 - active_bits),
+ .imms = @intCast(32 - active_bits - 1),
+ } }),
+ 33...64 => .ands(.xzr, src_mat.ra.x(), .{ .immediate = .{
+ .N = .doubleword,
+ .immr = @intCast(64 - active_bits),
+ .imms = @intCast(64 - active_bits - 1),
+ } }),
+ });
+ try src_mat.finish(isel);
+ }
+ }
+ } else return isel.fail("too big {s} {f} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty), isel.fmtType(src_ty) });
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.trunc => |air_tag| {
if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| unused: {
defer dst_vi.value.deref(isel);
@@ -5096,14 +5460,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .optional_payload_ptr => {
- if (isel.live_values.fetchRemove(air.inst_index)) |dst_vi| {
- defer dst_vi.value.deref(isel);
- const ty_op = air.data(air.inst_index).ty_op;
- try dst_vi.value.move(isel, ty_op.operand);
- }
- if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
- },
.optional_payload => {
if (isel.live_values.fetchRemove(air.inst_index)) |payload_vi| unused: {
defer payload_vi.value.deref(isel);
@@ -5122,6 +5478,37 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .optional_payload_ptr => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
+ defer payload_ptr_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ try payload_ptr_vi.value.move(isel, ty_op.operand);
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
+ .optional_payload_ptr_set => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| {
+ defer payload_ptr_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ const opt_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
+ if (!opt_ty.optionalReprIsPayload(zcu)) {
+ const opt_ptr_vi = try isel.use(ty_op.operand);
+ const opt_ptr_mat = try opt_ptr_vi.matReg(isel);
+ const has_value_ra = try isel.allocIntReg();
+ defer isel.freeReg(has_value_ra);
+ try isel.storeReg(
+ has_value_ra,
+ 1,
+ opt_ptr_mat.ra,
+ opt_ty.optionalChild(zcu).abiSize(zcu),
+ );
+ try opt_ptr_mat.finish(isel);
+ try isel.emit(.movz(has_value_ra.w(), 1, .{ .lsl = .@"0" }));
+ }
+ try payload_ptr_vi.value.move(isel, ty_op.operand);
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.wrap_optional => {
if (isel.live_values.fetchRemove(air.inst_index)) |opt_vi| unused: {
defer opt_vi.value.deref(isel);
@@ -5179,6 +5566,93 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .unwrap_errunion_payload_ptr => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
+ defer payload_ptr_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ switch (codegen.errUnionPayloadOffset(ty_op.ty.toType().childType(zcu), zcu)) {
+ 0 => try payload_ptr_vi.value.move(isel, ty_op.operand),
+ else => |payload_offset| {
+ const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
+ const error_union_ptr_vi = try isel.use(ty_op.operand);
+ const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
+ const lo12: u12 = @truncate(payload_offset >> 0);
+ const hi12: u12 = @intCast(payload_offset >> 12);
+ if (hi12 > 0) try isel.emit(.add(
+ payload_ptr_ra.x(),
+ if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
+ .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
+ ));
+ if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
+ try error_union_ptr_mat.finish(isel);
+ },
+ }
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
+ .unwrap_errunion_err_ptr => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |error_ptr_vi| unused: {
+ defer error_ptr_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ switch (codegen.errUnionErrorOffset(
+ isel.air.typeOf(ty_op.operand, ip).childType(zcu).errorUnionPayload(zcu),
+ zcu,
+ )) {
+ 0 => try error_ptr_vi.value.move(isel, ty_op.operand),
+ else => |error_offset| {
+ const error_ptr_ra = try error_ptr_vi.value.defReg(isel) orelse break :unused;
+ const error_union_ptr_vi = try isel.use(ty_op.operand);
+ const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
+ const lo12: u12 = @truncate(error_offset >> 0);
+ const hi12: u12 = @intCast(error_offset >> 12);
+ if (hi12 > 0) try isel.emit(.add(
+ error_ptr_ra.x(),
+ if (lo12 > 0) error_ptr_ra.x() else error_union_ptr_mat.ra.x(),
+ .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
+ ));
+ if (lo12 > 0) try isel.emit(.add(error_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
+ try error_union_ptr_mat.finish(isel);
+ },
+ }
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
+ .errunion_payload_ptr_set => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |payload_ptr_vi| unused: {
+ defer payload_ptr_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ const payload_ty = ty_op.ty.toType().childType(zcu);
+ const error_union_ty = isel.air.typeOf(ty_op.operand, ip).childType(zcu);
+ const error_set_size = error_union_ty.errorUnionSet(zcu).abiSize(zcu);
+ const error_union_ptr_vi = try isel.use(ty_op.operand);
+ const error_union_ptr_mat = try error_union_ptr_vi.matReg(isel);
+ if (error_set_size > 0) try isel.storeReg(
+ .zr,
+ error_set_size,
+ error_union_ptr_mat.ra,
+ codegen.errUnionErrorOffset(payload_ty, zcu),
+ );
+ switch (codegen.errUnionPayloadOffset(payload_ty, zcu)) {
+ 0 => {
+ try error_union_ptr_mat.finish(isel);
+ try payload_ptr_vi.value.move(isel, ty_op.operand);
+ },
+ else => |payload_offset| {
+ const payload_ptr_ra = try payload_ptr_vi.value.defReg(isel) orelse break :unused;
+ const lo12: u12 = @truncate(payload_offset >> 0);
+ const hi12: u12 = @intCast(payload_offset >> 12);
+ if (hi12 > 0) try isel.emit(.add(
+ payload_ptr_ra.x(),
+ if (lo12 > 0) payload_ptr_ra.x() else error_union_ptr_mat.ra.x(),
+ .{ .shifted_immediate = .{ .immediate = hi12, .lsl = .@"12" } },
+ ));
+ if (lo12 > 0) try isel.emit(.add(payload_ptr_ra.x(), error_union_ptr_mat.ra.x(), .{ .immediate = lo12 }));
+ try error_union_ptr_mat.finish(isel);
+ },
+ }
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.wrap_errunion_payload => {
if (isel.live_values.fetchRemove(air.inst_index)) |error_union_vi| {
defer error_union_vi.value.deref(isel);
@@ -5365,6 +5839,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .set_union_tag => {
+ const bin_op = air.data(air.inst_index).bin_op;
+ const union_ty = isel.air.typeOf(bin_op.lhs, ip).childType(zcu);
+ const union_layout = union_ty.unionGetLayout(zcu);
+ const tag_vi = try isel.use(bin_op.rhs);
+ const union_ptr_vi = try isel.use(bin_op.lhs);
+ const union_ptr_mat = try union_ptr_vi.matReg(isel);
+ try tag_vi.store(isel, isel.air.typeOf(bin_op.rhs, ip), union_ptr_mat.ra, .{
+ .offset = union_layout.tagOffset(),
+ });
+ try union_ptr_mat.finish(isel);
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
+ .get_union_tag => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |tag_vi| {
+ defer tag_vi.value.deref(isel);
+ const ty_op = air.data(air.inst_index).ty_op;
+ const union_ty = isel.air.typeOf(ty_op.operand, ip);
+ const union_layout = union_ty.unionGetLayout(zcu);
+ const union_vi = try isel.use(ty_op.operand);
+ var tag_part_it = union_vi.field(union_ty, union_layout.tagOffset(), union_layout.tag_size);
+ const tag_part_vi = try tag_part_it.only(isel);
+ try tag_vi.value.copy(isel, ty_op.ty.toType(), tag_part_vi.?);
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.slice => {
if (isel.live_values.fetchRemove(air.inst_index)) |slice_vi| {
defer slice_vi.value.deref(isel);
@@ -5781,7 +6281,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (dst_int_info.bits) {
+ .name = switch (dst_int_info.bits) {
else => unreachable,
1...32 => switch (dst_int_info.signedness) {
.signed => switch (src_bits) {
@@ -5921,7 +6421,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (src_int_info.bits) {
+ .name = switch (src_int_info.bits) {
else => unreachable,
1...32 => switch (src_int_info.signedness) {
.signed => switch (dst_bits) {
@@ -6004,14 +6504,20 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .memset => |air_tag| {
+ .memset, .memset_safe => |air_tag| {
const bin_op = air.data(air.inst_index).bin_op;
const dst_ty = isel.air.typeOf(bin_op.lhs, ip);
const dst_info = dst_ty.ptrInfo(zcu);
const fill_byte: union(enum) { constant: u8, value: Air.Inst.Ref } = fill_byte: {
- if (bin_op.rhs.toInterned()) |fill_val|
+ if (bin_op.rhs.toInterned()) |fill_val| {
+ if (ip.isUndef(fill_val)) switch (air_tag) {
+ else => unreachable,
+ .memset => break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag,
+ .memset_safe => break :fill_byte .{ .constant = 0xaa },
+ };
if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|
break :fill_byte .{ .constant = fill_byte };
+ }
switch (dst_ty.elemType2(zcu).abiSize(zcu)) {
0 => unreachable,
1 => break :fill_byte .{ .value = bin_op.rhs },
@@ -6070,8 +6576,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
.c => unreachable,
}
- if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
- break :air_tag;
+ break :air_tag if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
else => return isel.fail("too big {s} {f}", .{ @tagName(air_tag), isel.fmtType(dst_ty) }),
}
@@ -6082,7 +6587,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memset",
+ .name = "memset",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -6128,7 +6633,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = @tagName(air_tag),
+ .name = @tagName(air_tag),
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -6217,6 +6722,72 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .error_name => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |name_vi| unused: {
+ defer name_vi.value.deref(isel);
+ var ptr_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 0, 8);
+ const ptr_part_vi = try ptr_part_it.only(isel);
+ const ptr_part_ra = try ptr_part_vi.?.defReg(isel);
+ var len_part_it = name_vi.value.field(.slice_const_u8_sentinel_0, 8, 8);
+ const len_part_vi = try len_part_it.only(isel);
+ const len_part_ra = try len_part_vi.?.defReg(isel);
+ if (ptr_part_ra == null and len_part_ra == null) break :unused;
+
+ const un_op = air.data(air.inst_index).un_op;
+ const error_vi = try isel.use(un_op);
+ const error_mat = try error_vi.matReg(isel);
+ const ptr_ra = try isel.allocIntReg();
+ defer isel.freeReg(ptr_ra);
+ const start_ra, const end_ra = range_ras: {
+ const name_lock: RegLock = if (len_part_ra != null) if (ptr_part_ra) |name_ptr_ra|
+ isel.tryLockReg(name_ptr_ra)
+ else
+ .empty else .empty;
+ defer name_lock.unlock(isel);
+ break :range_ras .{ try isel.allocIntReg(), try isel.allocIntReg() };
+ };
+ defer {
+ isel.freeReg(start_ra);
+ isel.freeReg(end_ra);
+ }
+ if (len_part_ra) |name_len_ra| try isel.emit(.sub(
+ name_len_ra.w(),
+ end_ra.w(),
+ .{ .register = start_ra.w() },
+ ));
+ if (ptr_part_ra) |name_ptr_ra| try isel.emit(.add(
+ name_ptr_ra.x(),
+ ptr_ra.x(),
+ .{ .extended_register = .{
+ .register = start_ra.w(),
+ .extend = .{ .uxtw = 0 },
+ } },
+ ));
+ if (len_part_ra) |_| try isel.emit(.sub(end_ra.w(), end_ra.w(), .{ .immediate = 1 }));
+ try isel.emit(.ldp(start_ra.w(), end_ra.w(), .{ .base = start_ra.x() }));
+ try isel.emit(.add(start_ra.x(), ptr_ra.x(), .{ .extended_register = .{
+ .register = error_mat.ra.w(),
+ .extend = switch (zcu.errorSetBits()) {
+ else => unreachable,
+ 1...8 => .{ .uxtb = 2 },
+ 9...16 => .{ .uxth = 2 },
+ 17...32 => .{ .uxtw = 2 },
+ },
+ } }));
+ try isel.lazy_relocs.append(gpa, .{
+ .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
+ .reloc = .{ .label = @intCast(isel.instructions.items.len) },
+ });
+ try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
+ try isel.lazy_relocs.append(gpa, .{
+ .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
+ .reloc = .{ .label = @intCast(isel.instructions.items.len) },
+ });
+ try isel.emit(.adrp(ptr_ra.x(), 0));
+ try error_mat.finish(isel);
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.aggregate_init => {
if (isel.live_values.fetchRemove(air.inst_index)) |agg_vi| {
defer agg_vi.value.deref(isel);
@@ -6311,7 +6882,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = "memcpy",
+ .name = "memcpy",
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.bl(0));
@@ -6427,7 +6998,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
try call.prepareCallee(isel);
try isel.global_relocs.append(gpa, .{
- .global = switch (bits) {
+ .name = switch (bits) {
else => unreachable,
16 => "__fmah",
32 => "fmaf",
@@ -6508,6 +7079,32 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
+ .cmp_lt_errors_len => {
+ if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: {
+ defer is_vi.value.deref(isel);
+ const is_ra = try is_vi.value.defReg(isel) orelse break :unused;
+ try isel.emit(.csinc(is_ra.w(), .wzr, .wzr, .invert(.ls)));
+
+ const un_op = air.data(air.inst_index).un_op;
+ const error_vi = try isel.use(un_op);
+ const error_mat = try error_vi.matReg(isel);
+ const ptr_ra = try isel.allocIntReg();
+ defer isel.freeReg(ptr_ra);
+ try isel.emit(.subs(.wzr, error_mat.ra.w(), .{ .register = ptr_ra.w() }));
+ try isel.lazy_relocs.append(gpa, .{
+ .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
+ .reloc = .{ .label = @intCast(isel.instructions.items.len) },
+ });
+ try isel.emit(.ldr(ptr_ra.w(), .{ .base = ptr_ra.x() }));
+ try isel.lazy_relocs.append(gpa, .{
+ .symbol = .{ .kind = .const_data, .ty = .anyerror_type },
+ .reloc = .{ .label = @intCast(isel.instructions.items.len) },
+ });
+ try isel.emit(.adrp(ptr_ra.x(), 0));
+ try error_mat.finish(isel);
+ }
+ if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
+ },
.runtime_nav_ptr => {
if (isel.live_values.fetchRemove(air.inst_index)) |ptr_vi| unused: {
defer ptr_vi.value.deref(isel);
@@ -6516,19 +7113,19 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
const ty_nav = air.data(air.inst_index).ty_nav;
if (ZigType.fromInterned(ip.getNav(ty_nav.nav).typeOf(ip)).isFnOrHasRuntimeBits(zcu)) switch (true) {
false => {
- try isel.nav_relocs.append(zcu.gpa, .{
+ try isel.nav_relocs.append(gpa, .{
.nav = ty_nav.nav,
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.adr(ptr_ra.x(), 0));
},
true => {
- try isel.nav_relocs.append(zcu.gpa, .{
+ try isel.nav_relocs.append(gpa, .{
.nav = ty_nav.nav,
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
try isel.emit(.add(ptr_ra.x(), ptr_ra.x(), .{ .immediate = 0 }));
- try isel.nav_relocs.append(zcu.gpa, .{
+ try isel.nav_relocs.append(gpa, .{
.nav = ty_nav.nav,
.reloc = .{ .label = @intCast(isel.instructions.items.len) },
});
@@ -6538,9 +7135,6 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) !void {
}
if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
},
- .add_safe,
- .sub_safe,
- .mul_safe,
.inferred_alloc,
.inferred_alloc_comptime,
.int_from_float_safe,
@@ -6642,8 +7236,8 @@ pub fn layout(
wip_mir_log.debug("{f}
:\n", .{nav.fqn.fmt(ip)});
const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
- const stack_size_low: u12 = @truncate(stack_size >> 0);
- const stack_size_high: u12 = @truncate(stack_size >> 12);
+ const stack_size_lo: u12 = @truncate(stack_size >> 0);
+ const stack_size_hi: u12 = @truncate(stack_size >> 12);
var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
class: enum { integer, vector },
@@ -6771,6 +7365,9 @@ pub fn layout(
saves_len += 1;
saves_size += 8;
deferred_gr = null;
+ } else switch (@as(u1, @truncate(saved_gra_len))) {
+ 0 => {},
+ 1 => saves_size += 8,
}
save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;
while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
@@ -6793,65 +7390,90 @@ pub fn layout(
{
wip_mir_log.debug("{f}:", .{nav.fqn.fmt(ip)});
var save_index: usize = 0;
- while (save_index < saves.len) {
- if (save_index + 2 <= saves.len and saves[save_index + 0].class == saves[save_index + 1].class and
- saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
- {
- try isel.emit(.stp(
- saves[save_index + 0].register,
- saves[save_index + 1].register,
- switch (saves[save_index + 0].offset) {
- 0 => .{ .pre_index = .{
- .base = .sp,
- .index = @intCast(-@as(i11, saves_size)),
- } },
- else => |offset| .{ .signed_offset = .{
- .base = .sp,
- .offset = @intCast(offset),
- } },
- },
- ));
- save_index += 2;
- } else {
- try isel.emit(.str(
- saves[save_index].register,
- switch (saves[save_index].offset) {
- 0 => .{ .pre_index = .{
- .base = .sp,
- .index = @intCast(-@as(i11, saves_size)),
- } },
- else => |offset| .{ .unsigned_offset = .{
- .base = .sp,
- .offset = @intCast(offset),
- } },
- },
- ));
- save_index += 1;
- }
- }
+ while (save_index < saves.len) if (save_index + 2 <= saves.len and
+ saves[save_index + 0].class == saves[save_index + 1].class and
+ saves[save_index + 0].size == saves[save_index + 1].size and
+ saves[save_index + 0].offset + saves[save_index + 0].size == saves[save_index + 1].offset)
+ {
+ try isel.emit(.stp(
+ saves[save_index + 0].register,
+ saves[save_index + 1].register,
+ switch (saves[save_index + 0].offset) {
+ 0 => .{ .pre_index = .{
+ .base = .sp,
+ .index = @intCast(-@as(i11, saves_size)),
+ } },
+ else => |offset| .{ .signed_offset = .{
+ .base = .sp,
+ .offset = @intCast(offset),
+ } },
+ },
+ ));
+ save_index += 2;
+ } else {
+ try isel.emit(.str(
+ saves[save_index].register,
+ switch (saves[save_index].offset) {
+ 0 => .{ .pre_index = .{
+ .base = .sp,
+ .index = @intCast(-@as(i11, saves_size)),
+ } },
+ else => |offset| .{ .unsigned_offset = .{
+ .base = .sp,
+ .offset = @intCast(offset),
+ } },
+ },
+ ));
+ save_index += 1;
+ };
+ try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
const scratch_reg: Register = if (isel.stack_align == .@"16")
.sp
- else if (stack_size == 0)
+ else if (stack_size == 0 and frame_record_offset == 0)
.fp
else
- .x9;
- try isel.emit(.add(.fp, .sp, .{ .immediate = frame_record_offset }));
- if (stack_size_high > 0) try isel.emit(.sub(scratch_reg, .sp, .{
- .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
- }));
- if (stack_size_low > 0) try isel.emit(.sub(
- scratch_reg,
- if (stack_size_high > 0) scratch_reg else .sp,
- .{ .immediate = stack_size_low },
- ));
- if (isel.stack_align != .@"16") {
- try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
- .N = .doubleword,
- .immr = -%isel.stack_align.toLog2Units(),
- .imms = ~isel.stack_align.toLog2Units(),
- } }));
+ .ip0;
+ if (mod.stack_check) {
+ if (stack_size_hi > 2) {
+ try isel.movImmediate(.ip1, stack_size_hi);
+ const loop_label = isel.instructions.items.len;
+ try isel.emit(.sub(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
+ }));
+ try isel.emit(.sub(.ip1, .ip1, .{ .immediate = 1 }));
+ try isel.emit(.ldr(.xzr, .{ .base = .sp }));
+ try isel.emit(.cbnz(.ip1, -@as(i21, @intCast(
+ (isel.instructions.items.len - loop_label) << 2,
+ ))));
+ } else for (0..stack_size_hi) |_| {
+ try isel.emit(.sub(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = 1, .lsl = .@"12" },
+ }));
+ try isel.emit(.ldr(.xzr, .{ .base = .sp }));
+ }
+ if (stack_size_lo > 0) try isel.emit(.sub(
+ scratch_reg,
+ .sp,
+ .{ .immediate = stack_size_lo },
+ )) else if (scratch_reg.alias == Register.Alias.ip0)
+ try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
+ } else {
+ if (stack_size_hi > 0) try isel.emit(.sub(scratch_reg, .sp, .{
+ .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
+ }));
+ if (stack_size_lo > 0) try isel.emit(.sub(
+ scratch_reg,
+ if (stack_size_hi > 0) scratch_reg else .sp,
+ .{ .immediate = stack_size_lo },
+ )) else if (scratch_reg.alias == Register.Alias.ip0 and stack_size_hi == 0)
+ try isel.emit(.add(scratch_reg, .sp, .{ .immediate = 0 }));
}
+ if (isel.stack_align != .@"16") try isel.emit(.@"and"(.sp, scratch_reg, .{ .immediate = .{
+ .N = .doubleword,
+ .immr = -%isel.stack_align.toLog2Units(),
+ .imms = ~isel.stack_align.toLog2Units(),
+ } }));
wip_mir_log.debug("", .{});
}
@@ -6896,17 +7518,17 @@ pub fn layout(
save_index += 1;
} else save_index += 1;
}
- if (isel.stack_align != .@"16" or (stack_size_low > 0 and stack_size_high > 0)) {
+ if (isel.stack_align != .@"16" or (stack_size_lo > 0 and stack_size_hi > 0)) {
try isel.emit(switch (frame_record_offset) {
0 => .add(.sp, .fp, .{ .immediate = 0 }),
else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
});
} else {
- if (stack_size_high > 0) try isel.emit(.add(.sp, .sp, .{
- .shifted_immediate = .{ .immediate = stack_size_high, .lsl = .@"12" },
+ if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
+ .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
}));
- if (stack_size_low > 0) try isel.emit(.add(.sp, .sp, .{
- .immediate = stack_size_low,
+ if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
+ .immediate = stack_size_lo,
}));
}
wip_mir_log.debug("{f}:\n", .{nav.fqn.fmt(ip)});
@@ -6977,11 +7599,43 @@ fn fmtConstant(isel: *Select, constant: Constant) @typeInfo(@TypeOf(Constant.fmt
return constant.fmtValue(isel.pt);
}
+fn block(
+ isel: *Select,
+ air_inst_index: Air.Inst.Index,
+ res_ty: ZigType,
+ air_body: []const Air.Inst.Index,
+) !void {
+ if (res_ty.toIntern() != .noreturn_type) {
+ isel.blocks.putAssumeCapacityNoClobber(air_inst_index, .{
+ .live_registers = isel.live_registers,
+ .target_label = @intCast(isel.instructions.items.len),
+ });
+ }
+ try isel.body(air_body);
+ if (res_ty.toIntern() != .noreturn_type) {
+ const block_entry = isel.blocks.pop().?;
+ assert(block_entry.key == air_inst_index);
+ if (isel.live_values.fetchRemove(air_inst_index)) |result_vi| result_vi.value.deref(isel);
+ }
+}
+
fn emit(isel: *Select, instruction: codegen.aarch64.encoding.Instruction) !void {
wip_mir_log.debug(" | {f}", .{instruction});
try isel.instructions.append(isel.pt.zcu.gpa, instruction);
}
+fn emitPanic(isel: *Select, panic_id: Zcu.SimplePanicId) !void {
+ const zcu = isel.pt.zcu;
+ try isel.nav_relocs.append(zcu.gpa, .{
+ .nav = switch (zcu.intern_pool.indexToKey(zcu.builtin_decl_values.get(panic_id.toBuiltin()))) {
+ else => unreachable,
+ inline .@"extern", .func => |func| func.owner_nav,
+ },
+ .reloc = .{ .label = @intCast(isel.instructions.items.len) },
+ });
+ try isel.emit(.bl(0));
+}
+
fn emitLiteral(isel: *Select, bytes: []const u8) !void {
const words: []align(1) const u32 = @ptrCast(bytes);
const literals = try isel.literals.addManyAsSlice(isel.pt.zcu.gpa, words.len);
@@ -8028,6 +8682,32 @@ pub const Value = struct {
}
}
+ const AddOrSubtractOptions = struct {
+ overflow: Overflow,
+
+ const Overflow = union(enum) {
+ @"unreachable",
+ panic: Zcu.SimplePanicId,
+ wrap,
+ ra: Register.Alias,
+
+ fn defCond(overflow: Overflow, isel: *Select, cond: codegen.aarch64.encoding.ConditionCode) !void {
+ switch (overflow) {
+ .@"unreachable" => unreachable,
+ .panic => |panic_id| {
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(panic_id);
+ try isel.emit(.@"b."(
+ cond.invert(),
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ },
+ .wrap => {},
+ .ra => |overflow_ra| try isel.emit(.csinc(overflow_ra.w(), .wzr, .wzr, cond.invert())),
+ }
+ }
+ };
+ };
fn addOrSubtract(
res_vi: Value.Index,
isel: *Select,
@@ -8035,19 +8715,21 @@ pub const Value = struct {
lhs_vi: Value.Index,
op: codegen.aarch64.encoding.Instruction.AddSubtractOp,
rhs_vi: Value.Index,
- opts: struct {
- wrap: bool,
- overflow_ra: Register.Alias = .zr,
- },
+ opts: AddOrSubtractOptions,
) !void {
- assert(opts.wrap or opts.overflow_ra == .zr);
const zcu = isel.pt.zcu;
if (!ty.isAbiInt(zcu)) return isel.fail("bad {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
const int_info = ty.intInfo(zcu);
if (int_info.bits > 128) return isel.fail("too big {s} {f}", .{ @tagName(op), isel.fmtType(ty) });
var part_offset = res_vi.size(isel);
- var need_wrap = opts.wrap;
- var need_carry = opts.overflow_ra != .zr;
+ var need_wrap = switch (opts.overflow) {
+ .@"unreachable" => false,
+ .panic, .wrap, .ra => true,
+ };
+ var need_carry = switch (opts.overflow) {
+ .@"unreachable", .wrap => false,
+ .panic, .ra => true,
+ };
while (part_offset > 0) : (need_wrap = false) {
const part_size = @min(part_offset, 8);
part_offset -= part_size;
@@ -8057,48 +8739,87 @@ pub const Value = struct {
const unwrapped_res_part_ra = unwrapped_res_part_ra: {
if (!need_wrap) break :unwrapped_res_part_ra wrapped_res_part_ra;
if (int_info.bits % 32 == 0) {
- if (opts.overflow_ra != .zr) try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(switch (int_info.signedness) {
+ try opts.overflow.defCond(isel, switch (int_info.signedness) {
.signed => .vs,
.unsigned => switch (op) {
.add => .cs,
.sub => .cc,
},
- })));
+ });
break :unwrapped_res_part_ra wrapped_res_part_ra;
}
- const wrapped_part_ra, const unwrapped_part_ra = if (opts.overflow_ra != .zr) part_ra: {
- switch (op) {
- .add => {},
- .sub => switch (int_info.signedness) {
- .signed => {},
- .unsigned => {
- try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.cc)));
- break :part_ra .{ wrapped_res_part_ra, wrapped_res_part_ra };
- },
+ need_carry = false;
+ const wrapped_part_ra, const unwrapped_part_ra = part_ra: switch (opts.overflow) {
+ .@"unreachable" => unreachable,
+ .panic, .ra => switch (int_info.signedness) {
+ .signed => {
+ try opts.overflow.defCond(isel, .ne);
+ const wrapped_part_ra = switch (wrapped_res_part_ra) {
+ else => |res_part_ra| res_part_ra,
+ .zr => try isel.allocIntReg(),
+ };
+ errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
+ const unwrapped_part_ra = unwrapped_part_ra: {
+ const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
+ else => |res_part_ra| isel.lockReg(res_part_ra),
+ .zr => .empty,
+ };
+ defer wrapped_res_part_lock.unlock(isel);
+ break :unwrapped_part_ra try isel.allocIntReg();
+ };
+ errdefer isel.freeReg(unwrapped_part_ra);
+ switch (part_size) {
+ else => unreachable,
+ 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),
+ 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),
+ }
+ break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };
},
- }
- try isel.emit(.csinc(opts.overflow_ra.w(), .wzr, .wzr, .invert(.ne)));
- const wrapped_part_ra = switch (wrapped_res_part_ra) {
- else => |res_part_ra| res_part_ra,
- .zr => try isel.allocIntReg(),
- };
- errdefer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
- const unwrapped_part_ra = unwrapped_part_ra: {
- const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
- else => |res_part_ra| isel.lockReg(res_part_ra),
- .zr => .empty,
- };
- defer wrapped_res_part_lock.unlock(isel);
- break :unwrapped_part_ra try isel.allocIntReg();
- };
- errdefer isel.freeReg(unwrapped_part_ra);
- switch (part_size) {
- else => unreachable,
- 1...4 => try isel.emit(.subs(.wzr, wrapped_part_ra.w(), .{ .register = unwrapped_part_ra.w() })),
- 5...8 => try isel.emit(.subs(.xzr, wrapped_part_ra.x(), .{ .register = unwrapped_part_ra.x() })),
- }
- break :part_ra .{ wrapped_part_ra, unwrapped_part_ra };
- } else .{ wrapped_res_part_ra, wrapped_res_part_ra };
+ .unsigned => {
+ const unwrapped_part_ra = unwrapped_part_ra: {
+ const wrapped_res_part_lock: RegLock = switch (wrapped_res_part_ra) {
+ else => |res_part_ra| isel.lockReg(res_part_ra),
+ .zr => .empty,
+ };
+ defer wrapped_res_part_lock.unlock(isel);
+ break :unwrapped_part_ra try isel.allocIntReg();
+ };
+ errdefer isel.freeReg(unwrapped_part_ra);
+ const bit: u6 = @truncate(int_info.bits);
+ switch (opts.overflow) {
+ .@"unreachable", .wrap => unreachable,
+ .panic => |panic_id| {
+ const skip_label = isel.instructions.items.len;
+ try isel.emitPanic(panic_id);
+ try isel.emit(.tbz(
+ switch (bit) {
+ 0, 32 => unreachable,
+ 1...31 => unwrapped_part_ra.w(),
+ 33...63 => unwrapped_part_ra.x(),
+ },
+ bit,
+ @intCast((isel.instructions.items.len + 1 - skip_label) << 2),
+ ));
+ },
+ .ra => |overflow_ra| try isel.emit(switch (bit) {
+ 0, 32 => unreachable,
+ 1...31 => .ubfm(overflow_ra.w(), unwrapped_part_ra.w(), .{
+ .N = .word,
+ .immr = bit,
+ .imms = bit,
+ }),
+ 33...63 => .ubfm(overflow_ra.x(), unwrapped_part_ra.x(), .{
+ .N = .doubleword,
+ .immr = bit,
+ .imms = bit,
+ }),
+ }),
+ }
+ break :part_ra .{ wrapped_res_part_ra, unwrapped_part_ra };
+ },
+ },
+ .wrap => .{ wrapped_res_part_ra, wrapped_res_part_ra },
+ };
defer if (wrapped_part_ra != wrapped_res_part_ra) isel.freeReg(wrapped_part_ra);
errdefer if (unwrapped_part_ra != wrapped_res_part_ra) isel.freeReg(unwrapped_part_ra);
if (wrapped_part_ra != .zr) try isel.emit(switch (part_size) {
@@ -8574,41 +9295,15 @@ pub const Value = struct {
expected_live_registers: *const LiveRegisters,
) !void {
try vi.liveIn(isel, src_ra, expected_live_registers);
- const offset_from_parent: i65, const parent_vi = vi.valueParent(isel);
+ const offset_from_parent, const parent_vi = vi.valueParent(isel);
switch (parent_vi.parent(isel)) {
.unallocated => {},
- .stack_slot => |stack_slot| {
- const offset = stack_slot.offset + offset_from_parent;
- try isel.emit(switch (vi.size(isel)) {
- else => unreachable,
- 1 => if (src_ra.isVector()) .str(src_ra.b(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }) else .strb(src_ra.w(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }),
- 2 => if (src_ra.isVector()) .str(src_ra.h(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }) else .strh(src_ra.w(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }),
- 4 => .str(if (src_ra.isVector()) src_ra.s() else src_ra.w(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }),
- 8 => .str(if (src_ra.isVector()) src_ra.d() else src_ra.x(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }),
- 16 => .str(src_ra.q(), .{ .unsigned_offset = .{
- .base = stack_slot.base.x(),
- .offset = @intCast(offset),
- } }),
- });
- },
+ .stack_slot => |stack_slot| if (stack_slot.base != Register.Alias.fp) try isel.storeReg(
+ src_ra,
+ vi.size(isel),
+ stack_slot.base,
+ @as(i65, stack_slot.offset) + offset_from_parent,
+ ),
else => unreachable,
}
try vi.spillReg(isel, src_ra, 0, expected_live_registers);
@@ -9027,8 +9722,14 @@ pub const Value = struct {
} },
},
.struct_type => {
- const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
const loaded_struct = ip.loadStructType(ty.toIntern());
+ switch (loaded_struct.layout) {
+ .auto, .@"extern" => {},
+ .@"packed" => continue :type_key .{
+ .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
+ },
+ }
+ const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
if (loaded_struct.field_types.len > Value.max_parts and
(std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
@@ -9136,6 +9837,77 @@ pub const Value = struct {
if (part.is_vector) subpart_vi.setIsVector(isel);
}
},
+ .union_type => {
+ const loaded_union = ip.loadUnionType(ty.toIntern());
+ switch (loaded_union.flagsUnordered(ip).layout) {
+ .auto, .@"extern" => {},
+ .@"packed" => continue :type_key .{ .int_type = .{
+ .signedness = .unsigned,
+ .bits = @intCast(ty.bitSize(zcu)),
+ } },
+ }
+ const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0;
+ if ((std.math.divCeil(u64, size, @as(u64, 1) << min_part_log2_stride) catch unreachable) > Value.max_parts)
+ return isel.fail("Value.FieldPartIterator.next({f})", .{isel.fmtType(ty)});
+ const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
+ const alignment = vi.alignment(isel);
+ const tag_offset = union_layout.tagOffset();
+ const payload_offset = union_layout.payloadOffset();
+ const Part = struct { offset: u64, size: u64, signedness: ?std.builtin.Signedness };
+ var parts: [2]Part = undefined;
+ var parts_len: Value.PartsLen = 0;
+ var field_end: u64 = 0;
+ for (0..2) |field_index| {
+ const field: enum { tag, payload } = switch (field_index) {
+ 0 => if (tag_offset < payload_offset) .tag else .payload,
+ 1 => if (tag_offset < payload_offset) .payload else .tag,
+ else => unreachable,
+ };
+ const field_size, const field_begin = switch (field) {
+ .tag => .{ union_layout.tag_size, tag_offset },
+ .payload => .{ union_layout.payload_size, payload_offset },
+ };
+ if (field_begin >= offset + size) break;
+ if (field_size == 0) continue;
+ field_end = field_begin + field_size;
+ if (field_end <= offset) continue;
+ const field_signedness = field_signedness: switch (field) {
+ .tag => {
+ if (offset >= field_begin and offset + size <= field_begin + field_size) {
+ ty = .fromInterned(loaded_union.enum_tag_ty);
+ ty_size = field_size;
+ offset -= field_begin;
+ continue :type_key ip.indexToKey(loaded_union.enum_tag_ty);
+ }
+ break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness;
+ },
+ .payload => null,
+ };
+ if (parts_len > 0) combine: {
+ const prev_part = &parts[parts_len - 1];
+ const combined_size = field_end - prev_part.offset;
+ if (combined_size > @as(u64, 1) << @min(
+ min_part_log2_stride,
+ alignment.toLog2Units(),
+ @ctz(prev_part.offset),
+ )) break :combine;
+ prev_part.size = combined_size;
+ prev_part.signedness = null;
+ continue;
+ }
+ parts[parts_len] = .{
+ .offset = field_begin,
+ .size = field_size,
+ .signedness = field_signedness,
+ };
+ parts_len += 1;
+ }
+ vi.setParts(isel, parts_len);
+ for (parts[0..parts_len]) |part| {
+ const subpart_vi = vi.addPart(isel, part.offset - offset, part.size);
+ if (part.signedness) |signedness| subpart_vi.setSignedness(isel, signedness);
+ }
+ },
.opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
.enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
.error_set_type,
@@ -9555,21 +10327,29 @@ pub const Value = struct {
var base_ptr = ip.indexToKey(base).ptr;
const eu_ty = ip.indexToKey(base_ptr.ty).ptr_type.child;
const payload_ty = ip.indexToKey(eu_ty).error_union_type.payload_type;
- base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu);
+ base_ptr.byte_offset += codegen.errUnionPayloadOffset(.fromInterned(payload_ty), zcu) + ptr.byte_offset;
+ continue :constant_key .{ .ptr = base_ptr };
+ },
+ .opt_payload => |base| {
+ var base_ptr = ip.indexToKey(base).ptr;
+ base_ptr.byte_offset += ptr.byte_offset;
continue :constant_key .{ .ptr = base_ptr };
},
- .opt_payload => |base| continue :constant_key .{ .ptr = ip.indexToKey(base).ptr },
.field => |field| {
var base_ptr = ip.indexToKey(field.base).ptr;
const agg_ty: ZigType = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child);
- base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu);
+ base_ptr.byte_offset += agg_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset;
continue :constant_key .{ .ptr = base_ptr };
},
.comptime_alloc, .comptime_field, .arr_elem => unreachable,
};
},
.slice => |slice| switch (offset) {
- 0 => continue :constant_key .{ .ptr = ip.indexToKey(slice.ptr).ptr },
+ 0 => continue :constant_key switch (ip.indexToKey(slice.ptr)) {
+ else => unreachable,
+ .undef => |undef| .{ .undef = undef },
+ .ptr => |ptr| .{ .ptr = ptr },
+ },
else => {
assert(offset == @divExact(isel.target.ptrBitWidth(), 8));
offset = 0;
@@ -10622,16 +11402,14 @@ pub const CallAbiIterator = struct {
{
const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
const offset = codegen.errUnionErrorOffset(payload_ty, zcu);
- const size = error_set_ty.abiSize(zcu);
- const end = offset % 8 + size;
+ const end = offset % 8 + error_set_ty.abiSize(zcu);
const part_index: usize = @intCast(offset / 8);
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
}
{
const offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
- const size = payload_ty.abiSize(zcu);
- const end = offset % 8 + size;
+ const end = offset % 8 + payload_ty.abiSize(zcu);
const part_index: usize = @intCast(offset / 8);
sizes[part_index] = @max(sizes[part_index], @min(end, 8));
if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
@@ -10675,8 +11453,14 @@ pub const CallAbiIterator = struct {
=> unreachable,
},
.struct_type => {
- const size = wip_vi.size(isel);
const loaded_struct = ip.loadStructType(ty.toIntern());
+ switch (loaded_struct.layout) {
+ .auto, .@"extern" => {},
+ .@"packed" => continue :type_key .{
+ .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type,
+ },
+ }
+ const size = wip_vi.size(isel);
if (size <= 16 * 4) homogeneous_aggregate: {
const fdt = homogeneousStructBaseType(zcu, &loaded_struct) orelse break :homogeneous_aggregate;
const parts_len = @shrExact(size, fdt.log2Size());
@@ -10761,6 +11545,40 @@ pub const CallAbiIterator = struct {
else => it.indirect(isel, wip_vi),
}
},
+ .union_type => {
+ const loaded_union = ip.loadUnionType(ty.toIntern());
+ switch (loaded_union.flagsUnordered(ip).layout) {
+ .auto, .@"extern" => {},
+ .@"packed" => continue :type_key .{ .int_type = .{
+ .signedness = .unsigned,
+ .bits = @intCast(ty.bitSize(zcu)),
+ } },
+ }
+ switch (wip_vi.size(isel)) {
+ 0 => unreachable,
+ 1...8 => it.integer(isel, wip_vi),
+ 9...16 => {
+ const union_layout = ZigType.getUnionLayout(loaded_union, zcu);
+ var sizes: [2]u64 = @splat(0);
+ {
+ const offset = union_layout.tagOffset();
+ const end = offset % 8 + union_layout.tag_size;
+ const part_index: usize = @intCast(offset / 8);
+ sizes[part_index] = @max(sizes[part_index], @min(end, 8));
+ if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
+ }
+ {
+ const offset = union_layout.payloadOffset();
+ const end = offset % 8 + union_layout.payload_size;
+ const part_index: usize = @intCast(offset / 8);
+ sizes[part_index] = @max(sizes[part_index], @min(end, 8));
+ if (end > 8) sizes[part_index + 1] = @max(sizes[part_index + 1], end - 8);
+ }
+ it.integers(isel, wip_vi, sizes);
+ },
+ else => it.indirect(isel, wip_vi),
+ }
+ },
.opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque },
.enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty),
.error_set_type,
diff --git a/src/codegen/aarch64/encoding.zig b/src/codegen/aarch64/encoding.zig
index 1697b2957b..727b88c729 100644
--- a/src/codegen/aarch64/encoding.zig
+++ b/src/codegen/aarch64/encoding.zig
@@ -151,6 +151,7 @@ pub const Register = struct {
pub const wzr: Register = .{ .alias = .zr, .format = .{ .integer = .word } };
pub const wsp: Register = .{ .alias = .sp, .format = .{ .integer = .word } };
+ pub const ip = x16;
pub const ip0 = x16;
pub const ip1 = x17;
pub const fp = x29;
@@ -774,6 +775,7 @@ pub const Register = struct {
ffr,
+ pub const ip: Alias = .r16;
pub const ip0: Alias = .r16;
pub const ip1: Alias = .r17;
pub const fp: Alias = .r29;
diff --git a/src/codegen/aarch64/instructions.zon b/src/codegen/aarch64/instructions.zon
index 85de196050..48b8eaa21f 100644
--- a/src/codegen/aarch64/instructions.zon
+++ b/src/codegen/aarch64/instructions.zon
@@ -213,6 +213,63 @@
},
.encode = .{ .ands, .Xd, .Xn, .{ .shifted_register_explicit = .{ .register = .Xm, .shift = .shift, .amount = .amount } } },
},
+ // C6.2.16 ASR (register)
+ .{
+ .pattern = "ASR , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .asrv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "ASR , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .asrv, .Xd, .Xn, .Xm },
+ },
+ // C6.2.17 ASR (immediate)
+ .{
+ .pattern = "ASR , , #",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
+ },
+ .encode = .{ .sbfm, .Wd, .Wn, .{ .N = .word, .immr = .shift, .imms = 31 } },
+ },
+ .{
+ .pattern = "ASR , , #",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
+ },
+ .encode = .{ .sbfm, .Xd, .Xn, .{ .N = .doubleword, .immr = .shift, .imms = 63 } },
+ },
+ // C6.2.18 ASRV
+ .{
+ .pattern = "ASRV , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .asrv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "ASRV , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .asrv, .Xd, .Xn, .Xm },
+ },
// C6.2.35 BLR
.{
.pattern = "BLR ",
@@ -681,6 +738,82 @@
},
.encode = .{ .ldr, .Xt, .{ .unsigned_offset = .{ .base = .Xn, .offset = .pimm } } },
},
+ // C6.2.212 LSL (register)
+ .{
+ .pattern = "LSL , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .lslv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "LSL , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .lslv, .Xd, .Xn, .Xm },
+ },
+ // C6.2.214 LSLV
+ .{
+ .pattern = "LSLV , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .lslv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "LSLV , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .lslv, .Xd, .Xn, .Xm },
+ },
+ // C6.2.215 LSR (register)
+ .{
+ .pattern = "LSR , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .lsrv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "LSR , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .lsrv, .Xd, .Xn, .Xm },
+ },
+ // C6.2.217 LSRV
+ .{
+ .pattern = "LSRV , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .lsrv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "LSRV , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .lsrv, .Xd, .Xn, .Xm },
+ },
// C6.2.220 MOV (to/from SP)
.{
.pattern = "MOV WSP, ",
@@ -964,6 +1097,63 @@
},
.encode = .{ .ret, .Xn },
},
+ // C6.2.261 ROR (immediate)
+ .{
+ .pattern = "ROR , , #",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Ws = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 5 } } },
+ },
+ .encode = .{ .extr, .Wd, .Ws, .Ws, .shift },
+ },
+ .{
+ .pattern = "ROR , , #",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xs = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .shift = .{ .imm = .{ .type = .{ .signedness = .unsigned, .bits = 6 } } },
+ },
+ .encode = .{ .extr, .Xd, .Xs, .Xs, .shift },
+ },
+ // C6.2.262 ROR (register)
+ .{
+ .pattern = "ROR , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .rorv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "ROR , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .rorv, .Xd, .Xn, .Xm },
+ },
+ // C6.2.263 RORV
+ .{
+ .pattern = "RORV , , ",
+ .symbols = .{
+ .Wd = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wn = .{ .reg = .{ .format = .{ .integer = .word } } },
+ .Wm = .{ .reg = .{ .format = .{ .integer = .word } } },
+ },
+ .encode = .{ .rorv, .Wd, .Wn, .Wm },
+ },
+ .{
+ .pattern = "RORV , , ",
+ .symbols = .{
+ .Xd = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xn = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ .Xm = .{ .reg = .{ .format = .{ .integer = .doubleword } } },
+ },
+ .encode = .{ .rorv, .Xd, .Xn, .Xm },
+ },
// C6.2.268 SBFM
.{
.pattern = "SBFM , , #, #",
diff --git a/src/target.zig b/src/target.zig
index e59c3eda05..ad83414c23 100644
--- a/src/target.zig
+++ b/src/target.zig
@@ -248,9 +248,13 @@ pub fn selfHostedBackendIsAsRobustAsLlvm(target: *const std.Target) bool {
return false;
}
-pub fn supportsStackProbing(target: *const std.Target) bool {
- return target.os.tag != .windows and target.os.tag != .uefi and
- (target.cpu.arch == .x86 or target.cpu.arch == .x86_64);
+pub fn supportsStackProbing(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
+ return switch (backend) {
+ .stage2_aarch64, .stage2_x86_64 => true,
+ .stage2_llvm => target.os.tag != .windows and target.os.tag != .uefi and
+ (target.cpu.arch == .x86 or target.cpu.arch == .x86_64),
+ else => false,
+ };
}
pub fn supportsStackProtector(target: *const std.Target, backend: std.builtin.CompilerBackend) bool {
@@ -347,7 +351,7 @@ pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.builtin.Opti
}
}
-pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {
+pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
switch (target.os.tag) {
.plan9 => return false,
else => {},
@@ -369,7 +373,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target, use_llvm: bool, comptime
};
}
-pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime have_llvm: bool) bool {
+pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, have_llvm: bool) bool {
switch (target.cpu.arch) {
.spirv32, .spirv64 => return false,
// Remove this once https://github.com/ziglang/zig/issues/23715 is fixed
@@ -378,6 +382,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target, use_llvm: bool, comptime ha
}
return switch (zigBackend(target, use_llvm)) {
.stage2_llvm => true,
+ .stage2_wasm => false,
.stage2_x86_64 => switch (target.ofmt) {
.elf, .macho => true,
else => have_llvm,
@@ -856,6 +861,7 @@ pub fn zigBackend(target: *const std.Target, use_llvm: bool) std.builtin.Compile
pub inline fn backendSupportsFeature(backend: std.builtin.CompilerBackend, comptime feature: Feature) bool {
return switch (feature) {
.panic_fn => switch (backend) {
+ .stage2_aarch64,
.stage2_c,
.stage2_llvm,
.stage2_x86_64,
diff --git a/test/behavior/decl_literals.zig b/test/behavior/decl_literals.zig
index 169c705a6b..f96f461771 100644
--- a/test/behavior/decl_literals.zig
+++ b/test/behavior/decl_literals.zig
@@ -33,7 +33,6 @@ test "decl literal with pointer" {
}
test "call decl literal with optional" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -74,7 +73,6 @@ test "call decl literal" {
}
test "call decl literal with error union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
const S = struct {
diff --git a/test/behavior/error.zig b/test/behavior/error.zig
index eff2cf855f..ae99c0a7e8 100644
--- a/test/behavior/error.zig
+++ b/test/behavior/error.zig
@@ -590,7 +590,6 @@ test "error union comptime caching" {
}
test "@errorName" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -605,7 +604,6 @@ fn gimmeItBroke() anyerror {
}
test "@errorName sentinel length matches slice length" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -883,7 +881,6 @@ test "catch within a function that calls no errorable functions" {
}
test "error from comptime string" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -946,7 +943,6 @@ test "optional error set function parameter" {
}
test "returning an error union containing a type with no runtime bits" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig
index 59742cf3f6..742b306059 100644
--- a/test/behavior/field_parent_ptr.zig
+++ b/test/behavior/field_parent_ptr.zig
@@ -587,7 +587,6 @@ test "@fieldParentPtr extern struct last zero-bit field" {
}
test "@fieldParentPtr unaligned packed struct" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -726,7 +725,6 @@ test "@fieldParentPtr unaligned packed struct" {
}
test "@fieldParentPtr aligned packed struct" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/inline_switch.zig b/test/behavior/inline_switch.zig
index a6f664ded8..a1efe7ab02 100644
--- a/test/behavior/inline_switch.zig
+++ b/test/behavior/inline_switch.zig
@@ -43,7 +43,6 @@ test "inline switch enums" {
const U = union(E) { a: void, b: u2, c: u3, d: u4 };
test "inline switch unions" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -105,7 +104,6 @@ test "inline else enum" {
}
test "inline else int with gaps" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO
diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig
index 3a63dfb1ac..11d4ee0537 100644
--- a/test/behavior/optional.zig
+++ b/test/behavior/optional.zig
@@ -319,7 +319,6 @@ test "assigning to an unwrapped optional field in an inline loop" {
}
test "coerce an anon struct literal to optional struct" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -447,7 +446,6 @@ test "optional pointer to zero bit optional payload" {
}
test "optional pointer to zero bit error union payload" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/return_address.zig b/test/behavior/return_address.zig
index ba342956b3..d7fb76d3b0 100644
--- a/test/behavior/return_address.zig
+++ b/test/behavior/return_address.zig
@@ -6,7 +6,6 @@ fn retAddr() usize {
}
test "return address" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig
index ba69ae0990..3c4c4d7f80 100644
--- a/test/behavior/struct.zig
+++ b/test/behavior/struct.zig
@@ -797,7 +797,6 @@ test "fn with C calling convention returns struct by value" {
}
test "non-packed struct with u128 entry in union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -1026,7 +1025,6 @@ test "packed struct with undefined initializers" {
}
test "for loop over pointers to struct, getting field from struct pointer" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1093,7 +1091,6 @@ test "anon init through error unions and optionals" {
}
test "anon init through optional" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -1113,7 +1110,6 @@ test "anon init through optional" {
}
test "anon init through error union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -1398,7 +1394,6 @@ test "struct has only one reference" {
}
test "no dependency loop on pointer to optional struct" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig
index 764080b937..0d0cb0e4f4 100644
--- a/test/behavior/switch.zig
+++ b/test/behavior/switch.zig
@@ -8,7 +8,6 @@ const minInt = std.math.minInt;
const maxInt = std.math.maxInt;
test "switch with numbers" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -300,7 +299,6 @@ fn switchProngWithVarFn(a: SwitchProngWithVarEnum) !void {
}
test "switch on enum using pointer capture" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -361,7 +359,6 @@ fn testSwitchHandleAllCasesRange(x: u8) u8 {
}
test "switch on union with some prongs capturing" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -976,8 +973,6 @@ test "switch prong captures range" {
}
test "prong with inline call to unreachable" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
const U = union(enum) {
void: void,
bool: bool,
diff --git a/test/behavior/switch_on_captured_error.zig b/test/behavior/switch_on_captured_error.zig
index 75a4280d62..9aae1c7fbe 100644
--- a/test/behavior/switch_on_captured_error.zig
+++ b/test/behavior/switch_on_captured_error.zig
@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
const builtin = @import("builtin");
test "switch on error union catch capture" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
diff --git a/test/behavior/union.zig b/test/behavior/union.zig
index bbace0f706..fb05b9edbb 100644
--- a/test/behavior/union.zig
+++ b/test/behavior/union.zig
@@ -160,7 +160,6 @@ test "unions embedded in aggregate types" {
}
test "constant tagged union with payload" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -263,7 +262,6 @@ fn testComparison() !void {
}
test "comparison between union and enum literal" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -279,7 +277,6 @@ const TheUnion = union(TheTag) {
C: i32,
};
test "cast union to tag type of union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -300,7 +297,6 @@ test "union field access gives the enum values" {
}
test "cast tag type of union to union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -316,7 +312,6 @@ const Value2 = union(Letter2) {
};
test "implicit cast union to its tag type" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -495,7 +490,6 @@ test "initialize global array of union" {
}
test "update the tag value for zero-sized unions" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -734,7 +728,6 @@ test "union with only 1 field casted to its enum type which has enum value speci
}
test "@intFromEnum works on unions" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -848,7 +841,6 @@ test "@unionInit stored to a const" {
}
test "@unionInit can modify a union type" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -871,7 +863,6 @@ test "@unionInit can modify a union type" {
}
test "@unionInit can modify a pointer value" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -990,7 +981,6 @@ test "function call result coerces from tagged union to the tag" {
}
test "switching on non exhaustive union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1176,7 +1166,6 @@ test "comptime equality of extern unions with same tag" {
}
test "union tag is set when initiated as a temporary value at runtime" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
@@ -1216,7 +1205,6 @@ test "extern union most-aligned field is smaller" {
}
test "return an extern union from C calling convention" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
@@ -1248,7 +1236,6 @@ test "return an extern union from C calling convention" {
}
test "noreturn field in union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
@@ -1481,8 +1468,6 @@ test "reinterpreting enum value inside packed union" {
}
test "access the tag of a global tagged union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
const U = union(enum) {
a,
b: u8,
@@ -2111,7 +2096,6 @@ test "runtime union init, most-aligned field != largest" {
}
test "copied union field doesn't alias source" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
@@ -2334,8 +2318,6 @@ test "assign global tagged union" {
}
test "set mutable union by switching on same union" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
const U = union(enum) {
foo,
bar: usize,
diff --git a/test/behavior/union_with_members.zig b/test/behavior/union_with_members.zig
index 288d47d9cb..9303ac14da 100644
--- a/test/behavior/union_with_members.zig
+++ b/test/behavior/union_with_members.zig
@@ -17,7 +17,6 @@ const ET = union(enum) {
};
test "enum with members" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/behavior/while.zig b/test/behavior/while.zig
index db3d299b55..d6323babf5 100644
--- a/test/behavior/while.zig
+++ b/test/behavior/while.zig
@@ -344,7 +344,6 @@ test "else continue outer while" {
}
test "try terminating an infinite loop" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
diff --git a/test/cases/array_in_anon_struct.zig b/test/cases/array_in_anon_struct.zig
index 5961b3f723..8c4f5ea051 100644
--- a/test/cases/array_in_anon_struct.zig
+++ b/test/cases/array_in_anon_struct.zig
@@ -19,4 +19,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig
index 8bbc3154a1..5f42b7d9af 100644
--- a/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig
+++ b/test/cases/compile_errors/callconv_interrupt_on_unsupported_platform.zig
@@ -7,5 +7,5 @@ export fn entry3() callconv(.avr_interrupt) void {}
// target=aarch64-linux-none
//
// :1:30: error: calling convention 'x86_64_interrupt' only available on architectures 'x86_64'
-// :1:30: error: calling convention 'x86_interrupt' only available on architectures 'x86'
-// :1:30: error: calling convention 'avr_interrupt' only available on architectures 'avr'
+// :2:30: error: calling convention 'x86_interrupt' only available on architectures 'x86'
+// :3:30: error: calling convention 'avr_interrupt' only available on architectures 'avr'
diff --git a/test/cases/compile_errors/error_set_membership.zig b/test/cases/compile_errors/error_set_membership.zig
index 67826f4db9..a146bd39ba 100644
--- a/test/cases/compile_errors/error_set_membership.zig
+++ b/test/cases/compile_errors/error_set_membership.zig
@@ -25,7 +25,7 @@ pub fn main() Error!void {
// error
// backend=stage2
-// target=native
+// target=x86_64-linux
//
// :23:29: error: expected type 'error{InvalidCharacter}', found '@typeInfo(@typeInfo(@TypeOf(tmp.fooey)).@"fn".return_type.?).error_union.error_set'
// :23:29: note: 'error.InvalidDirection' not a member of destination error set
diff --git a/test/cases/compile_errors/function_ptr_alignment.zig b/test/cases/compile_errors/function_ptr_alignment.zig
index cf97e61f40..fd8aec06d0 100644
--- a/test/cases/compile_errors/function_ptr_alignment.zig
+++ b/test/cases/compile_errors/function_ptr_alignment.zig
@@ -10,7 +10,7 @@ comptime {
// error
// backend=stage2
-// target=native
+// target=x86_64-linux
//
// :8:41: error: expected type '*align(2) const fn () void', found '*const fn () void'
// :8:41: note: pointer alignment '1' cannot cast into pointer alignment '2'
diff --git a/test/cases/compile_errors/issue_15572_break_on_inline_while.zig b/test/cases/compile_errors/issue_15572_break_on_inline_while.zig
index f264e695c0..69d5c11eab 100644
--- a/test/cases/compile_errors/issue_15572_break_on_inline_while.zig
+++ b/test/cases/compile_errors/issue_15572_break_on_inline_while.zig
@@ -15,6 +15,6 @@ pub fn main() void {
// error
// backend=stage2
-// target=native
+// target=x86_64-linux
//
// :9:28: error: incompatible types: 'builtin.Type.EnumField' and 'void'
diff --git a/test/cases/compile_errors/switch_on_non_err_union.zig b/test/cases/compile_errors/switch_on_non_err_union.zig
index 87624b21dc..e79a181e62 100644
--- a/test/cases/compile_errors/switch_on_non_err_union.zig
+++ b/test/cases/compile_errors/switch_on_non_err_union.zig
@@ -6,6 +6,6 @@ pub fn main() void {
// error
// backend=stage2
-// target=native
+// target=x86_64-linux
//
// :2:23: error: expected error union type, found 'bool'
diff --git a/test/cases/pic_freestanding.zig b/test/cases/pic_freestanding.zig
index 86e37662e2..eda1399887 100644
--- a/test/cases/pic_freestanding.zig
+++ b/test/cases/pic_freestanding.zig
@@ -1,7 +1,7 @@
const builtin = @import("builtin");
const std = @import("std");
-fn _start() callconv(.naked) void {}
+pub fn _start() callconv(.naked) void {}
comptime {
@export(&_start, .{ .name = if (builtin.cpu.arch.isMIPS()) "__start" else "_start" });
diff --git a/test/cases/safety/@alignCast misaligned.zig b/test/cases/safety/@alignCast misaligned.zig
index e523a9d120..017c46a98d 100644
--- a/test/cases/safety/@alignCast misaligned.zig
+++ b/test/cases/safety/@alignCast misaligned.zig
@@ -22,4 +22,4 @@ fn foo(bytes: []u8) u32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@enumFromInt - no matching tag value.zig b/test/cases/safety/@enumFromInt - no matching tag value.zig
index 0021a4d397..7953b93358 100644
--- a/test/cases/safety/@enumFromInt - no matching tag value.zig
+++ b/test/cases/safety/@enumFromInt - no matching tag value.zig
@@ -23,4 +23,4 @@ fn baz(_: Foo) void {}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@enumFromInt truncated bits - exhaustive.zig b/test/cases/safety/@enumFromInt truncated bits - exhaustive.zig
index 92065c4892..ace1e08d11 100644
--- a/test/cases/safety/@enumFromInt truncated bits - exhaustive.zig
+++ b/test/cases/safety/@enumFromInt truncated bits - exhaustive.zig
@@ -20,4 +20,4 @@ pub fn main() u8 {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig b/test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig
index 25959c9ffd..8f20081610 100644
--- a/test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig
+++ b/test/cases/safety/@enumFromInt truncated bits - nonexhaustive.zig
@@ -20,4 +20,4 @@ pub fn main() u8 {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@errorCast error not present in destination.zig b/test/cases/safety/@errorCast error not present in destination.zig
index 74e81f2a60..a121d3e6e8 100644
--- a/test/cases/safety/@errorCast error not present in destination.zig
+++ b/test/cases/safety/@errorCast error not present in destination.zig
@@ -18,4 +18,4 @@ fn foo(set1: Set1) Set2 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@errorCast error union casted to disjoint set.zig b/test/cases/safety/@errorCast error union casted to disjoint set.zig
index 2696a037c7..a84f61d8e5 100644
--- a/test/cases/safety/@errorCast error union casted to disjoint set.zig
+++ b/test/cases/safety/@errorCast error union casted to disjoint set.zig
@@ -17,4 +17,4 @@ fn foo() anyerror!i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intCast to u0.zig b/test/cases/safety/@intCast to u0.zig
index 4394f63f54..219f42f213 100644
--- a/test/cases/safety/@intCast to u0.zig
+++ b/test/cases/safety/@intCast to u0.zig
@@ -19,4 +19,4 @@ fn bar(one: u1, not_zero: i32) void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig
index 38ec595b45..70f0cebb93 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 max.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig
index 97a651855b..bc35aa6e23 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - i0 min.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig
index cc19ee84ff..56e87423a1 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - signed max.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig
index abc95e396a..61704a8733 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - signed min.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig
index f488d0291f..361a528498 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 max.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig
index 8d459e1a5c..5706d192d5 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - u0 min.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig
index 95122abc8c..842aaaa1de 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned max.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig
index fbc7cf18ac..c1e8af2f5e 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - unsigned min.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig
index 35b4c91509..96e1c5594e 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - vector max.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig b/test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig
index 94ad509772..cf17014d3f 100644
--- a/test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - boundary case - vector min.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - negative out of range.zig b/test/cases/safety/@intFromFloat cannot fit - negative out of range.zig
index 80edbdfd3c..23d9f87ac1 100644
--- a/test/cases/safety/@intFromFloat cannot fit - negative out of range.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - negative out of range.zig
@@ -17,4 +17,4 @@ fn bar(a: f32) i8 {
fn baz(_: i8) void {}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig b/test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig
index ee0c040273..9d28ee0aaa 100644
--- a/test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - negative to unsigned.zig
@@ -17,4 +17,4 @@ fn bar(a: f32) u8 {
fn baz(_: u8) void {}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@intFromFloat cannot fit - positive out of range.zig b/test/cases/safety/@intFromFloat cannot fit - positive out of range.zig
index c526a70047..2e76a9b253 100644
--- a/test/cases/safety/@intFromFloat cannot fit - positive out of range.zig
+++ b/test/cases/safety/@intFromFloat cannot fit - positive out of range.zig
@@ -17,4 +17,4 @@ fn bar(a: f32) u8 {
fn baz(_: u8) void {}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig b/test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig
index 4944a239e2..eb45f357dd 100644
--- a/test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig
+++ b/test/cases/safety/@ptrFromInt address zero to non-optional byte-aligned pointer.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig b/test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig
index a217de3073..308f97ad12 100644
--- a/test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig
+++ b/test/cases/safety/@ptrFromInt address zero to non-optional pointer.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@ptrFromInt with misaligned address.zig b/test/cases/safety/@ptrFromInt with misaligned address.zig
index b95c1b320f..1383a4c3c3 100644
--- a/test/cases/safety/@ptrFromInt with misaligned address.zig
+++ b/test/cases/safety/@ptrFromInt with misaligned address.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@tagName on corrupted enum value.zig b/test/cases/safety/@tagName on corrupted enum value.zig
index df6a3f45e0..450d0ee2e0 100644
--- a/test/cases/safety/@tagName on corrupted enum value.zig
+++ b/test/cases/safety/@tagName on corrupted enum value.zig
@@ -23,4 +23,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/@tagName on corrupted union value.zig b/test/cases/safety/@tagName on corrupted union value.zig
index 7b856e57b9..b61a72420e 100644
--- a/test/cases/safety/@tagName on corrupted union value.zig
+++ b/test/cases/safety/@tagName on corrupted union value.zig
@@ -24,4 +24,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/array slice sentinel mismatch vector.zig b/test/cases/safety/array slice sentinel mismatch vector.zig
index 55ff4b3e39..f374f1b9d5 100644
--- a/test/cases/safety/array slice sentinel mismatch vector.zig
+++ b/test/cases/safety/array slice sentinel mismatch vector.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/array slice sentinel mismatch.zig b/test/cases/safety/array slice sentinel mismatch.zig
index ab7a513b39..deb43250ec 100644
--- a/test/cases/safety/array slice sentinel mismatch.zig
+++ b/test/cases/safety/array slice sentinel mismatch.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/bad union field access.zig b/test/cases/safety/bad union field access.zig
index 14ebb1f344..a2778237c4 100644
--- a/test/cases/safety/bad union field access.zig
+++ b/test/cases/safety/bad union field access.zig
@@ -24,4 +24,4 @@ fn bar(f: *Foo) void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/calling panic.zig b/test/cases/safety/calling panic.zig
index 7b8a478be3..7ac512eadc 100644
--- a/test/cases/safety/calling panic.zig
+++ b/test/cases/safety/calling panic.zig
@@ -13,4 +13,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/cast []u8 to bigger slice of wrong size.zig b/test/cases/safety/cast []u8 to bigger slice of wrong size.zig
index b6b8e89bf9..65dda78751 100644
--- a/test/cases/safety/cast []u8 to bigger slice of wrong size.zig
+++ b/test/cases/safety/cast []u8 to bigger slice of wrong size.zig
@@ -18,4 +18,4 @@ fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/cast integer to global error and no code matches.zig b/test/cases/safety/cast integer to global error and no code matches.zig
index fa0474a88c..2b9cadf811 100644
--- a/test/cases/safety/cast integer to global error and no code matches.zig
+++ b/test/cases/safety/cast integer to global error and no code matches.zig
@@ -16,4 +16,4 @@ fn bar(x: u16) anyerror {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/empty slice with sentinel out of bounds.zig b/test/cases/safety/empty slice with sentinel out of bounds.zig
index 51846f894f..2d9494826d 100644
--- a/test/cases/safety/empty slice with sentinel out of bounds.zig
+++ b/test/cases/safety/empty slice with sentinel out of bounds.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/exact division failure - vectors.zig b/test/cases/safety/exact division failure - vectors.zig
index 30d5dcf11a..398ae7a4cd 100644
--- a/test/cases/safety/exact division failure - vectors.zig
+++ b/test/cases/safety/exact division failure - vectors.zig
@@ -20,4 +20,4 @@ fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/exact division failure.zig b/test/cases/safety/exact division failure.zig
index be86853c77..0831bb4e09 100644
--- a/test/cases/safety/exact division failure.zig
+++ b/test/cases/safety/exact division failure.zig
@@ -18,4 +18,4 @@ fn divExact(a: i32, b: i32) i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/for_len_mismatch.zig b/test/cases/safety/for_len_mismatch.zig
index 8841f11aa7..55bb7bf8b5 100644
--- a/test/cases/safety/for_len_mismatch.zig
+++ b/test/cases/safety/for_len_mismatch.zig
@@ -22,4 +22,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/for_len_mismatch_three.zig b/test/cases/safety/for_len_mismatch_three.zig
index 4efe18d3cd..b4256b0eee 100644
--- a/test/cases/safety/for_len_mismatch_three.zig
+++ b/test/cases/safety/for_len_mismatch_three.zig
@@ -21,4 +21,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/ignored expression integer overflow.zig b/test/cases/safety/ignored expression integer overflow.zig
index 1089010854..859c615e42 100644
--- a/test/cases/safety/ignored expression integer overflow.zig
+++ b/test/cases/safety/ignored expression integer overflow.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/integer addition overflow.zig b/test/cases/safety/integer addition overflow.zig
index 499e8b1015..119800c686 100644
--- a/test/cases/safety/integer addition overflow.zig
+++ b/test/cases/safety/integer addition overflow.zig
@@ -20,4 +20,4 @@ fn add(a: u16, b: u16) u16 {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/integer division by zero - vectors.zig b/test/cases/safety/integer division by zero - vectors.zig
index 63e77a0dd4..d3ddfa06c6 100644
--- a/test/cases/safety/integer division by zero - vectors.zig
+++ b/test/cases/safety/integer division by zero - vectors.zig
@@ -19,4 +19,4 @@ fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/integer division by zero.zig b/test/cases/safety/integer division by zero.zig
index e8eba5c4f0..dc12dde343 100644
--- a/test/cases/safety/integer division by zero.zig
+++ b/test/cases/safety/integer division by zero.zig
@@ -17,4 +17,4 @@ fn div0(a: i32, b: i32) i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/integer multiplication overflow.zig b/test/cases/safety/integer multiplication overflow.zig
index f7f4148a15..4380ec6d51 100644
--- a/test/cases/safety/integer multiplication overflow.zig
+++ b/test/cases/safety/integer multiplication overflow.zig
@@ -18,4 +18,4 @@ fn mul(a: u16, b: u16) u16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/integer negation overflow.zig b/test/cases/safety/integer negation overflow.zig
index cfdfed0429..1c6610ae6f 100644
--- a/test/cases/safety/integer negation overflow.zig
+++ b/test/cases/safety/integer negation overflow.zig
@@ -18,4 +18,4 @@ fn neg(a: i16) i16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/integer subtraction overflow.zig b/test/cases/safety/integer subtraction overflow.zig
index 14e9131c3b..9211c877e4 100644
--- a/test/cases/safety/integer subtraction overflow.zig
+++ b/test/cases/safety/integer subtraction overflow.zig
@@ -18,4 +18,4 @@ fn sub(a: u16, b: u16) u16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memcpy_alias.zig b/test/cases/safety/memcpy_alias.zig
index f7a1a16024..62c30ec459 100644
--- a/test/cases/safety/memcpy_alias.zig
+++ b/test/cases/safety/memcpy_alias.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memcpy_len_mismatch.zig b/test/cases/safety/memcpy_len_mismatch.zig
index 0ef22b959c..aa9b3fd63f 100644
--- a/test/cases/safety/memcpy_len_mismatch.zig
+++ b/test/cases/safety/memcpy_len_mismatch.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memmove_len_mismatch.zig b/test/cases/safety/memmove_len_mismatch.zig
index 881af9f336..fa22597122 100644
--- a/test/cases/safety/memmove_len_mismatch.zig
+++ b/test/cases/safety/memmove_len_mismatch.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memset_array_undefined_bytes.zig b/test/cases/safety/memset_array_undefined_bytes.zig
index 20a65d65d6..47865a8def 100644
--- a/test/cases/safety/memset_array_undefined_bytes.zig
+++ b/test/cases/safety/memset_array_undefined_bytes.zig
@@ -15,4 +15,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memset_array_undefined_large.zig b/test/cases/safety/memset_array_undefined_large.zig
index a52bfecbf0..10f57521cf 100644
--- a/test/cases/safety/memset_array_undefined_large.zig
+++ b/test/cases/safety/memset_array_undefined_large.zig
@@ -15,4 +15,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memset_slice_undefined_bytes.zig b/test/cases/safety/memset_slice_undefined_bytes.zig
index fb67999306..4d76bbc414 100644
--- a/test/cases/safety/memset_slice_undefined_bytes.zig
+++ b/test/cases/safety/memset_slice_undefined_bytes.zig
@@ -17,4 +17,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/memset_slice_undefined_large.zig b/test/cases/safety/memset_slice_undefined_large.zig
index 166557240c..e404e35226 100644
--- a/test/cases/safety/memset_slice_undefined_large.zig
+++ b/test/cases/safety/memset_slice_undefined_large.zig
@@ -17,4 +17,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/modrem by zero.zig b/test/cases/safety/modrem by zero.zig
index 35b7e37e3a..fac10065ed 100644
--- a/test/cases/safety/modrem by zero.zig
+++ b/test/cases/safety/modrem by zero.zig
@@ -17,4 +17,4 @@ fn div0(a: u32, b: u32) u32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/modulus by zero.zig b/test/cases/safety/modulus by zero.zig
index cdeab00dbc..1c0c8ba3a9 100644
--- a/test/cases/safety/modulus by zero.zig
+++ b/test/cases/safety/modulus by zero.zig
@@ -17,4 +17,4 @@ fn mod0(a: i32, b: i32) i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/noreturn returned.zig b/test/cases/safety/noreturn returned.zig
index c92fb08e62..b91a6def49 100644
--- a/test/cases/safety/noreturn returned.zig
+++ b/test/cases/safety/noreturn returned.zig
@@ -20,4 +20,4 @@ pub fn main() void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/optional unwrap operator on C pointer.zig b/test/cases/safety/optional unwrap operator on C pointer.zig
index 98135cfae4..4deb62bc25 100644
--- a/test/cases/safety/optional unwrap operator on C pointer.zig
+++ b/test/cases/safety/optional unwrap operator on C pointer.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/optional unwrap operator on null pointer.zig b/test/cases/safety/optional unwrap operator on null pointer.zig
index 6ac54e6bd0..97d07626f5 100644
--- a/test/cases/safety/optional unwrap operator on null pointer.zig
+++ b/test/cases/safety/optional unwrap operator on null pointer.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/optional_empty_error_set.zig b/test/cases/safety/optional_empty_error_set.zig
index dbe39d00c3..1ee1690d51 100644
--- a/test/cases/safety/optional_empty_error_set.zig
+++ b/test/cases/safety/optional_empty_error_set.zig
@@ -19,4 +19,4 @@ fn foo() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/out of bounds array slice by length.zig b/test/cases/safety/out of bounds array slice by length.zig
index 325749a5eb..df613b1d53 100644
--- a/test/cases/safety/out of bounds array slice by length.zig
+++ b/test/cases/safety/out of bounds array slice by length.zig
@@ -17,4 +17,4 @@ fn foo(a: u32) u32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/out of bounds slice access.zig b/test/cases/safety/out of bounds slice access.zig
index f4f34a203f..d5ebf6d531 100644
--- a/test/cases/safety/out of bounds slice access.zig
+++ b/test/cases/safety/out of bounds slice access.zig
@@ -18,4 +18,4 @@ fn bar(a: []const i32) i32 {
fn baz(_: i32) void {}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/pointer casting null to non-optional pointer.zig b/test/cases/safety/pointer casting null to non-optional pointer.zig
index 33da071e73..ef61f162b4 100644
--- a/test/cases/safety/pointer casting null to non-optional pointer.zig
+++ b/test/cases/safety/pointer casting null to non-optional pointer.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/pointer casting to null function pointer.zig b/test/cases/safety/pointer casting to null function pointer.zig
index a57e71cb8f..1ce1ebc266 100644
--- a/test/cases/safety/pointer casting to null function pointer.zig
+++ b/test/cases/safety/pointer casting to null function pointer.zig
@@ -20,4 +20,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/pointer slice sentinel mismatch.zig b/test/cases/safety/pointer slice sentinel mismatch.zig
index 519b04b916..a400c0bc35 100644
--- a/test/cases/safety/pointer slice sentinel mismatch.zig
+++ b/test/cases/safety/pointer slice sentinel mismatch.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/remainder division by zero.zig b/test/cases/safety/remainder division by zero.zig
index 2d938a2fd6..3749c3d5d7 100644
--- a/test/cases/safety/remainder division by zero.zig
+++ b/test/cases/safety/remainder division by zero.zig
@@ -17,4 +17,4 @@ fn rem0(a: i32, b: i32) i32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/shift left by huge amount.zig b/test/cases/safety/shift left by huge amount.zig
index 374b03d123..b6b88ba870 100644
--- a/test/cases/safety/shift left by huge amount.zig
+++ b/test/cases/safety/shift left by huge amount.zig
@@ -19,4 +19,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/shift right by huge amount.zig b/test/cases/safety/shift right by huge amount.zig
index 173e6fcd7e..664e2b5473 100644
--- a/test/cases/safety/shift right by huge amount.zig
+++ b/test/cases/safety/shift right by huge amount.zig
@@ -19,4 +19,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/signed integer division overflow - vectors.zig b/test/cases/safety/signed integer division overflow - vectors.zig
index 0de062094d..7a696c4b4d 100644
--- a/test/cases/safety/signed integer division overflow - vectors.zig
+++ b/test/cases/safety/signed integer division overflow - vectors.zig
@@ -20,4 +20,4 @@ fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/signed integer division overflow.zig b/test/cases/safety/signed integer division overflow.zig
index 0d67f72649..acbb3d4e16 100644
--- a/test/cases/safety/signed integer division overflow.zig
+++ b/test/cases/safety/signed integer division overflow.zig
@@ -18,4 +18,4 @@ fn div(a: i16, b: i16) i16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig b/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
index fa0eec94c0..f47083d4df 100644
--- a/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
+++ b/test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig b/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
index 6ce662cdc7..881b3c1631 100644
--- a/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
+++ b/test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
@@ -17,4 +17,4 @@ fn unsigned_cast(x: i32) u32 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/signed shift left overflow.zig b/test/cases/safety/signed shift left overflow.zig
index 54a51e0ccd..0cab01ca02 100644
--- a/test/cases/safety/signed shift left overflow.zig
+++ b/test/cases/safety/signed shift left overflow.zig
@@ -18,4 +18,4 @@ fn shl(a: i16, b: u4) i16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/signed shift right overflow.zig b/test/cases/safety/signed shift right overflow.zig
index 1a0c5973c9..9fe3fe7873 100644
--- a/test/cases/safety/signed shift right overflow.zig
+++ b/test/cases/safety/signed shift right overflow.zig
@@ -18,4 +18,4 @@ fn shr(a: i16, b: u4) i16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/signed-unsigned vector cast.zig b/test/cases/safety/signed-unsigned vector cast.zig
index 919562b06c..22d4073694 100644
--- a/test/cases/safety/signed-unsigned vector cast.zig
+++ b/test/cases/safety/signed-unsigned vector cast.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/slice by length sentinel mismatch on lhs.zig b/test/cases/safety/slice by length sentinel mismatch on lhs.zig
index c66a968d4b..85785ce769 100644
--- a/test/cases/safety/slice by length sentinel mismatch on lhs.zig
+++ b/test/cases/safety/slice by length sentinel mismatch on lhs.zig
@@ -15,4 +15,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice by length sentinel mismatch on rhs.zig b/test/cases/safety/slice by length sentinel mismatch on rhs.zig
index a4a2189a9c..64fe818d1e 100644
--- a/test/cases/safety/slice by length sentinel mismatch on rhs.zig
+++ b/test/cases/safety/slice by length sentinel mismatch on rhs.zig
@@ -15,4 +15,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice sentinel mismatch - floats.zig b/test/cases/safety/slice sentinel mismatch - floats.zig
index be63272f0c..b31855ab42 100644
--- a/test/cases/safety/slice sentinel mismatch - floats.zig
+++ b/test/cases/safety/slice sentinel mismatch - floats.zig
@@ -17,4 +17,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/slice sentinel mismatch - optional pointers.zig b/test/cases/safety/slice sentinel mismatch - optional pointers.zig
index 38ab78b2c1..4337fe448d 100644
--- a/test/cases/safety/slice sentinel mismatch - optional pointers.zig
+++ b/test/cases/safety/slice sentinel mismatch - optional pointers.zig
@@ -17,4 +17,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice slice sentinel mismatch.zig b/test/cases/safety/slice slice sentinel mismatch.zig
index 51d4c16596..76224f966d 100644
--- a/test/cases/safety/slice slice sentinel mismatch.zig
+++ b/test/cases/safety/slice slice sentinel mismatch.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice start index greater than end index.zig b/test/cases/safety/slice start index greater than end index.zig
index a6dde3ac63..684020b8a7 100644
--- a/test/cases/safety/slice start index greater than end index.zig
+++ b/test/cases/safety/slice start index greater than end index.zig
@@ -21,4 +21,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice with sentinel out of bounds - runtime len.zig b/test/cases/safety/slice with sentinel out of bounds - runtime len.zig
index 7039f541e3..b9ef281144 100644
--- a/test/cases/safety/slice with sentinel out of bounds - runtime len.zig
+++ b/test/cases/safety/slice with sentinel out of bounds - runtime len.zig
@@ -20,4 +20,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice with sentinel out of bounds.zig b/test/cases/safety/slice with sentinel out of bounds.zig
index 8439e8c737..f07d393a0e 100644
--- a/test/cases/safety/slice with sentinel out of bounds.zig
+++ b/test/cases/safety/slice with sentinel out of bounds.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice_cast_change_len_0.zig b/test/cases/safety/slice_cast_change_len_0.zig
index d32bdfc920..96d94cfad5 100644
--- a/test/cases/safety/slice_cast_change_len_0.zig
+++ b/test/cases/safety/slice_cast_change_len_0.zig
@@ -24,4 +24,4 @@ const std = @import("std");
// run
// backend=stage2,llvm
-// target=x86_64-linux
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice_cast_change_len_1.zig b/test/cases/safety/slice_cast_change_len_1.zig
index 5d3728bcdc..21a1d69558 100644
--- a/test/cases/safety/slice_cast_change_len_1.zig
+++ b/test/cases/safety/slice_cast_change_len_1.zig
@@ -24,4 +24,4 @@ const std = @import("std");
// run
// backend=stage2,llvm
-// target=x86_64-linux
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slice_cast_change_len_2.zig b/test/cases/safety/slice_cast_change_len_2.zig
index 3a25d27504..5da254e903 100644
--- a/test/cases/safety/slice_cast_change_len_2.zig
+++ b/test/cases/safety/slice_cast_change_len_2.zig
@@ -24,4 +24,4 @@ const std = @import("std");
// run
// backend=stage2,llvm
-// target=x86_64-linux
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slicing null C pointer - runtime len.zig b/test/cases/safety/slicing null C pointer - runtime len.zig
index 763553b04a..831224edee 100644
--- a/test/cases/safety/slicing null C pointer - runtime len.zig
+++ b/test/cases/safety/slicing null C pointer - runtime len.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/slicing null C pointer.zig b/test/cases/safety/slicing null C pointer.zig
index a928fd585f..53da877c59 100644
--- a/test/cases/safety/slicing null C pointer.zig
+++ b/test/cases/safety/slicing null C pointer.zig
@@ -17,4 +17,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/switch else on corrupt enum value - one prong.zig b/test/cases/safety/switch else on corrupt enum value - one prong.zig
index 73f6ed9dc8..b2ef933080 100644
--- a/test/cases/safety/switch else on corrupt enum value - one prong.zig
+++ b/test/cases/safety/switch else on corrupt enum value - one prong.zig
@@ -21,4 +21,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/switch else on corrupt enum value - union.zig b/test/cases/safety/switch else on corrupt enum value - union.zig
index 77dacd86c6..933f7995a5 100644
--- a/test/cases/safety/switch else on corrupt enum value - union.zig
+++ b/test/cases/safety/switch else on corrupt enum value - union.zig
@@ -26,4 +26,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/switch else on corrupt enum value.zig b/test/cases/safety/switch else on corrupt enum value.zig
index 228e3c70ec..300de27e93 100644
--- a/test/cases/safety/switch else on corrupt enum value.zig
+++ b/test/cases/safety/switch else on corrupt enum value.zig
@@ -20,4 +20,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/switch on corrupted enum value.zig b/test/cases/safety/switch on corrupted enum value.zig
index 4d46d2e7a7..74ec3a4057 100644
--- a/test/cases/safety/switch on corrupted enum value.zig
+++ b/test/cases/safety/switch on corrupted enum value.zig
@@ -24,4 +24,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/switch on corrupted union value.zig b/test/cases/safety/switch on corrupted union value.zig
index 0f622dcbd8..cede4feb04 100644
--- a/test/cases/safety/switch on corrupted union value.zig
+++ b/test/cases/safety/switch on corrupted union value.zig
@@ -24,4 +24,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/truncating vector cast.zig b/test/cases/safety/truncating vector cast.zig
index 9b222e6918..f6271a094e 100644
--- a/test/cases/safety/truncating vector cast.zig
+++ b/test/cases/safety/truncating vector cast.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/unreachable.zig b/test/cases/safety/unreachable.zig
index fc1e886540..1094123cba 100644
--- a/test/cases/safety/unreachable.zig
+++ b/test/cases/safety/unreachable.zig
@@ -12,4 +12,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig b/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
index 185cde9973..7f27c5fcd5 100644
--- a/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
+++ b/test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
@@ -16,4 +16,4 @@ pub fn main() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/unsigned shift left overflow.zig b/test/cases/safety/unsigned shift left overflow.zig
index e2f58f0f3b..1098a80c8e 100644
--- a/test/cases/safety/unsigned shift left overflow.zig
+++ b/test/cases/safety/unsigned shift left overflow.zig
@@ -18,4 +18,4 @@ fn shl(a: u16, b: u4) u16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/unsigned shift right overflow.zig b/test/cases/safety/unsigned shift right overflow.zig
index 6ded52098d..e9ad8571b6 100644
--- a/test/cases/safety/unsigned shift right overflow.zig
+++ b/test/cases/safety/unsigned shift right overflow.zig
@@ -18,4 +18,4 @@ fn shr(a: u16, b: u4) u16 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/unsigned-signed vector cast.zig b/test/cases/safety/unsigned-signed vector cast.zig
index 6501643b36..5b3b58d928 100644
--- a/test/cases/safety/unsigned-signed vector cast.zig
+++ b/test/cases/safety/unsigned-signed vector cast.zig
@@ -18,4 +18,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/unwrap error switch.zig b/test/cases/safety/unwrap error switch.zig
index b3194bd2e0..a1a148cfd9 100644
--- a/test/cases/safety/unwrap error switch.zig
+++ b/test/cases/safety/unwrap error switch.zig
@@ -18,4 +18,4 @@ fn bar() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/unwrap error.zig b/test/cases/safety/unwrap error.zig
index 9fe7d437bc..dd157c8721 100644
--- a/test/cases/safety/unwrap error.zig
+++ b/test/cases/safety/unwrap error.zig
@@ -16,4 +16,4 @@ fn bar() !void {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/value does not fit in shortening cast - u0.zig b/test/cases/safety/value does not fit in shortening cast - u0.zig
index f29df8d8af..9d77b3f1c8 100644
--- a/test/cases/safety/value does not fit in shortening cast - u0.zig
+++ b/test/cases/safety/value does not fit in shortening cast - u0.zig
@@ -18,4 +18,4 @@ fn shorten_cast(x: u8) u0 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/value does not fit in shortening cast.zig b/test/cases/safety/value does not fit in shortening cast.zig
index 415ac95dbb..9b6af39967 100644
--- a/test/cases/safety/value does not fit in shortening cast.zig
+++ b/test/cases/safety/value does not fit in shortening cast.zig
@@ -18,4 +18,4 @@ fn shorten_cast(x: i32) i8 {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/vector integer addition overflow.zig b/test/cases/safety/vector integer addition overflow.zig
index db08d8b241..64f6e238e0 100644
--- a/test/cases/safety/vector integer addition overflow.zig
+++ b/test/cases/safety/vector integer addition overflow.zig
@@ -19,4 +19,4 @@ fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/vector integer multiplication overflow.zig b/test/cases/safety/vector integer multiplication overflow.zig
index 61176fd482..69d0dde16d 100644
--- a/test/cases/safety/vector integer multiplication overflow.zig
+++ b/test/cases/safety/vector integer multiplication overflow.zig
@@ -19,4 +19,4 @@ fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/vector integer negation overflow.zig b/test/cases/safety/vector integer negation overflow.zig
index f1f36ff294..72182cfdfc 100644
--- a/test/cases/safety/vector integer negation overflow.zig
+++ b/test/cases/safety/vector integer negation overflow.zig
@@ -19,4 +19,4 @@ fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/vector integer subtraction overflow.zig b/test/cases/safety/vector integer subtraction overflow.zig
index 9ba942469c..8ac2c6d756 100644
--- a/test/cases/safety/vector integer subtraction overflow.zig
+++ b/test/cases/safety/vector integer subtraction overflow.zig
@@ -19,4 +19,4 @@ fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/cases/safety/zero casted to error.zig b/test/cases/safety/zero casted to error.zig
index 1ffa995260..7a02ec2b71 100644
--- a/test/cases/safety/zero casted to error.zig
+++ b/test/cases/safety/zero casted to error.zig
@@ -16,4 +16,4 @@ fn bar(x: u16) anyerror {
}
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/taking_pointer_of_global_tagged_union.zig b/test/cases/taking_pointer_of_global_tagged_union.zig
index accb22667d..adc71d81c0 100644
--- a/test/cases/taking_pointer_of_global_tagged_union.zig
+++ b/test/cases/taking_pointer_of_global_tagged_union.zig
@@ -23,4 +23,4 @@ pub fn main() !void {
// run
// backend=stage2,llvm
-// target=native
+// target=x86_64-linux
diff --git a/test/src/Cases.zig b/test/src/Cases.zig
index bd93599171..60a564bc16 100644
--- a/test/src/Cases.zig
+++ b/test/src/Cases.zig
@@ -436,7 +436,7 @@ fn addFromDirInner(
const target = &resolved_target.result;
for (backends) |backend| {
if (backend == .stage2 and
- target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64)
+ target.cpu.arch != .aarch64 and target.cpu.arch != .wasm32 and target.cpu.arch != .x86_64 and target.cpu.arch != .spirv64)
{
// Other backends don't support new liveness format
continue;
@@ -447,10 +447,6 @@ fn addFromDirInner(
// Rosetta has issues with ZLD
continue;
}
- if (backend == .stage2 and target.ofmt == .coff) {
- // COFF linker has bitrotted
- continue;
- }
const next = ctx.cases.items.len;
try ctx.cases.append(.{