authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-08-13 20:32:18+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-08-13 20:32:18+00:00
logd2342370fe85491cb8216ccce9cc8fb5259376e2
tree477bd5ea0405caa3f6f3e2fbfcd44951e1c78b73
parent7e07f3d4f95f9e7a0d95ee7b9335798eccb470c7
parentc9d9fd53a61cbc656f543a3fa778ac4c72a58701
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12438 from joachimschmidt557/stage2-arm

stage2 ARM: misc improvements

2 files changed, 183 insertions(+), 68 deletions(-)

src/arch/arm/CodeGen.zig+164-30
...@@ -247,6 +247,31 @@ const BigTomb = struct {...@@ -247,6 +247,31 @@ const BigTomb = struct {
247 log.debug("%{d} => {}", .{ bt.inst, result });247 log.debug("%{d} => {}", .{ bt.inst, result });
248 const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1];248 const branch = &bt.function.branch_stack.items[bt.function.branch_stack.items.len - 1];
249 branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result);249 branch.inst_table.putAssumeCapacityNoClobber(bt.inst, result);
250
251 switch (result) {
252 .register => |reg| {
253 // In some cases (such as bitcast), an operand
254 // may be the same MCValue as the result. If
255 // that operand died and was a register, it
256 // was freed by processDeath. We have to
257 // "re-allocate" the register.
258 if (bt.function.register_manager.isRegFree(reg)) {
259 bt.function.register_manager.getRegAssumeFree(reg, bt.inst);
260 }
261 },
262 .register_c_flag,
263 .register_v_flag,
264 => |reg| {
265 if (bt.function.register_manager.isRegFree(reg)) {
266 bt.function.register_manager.getRegAssumeFree(reg, bt.inst);
267 }
268 bt.function.cpsr_flags_inst = bt.inst;
269 },
270 .cpsr_flags => {
271 bt.function.cpsr_flags_inst = bt.inst;
272 },
273 else => {},
274 }
250 }275 }
251 bt.function.finishAirBookkeeping();276 bt.function.finishAirBookkeeping();
252 }277 }
...@@ -332,7 +357,7 @@ pub fn generate(...@@ -332,7 +357,7 @@ pub fn generate(
332 };357 };
333358
334 for (function.dbg_arg_relocs.items) |reloc| {359 for (function.dbg_arg_relocs.items) |reloc| {
335 try function.genArgDbgInfo(reloc.inst, reloc.index, call_info.stack_byte_count);360 try function.genArgDbgInfo(reloc.inst, reloc.index);
336 }361 }
337362
338 var mir = Mir{363 var mir = Mir{
...@@ -351,7 +376,8 @@ pub fn generate(...@@ -351,7 +376,8 @@ pub fn generate(
351 .prev_di_pc = 0,376 .prev_di_pc = 0,
352 .prev_di_line = module_fn.lbrace_line,377 .prev_di_line = module_fn.lbrace_line,
353 .prev_di_column = module_fn.lbrace_column,378 .prev_di_column = module_fn.lbrace_column,
354 .prologue_stack_space = call_info.stack_byte_count + function.saved_regs_stack_space,379 .stack_size = function.max_end_stack,
380 .saved_regs_stack_space = function.saved_regs_stack_space,
355 };381 };
356 defer emit.deinit();382 defer emit.deinit();
357383
...@@ -464,6 +490,7 @@ fn gen(self: *Self) !void {...@@ -464,6 +490,7 @@ fn gen(self: *Self) !void {
464 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;490 const total_stack_size = self.max_end_stack + self.saved_regs_stack_space;
465 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);491 const aligned_total_stack_end = mem.alignForwardGeneric(u32, total_stack_size, self.stack_align);
466 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;492 const stack_size = aligned_total_stack_end - self.saved_regs_stack_space;
493 self.max_end_stack = stack_size;
467 if (Instruction.Operand.fromU32(stack_size)) |op| {494 if (Instruction.Operand.fromU32(stack_size)) |op| {
468 self.mir_instructions.set(sub_reloc, .{495 self.mir_instructions.set(sub_reloc, .{
469 .tag = .sub,496 .tag = .sub,
...@@ -1812,7 +1839,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV...@@ -1812,7 +1839,7 @@ fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCV
1812 switch (error_union_mcv) {1839 switch (error_union_mcv) {
1813 .register => return self.fail("TODO errUnionErr for registers", .{}),1840 .register => return self.fail("TODO errUnionErr for registers", .{}),
1814 .stack_argument_offset => |off| {1841 .stack_argument_offset => |off| {
1815 return MCValue{ .stack_argument_offset = off - err_offset };1842 return MCValue{ .stack_argument_offset = off + err_offset };
1816 },1843 },
1817 .stack_offset => |off| {1844 .stack_offset => |off| {
1818 return MCValue{ .stack_offset = off - err_offset };1845 return MCValue{ .stack_offset = off - err_offset };
...@@ -1849,7 +1876,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)...@@ -1849,7 +1876,7 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type)
1849 switch (error_union_mcv) {1876 switch (error_union_mcv) {
1850 .register => return self.fail("TODO errUnionPayload for registers", .{}),1877 .register => return self.fail("TODO errUnionPayload for registers", .{}),
1851 .stack_argument_offset => |off| {1878 .stack_argument_offset => |off| {
1852 return MCValue{ .stack_argument_offset = off - payload_offset };1879 return MCValue{ .stack_argument_offset = off + payload_offset };
1853 },1880 },
1854 .stack_offset => |off| {1881 .stack_offset => |off| {
1855 return MCValue{ .stack_offset = off - payload_offset };1882 return MCValue{ .stack_offset = off - payload_offset };
...@@ -1983,7 +2010,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {...@@ -1983,7 +2010,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
1983 .dead, .unreach => unreachable,2010 .dead, .unreach => unreachable,
1984 .register => unreachable, // a slice doesn't fit in one register2011 .register => unreachable, // a slice doesn't fit in one register
1985 .stack_argument_offset => |off| {2012 .stack_argument_offset => |off| {
1986 break :result MCValue{ .stack_argument_offset = off - 4 };2013 break :result MCValue{ .stack_argument_offset = off + 4 };
1987 },2014 },
1988 .stack_offset => |off| {2015 .stack_offset => |off| {
1989 break :result MCValue{ .stack_offset = off - 4 };2016 break :result MCValue{ .stack_offset = off - 4 };
...@@ -2259,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2259,16 +2286,17 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2259 .register_c_flag,2286 .register_c_flag,
2260 .register_v_flag,2287 .register_v_flag,
2261 => unreachable, // cannot hold an address2288 => unreachable, // cannot hold an address
2262 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),2289 .immediate => |imm| {
2263 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),2290 try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm });
2291 },
2292 .ptr_stack_offset => |off| {
2293 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });
2294 },
2264 .register => |reg| {2295 .register => |reg| {
2265 const reg_lock = self.register_manager.lockReg(reg);2296 const reg_lock = self.register_manager.lockReg(reg);
2266 defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked);2297 defer if (reg_lock) |reg_locked| self.register_manager.unlockReg(reg_locked);
22672298
2268 switch (dst_mcv) {2299 switch (dst_mcv) {
2269 .dead => unreachable,
2270 .undef => unreachable,
2271 .cpsr_flags => unreachable,
2272 .register => |dst_reg| {2300 .register => |dst_reg| {
2273 try self.genLdrRegister(dst_reg, reg, elem_ty);2301 try self.genLdrRegister(dst_reg, reg, elem_ty);
2274 },2302 },
...@@ -2304,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2304,7 +2332,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2304 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);2332 try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg);
2305 }2333 }
2306 },2334 },
2307 else => return self.fail("TODO load from register into {}", .{dst_mcv}),2335 else => unreachable, // attempting to load into non-register or non-stack MCValue
2308 }2336 }
2309 },2337 },
2310 .memory,2338 .memory,
...@@ -2401,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2401,7 +2429,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2401 // sub src_reg, fp, #off2429 // sub src_reg, fp, #off
2402 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });2430 try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off });
2403 },2431 },
2404 .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }),2432 .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }),
2405 .stack_argument_offset => |off| {2433 .stack_argument_offset => |off| {
2406 _ = try self.addInst(.{2434 _ = try self.addInst(.{
2407 .tag = .ldr_ptr_stack_argument,2435 .tag = .ldr_ptr_stack_argument,
...@@ -2507,7 +2535,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2507,7 +2535,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2507 switch (mcv) {2535 switch (mcv) {
2508 .dead, .unreach => unreachable,2536 .dead, .unreach => unreachable,
2509 .stack_argument_offset => |off| {2537 .stack_argument_offset => |off| {
2510 break :result MCValue{ .stack_argument_offset = off - struct_field_offset };2538 break :result MCValue{ .stack_argument_offset = off + struct_field_offset };
2511 },2539 },
2512 .stack_offset => |off| {2540 .stack_offset => |off| {
2513 break :result MCValue{ .stack_offset = off - struct_field_offset };2541 break :result MCValue{ .stack_offset = off - struct_field_offset };
...@@ -3347,6 +3375,102 @@ fn genInlineMemcpy(...@@ -3347,6 +3375,102 @@ fn genInlineMemcpy(
3347 // end:3375 // end:
3348}3376}
33493377
3378fn genInlineMemset(
3379 self: *Self,
3380 dst: MCValue,
3381 val: MCValue,
3382 len: MCValue,
3383) !void {
3384 const dst_reg = switch (dst) {
3385 .register => |r| r,
3386 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),
3387 };
3388 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
3389 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
3390
3391 const val_reg = switch (val) {
3392 .register => |r| r,
3393 else => try self.copyToTmpRegister(Type.initTag(.u8), val),
3394 };
3395 const val_reg_lock = self.register_manager.lockReg(val_reg);
3396 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
3397
3398 const len_reg = switch (len) {
3399 .register => |r| r,
3400 else => try self.copyToTmpRegister(Type.usize, len),
3401 };
3402 const len_reg_lock = self.register_manager.lockReg(len_reg);
3403 defer if (len_reg_lock) |lock| self.register_manager.unlockReg(lock);
3404
3405 const count_reg = try self.register_manager.allocReg(null, gp);
3406
3407 try self.genInlineMemsetCode(dst_reg, val_reg, len_reg, count_reg);
3408}
3409
3410fn genInlineMemsetCode(
3411 self: *Self,
3412 dst: Register,
3413 val: Register,
3414 len: Register,
3415 count: Register,
3416) !void {
3417 // mov count, #0
3418 _ = try self.addInst(.{
3419 .tag = .mov,
3420 .data = .{ .rr_op = .{
3421 .rd = count,
3422 .rn = .r0,
3423 .op = Instruction.Operand.imm(0, 0),
3424 } },
3425 });
3426
3427 // loop:
3428 // cmp count, len
3429 _ = try self.addInst(.{
3430 .tag = .cmp,
3431 .data = .{ .rr_op = .{
3432 .rd = .r0,
3433 .rn = count,
3434 .op = Instruction.Operand.reg(len, Instruction.Operand.Shift.none),
3435 } },
3436 });
3437
3438 // bge end
3439 _ = try self.addInst(.{
3440 .tag = .b,
3441 .cond = .ge,
3442 .data = .{ .inst = @intCast(u32, self.mir_instructions.len + 4) },
3443 });
3444
3445 // strb val, [src, count]
3446 _ = try self.addInst(.{
3447 .tag = .strb,
3448 .data = .{ .rr_offset = .{
3449 .rt = val,
3450 .rn = dst,
3451 .offset = .{ .offset = Instruction.Offset.reg(count, .none) },
3452 } },
3453 });
3454
3455 // add count, count, #1
3456 _ = try self.addInst(.{
3457 .tag = .add,
3458 .data = .{ .rr_op = .{
3459 .rd = count,
3460 .rn = count,
3461 .op = Instruction.Operand.imm(1, 0),
3462 } },
3463 });
3464
3465 // b loop
3466 _ = try self.addInst(.{
3467 .tag = .b,
3468 .data = .{ .inst = @intCast(u32, self.mir_instructions.len - 4) },
3469 });
3470
3471 // end:
3472}
3473
3350/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,3474/// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
3351/// after codegen for this symbol is done.3475/// after codegen for this symbol is done.
3352fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {3476fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
...@@ -3369,9 +3493,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {...@@ -3369,9 +3493,7 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) error{OutOfMemory}!void {
3369 }3493 }
3370}3494}
33713495
3372fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_count: u32) error{OutOfMemory}!void {3496fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfMemory}!void {
3373 const prologue_stack_space = stack_byte_count + self.saved_regs_stack_space;
3374
3375 const mcv = self.args[arg_index];3497 const mcv = self.args[arg_index];
3376 const ty = self.air.instructions.items(.data)[inst].ty;3498 const ty = self.air.instructions.items(.data)[inst].ty;
3377 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);3499 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, arg_index);
...@@ -3404,7 +3526,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c...@@ -3404,7 +3526,7 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32, stack_byte_c
3404 // const abi_size = @intCast(u32, ty.abiSize(self.target.*));3526 // const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3405 const adjusted_stack_offset = switch (mcv) {3527 const adjusted_stack_offset = switch (mcv) {
3406 .stack_offset => |offset| -@intCast(i32, offset),3528 .stack_offset => |offset| -@intCast(i32, offset),
3407 .stack_argument_offset => |offset| @intCast(i32, prologue_stack_space - offset),3529 .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset),
3408 else => unreachable,3530 else => unreachable,
3409 };3531 };
34103532
...@@ -3524,7 +3646,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3524,7 +3646,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3524 try self.register_manager.getReg(reg, null);3646 try self.register_manager.getReg(reg, null);
3525 }3647 }
35263648
3527 if (info.return_value == .stack_offset) {3649 // If returning by reference, r0 will contain the address of where
3650 // to put the result into. In that case, make sure that r0 remains
3651 // untouched by the parameter passing code
3652 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
3528 log.debug("airCall: return by reference", .{});3653 log.debug("airCall: return by reference", .{});
3529 const ret_ty = fn_ty.fnReturnType();3654 const ret_ty = fn_ty.fnReturnType();
3530 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));3655 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
...@@ -3540,7 +3665,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3540,7 +3665,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3540 try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });3665 try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });
35413666
3542 info.return_value = .{ .stack_offset = stack_offset };3667 info.return_value = .{ .stack_offset = stack_offset };
3543 }3668
3669 break :blk self.register_manager.lockRegAssumeUnused(.r0);
3670 } else null;
3671 defer if (r0_lock) |reg| self.register_manager.unlockReg(reg);
35443672
3545 // Make space for the arguments passed via the stack3673 // Make space for the arguments passed via the stack
3546 self.max_end_stack += info.stack_byte_count;3674 self.max_end_stack += info.stack_byte_count;
...@@ -3559,7 +3687,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3559,7 +3687,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3559 .stack_offset => unreachable,3687 .stack_offset => unreachable,
3560 .stack_argument_offset => |offset| try self.genSetStackArgument(3688 .stack_argument_offset => |offset| try self.genSetStackArgument(
3561 arg_ty,3689 arg_ty,
3562 info.stack_byte_count - offset,3690 offset,
3563 arg_mcv,3691 arg_mcv,
3564 ),3692 ),
3565 else => unreachable,3693 else => unreachable,
...@@ -4621,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4621,11 +4749,15 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4621 if (!self.wantSafety())4749 if (!self.wantSafety())
4622 return; // The already existing value will do just fine.4750 return; // The already existing value will do just fine.
4623 // TODO Upgrade this to a memset call when we have that available.4751 // TODO Upgrade this to a memset call when we have that available.
4624 switch (ty.abiSize(self.target.*)) {4752 switch (abi_size) {
4625 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),4753 1 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
4626 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),4754 2 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
4627 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),4755 4 => try self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
4628 else => return self.fail("TODO implement memset", .{}),4756 else => try self.genInlineMemset(
4757 .{ .ptr_stack_offset = stack_offset },
4758 .{ .immediate = 0xaa },
4759 .{ .immediate = abi_size },
4760 ),
4629 }4761 }
4630 },4762 },
4631 .cpsr_flags,4763 .cpsr_flags,
...@@ -5037,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5037,9 +5169,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5037 return; // The already existing value will do just fine.5169 return; // The already existing value will do just fine.
5038 // TODO Upgrade this to a memset call when we have that available.5170 // TODO Upgrade this to a memset call when we have that available.
5039 switch (abi_size) {5171 switch (abi_size) {
5040 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),5172 1 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }),
5041 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),5173 2 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }),
5042 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),5174 4 => try self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
5043 else => return self.fail("TODO implement memset", .{}),5175 else => return self.fail("TODO implement memset", .{}),
5044 }5176 }
5045 },5177 },
...@@ -5653,8 +5785,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5653,8 +5785,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5653 if (ty.abiAlignment(self.target.*) == 8)5785 if (ty.abiAlignment(self.target.*) == 8)
5654 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);5786 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
56555787
5656 nsaa += param_size;
5657 result.args[i] = .{ .stack_argument_offset = nsaa };5788 result.args[i] = .{ .stack_argument_offset = nsaa };
5789 nsaa += param_size;
5658 }5790 }
5659 }5791 }
56605792
...@@ -5687,9 +5819,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5687,9 +5819,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5687 for (param_types) |ty, i| {5819 for (param_types) |ty, i| {
5688 if (ty.abiSize(self.target.*) > 0) {5820 if (ty.abiSize(self.target.*) > 0) {
5689 const param_size = @intCast(u32, ty.abiSize(self.target.*));5821 const param_size = @intCast(u32, ty.abiSize(self.target.*));
5822 const param_alignment = ty.abiAlignment(self.target.*);
56905823
5691 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)) + param_size;5824 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
5692 result.args[i] = .{ .stack_argument_offset = stack_offset };5825 result.args[i] = .{ .stack_argument_offset = stack_offset };
5826 stack_offset += param_size;
5693 } else {5827 } else {
5694 result.args[i] = .{ .none = {} };5828 result.args[i] = .{ .none = {} };
5695 }5829 }
src/arch/arm/Emit.zig+19-38
...@@ -33,9 +33,13 @@ prev_di_column: u32,...@@ -33,9 +33,13 @@ prev_di_column: u32,
33/// Relative to the beginning of `code`.33/// Relative to the beginning of `code`.
34prev_di_pc: usize,34prev_di_pc: usize,
3535
36/// The amount of stack space consumed by all stack arguments as well36/// The amount of stack space consumed by the saved callee-saved
37/// as the saved callee-saved registers37/// registers in bytes
38prologue_stack_space: u32,38saved_regs_stack_space: u32,
39
40/// The final stack frame size of the function (already aligned to the
41/// respective stack alignment). Does not include prologue stack space.
42stack_size: u32,
3943
40/// The branch type of every branch44/// The branch type of every branch
41branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},45branch_types: std.AutoHashMapUnmanaged(Mir.Inst.Index, BranchType) = .{},
...@@ -500,14 +504,15 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -500,14 +504,15 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
500 const tag = emit.mir.instructions.items(.tag)[inst];504 const tag = emit.mir.instructions.items(.tag)[inst];
501 const cond = emit.mir.instructions.items(.cond)[inst];505 const cond = emit.mir.instructions.items(.cond)[inst];
502 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;506 const r_stack_offset = emit.mir.instructions.items(.data)[inst].r_stack_offset;
507 const rt = r_stack_offset.rt;
503508
504 const raw_offset = emit.prologue_stack_space - r_stack_offset.stack_offset;509 const raw_offset = emit.stack_size + emit.saved_regs_stack_space + r_stack_offset.stack_offset;
505 switch (tag) {510 switch (tag) {
506 .ldr_ptr_stack_argument => {511 .ldr_ptr_stack_argument => {
507 const operand = Instruction.Operand.fromU32(raw_offset) orelse512 const operand = Instruction.Operand.fromU32(raw_offset) orelse
508 return emit.fail("TODO mirLoadStack larger offsets", .{});513 return emit.fail("TODO mirLoadStack larger offsets", .{});
509514
510 try emit.writeInstruction(Instruction.add(cond, r_stack_offset.rt, .fp, operand));515 try emit.writeInstruction(Instruction.add(cond, rt, .sp, operand));
511 },516 },
512 .ldr_stack_argument,517 .ldr_stack_argument,
513 .ldrb_stack_argument,518 .ldrb_stack_argument,
...@@ -516,23 +521,11 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -516,23 +521,11 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
516 break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));521 break :blk Instruction.Offset.imm(@intCast(u12, raw_offset));
517 } else return emit.fail("TODO mirLoadStack larger offsets", .{});522 } else return emit.fail("TODO mirLoadStack larger offsets", .{});
518523
519 const ldr = switch (tag) {524 switch (tag) {
520 .ldr_stack_argument => &Instruction.ldr,525 .ldr_stack_argument => try emit.writeInstruction(Instruction.ldr(cond, rt, .sp, .{ .offset = offset })),
521 .ldrb_stack_argument => &Instruction.ldrb,526 .ldrb_stack_argument => try emit.writeInstruction(Instruction.ldrb(cond, rt, .sp, .{ .offset = offset })),
522 else => unreachable,527 else => unreachable,
523 };528 }
524
525 const ldr_workaround = switch (builtin.zig_backend) {
526 .stage1 => ldr.*,
527 else => ldr,
528 };
529
530 try emit.writeInstruction(ldr_workaround(
531 cond,
532 r_stack_offset.rt,
533 .fp,
534 .{ .offset = offset },
535 ));
536 },529 },
537 .ldrh_stack_argument,530 .ldrh_stack_argument,
538 .ldrsb_stack_argument,531 .ldrsb_stack_argument,
...@@ -542,24 +535,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -542,24 +535,12 @@ fn mirLoadStackArgument(emit: *Emit, inst: Mir.Inst.Index) !void {
542 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));535 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, raw_offset));
543 } else return emit.fail("TODO mirLoadStack larger offsets", .{});536 } else return emit.fail("TODO mirLoadStack larger offsets", .{});
544537
545 const ldr = switch (tag) {538 switch (tag) {
546 .ldrh_stack_argument => &Instruction.ldrh,539 .ldrh_stack_argument => try emit.writeInstruction(Instruction.ldrh(cond, rt, .sp, .{ .offset = offset })),
547 .ldrsb_stack_argument => &Instruction.ldrsb,540 .ldrsb_stack_argument => try emit.writeInstruction(Instruction.ldrsb(cond, rt, .sp, .{ .offset = offset })),
548 .ldrsh_stack_argument => &Instruction.ldrsh,541 .ldrsh_stack_argument => try emit.writeInstruction(Instruction.ldrsh(cond, rt, .sp, .{ .offset = offset })),
549 else => unreachable,542 else => unreachable,
550 };543 }
551
552 const ldr_workaround = switch (builtin.zig_backend) {
553 .stage1 => ldr.*,
554 else => ldr,
555 };
556
557 try emit.writeInstruction(ldr_workaround(
558 cond,
559 r_stack_offset.rt,
560 .fp,
561 .{ .offset = offset },
562 ));
563 },544 },
564 else => unreachable,545 else => unreachable,
565 }546 }