authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-07-27 11:42:09-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-27 11:42:09-07:00
log89cd42ee806cff64a21cd4eef6c87f0f7337f413
treea58ca0c2486476a333a2fedcf1458ebe42d77e31
parentda408bd6fce9e07daccd35f9257e6819f58fc767
parentb26e732bd0a33161b079202e9df9dda4b918b2bb
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24600 from jacobly0/aarch64

aarch64: continued progress

7 files changed, 513 insertions(+), 180 deletions(-)

src/codegen/aarch64.zig+31-21
......@@ -19,8 +19,12 @@ pub fn generate(
1919) !Mir {
2020 const zcu = pt.zcu;
2121 const gpa = zcu.gpa;
22 const ip = &zcu.intern_pool;
2223 const func = zcu.funcInfo(func_index);
23 const func_type = zcu.intern_pool.indexToKey(func.ty).func_type;
24 const func_zir = func.zir_body_inst.resolveFull(ip).?;
25 const file = zcu.fileByIndex(func_zir.file);
26 const named_params_len = file.zir.?.getParamBody(func_zir.inst).len;
27 const func_type = ip.indexToKey(func.ty).func_type;
2428 assert(liveness.* == null);
2529
2630 const mod = zcu.navFileScope(func.owner_nav).mod.?;
......@@ -61,23 +65,32 @@ pub fn generate(
6165 .values = .empty,
6266 };
6367 defer isel.deinit();
68 const is_sysv = !isel.target.os.tag.isDarwin() and isel.target.os.tag != .windows;
69 const is_sysv_var_args = is_sysv and func_type.is_var_args;
6470
6571 const air_main_body = air.getMainBody();
6672 var param_it: Select.CallAbiIterator = .init;
6773 const air_args = for (air_main_body, 0..) |air_inst_index, body_index| {
6874 if (air.instructions.items(.tag)[@intFromEnum(air_inst_index)] != .arg) break air_main_body[0..body_index];
69 const param_ty = air.instructions.items(.data)[@intFromEnum(air_inst_index)].arg.ty.toType();
70 const param_vi = try param_it.param(&isel, param_ty);
75 const arg = air.instructions.items(.data)[@intFromEnum(air_inst_index)].arg;
76 const param_ty = arg.ty.toType();
77 const param_vi = param_vi: {
78 if (arg.zir_param_index >= named_params_len) {
79 assert(func_type.is_var_args);
80 if (!is_sysv) break :param_vi try param_it.nonSysvVarArg(&isel, param_ty);
81 }
82 break :param_vi try param_it.param(&isel, param_ty);
83 };
7184 tracking_log.debug("${d} <- %{d}", .{ @intFromEnum(param_vi.?), @intFromEnum(air_inst_index) });
7285 try isel.live_values.putNoClobber(gpa, air_inst_index, param_vi.?);
7386 } else unreachable;
7487
7588 const saved_gra_start = if (mod.strip) param_it.ngrn else Select.CallAbiIterator.ngrn_start;
76 const saved_gra_end = if (func_type.is_var_args) Select.CallAbiIterator.ngrn_end else param_it.ngrn;
89 const saved_gra_end = if (is_sysv_var_args) Select.CallAbiIterator.ngrn_end else param_it.ngrn;
7790 const saved_gra_len = @intFromEnum(saved_gra_end) - @intFromEnum(saved_gra_start);
7891
7992 const saved_vra_start = if (mod.strip) param_it.nsrn else Select.CallAbiIterator.nsrn_start;
80 const saved_vra_end = if (func_type.is_var_args) Select.CallAbiIterator.nsrn_end else param_it.nsrn;
93 const saved_vra_end = if (is_sysv_var_args) Select.CallAbiIterator.nsrn_end else param_it.nsrn;
8194 const saved_vra_len = @intFromEnum(saved_vra_end) - @intFromEnum(saved_vra_start);
8295
8396 const frame_record = 2;
......@@ -85,11 +98,16 @@ pub fn generate(
8598 .base = .fp,
8699 .offset = 8 * std.mem.alignForward(u7, frame_record + saved_gra_len, 2),
87100 };
88 isel.va_list = .{
89 .__stack = named_stack_args.withOffset(param_it.nsaa),
90 .__gr_top = named_stack_args,
91 .__vr_top = .{ .base = .fp, .offset = 0 },
92 };
101 const stack_var_args = named_stack_args.withOffset(param_it.nsaa);
102 const gr_top = named_stack_args;
103 const vr_top: Select.Value.Indirect = .{ .base = .fp, .offset = 0 };
104 isel.va_list = if (is_sysv) .{ .sysv = .{
105 .__stack = stack_var_args,
106 .__gr_top = gr_top,
107 .__vr_top = vr_top,
108 .__gr_offs = @as(i32, @intFromEnum(Select.CallAbiIterator.ngrn_end) - @intFromEnum(param_it.ngrn)) * -8,
109 .__vr_offs = @as(i32, @intFromEnum(Select.CallAbiIterator.nsrn_end) - @intFromEnum(param_it.nsrn)) * -16,
110 } } else .{ .other = stack_var_args };
93111
94112 // translate arg locations from caller-based to callee-based
95113 for (air_args) |air_inst_index| {
......@@ -106,11 +124,9 @@ pub fn generate(
106124 const first_passed_part_vi = part_it.next().?;
107125 const hint_ra = first_passed_part_vi.hint(&isel).?;
108126 passed_vi.setParent(&isel, .{ .stack_slot = if (hint_ra.isVector())
109 isel.va_list.__vr_top.withOffset(@as(i8, -16) *
110 (@intFromEnum(saved_vra_end) - @intFromEnum(hint_ra)))
127 vr_top.withOffset(@as(i8, -16) * (@intFromEnum(saved_vra_end) - @intFromEnum(hint_ra)))
111128 else
112 isel.va_list.__gr_top.withOffset(@as(i8, -8) *
113 (@intFromEnum(saved_gra_end) - @intFromEnum(hint_ra))) });
129 gr_top.withOffset(@as(i8, -8) * (@intFromEnum(saved_gra_end) - @intFromEnum(hint_ra))) });
114130 },
115131 .stack_slot => |stack_slot| {
116132 assert(stack_slot.base == .sp);
......@@ -152,13 +168,7 @@ pub fn generate(
152168 isel.verify(true);
153169
154170 const prologue = isel.instructions.items.len;
155 const epilogue = try isel.layout(
156 param_it,
157 func_type.is_var_args,
158 saved_gra_len,
159 saved_vra_len,
160 mod,
161 );
171 const epilogue = try isel.layout(param_it, is_sysv_var_args, saved_gra_len, saved_vra_len, mod);
162172
163173 const instructions = try isel.instructions.toOwnedSlice(gpa);
164174 var mir: Mir = .{
src/codegen/aarch64/Select.zig+462-120
......@@ -28,10 +28,15 @@ literal_relocs: std.ArrayListUnmanaged(codegen.aarch64.Mir.Reloc.Literal),
2828
2929// Stack Frame
3030returns: bool,
31va_list: struct {
32 __stack: Value.Indirect,
33 __gr_top: Value.Indirect,
34 __vr_top: Value.Indirect,
31va_list: union(enum) {
32 other: Value.Indirect,
33 sysv: struct {
34 __stack: Value.Indirect,
35 __gr_top: Value.Indirect,
36 __vr_top: Value.Indirect,
37 __gr_offs: i32,
38 __vr_offs: i32,
39 },
3540},
3641stack_size: u24,
3742stack_align: InternPool.Alignment,
......@@ -408,13 +413,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
408413
409414 air_body_index += 1;
410415 },
411 .breakpoint,
412 .dbg_stmt,
413 .dbg_empty_stmt,
414 .dbg_var_ptr,
415 .dbg_var_val,
416 .dbg_arg_inline,
417 => {
416 .breakpoint, .dbg_stmt, .dbg_empty_stmt, .dbg_var_ptr, .dbg_var_val, .dbg_arg_inline, .c_va_end => {
418417 air_body_index += 1;
419418 air_inst_index = air_body[air_body_index];
420419 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
......@@ -428,23 +427,43 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
428427 const extra = isel.air.extraData(Air.Call, pl_op.payload);
429428 const args: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra.end..][0..extra.data.args_len]);
430429 isel.saved_registers.insert(.lr);
430 const callee_ty = isel.air.typeOf(pl_op.operand, ip);
431 const func_info = switch (ip.indexToKey(callee_ty.toIntern())) {
432 else => unreachable,
433 .func_type => |func_type| func_type,
434 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.child).func_type,
435 };
431436
432437 try isel.analyzeUse(pl_op.operand);
433438 var param_it: CallAbiIterator = .init;
434 for (args) |arg| {
439 for (args, 0..) |arg, arg_index| {
435440 const restore_values_len = isel.values.items.len;
436441 defer isel.values.shrinkRetainingCapacity(restore_values_len);
437 const param_vi = try param_it.param(isel, isel.air.typeOf(arg, ip)) orelse continue;
438 const param_parent = param_vi.parent(isel);
439 switch (switch (param_parent) {
440 .unallocated, .stack_slot => param_parent,
442 const param_vi = param_vi: {
443 const param_ty = isel.air.typeOf(arg, ip);
444 if (arg_index >= func_info.param_types.len) {
445 assert(func_info.is_var_args);
446 switch (isel.va_list) {
447 .other => break :param_vi try param_it.nonSysvVarArg(isel, param_ty),
448 .sysv => {},
449 }
450 }
451 break :param_vi try param_it.param(isel, param_ty);
452 } orelse continue;
453 defer param_vi.deref(isel);
454 const passed_vi = switch (param_vi.parent(isel)) {
455 .unallocated, .stack_slot => param_vi,
441456 .value, .constant => unreachable,
442 .address => |address_vi| address_vi.parent(isel),
443 }) {
457 .address => |address_vi| address_vi,
458 };
459 switch (passed_vi.parent(isel)) {
444460 .unallocated => {},
445461 .stack_slot => |stack_slot| {
446462 assert(stack_slot.base == .sp);
447 isel.stack_size = @max(isel.stack_size, stack_slot.offset);
463 isel.stack_size = @max(
464 isel.stack_size,
465 stack_slot.offset + @as(u24, @intCast(passed_vi.size(isel))),
466 );
448467 },
449468 .value, .constant, .address => unreachable,
450469 }
......@@ -802,7 +821,7 @@ pub fn analyze(isel: *Select, air_body: []const Air.Inst.Index) !void {
802821 air_inst_index = air_body[air_body_index];
803822 continue :air_tag air_tags[@intFromEnum(air_inst_index)];
804823 },
805 .set_err_return_trace, .c_va_end => {
824 .set_err_return_trace => {
806825 const un_op = air_data[@intFromEnum(air_inst_index)].un_op;
807826
808827 try isel.analyzeUse(un_op);
......@@ -2474,6 +2493,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
24742493 }
24752494 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
24762495 },
2496 .inferred_alloc, .inferred_alloc_comptime => unreachable,
24772497 .assembly => {
24782498 const ty_pl = air.data(air.inst_index).ty_pl;
24792499 const extra = isel.air.extraData(Air.Asm, ty_pl.payload);
......@@ -3389,6 +3409,12 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
33893409 const pl_op = air.data(air.inst_index).pl_op;
33903410 const extra = isel.air.extraData(Air.Call, pl_op.payload);
33913411 const args: []const Air.Inst.Ref = @ptrCast(isel.air.extra.items[extra.end..][0..extra.data.args_len]);
3412 const callee_ty = isel.air.typeOf(pl_op.operand, ip);
3413 const func_info = switch (ip.indexToKey(callee_ty.toIntern())) {
3414 else => unreachable,
3415 .func_type => |func_type| func_type,
3416 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.child).func_type,
3417 };
33923418
33933419 try call.prepareReturn(isel);
33943420 const maybe_def_ret_vi = isel.live_values.fetchRemove(air.inst_index);
......@@ -3455,41 +3481,50 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
34553481 ret_addr_vi.hint(isel).?,
34563482 );
34573483 var param_it: CallAbiIterator = .init;
3458 for (args) |arg| {
3459 const param_vi = try param_it.param(isel, isel.air.typeOf(arg, ip)) orelse continue;
3484 for (args, 0..) |arg, arg_index| {
3485 const param_ty = isel.air.typeOf(arg, ip);
3486 const param_vi = param_vi: {
3487 if (arg_index >= func_info.param_types.len) {
3488 assert(func_info.is_var_args);
3489 switch (isel.va_list) {
3490 .other => break :param_vi try param_it.nonSysvVarArg(isel, param_ty),
3491 .sysv => {},
3492 }
3493 }
3494 break :param_vi try param_it.param(isel, param_ty);
3495 } orelse continue;
34603496 defer param_vi.deref(isel);
34613497 const arg_vi = try isel.use(arg);
3462 const passed_vi = switch (param_vi.parent(isel)) {
3463 .unallocated, .stack_slot => param_vi,
3464 .value, .constant => unreachable,
3465 .address => |address_vi| {
3466 try call.paramAddress(isel, arg_vi, address_vi.hint(isel).?);
3467 continue;
3498 switch (param_vi.parent(isel)) {
3499 .unallocated => if (param_vi.hint(isel)) |param_ra| {
3500 try call.paramLiveOut(isel, arg_vi, param_ra);
3501 } else {
3502 var param_part_it = param_vi.parts(isel);
3503 var arg_part_it = arg_vi.parts(isel);
3504 if (arg_part_it.only()) |_| {
3505 try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining);
3506 arg_vi.setParts(isel, param_part_it.remaining);
3507 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
3508 isel,
3509 param_part_vi.get(isel).offset_from_parent,
3510 param_part_vi.size(isel),
3511 );
3512 param_part_it = param_vi.parts(isel);
3513 arg_part_it = arg_vi.parts(isel);
3514 }
3515 while (param_part_it.next()) |param_part_vi| {
3516 const arg_part_vi = arg_part_it.next().?;
3517 assert(arg_part_vi.get(isel).offset_from_parent ==
3518 param_part_vi.get(isel).offset_from_parent);
3519 assert(arg_part_vi.size(isel) == param_part_vi.size(isel));
3520 try call.paramLiveOut(isel, arg_part_vi, param_part_vi.hint(isel).?);
3521 }
34683522 },
3469 };
3470 if (passed_vi.hint(isel)) |param_ra| {
3471 try call.paramLiveOut(isel, arg_vi, param_ra);
3472 } else {
3473 var param_part_it = passed_vi.parts(isel);
3474 var arg_part_it = arg_vi.parts(isel);
3475 if (arg_part_it.only()) |_| {
3476 try isel.values.ensureUnusedCapacity(gpa, param_part_it.remaining);
3477 arg_vi.setParts(isel, param_part_it.remaining);
3478 while (param_part_it.next()) |param_part_vi| _ = arg_vi.addPart(
3479 isel,
3480 param_part_vi.get(isel).offset_from_parent,
3481 param_part_vi.size(isel),
3482 );
3483 param_part_it = passed_vi.parts(isel);
3484 arg_part_it = arg_vi.parts(isel);
3485 }
3486 while (param_part_it.next()) |param_part_vi| {
3487 const arg_part_vi = arg_part_it.next().?;
3488 assert(arg_part_vi.get(isel).offset_from_parent ==
3489 param_part_vi.get(isel).offset_from_parent);
3490 assert(arg_part_vi.size(isel) == param_part_vi.size(isel));
3491 try call.paramLiveOut(isel, arg_part_vi, param_part_vi.hint(isel).?);
3492 }
3523 .stack_slot => |stack_slot| try arg_vi.store(isel, param_ty, stack_slot.base, .{
3524 .offset = @intCast(stack_slot.offset),
3525 }),
3526 .value, .constant => unreachable,
3527 .address => |address_vi| try call.paramAddress(isel, arg_vi, address_vi.hint(isel).?),
34933528 }
34943529 }
34953530 try call.finishParams(isel);
......@@ -4828,9 +4863,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
48284863
48294864 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
48304865 },
4831 .dbg_stmt => {
4832 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
4833 },
4866 .dbg_stmt => if (air.next()) |next_air_tag| continue :air_tag next_air_tag,
48344867 .dbg_empty_stmt => {
48354868 try isel.emit(.nop());
48364869 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
......@@ -7079,6 +7112,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
70797112 }
70807113 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
70817114 },
7115 .wasm_memory_size, .wasm_memory_grow => unreachable,
70827116 .cmp_lt_errors_len => {
70837117 if (isel.live_values.fetchRemove(air.inst_index)) |is_vi| unused: {
70847118 defer is_vi.value.deref(isel);
......@@ -7135,16 +7169,266 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
71357169 }
71367170 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
71377171 },
7138 .inferred_alloc,
7139 .inferred_alloc_comptime,
7140 .int_from_float_safe,
7141 .int_from_float_optimized_safe,
7142 .wasm_memory_size,
7143 .wasm_memory_grow,
7144 .work_item_id,
7145 .work_group_size,
7146 .work_group_id,
7147 => unreachable,
7172 .c_va_arg => {
7173 const maybe_arg_vi = isel.live_values.fetchRemove(air.inst_index);
7174 defer if (maybe_arg_vi) |arg_vi| arg_vi.value.deref(isel);
7175 const ty_op = air.data(air.inst_index).ty_op;
7176 const ty = ty_op.ty.toType();
7177 var param_it: CallAbiIterator = .init;
7178 const param_vi = try param_it.param(isel, ty);
7179 defer param_vi.?.deref(isel);
7180 const passed_vi = switch (param_vi.?.parent(isel)) {
7181 .unallocated => param_vi.?,
7182 .stack_slot, .value, .constant => unreachable,
7183 .address => |address_vi| address_vi,
7184 };
7185 const passed_size: u5 = @intCast(passed_vi.alignment(isel).forward(passed_vi.size(isel)));
7186 const passed_is_vector = passed_vi.isVector(isel);
7187
7188 const va_list_ptr_vi = try isel.use(ty_op.operand);
7189 const va_list_ptr_mat = try va_list_ptr_vi.matReg(isel);
7190 const offs_ra = try isel.allocIntReg();
7191 defer isel.freeReg(offs_ra);
7192 const stack_ra = try isel.allocIntReg();
7193 defer isel.freeReg(stack_ra);
7194
7195 var part_vis: [2]Value.Index = undefined;
7196 var arg_part_ras: [2]?Register.Alias = @splat(null);
7197 const parts_len = parts_len: {
7198 var parts_len: u2 = 0;
7199 var part_it = passed_vi.parts(isel);
7200 while (part_it.next()) |part_vi| : (parts_len += 1) {
7201 part_vis[parts_len] = part_vi;
7202 const arg_vi = maybe_arg_vi orelse continue;
7203 const part_offset, const part_size = part_vi.position(isel);
7204 var arg_part_it = arg_vi.value.field(ty, part_offset, part_size);
7205 const arg_part_vi = try arg_part_it.only(isel);
7206 arg_part_ras[parts_len] = try arg_part_vi.?.defReg(isel);
7207 }
7208 break :parts_len parts_len;
7209 };
7210
7211 const done_label = isel.instructions.items.len;
7212 try isel.emit(.str(stack_ra.x(), .{ .unsigned_offset = .{
7213 .base = va_list_ptr_mat.ra.x(),
7214 .offset = 0,
7215 } }));
7216 try isel.emit(switch (parts_len) {
7217 else => unreachable,
7218 1 => if (arg_part_ras[0]) |arg_part_ra| switch (part_vis[0].size(isel)) {
7219 else => unreachable,
7220 1 => if (arg_part_ra.isVector()) .ldr(arg_part_ra.b(), .{ .post_index = .{
7221 .base = stack_ra.x(),
7222 .index = passed_size,
7223 } }) else switch (part_vis[0].signedness(isel)) {
7224 .signed => .ldrsb(arg_part_ra.w(), .{ .post_index = .{
7225 .base = stack_ra.x(),
7226 .index = passed_size,
7227 } }),
7228 .unsigned => .ldrb(arg_part_ra.w(), .{ .post_index = .{
7229 .base = stack_ra.x(),
7230 .index = passed_size,
7231 } }),
7232 },
7233 2 => if (arg_part_ra.isVector()) .ldr(arg_part_ra.h(), .{ .post_index = .{
7234 .base = stack_ra.x(),
7235 .index = passed_size,
7236 } }) else switch (part_vis[0].signedness(isel)) {
7237 .signed => .ldrsh(arg_part_ra.w(), .{ .post_index = .{
7238 .base = stack_ra.x(),
7239 .index = passed_size,
7240 } }),
7241 .unsigned => .ldrh(arg_part_ra.w(), .{ .post_index = .{
7242 .base = stack_ra.x(),
7243 .index = passed_size,
7244 } }),
7245 },
7246 4 => .ldr(if (arg_part_ra.isVector()) arg_part_ra.s() else arg_part_ra.w(), .{ .post_index = .{
7247 .base = stack_ra.x(),
7248 .index = passed_size,
7249 } }),
7250 8 => .ldr(if (arg_part_ra.isVector()) arg_part_ra.d() else arg_part_ra.x(), .{ .post_index = .{
7251 .base = stack_ra.x(),
7252 .index = passed_size,
7253 } }),
7254 16 => .ldr(arg_part_ra.q(), .{ .post_index = .{
7255 .base = stack_ra.x(),
7256 .index = passed_size,
7257 } }),
7258 } else .add(stack_ra.x(), stack_ra.x(), .{ .immediate = passed_size }),
7259 2 => if (arg_part_ras[0] != null or arg_part_ras[1] != null) .ldp(
7260 @as(Register.Alias, arg_part_ras[0] orelse .zr).x(),
7261 @as(Register.Alias, arg_part_ras[1] orelse .zr).x(),
7262 .{ .post_index = .{
7263 .base = stack_ra.x(),
7264 .index = passed_size,
7265 } },
7266 ) else .add(stack_ra.x(), stack_ra.x(), .{ .immediate = passed_size }),
7267 });
7268 try isel.emit(.ldr(stack_ra.x(), .{ .unsigned_offset = .{
7269 .base = va_list_ptr_mat.ra.x(),
7270 .offset = 0,
7271 } }));
7272 switch (isel.va_list) {
7273 .other => {},
7274 .sysv => {
7275 const stack_label = isel.instructions.items.len;
7276 try isel.emit(.b(
7277 @intCast((isel.instructions.items.len + 1 - done_label) << 2),
7278 ));
7279 switch (parts_len) {
7280 else => unreachable,
7281 1 => if (arg_part_ras[0]) |arg_part_ra| try isel.emit(switch (part_vis[0].size(isel)) {
7282 else => unreachable,
7283 1 => if (arg_part_ra.isVector()) .ldr(arg_part_ra.b(), .{ .extended_register = .{
7284 .base = stack_ra.x(),
7285 .index = offs_ra.w(),
7286 .extend = .{ .sxtw = 0 },
7287 } }) else switch (part_vis[0].signedness(isel)) {
7288 .signed => .ldrsb(arg_part_ra.w(), .{ .extended_register = .{
7289 .base = stack_ra.x(),
7290 .index = offs_ra.w(),
7291 .extend = .{ .sxtw = 0 },
7292 } }),
7293 .unsigned => .ldrb(arg_part_ra.w(), .{ .extended_register = .{
7294 .base = stack_ra.x(),
7295 .index = offs_ra.w(),
7296 .extend = .{ .sxtw = 0 },
7297 } }),
7298 },
7299 2 => if (arg_part_ra.isVector()) .ldr(arg_part_ra.h(), .{ .extended_register = .{
7300 .base = stack_ra.x(),
7301 .index = offs_ra.w(),
7302 .extend = .{ .sxtw = 0 },
7303 } }) else switch (part_vis[0].signedness(isel)) {
7304 .signed => .ldrsh(arg_part_ra.w(), .{ .extended_register = .{
7305 .base = stack_ra.x(),
7306 .index = offs_ra.w(),
7307 .extend = .{ .sxtw = 0 },
7308 } }),
7309 .unsigned => .ldrh(arg_part_ra.w(), .{ .extended_register = .{
7310 .base = stack_ra.x(),
7311 .index = offs_ra.w(),
7312 .extend = .{ .sxtw = 0 },
7313 } }),
7314 },
7315 4 => .ldr(if (arg_part_ra.isVector()) arg_part_ra.s() else arg_part_ra.w(), .{ .extended_register = .{
7316 .base = stack_ra.x(),
7317 .index = offs_ra.w(),
7318 .extend = .{ .sxtw = 0 },
7319 } }),
7320 8 => .ldr(if (arg_part_ra.isVector()) arg_part_ra.d() else arg_part_ra.x(), .{ .extended_register = .{
7321 .base = stack_ra.x(),
7322 .index = offs_ra.w(),
7323 .extend = .{ .sxtw = 0 },
7324 } }),
7325 16 => .ldr(arg_part_ra.q(), .{ .extended_register = .{
7326 .base = stack_ra.x(),
7327 .index = offs_ra.w(),
7328 .extend = .{ .sxtw = 0 },
7329 } }),
7330 }),
7331 2 => if (arg_part_ras[0] != null or arg_part_ras[1] != null) {
7332 try isel.emit(.ldp(
7333 @as(Register.Alias, arg_part_ras[0] orelse .zr).x(),
7334 @as(Register.Alias, arg_part_ras[1] orelse .zr).x(),
7335 .{ .base = stack_ra.x() },
7336 ));
7337 try isel.emit(.add(stack_ra.x(), stack_ra.x(), .{ .extended_register = .{
7338 .register = offs_ra.w(),
7339 .extend = .{ .sxtw = 0 },
7340 } }));
7341 },
7342 }
7343 try isel.emit(.ldr(stack_ra.x(), .{ .unsigned_offset = .{
7344 .base = va_list_ptr_mat.ra.x(),
7345 .offset = if (passed_is_vector) 16 else 8,
7346 } }));
7347 try isel.emit(.@"b."(
7348 .gt,
7349 @intCast((isel.instructions.items.len + 1 - stack_label) << 2),
7350 ));
7351 try isel.emit(.str(stack_ra.w(), .{ .unsigned_offset = .{
7352 .base = va_list_ptr_mat.ra.x(),
7353 .offset = if (passed_is_vector) 28 else 24,
7354 } }));
7355 try isel.emit(.adds(stack_ra.w(), offs_ra.w(), .{ .immediate = passed_size }));
7356 try isel.emit(.tbz(
7357 offs_ra.w(),
7358 31,
7359 @intCast((isel.instructions.items.len + 1 - stack_label) << 2),
7360 ));
7361 try isel.emit(.ldr(offs_ra.w(), .{ .unsigned_offset = .{
7362 .base = va_list_ptr_mat.ra.x(),
7363 .offset = if (passed_is_vector) 28 else 24,
7364 } }));
7365 },
7366 }
7367 try va_list_ptr_mat.finish(isel);
7368 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
7369 },
7370 .c_va_copy => {
7371 if (isel.live_values.fetchRemove(air.inst_index)) |va_list_vi| {
7372 defer va_list_vi.value.deref(isel);
7373 const ty_op = air.data(air.inst_index).ty_op;
7374 const va_list_ptr_vi = try isel.use(ty_op.operand);
7375 const va_list_ptr_mat = try va_list_ptr_vi.matReg(isel);
7376 _ = try va_list_vi.value.load(isel, ty_op.ty.toType(), va_list_ptr_mat.ra, .{});
7377 try va_list_ptr_mat.finish(isel);
7378 }
7379 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
7380 },
7381 .c_va_end => if (air.next()) |next_air_tag| continue :air_tag next_air_tag,
7382 .c_va_start => {
7383 if (isel.live_values.fetchRemove(air.inst_index)) |va_list_vi| {
7384 defer va_list_vi.value.deref(isel);
7385 const ty = air.data(air.inst_index).ty;
7386 switch (isel.va_list) {
7387 .other => |va_list| if (try va_list_vi.value.defReg(isel)) |va_list_ra| try isel.emit(.add(
7388 va_list_ra.x(),
7389 va_list.base.x(),
7390 .{ .immediate = @intCast(va_list.offset) },
7391 )),
7392 .sysv => |va_list| {
7393 var vr_offs_it = va_list_vi.value.field(ty, 28, 4);
7394 const vr_offs_vi = try vr_offs_it.only(isel);
7395 if (try vr_offs_vi.?.defReg(isel)) |vr_offs_ra| try isel.movImmediate(
7396 vr_offs_ra.w(),
7397 @as(u32, @bitCast(va_list.__vr_offs)),
7398 );
7399 var gr_offs_it = va_list_vi.value.field(ty, 24, 4);
7400 const gr_offs_vi = try gr_offs_it.only(isel);
7401 if (try gr_offs_vi.?.defReg(isel)) |gr_offs_ra| try isel.movImmediate(
7402 gr_offs_ra.w(),
7403 @as(u32, @bitCast(va_list.__gr_offs)),
7404 );
7405 var vr_top_it = va_list_vi.value.field(ty, 16, 8);
7406 const vr_top_vi = try vr_top_it.only(isel);
7407 if (try vr_top_vi.?.defReg(isel)) |vr_top_ra| try isel.emit(.add(
7408 vr_top_ra.x(),
7409 va_list.__vr_top.base.x(),
7410 .{ .immediate = @intCast(va_list.__vr_top.offset) },
7411 ));
7412 var gr_top_it = va_list_vi.value.field(ty, 8, 8);
7413 const gr_top_vi = try gr_top_it.only(isel);
7414 if (try gr_top_vi.?.defReg(isel)) |gr_top_ra| try isel.emit(.add(
7415 gr_top_ra.x(),
7416 va_list.__gr_top.base.x(),
7417 .{ .immediate = @intCast(va_list.__gr_top.offset) },
7418 ));
7419 var stack_it = va_list_vi.value.field(ty, 0, 8);
7420 const stack_vi = try stack_it.only(isel);
7421 if (try stack_vi.?.defReg(isel)) |stack_ra| try isel.emit(.add(
7422 stack_ra.x(),
7423 va_list.__stack.base.x(),
7424 .{ .immediate = @intCast(va_list.__stack.offset) },
7425 ));
7426 },
7427 }
7428 }
7429 if (air.next()) |next_air_tag| continue :air_tag next_air_tag;
7430 },
7431 .work_item_id, .work_group_size, .work_group_id => unreachable,
71487432 }
71497433 assert(air.body_index == 0);
71507434}
......@@ -7225,7 +7509,7 @@ pub fn verify(isel: *Select, check_values: bool) void {
72257509pub fn layout(
72267510 isel: *Select,
72277511 incoming: CallAbiIterator,
7228 have_va: bool,
7512 is_sysv_var_args: bool,
72297513 saved_gra_len: u7,
72307514 saved_vra_len: u7,
72317515 mod: *const Package.Module,
......@@ -7236,8 +7520,6 @@ pub fn layout(
72367520 wip_mir_log.debug("{f}<body>:\n", .{nav.fqn.fmt(ip)});
72377521
72387522 const stack_size: u24 = @intCast(InternPool.Alignment.@"16".forward(isel.stack_size));
7239 const stack_size_lo: u12 = @truncate(stack_size >> 0);
7240 const stack_size_hi: u12 = @truncate(stack_size >> 12);
72417523
72427524 var saves_buf: [10 + 8 + 8 + 2 + 8]struct {
72437525 class: enum { integer, vector },
......@@ -7315,7 +7597,7 @@ pub fn layout(
73157597
73167598 // incoming vr arguments
73177599 save_ra = if (mod.strip) incoming.nsrn else CallAbiIterator.nsrn_start;
7318 while (save_ra != if (have_va) CallAbiIterator.nsrn_end else incoming.nsrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
7600 while (save_ra != if (is_sysv_var_args) CallAbiIterator.nsrn_end else incoming.nsrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
73197601 saves_size = std.mem.alignForward(u10, saves_size, 16);
73207602 saves_buf[saves_len] = .{
73217603 .class = .vector,
......@@ -7370,7 +7652,7 @@ pub fn layout(
73707652 1 => saves_size += 8,
73717653 }
73727654 save_ra = if (mod.strip) incoming.ngrn else CallAbiIterator.ngrn_start;
7373 while (save_ra != if (have_va) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
7655 while (save_ra != if (is_sysv_var_args) CallAbiIterator.ngrn_end else incoming.ngrn) : (save_ra = @enumFromInt(@intFromEnum(save_ra) + 1)) {
73747656 saves_size = std.mem.alignForward(u10, saves_size, 8);
73757657 saves_buf[saves_len] = .{
73767658 .class = .integer,
......@@ -7434,6 +7716,8 @@ pub fn layout(
74347716 .fp
74357717 else
74367718 .ip0;
7719 const stack_size_lo: u12 = @truncate(stack_size >> 0);
7720 const stack_size_hi: u12 = @truncate(stack_size >> 12);
74377721 if (mod.stack_check) {
74387722 if (stack_size_hi > 2) {
74397723 try isel.movImmediate(.ip1, stack_size_hi);
......@@ -7481,6 +7765,7 @@ pub fn layout(
74817765 if (isel.returns) {
74827766 try isel.emit(.ret(.lr));
74837767 var save_index: usize = 0;
7768 var first_offset: ?u10 = null;
74847769 while (save_index < saves.len) {
74857770 if (save_index + 2 <= saves.len and saves[save_index + 1].needs_restore and
74867771 saves[save_index + 0].class == saves[save_index + 1].class and
......@@ -7489,46 +7774,51 @@ pub fn layout(
74897774 try isel.emit(.ldp(
74907775 saves[save_index + 0].register,
74917776 saves[save_index + 1].register,
7492 switch (saves[save_index + 0].offset) {
7493 0 => .{ .post_index = .{
7494 .base = .sp,
7495 .index = @intCast(saves_size),
7496 } },
7497 else => |offset| .{ .signed_offset = .{
7777 if (first_offset) |offset| .{ .signed_offset = .{
7778 .base = .sp,
7779 .offset = @intCast(saves[save_index + 0].offset - offset),
7780 } } else form: {
7781 first_offset = @intCast(saves[save_index + 0].offset);
7782 break :form .{ .post_index = .{
74987783 .base = .sp,
7499 .offset = @intCast(offset),
7500 } },
7784 .index = @intCast(saves_size - first_offset.?),
7785 } };
75017786 },
75027787 ));
75037788 save_index += 2;
75047789 } else if (saves[save_index].needs_restore) {
75057790 try isel.emit(.ldr(
75067791 saves[save_index].register,
7507 switch (saves[save_index].offset) {
7508 0 => .{ .post_index = .{
7509 .base = .sp,
7510 .index = @intCast(saves_size),
7511 } },
7512 else => |offset| .{ .unsigned_offset = .{
7792 if (first_offset) |offset| .{ .unsigned_offset = .{
7793 .base = .sp,
7794 .offset = saves[save_index + 0].offset - offset,
7795 } } else form: {
7796 const offset = saves[save_index + 0].offset;
7797 first_offset = offset;
7798 break :form .{ .post_index = .{
75137799 .base = .sp,
7514 .offset = @intCast(offset),
7515 } },
7800 .index = @intCast(saves_size - offset),
7801 } };
75167802 },
75177803 ));
75187804 save_index += 1;
75197805 } else save_index += 1;
75207806 }
7521 if (isel.stack_align != .@"16" or (stack_size_lo > 0 and stack_size_hi > 0)) {
7522 try isel.emit(switch (frame_record_offset) {
7523 0 => .add(.sp, .fp, .{ .immediate = 0 }),
7524 else => |offset| .sub(.sp, .fp, .{ .immediate = offset }),
7525 });
7807 const offset = stack_size + first_offset.?;
7808 const offset_lo: u12 = @truncate(offset >> 0);
7809 const offset_hi: u12 = @truncate(offset >> 12);
7810 if (isel.stack_align != .@"16" or (offset_lo > 0 and offset_hi > 0)) {
7811 const fp_offset = @as(i11, first_offset.?) - frame_record_offset;
7812 try isel.emit(if (fp_offset >= 0)
7813 .add(.sp, .fp, .{ .immediate = @intCast(fp_offset) })
7814 else
7815 .sub(.sp, .fp, .{ .immediate = @intCast(-fp_offset) }));
75267816 } else {
7527 if (stack_size_hi > 0) try isel.emit(.add(.sp, .sp, .{
7528 .shifted_immediate = .{ .immediate = stack_size_hi, .lsl = .@"12" },
7817 if (offset_hi > 0) try isel.emit(.add(.sp, .sp, .{
7818 .shifted_immediate = .{ .immediate = offset_hi, .lsl = .@"12" },
75297819 }));
7530 if (stack_size_lo > 0) try isel.emit(.add(.sp, .sp, .{
7531 .immediate = stack_size_lo,
7820 if (offset_lo > 0) try isel.emit(.add(.sp, .sp, .{
7821 .immediate = offset_lo,
75327822 }));
75337823 }
75347824 wip_mir_log.debug("{f}<epilogue>:\n", .{nav.fqn.fmt(ip)});
......@@ -9493,6 +9783,11 @@ pub const Value = struct {
94939783 return it.vi;
94949784 }
94959785
9786 pub fn peek(it: PartIterator) ?Value.Index {
9787 var it_mut = it;
9788 return it_mut.next();
9789 }
9790
94969791 pub fn only(it: PartIterator) ?Value.Index {
94979792 return if (it.remaining == 1) it.vi else null;
94989793 }
......@@ -10119,11 +10414,12 @@ pub const Value = struct {
1011910414 } },
1012010415 .error_union => |error_union| {
1012110416 const error_union_type = ip.indexToKey(error_union.ty).error_union_type;
10417 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
1012210418 const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
10123 if (!ip.isNoReturn(error_union_type.error_set_type) and
10124 offset == codegen.errUnionErrorOffset(payload_ty, zcu))
10125 {
10126 offset = 0;
10419 const error_set_offset = codegen.errUnionErrorOffset(payload_ty, zcu);
10420 const error_set_size = error_set_ty.abiSize(zcu);
10421 if (offset >= error_set_offset and offset + size <= error_set_offset + error_set_size) {
10422 offset -= error_set_offset;
1012710423 continue :constant_key switch (error_union.val) {
1012810424 .err_name => |err_name| .{ .err = .{
1012910425 .ty = error_union_type.error_set_type,
......@@ -10135,15 +10431,18 @@ pub const Value = struct {
1013510431 } },
1013610432 };
1013710433 }
10138 assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu));
10139 offset -= @intCast(codegen.errUnionPayloadOffset(payload_ty, zcu));
10140 switch (error_union.val) {
10141 .err_name => continue :constant_key .{ .undef = error_union_type.payload_type },
10142 .payload => |payload| {
10143 constant = payload;
10144 constant_key = ip.indexToKey(payload);
10145 continue :constant_key constant_key;
10146 },
10434 const payload_offset = codegen.errUnionPayloadOffset(payload_ty, zcu);
10435 const payload_size = payload_ty.abiSize(zcu);
10436 if (offset >= payload_offset and offset + size <= payload_offset + payload_size) {
10437 offset -= payload_offset;
10438 switch (error_union.val) {
10439 .err_name => continue :constant_key .{ .undef = error_union_type.payload_type },
10440 .payload => |payload| {
10441 constant = payload;
10442 constant_key = ip.indexToKey(payload);
10443 continue :constant_key constant_key;
10444 },
10445 }
1014710446 }
1014810447 },
1014910448 .enum_tag => |enum_tag| continue :constant_key .{ .int = ip.indexToKey(enum_tag.int).int },
......@@ -10680,7 +10979,17 @@ fn hasRepeatedByteRepr(isel: *Select, constant: Constant) error{OutOfMemory}!?u8
1068010979fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMemory}!bool {
1068110980 const zcu = isel.pt.zcu;
1068210981 const ip = &zcu.intern_pool;
10683 switch (ip.indexToKey(constant.toIntern())) {
10982 if (try isel.writeKeyToMemory(ip.indexToKey(constant.toIntern()), buffer)) return true;
10983 constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) {
10984 error.OutOfMemory => return error.OutOfMemory,
10985 error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
10986 };
10987 return true;
10988}
10989fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) error{OutOfMemory}!bool {
10990 const zcu = isel.pt.zcu;
10991 const ip = &zcu.intern_pool;
10992 switch (constant_key) {
1068410993 .int_type,
1068510994 .ptr_type,
1068610995 .array_type,
......@@ -10702,6 +11011,37 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1070211011 .empty_enum_value,
1070311012 .memoized_call,
1070411013 => unreachable, // not a runtime value
11014 .err => |err| {
11015 const error_int = ip.getErrorValueIfExists(err.name).?;
11016 switch (buffer.len) {
11017 else => unreachable,
11018 inline 1...4 => |size| std.mem.writeInt(
11019 @Type(.{ .int = .{ .signedness = .unsigned, .bits = 8 * size } }),
11020 buffer[0..size],
11021 @intCast(error_int),
11022 isel.target.cpu.arch.endian(),
11023 ),
11024 }
11025 },
11026 .error_union => |error_union| {
11027 const error_union_type = ip.indexToKey(error_union.ty).error_union_type;
11028 const error_set_ty: ZigType = .fromInterned(error_union_type.error_set_type);
11029 const payload_ty: ZigType = .fromInterned(error_union_type.payload_type);
11030 const error_set = buffer[@intCast(codegen.errUnionErrorOffset(payload_ty, zcu))..][0..@intCast(error_set_ty.abiSize(zcu))];
11031 switch (error_union.val) {
11032 .err_name => |err_name| if (!try isel.writeKeyToMemory(.{ .err = .{
11033 .ty = error_set_ty.toIntern(),
11034 .name = err_name,
11035 } }, error_set)) return false,
11036 .payload => |payload| {
11037 if (!try isel.writeToMemory(
11038 .fromInterned(payload),
11039 buffer[@intCast(codegen.errUnionPayloadOffset(payload_ty, zcu))..][0..@intCast(payload_ty.abiSize(zcu))],
11040 )) return false;
11041 @memset(error_set, 0);
11042 },
11043 }
11044 },
1070511045 .opt => |opt| {
1070611046 const child_size: usize = @intCast(ZigType.fromInterned(ip.indexToKey(opt.ty).opt_type).abiSize(zcu));
1070711047 switch (opt.val) {
......@@ -10713,7 +11053,6 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1071311053 if (!ZigType.fromInterned(opt.ty).optionalReprIsPayload(zcu)) buffer[child_size] = @intFromBool(true);
1071411054 },
1071511055 }
10716 return true;
1071711056 },
1071811057 .aggregate => |aggregate| switch (ip.indexToKey(aggregate.ty)) {
1071911058 else => unreachable,
......@@ -10732,9 +11071,8 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1073211071 elem_offset += elem_size;
1073311072 },
1073411073 }
10735 return true;
1073611074 },
10737 .vector_type => {},
11075 .vector_type => return false,
1073811076 .struct_type => {
1073911077 const loaded_struct = ip.loadStructType(aggregate.ty);
1074011078 switch (loaded_struct.layout) {
......@@ -10757,9 +11095,8 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1075711095 }), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
1075811096 field_offset += field_size;
1075911097 }
10760 return true;
1076111098 },
10762 .@"extern", .@"packed" => {},
11099 .@"extern", .@"packed" => return false,
1076311100 }
1076411101 },
1076511102 .tuple_type => |tuple_type| {
......@@ -10776,15 +11113,10 @@ fn writeToMemory(isel: *Select, constant: Constant, buffer: []u8) error{OutOfMem
1077611113 }), buffer[@intCast(field_offset)..][0..@intCast(field_size)])) return false;
1077711114 field_offset += field_size;
1077811115 }
10779 return true;
1078011116 },
1078111117 },
10782 else => {},
11118 else => return false,
1078311119 }
10784 constant.writeToMemory(isel.pt, buffer) catch |err| switch (err) {
10785 error.OutOfMemory => return error.OutOfMemory,
10786 error.ReinterpretDeclRef, error.Unimplemented, error.IllDefinedMemoryLayout => return false,
10787 };
1078811120 return true;
1078911121}
1079011122
......@@ -11607,6 +11939,16 @@ pub const CallAbiIterator = struct {
1160711939 return wip_vi.ref(isel);
1160811940 }
1160911941
11942 pub fn nonSysvVarArg(it: *CallAbiIterator, isel: *Select, ty: ZigType) !?Value.Index {
11943 const ngrn = it.ngrn;
11944 defer it.ngrn = ngrn;
11945 it.ngrn = ngrn_end;
11946 const nsrn = it.nsrn;
11947 defer it.nsrn = nsrn;
11948 it.nsrn = nsrn_end;
11949 return it.param(isel, ty);
11950 }
11951
1161011952 pub fn ret(it: *CallAbiIterator, isel: *Select, ty: ZigType) !?Value.Index {
1161111953 const wip_vi = try it.param(isel, ty) orelse return null;
1161211954 switch (wip_vi.parent(isel)) {
src/codegen/aarch64/encoding.zig+20-20
......@@ -10089,26 +10089,26 @@ pub const Instruction = packed union {
1008910089 },
1009010090 } } } };
1009110091 },
10092 .signed_offset => |signed_offset| {
10093 assert(signed_offset.base.format.integer == .doubleword);
10094 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
10092 .pre_index => |pre_index| {
10093 assert(pre_index.base.format.integer == .doubleword);
10094 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
1009510095 .ldp = .{
1009610096 .Rt = t1.alias.encode(.{}),
10097 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
10097 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
1009810098 .Rt2 = t2.alias.encode(.{}),
10099 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
10099 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
1010010100 .sf = sf,
1010110101 },
1010210102 } } } };
1010310103 },
10104 .pre_index => |pre_index| {
10105 assert(pre_index.base.format.integer == .doubleword);
10106 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
10104 .signed_offset => |signed_offset| {
10105 assert(signed_offset.base.format.integer == .doubleword);
10106 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
1010710107 .ldp = .{
1010810108 .Rt = t1.alias.encode(.{}),
10109 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
10109 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
1011010110 .Rt2 = t2.alias.encode(.{}),
10111 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
10111 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
1011210112 .sf = sf,
1011310113 },
1011410114 } } } };
......@@ -11473,26 +11473,26 @@ pub const Instruction = packed union {
1147311473 },
1147411474 } } } };
1147511475 },
11476 .signed_offset => |signed_offset| {
11477 assert(signed_offset.base.format.integer == .doubleword);
11478 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
11476 .pre_index => |pre_index| {
11477 assert(pre_index.base.format.integer == .doubleword);
11478 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
1147911479 .stp = .{
1148011480 .Rt = t1.alias.encode(.{}),
11481 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
11481 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
1148211482 .Rt2 = t2.alias.encode(.{}),
11483 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
11483 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
1148411484 .sf = sf,
1148511485 },
1148611486 } } } };
1148711487 },
11488 .pre_index => |pre_index| {
11489 assert(pre_index.base.format.integer == .doubleword);
11490 return .{ .load_store = .{ .register_pair_pre_indexed = .{ .integer = .{
11488 .signed_offset => |signed_offset| {
11489 assert(signed_offset.base.format.integer == .doubleword);
11490 return .{ .load_store = .{ .register_pair_offset = .{ .integer = .{
1149111491 .stp = .{
1149211492 .Rt = t1.alias.encode(.{}),
11493 .Rn = pre_index.base.alias.encode(.{ .sp = true }),
11493 .Rn = signed_offset.base.alias.encode(.{ .sp = true }),
1149411494 .Rt2 = t2.alias.encode(.{}),
11495 .imm7 = @intCast(@shrExact(pre_index.index, @as(u2, 2) + @intFromEnum(sf))),
11495 .imm7 = @intCast(@shrExact(signed_offset.offset, @as(u2, 2) + @intFromEnum(sf))),
1149611496 .sf = sf,
1149711497 },
1149811498 } } } };
test/behavior/enum.zig-1
......@@ -926,7 +926,6 @@ test "enum literal casting to tagged union" {
926926const Bar = enum { A, B, C, D };
927927
928928test "enum literal casting to error union with payload enum" {
929 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
930929 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
931930
932931 var bar: error{B}!Bar = undefined;
test/behavior/error.zig-12
......@@ -145,14 +145,11 @@ test "implicit cast to optional to error union to return result loc" {
145145}
146146
147147test "fn returning empty error set can be passed as fn returning any error" {
148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149
150148 entry();
151149 comptime entry();
152150}
153151
154152test "fn returning empty error set can be passed as fn returning any error - pointer" {
155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
156153 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
157154
158155 entryPtr();
......@@ -404,7 +401,6 @@ fn intLiteral(str: []const u8) !?i64 {
404401}
405402
406403test "nested error union function call in optional unwrap" {
407 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
408404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
409405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
410406
......@@ -482,7 +478,6 @@ test "optional error set is the same size as error set" {
482478}
483479
484480test "nested catch" {
485 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
486481 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
487482
488483 const S = struct {
......@@ -698,7 +693,6 @@ test "coerce error set to the current inferred error set" {
698693}
699694
700695test "error union payload is properly aligned" {
701 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
702696 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
703697 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
704698 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -757,7 +751,6 @@ test "simple else prong allowed even when all errors handled" {
757751}
758752
759753test "pointer to error union payload" {
760 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
761754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
762755 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
763756 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -845,7 +838,6 @@ test "alignment of wrapping an error union payload" {
845838}
846839
847840test "compare error union and error set" {
848 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
849841 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
850842
851843 var a: anyerror = error.Foo;
......@@ -1034,8 +1026,6 @@ test "errorCast to adhoc inferred error set" {
10341026}
10351027
10361028test "@errorCast from error set to error union" {
1037 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1038
10391029 const S = struct {
10401030 fn doTheTest(set: error{ A, B }) error{A}!i32 {
10411031 return @errorCast(set);
......@@ -1046,8 +1036,6 @@ test "@errorCast from error set to error union" {
10461036}
10471037
10481038test "@errorCast from error union to error union" {
1049 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1050
10511039 const S = struct {
10521040 fn doTheTest(set: error{ A, B }!i32) error{A}!i32 {
10531041 return @errorCast(set);
test/behavior/var_args.zig-4
......@@ -92,7 +92,6 @@ fn doNothingWithFirstArg(args: anytype) void {
9292}
9393
9494test "simple variadic function" {
95 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9695 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9796 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9897 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -154,7 +153,6 @@ test "simple variadic function" {
154153}
155154
156155test "coerce reference to var arg" {
157 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
158156 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
160158 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -234,7 +232,6 @@ test "variadic functions" {
234232}
235233
236234test "copy VaList" {
237 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
238235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
239236 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
240237 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -269,7 +266,6 @@ test "copy VaList" {
269266}
270267
271268test "unused VaList arg" {
272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
273269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
274270 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
275271 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
test/behavior/while.zig-2
......@@ -174,7 +174,6 @@ test "while with optional as condition with else" {
174174}
175175
176176test "while with error union condition" {
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
178177 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179178 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
180179 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
......@@ -306,7 +305,6 @@ test "while optional 2 break statements and an else" {
306305}
307306
308307test "while error 2 break statements and an else" {
309 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
310308 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
311309 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
312310