| ... | ... | @@ -169,40 +169,6 @@ const MCValue = union(enum) { |
| 169 | 169 | cpsr_flags: Condition, |
| 170 | 170 | /// The value is a function argument passed via the stack. |
| 171 | 171 | stack_argument_offset: u32, |
| 172 | | |
| 173 | | fn isMemory(mcv: MCValue) bool { |
| 174 | | return switch (mcv) { |
| 175 | | .memory, .stack_offset, .stack_argument_offset => true, |
| 176 | | else => false, |
| 177 | | }; |
| 178 | | } |
| 179 | | |
| 180 | | fn isImmediate(mcv: MCValue) bool { |
| 181 | | return switch (mcv) { |
| 182 | | .immediate => true, |
| 183 | | else => false, |
| 184 | | }; |
| 185 | | } |
| 186 | | |
| 187 | | fn isMutable(mcv: MCValue) bool { |
| 188 | | return switch (mcv) { |
| 189 | | .none => unreachable, |
| 190 | | .unreach => unreachable, |
| 191 | | .dead => unreachable, |
| 192 | | |
| 193 | | .immediate, |
| 194 | | .memory, |
| 195 | | .cpsr_flags, |
| 196 | | .ptr_stack_offset, |
| 197 | | .undef, |
| 198 | | .stack_argument_offset, |
| 199 | | => false, |
| 200 | | |
| 201 | | .register, |
| 202 | | .stack_offset, |
| 203 | | => true, |
| 204 | | }; |
| 205 | | } |
| 206 | 172 | }; |
| 207 | 173 | |
| 208 | 174 | const Branch = struct { |
| ... | ... | @@ -447,6 +413,11 @@ fn gen(self: *Self) !void { |
| 447 | 413 | // sub sp, sp, #reloc |
| 448 | 414 | const sub_reloc = try self.addNop(); |
| 449 | 415 | |
| 416 | // The sub_sp_scratch_r4 instruction may use r4, so we mark r4 |
| 417 | // as allocated by this function. |
| 418 | const index = RegisterManager.indexOfRegIntoTracked(.r4).?; |
| 419 | self.register_manager.allocated_registers.set(index); |
| 420 | |
| 450 | 421 | if (self.ret_mcv == .stack_offset) { |
| 451 | 422 | // The address of where to store the return value is in |
| 452 | 423 | // r0. As this register might get overwritten along the |
| ... | ... | @@ -457,6 +428,28 @@ fn gen(self: *Self) !void { |
| 457 | 428 | self.ret_mcv = MCValue{ .stack_offset = stack_offset }; |
| 458 | 429 | } |
| 459 | 430 | |
| 431 | for (self.args) |*arg, arg_index| { |
| 432 | // Copy register arguments to the stack |
| 433 | switch (arg.*) { |
| 434 | .register => |reg| { |
| 435 | // The first AIR instructions of the main body are guaranteed |
| 436 | // to be the functions arguments |
| 437 | const inst = self.air.getMainBody()[arg_index]; |
| 438 | assert(self.air.instructions.items(.tag)[inst] == .arg); |
| 439 | |
| 440 | const ty = self.air.typeOfIndex(inst); |
| 441 | |
| 442 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 443 | const abi_align = ty.abiAlignment(self.target.*); |
| 444 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 445 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 446 | |
| 447 | arg.* = MCValue{ .stack_offset = stack_offset }; |
| 448 | }, |
| 449 | else => {}, |
| 450 | } |
| 451 | } |
| 452 | |
| 460 | 453 | _ = try self.addInst(.{ |
| 461 | 454 | .tag = .dbg_prologue_end, |
| 462 | 455 | .cond = undefined, |
| ... | ... | @@ -477,7 +470,6 @@ fn gen(self: *Self) !void { |
| 477 | 470 | self.saved_regs_stack_space += 4; |
| 478 | 471 | } |
| 479 | 472 | } |
| 480 | | |
| 481 | 473 | self.mir_instructions.set(push_reloc, .{ |
| 482 | 474 | .tag = .push, |
| 483 | 475 | .data = .{ .register_list = saved_regs }, |
| ... | ... | @@ -489,7 +481,7 @@ fn gen(self: *Self) !void { |
| 489 | 481 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; |
| 490 | 482 | self.max_end_stack = stack_size; |
| 491 | 483 | self.mir_instructions.set(sub_reloc, .{ |
| 492 | | .tag = .sub_sp_scratch_r0, |
| 484 | .tag = .sub_sp_scratch_r4, |
| 493 | 485 | .data = .{ .imm32 = stack_size }, |
| 494 | 486 | }); |
| 495 | 487 | |
| ... | ... | @@ -3796,7 +3788,8 @@ fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Typ |
| 3796 | 3788 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3797 | 3789 | 1 => .strb, |
| 3798 | 3790 | 2 => .strh, |
| 3799 | | 3, 4 => .str, |
| 3791 | 4 => .str, |
| 3792 | 3 => return self.fail("TODO: genStrRegister for abi_size={}", .{abi_size}), |
| 3800 | 3793 | else => unreachable, |
| 3801 | 3794 | }; |
| 3802 | 3795 | |
| ... | ... | @@ -3812,7 +3805,7 @@ fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Typ |
| 3812 | 3805 | } }; |
| 3813 | 3806 | |
| 3814 | 3807 | const data: Mir.Inst.Data = switch (abi_size) { |
| 3815 | | 1, 3, 4 => rr_offset, |
| 3808 | 1, 4 => rr_offset, |
| 3816 | 3809 | 2 => rr_extra_offset, |
| 3817 | 3810 | else => unreachable, |
| 3818 | 3811 | }; |
| ... | ... | @@ -4042,7 +4035,6 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfM |
| 4042 | 4035 | => { |
| 4043 | 4036 | switch (self.debug_output) { |
| 4044 | 4037 | .dwarf => |dw| { |
| 4045 | | // const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4046 | 4038 | const adjusted_stack_offset = switch (mcv) { |
| 4047 | 4039 | .stack_offset => |offset| -@intCast(i32, offset), |
| 4048 | 4040 | .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), |
| ... | ... | @@ -4078,38 +4070,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4078 | 4070 | const arg_index = self.arg_index; |
| 4079 | 4071 | self.arg_index += 1; |
| 4080 | 4072 | |
| 4081 | | const ty = self.air.typeOfIndex(inst); |
| 4082 | | |
| 4083 | | const result = self.args[arg_index]; |
| 4084 | | const mcv = switch (result) { |
| 4085 | | // Copy registers to the stack |
| 4086 | | .register => |reg| blk: { |
| 4087 | | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 4088 | | const abi_align = ty.abiAlignment(self.target.*); |
| 4089 | | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 4090 | | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 4091 | | |
| 4092 | | break :blk MCValue{ .stack_offset = stack_offset }; |
| 4093 | | }, |
| 4094 | | else => result, |
| 4095 | | }; |
| 4096 | | |
| 4097 | 4073 | try self.dbg_arg_relocs.append(self.gpa, .{ |
| 4098 | 4074 | .inst = inst, |
| 4099 | 4075 | .index = arg_index, |
| 4100 | 4076 | }); |
| 4101 | 4077 | |
| 4102 | | if (self.liveness.isUnused(inst)) |
| 4103 | | return self.finishAirBookkeeping(); |
| 4104 | | |
| 4105 | | switch (mcv) { |
| 4106 | | .register => |reg| { |
| 4107 | | self.register_manager.getRegAssumeFree(reg, inst); |
| 4108 | | }, |
| 4109 | | else => {}, |
| 4110 | | } |
| 4111 | | |
| 4112 | | return self.finishAir(inst, mcv, .{ .none, .none, .none }); |
| 4078 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index]; |
| 4079 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 4113 | 4080 | } |
| 4114 | 4081 | |
| 4115 | 4082 | fn airBreakpoint(self: *Self) !void { |