| ... | @@ -169,40 +169,6 @@ const MCValue = union(enum) { | ... | @@ -169,40 +169,6 @@ const MCValue = union(enum) { |
| 169 | cpsr_flags: Condition, | 169 | cpsr_flags: Condition, |
| 170 | /// The value is a function argument passed via the stack. | 170 | /// The value is a function argument passed via the stack. |
| 171 | stack_argument_offset: u32, | 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 | const Branch = struct { | 174 | const Branch = struct { |
| ... | @@ -447,6 +413,11 @@ fn gen(self: *Self) !void { | ... | @@ -447,6 +413,11 @@ fn gen(self: *Self) !void { |
| 447 | // sub sp, sp, #reloc | 413 | // sub sp, sp, #reloc |
| 448 | const sub_reloc = try self.addNop(); | 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 | if (self.ret_mcv == .stack_offset) { | 421 | if (self.ret_mcv == .stack_offset) { |
| 451 | // The address of where to store the return value is in | 422 | // The address of where to store the return value is in |
| 452 | // r0. As this register might get overwritten along the | 423 | // r0. As this register might get overwritten along the |
| ... | @@ -457,6 +428,28 @@ fn gen(self: *Self) !void { | ... | @@ -457,6 +428,28 @@ fn gen(self: *Self) !void { |
| 457 | self.ret_mcv = MCValue{ .stack_offset = stack_offset }; | 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 | _ = try self.addInst(.{ | 453 | _ = try self.addInst(.{ |
| 461 | .tag = .dbg_prologue_end, | 454 | .tag = .dbg_prologue_end, |
| 462 | .cond = undefined, | 455 | .cond = undefined, |
| ... | @@ -477,7 +470,6 @@ fn gen(self: *Self) !void { | ... | @@ -477,7 +470,6 @@ fn gen(self: *Self) !void { |
| 477 | self.saved_regs_stack_space += 4; | 470 | self.saved_regs_stack_space += 4; |
| 478 | } | 471 | } |
| 479 | } | 472 | } |
| 480 | | | |
| 481 | self.mir_instructions.set(push_reloc, .{ | 473 | self.mir_instructions.set(push_reloc, .{ |
| 482 | .tag = .push, | 474 | .tag = .push, |
| 483 | .data = .{ .register_list = saved_regs }, | 475 | .data = .{ .register_list = saved_regs }, |
| ... | @@ -489,7 +481,7 @@ fn gen(self: *Self) !void { | ... | @@ -489,7 +481,7 @@ fn gen(self: *Self) !void { |
| 489 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; | 481 | const stack_size = aligned_total_stack_end - self.saved_regs_stack_space; |
| 490 | self.max_end_stack = stack_size; | 482 | self.max_end_stack = stack_size; |
| 491 | self.mir_instructions.set(sub_reloc, .{ | 483 | self.mir_instructions.set(sub_reloc, .{ |
| 492 | .tag = .sub_sp_scratch_r0, | 484 | .tag = .sub_sp_scratch_r4, |
| 493 | .data = .{ .imm32 = stack_size }, | 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,7 +3788,8 @@ fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Typ |
| 3796 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3788 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3797 | 1 => .strb, | 3789 | 1 => .strb, |
| 3798 | 2 => .strh, | 3790 | 2 => .strh, |
| 3799 | 3, 4 => .str, | 3791 | 4 => .str, |
| | 3792 | 3 => return self.fail("TODO: genStrRegister for abi_size={}", .{abi_size}), |
| 3800 | else => unreachable, | 3793 | else => unreachable, |
| 3801 | }; | 3794 | }; |
| 3802 | | 3795 | |
| ... | @@ -3812,7 +3805,7 @@ fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Typ | ... | @@ -3812,7 +3805,7 @@ fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Typ |
| 3812 | } }; | 3805 | } }; |
| 3813 | | 3806 | |
| 3814 | const data: Mir.Inst.Data = switch (abi_size) { | 3807 | const data: Mir.Inst.Data = switch (abi_size) { |
| 3815 | 1, 3, 4 => rr_offset, | 3808 | 1, 4 => rr_offset, |
| 3816 | 2 => rr_extra_offset, | 3809 | 2 => rr_extra_offset, |
| 3817 | else => unreachable, | 3810 | else => unreachable, |
| 3818 | }; | 3811 | }; |
| ... | @@ -4042,7 +4035,6 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfM | ... | @@ -4042,7 +4035,6 @@ fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, arg_index: u32) error{OutOfM |
| 4042 | => { | 4035 | => { |
| 4043 | switch (self.debug_output) { | 4036 | switch (self.debug_output) { |
| 4044 | .dwarf => |dw| { | 4037 | .dwarf => |dw| { |
| 4045 | // const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | | |
| 4046 | const adjusted_stack_offset = switch (mcv) { | 4038 | const adjusted_stack_offset = switch (mcv) { |
| 4047 | .stack_offset => |offset| -@intCast(i32, offset), | 4039 | .stack_offset => |offset| -@intCast(i32, offset), |
| 4048 | .stack_argument_offset => |offset| @intCast(i32, self.saved_regs_stack_space + offset), | 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,38 +4070,13 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 4078 | const arg_index = self.arg_index; | 4070 | const arg_index = self.arg_index; |
| 4079 | self.arg_index += 1; | 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 | try self.dbg_arg_relocs.append(self.gpa, .{ | 4073 | try self.dbg_arg_relocs.append(self.gpa, .{ |
| 4098 | .inst = inst, | 4074 | .inst = inst, |
| 4099 | .index = arg_index, | 4075 | .index = arg_index, |
| 4100 | }); | 4076 | }); |
| 4101 | | 4077 | |
| 4102 | if (self.liveness.isUnused(inst)) | 4078 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index]; |
| 4103 | return self.finishAirBookkeeping(); | 4079 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 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 }); | | |
| 4113 | } | 4080 | } |
| 4114 | | 4081 | |
| 4115 | fn airBreakpoint(self: *Self) !void { | 4082 | fn airBreakpoint(self: *Self) !void { |