| ... | @@ -1170,10 +1170,10 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1170,10 +1170,10 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1170 | .dead, .unreach => unreachable, | 1170 | .dead, .unreach => unreachable, |
| 1171 | .register => unreachable, // a slice doesn't fit in one register | 1171 | .register => unreachable, // a slice doesn't fit in one register |
| 1172 | .stack_argument_offset => |off| { | 1172 | .stack_argument_offset => |off| { |
| 1173 | break :result MCValue{ .stack_argument_offset = off }; | 1173 | break :result MCValue{ .stack_argument_offset = off + 4 }; |
| 1174 | }, | 1174 | }, |
| 1175 | .stack_offset => |off| { | 1175 | .stack_offset => |off| { |
| 1176 | break :result MCValue{ .stack_offset = off }; | 1176 | break :result MCValue{ .stack_offset = off + 4 }; |
| 1177 | }, | 1177 | }, |
| 1178 | .memory => |addr| { | 1178 | .memory => |addr| { |
| 1179 | break :result MCValue{ .memory = addr }; | 1179 | break :result MCValue{ .memory = addr }; |
| ... | @@ -1192,10 +1192,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1192,10 +1192,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1192 | .dead, .unreach => unreachable, | 1192 | .dead, .unreach => unreachable, |
| 1193 | .register => unreachable, // a slice doesn't fit in one register | 1193 | .register => unreachable, // a slice doesn't fit in one register |
| 1194 | .stack_argument_offset => |off| { | 1194 | .stack_argument_offset => |off| { |
| 1195 | break :result MCValue{ .stack_argument_offset = off + 4 }; | 1195 | break :result MCValue{ .stack_argument_offset = off }; |
| 1196 | }, | 1196 | }, |
| 1197 | .stack_offset => |off| { | 1197 | .stack_offset => |off| { |
| 1198 | break :result MCValue{ .stack_offset = off + 4 }; | 1198 | break :result MCValue{ .stack_offset = off }; |
| 1199 | }, | 1199 | }, |
| 1200 | .memory => |addr| { | 1200 | .memory => |addr| { |
| 1201 | break :result MCValue{ .memory = addr + 4 }; | 1201 | break :result MCValue{ .memory = addr + 4 }; |
| ... | @@ -1260,7 +1260,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1260,7 +1260,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1260 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); | 1260 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); |
| 1261 | | 1261 | |
| 1262 | const base_mcv: MCValue = switch (slice_mcv) { | 1262 | const base_mcv: MCValue = switch (slice_mcv) { |
| 1263 | .stack_offset => .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, slice_mcv) }, | 1263 | .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off + 4 }) }, |
| 1264 | else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}), | 1264 | else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}), |
| 1265 | }; | 1265 | }; |
| 1266 | self.register_manager.freezeRegs(&.{base_mcv.register}); | 1266 | self.register_manager.freezeRegs(&.{base_mcv.register}); |
| ... | @@ -1471,36 +1471,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -1471,36 +1471,6 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1471 | | 1471 | |
| 1472 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); | 1472 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 1473 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); | 1473 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 1474 | } else if (elem_size == 8) { | | |
| 1475 | // TODO generalize this: maybe add a | | |
| 1476 | // genArmMemcpy function which manually copies | | |
| 1477 | // data if the size is below a certain | | |
| 1478 | // threshold and calls "memcpy" if the size is | | |
| 1479 | // larger | | |
| 1480 | | | |
| 1481 | const usize_ty = Type.initTag(.usize); | | |
| 1482 | const tmp_regs = try self.register_manager.allocRegs(2, .{ null, null }); | | |
| 1483 | self.register_manager.freezeRegs(&tmp_regs); | | |
| 1484 | defer self.register_manager.unfreezeRegs(&tmp_regs); | | |
| 1485 | | | |
| 1486 | _ = try self.addInst(.{ | | |
| 1487 | .tag = .ldr, | | |
| 1488 | .data = .{ .rr_offset = .{ | | |
| 1489 | .rt = tmp_regs[0], | | |
| 1490 | .rn = reg, | | |
| 1491 | .offset = .{ .offset = Instruction.Offset.none }, | | |
| 1492 | } }, | | |
| 1493 | }); | | |
| 1494 | _ = try self.addInst(.{ | | |
| 1495 | .tag = .ldr, | | |
| 1496 | .data = .{ .rr_offset = .{ | | |
| 1497 | .rt = tmp_regs[1], | | |
| 1498 | .rn = reg, | | |
| 1499 | .offset = .{ .offset = Instruction.Offset.imm(4) }, | | |
| 1500 | } }, | | |
| 1501 | }); | | |
| 1502 | try self.genSetStack(usize_ty, off, MCValue{ .register = tmp_regs[0] }); | | |
| 1503 | try self.genSetStack(usize_ty, off + 4, MCValue{ .register = tmp_regs[1] }); | | |
| 1504 | } else { | 1474 | } else { |
| 1505 | // TODO optimize the register allocation | 1475 | // TODO optimize the register allocation |
| 1506 | const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }); | 1476 | const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }); |
| ... | @@ -1677,7 +1647,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -1677,7 +1647,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 1677 | .ptr_stack_offset => |off| { | 1647 | .ptr_stack_offset => |off| { |
| 1678 | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; | 1648 | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; |
| 1679 | }, | 1649 | }, |
| 1680 | .stack_argument_offset => { | 1650 | else => { |
| 1681 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ | 1651 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| 1682 | .immediate = struct_field_offset, | 1652 | .immediate = struct_field_offset, |
| 1683 | }); | 1653 | }); |
| ... | @@ -1699,7 +1669,6 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde | ... | @@ -1699,7 +1669,6 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 1699 | ); | 1669 | ); |
| 1700 | break :result MCValue{ .register = dst_reg }; | 1670 | break :result MCValue{ .register = dst_reg }; |
| 1701 | }, | 1671 | }, |
| 1702 | else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}), | | |
| 1703 | } | 1672 | } |
| 1704 | }; | 1673 | }; |
| 1705 | } | 1674 | } |
| ... | @@ -3200,9 +3169,9 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { | ... | @@ -3200,9 +3169,9 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void { |
| 3200 | } | 3169 | } |
| 3201 | | 3170 | |
| 3202 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 3171 | fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| | 3172 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3203 | switch (mcv) { | 3173 | switch (mcv) { |
| 3204 | .dead => unreachable, | 3174 | .dead => unreachable, |
| 3205 | .ptr_embedded_in_code => unreachable, | | |
| 3206 | .unreach, .none => return, // Nothing to do. | 3175 | .unreach, .none => return, // Nothing to do. |
| 3207 | .undef => { | 3176 | .undef => { |
| 3208 | if (!self.wantSafety()) | 3177 | if (!self.wantSafety()) |
| ... | @@ -3215,23 +3184,16 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3215,23 +3184,16 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3215 | else => return self.fail("TODO implement memset", .{}), | 3184 | else => return self.fail("TODO implement memset", .{}), |
| 3216 | } | 3185 | } |
| 3217 | }, | 3186 | }, |
| 3218 | .ptr_stack_offset => { | | |
| 3219 | const reg = try self.copyToTmpRegister(ty, mcv); | | |
| 3220 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | | |
| 3221 | }, | | |
| 3222 | .compare_flags_unsigned, | 3187 | .compare_flags_unsigned, |
| 3223 | .compare_flags_signed, | 3188 | .compare_flags_signed, |
| 3224 | .immediate, | 3189 | .immediate, |
| | 3190 | .ptr_stack_offset, |
| | 3191 | .ptr_embedded_in_code, |
| 3225 | => { | 3192 | => { |
| 3226 | const reg = try self.copyToTmpRegister(ty, mcv); | 3193 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3227 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3194 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3228 | }, | 3195 | }, |
| 3229 | .embedded_in_code => |code_offset| { | | |
| 3230 | _ = code_offset; | | |
| 3231 | return self.fail("TODO implement set stack variable from embedded_in_code", .{}); | | |
| 3232 | }, | | |
| 3233 | .register => |reg| { | 3196 | .register => |reg| { |
| 3234 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | | |
| 3235 | const adj_off = stack_offset + abi_size; | 3197 | const adj_off = stack_offset + abi_size; |
| 3236 | | 3198 | |
| 3237 | switch (abi_size) { | 3199 | switch (abi_size) { |
| ... | @@ -3279,24 +3241,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3279,24 +3241,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3279 | } | 3241 | } |
| 3280 | }, | 3242 | }, |
| 3281 | .memory, | 3243 | .memory, |
| | 3244 | .embedded_in_code, |
| 3282 | .stack_argument_offset, | 3245 | .stack_argument_offset, |
| | 3246 | .stack_offset, |
| 3283 | => { | 3247 | => { |
| 3284 | if (ty.abiSize(self.target.*) <= 4) { | 3248 | switch (mcv) { |
| 3285 | const reg = try self.copyToTmpRegister(ty, mcv); | 3249 | .stack_offset => |off| { |
| 3286 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3250 | if (stack_offset == off) |
| 3287 | } else { | 3251 | return; // Copy stack variable to itself; nothing to do. |
| 3288 | return self.fail("TODO implement memcpy", .{}); | 3252 | }, |
| | 3253 | else => {}, |
| 3289 | } | 3254 | } |
| 3290 | }, | | |
| 3291 | .stack_offset => |off| { | | |
| 3292 | if (stack_offset == off) | | |
| 3293 | return; // Copy stack variable to itself; nothing to do. | | |
| 3294 | | 3255 | |
| 3295 | if (ty.abiSize(self.target.*) <= 4) { | 3256 | if (abi_size <= 4) { |
| 3296 | const reg = try self.copyToTmpRegister(ty, mcv); | 3257 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3297 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3258 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3298 | } else { | 3259 | } else { |
| 3299 | // TODO optimize the register allocation | 3260 | // TODO call extern memcpy |
| 3300 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); | 3261 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3301 | const src_reg = regs[0]; | 3262 | const src_reg = regs[0]; |
| 3302 | const dst_reg = regs[1]; | 3263 | const dst_reg = regs[1]; |
| ... | @@ -3304,22 +3265,31 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3304,22 +3265,31 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3304 | const count_reg = regs[3]; | 3265 | const count_reg = regs[3]; |
| 3305 | const tmp_reg = regs[4]; | 3266 | const tmp_reg = regs[4]; |
| 3306 | | 3267 | |
| 3307 | // sub src_reg, fp, #off | 3268 | switch (mcv) { |
| 3308 | const adj_src_offset = off + @intCast(u32, ty.abiSize(self.target.*)); | 3269 | .stack_offset => |off| { |
| 3309 | const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else { | 3270 | // sub src_reg, fp, #off |
| 3310 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); | 3271 | const adj_src_offset = off + @intCast(u32, abi_size); |
| 3311 | }; | 3272 | const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else { |
| 3312 | _ = try self.addInst(.{ | 3273 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 3313 | .tag = .sub, | 3274 | }; |
| 3314 | .data = .{ .rr_op = .{ | 3275 | _ = try self.addInst(.{ |
| 3315 | .rd = src_reg, | 3276 | .tag = .sub, |
| 3316 | .rn = .fp, | 3277 | .data = .{ .rr_op = .{ |
| 3317 | .op = src_offset_op, | 3278 | .rd = src_reg, |
| 3318 | } }, | 3279 | .rn = .fp, |
| 3319 | }); | 3280 | .op = src_offset_op, |
| | 3281 | } }, |
| | 3282 | }); |
| | 3283 | }, |
| | 3284 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| | 3285 | .embedded_in_code, |
| | 3286 | .stack_argument_offset, |
| | 3287 | => return self.fail("TODO genSetStack with src={}", .{mcv}), |
| | 3288 | else => unreachable, |
| | 3289 | } |
| 3320 | | 3290 | |
| 3321 | // sub dst_reg, fp, #stack_offset | 3291 | // sub dst_reg, fp, #stack_offset |
| 3322 | const adj_dst_offset = stack_offset + @intCast(u32, ty.abiSize(self.target.*)); | 3292 | const adj_dst_offset = stack_offset + abi_size; |
| 3323 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { | 3293 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { |
| 3324 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); | 3294 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 3325 | }; | 3295 | }; |
| ... | @@ -3332,9 +3302,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3332,9 +3302,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3332 | } }, | 3302 | } }, |
| 3333 | }); | 3303 | }); |
| 3334 | | 3304 | |
| 3335 | // mov len, #elem_size | 3305 | // mov len, #abi_size |
| 3336 | const elem_size = @intCast(u32, ty.abiSize(self.target.*)); | 3306 | const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(abi_size)) |x| x else { |
| 3337 | const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(elem_size)) |x| x else { | | |
| 3338 | return self.fail("TODO load: set reg to elem_size with all possible sizes", .{}); | 3307 | return self.fail("TODO load: set reg to elem_size with all possible sizes", .{}); |
| 3339 | }; | 3308 | }; |
| 3340 | _ = try self.addInst(.{ | 3309 | _ = try self.addInst(.{ |
| ... | @@ -3619,6 +3588,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3619,6 +3588,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3619 | } | 3588 | } |
| 3620 | | 3589 | |
| 3621 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { | 3590 | fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void { |
| | 3591 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3622 | switch (mcv) { | 3592 | switch (mcv) { |
| 3623 | .dead => unreachable, | 3593 | .dead => unreachable, |
| 3624 | .none, .unreach => return, | 3594 | .none, .unreach => return, |
| ... | @@ -3634,7 +3604,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -3634,7 +3604,6 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3634 | } | 3604 | } |
| 3635 | }, | 3605 | }, |
| 3636 | .register => |reg| { | 3606 | .register => |reg| { |
| 3637 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); | | |
| 3638 | const adj_off = stack_offset - abi_size; | 3607 | const adj_off = stack_offset - abi_size; |
| 3639 | | 3608 | |
| 3640 | switch (abi_size) { | 3609 | switch (abi_size) { |
| ... | @@ -3675,28 +3644,86 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -3675,28 +3644,86 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3675 | else => return self.fail("TODO implement storing other types abi_size={}", .{abi_size}), | 3644 | else => return self.fail("TODO implement storing other types abi_size={}", .{abi_size}), |
| 3676 | } | 3645 | } |
| 3677 | }, | 3646 | }, |
| 3678 | .immediate, | | |
| 3679 | .compare_flags_signed, | | |
| 3680 | .compare_flags_unsigned, | | |
| 3681 | .stack_offset, | 3647 | .stack_offset, |
| 3682 | .memory, | 3648 | .memory, |
| 3683 | .stack_argument_offset, | 3649 | .stack_argument_offset, |
| 3684 | .embedded_in_code, | 3650 | .embedded_in_code, |
| 3685 | => { | 3651 | => { |
| 3686 | if (ty.abiSize(self.target.*) <= 4) { | 3652 | if (abi_size <= 4) { |
| 3687 | const reg = try self.copyToTmpRegister(ty, mcv); | 3653 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3688 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); | 3654 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); |
| 3689 | } else { | 3655 | } else { |
| 3690 | return self.fail("TODO implement memcpy", .{}); | 3656 | // TODO call extern memcpy |
| | 3657 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| | 3658 | const src_reg = regs[0]; |
| | 3659 | const dst_reg = regs[1]; |
| | 3660 | const len_reg = regs[2]; |
| | 3661 | const count_reg = regs[3]; |
| | 3662 | const tmp_reg = regs[4]; |
| | 3663 | |
| | 3664 | switch (mcv) { |
| | 3665 | .stack_offset => |off| { |
| | 3666 | // sub src_reg, fp, #off |
| | 3667 | const adj_src_offset = off + abi_size; |
| | 3668 | const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else { |
| | 3669 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| | 3670 | }; |
| | 3671 | _ = try self.addInst(.{ |
| | 3672 | .tag = .sub, |
| | 3673 | .data = .{ .rr_op = .{ |
| | 3674 | .rd = src_reg, |
| | 3675 | .rn = .fp, |
| | 3676 | .op = src_offset_op, |
| | 3677 | } }, |
| | 3678 | }); |
| | 3679 | }, |
| | 3680 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| | 3681 | .stack_argument_offset, |
| | 3682 | .embedded_in_code, |
| | 3683 | => return self.fail("TODO genSetStackArgument src={}", .{mcv}), |
| | 3684 | else => unreachable, |
| | 3685 | } |
| | 3686 | |
| | 3687 | // add dst_reg, sp, #stack_offset |
| | 3688 | const adj_dst_offset = stack_offset - abi_size; |
| | 3689 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { |
| | 3690 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| | 3691 | }; |
| | 3692 | _ = try self.addInst(.{ |
| | 3693 | .tag = .add, |
| | 3694 | .data = .{ .rr_op = .{ |
| | 3695 | .rd = dst_reg, |
| | 3696 | .rn = .sp, |
| | 3697 | .op = dst_offset_op, |
| | 3698 | } }, |
| | 3699 | }); |
| | 3700 | |
| | 3701 | // mov len, #abi_size |
| | 3702 | const len_op: Instruction.Operand = if (Instruction.Operand.fromU32(abi_size)) |x| x else { |
| | 3703 | return self.fail("TODO load: set reg to elem_size with all possible sizes", .{}); |
| | 3704 | }; |
| | 3705 | _ = try self.addInst(.{ |
| | 3706 | .tag = .mov, |
| | 3707 | .data = .{ .rr_op = .{ |
| | 3708 | .rd = len_reg, |
| | 3709 | .rn = .r0, |
| | 3710 | .op = len_op, |
| | 3711 | } }, |
| | 3712 | }); |
| | 3713 | |
| | 3714 | // memcpy(src, dst, len) |
| | 3715 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); |
| 3691 | } | 3716 | } |
| 3692 | }, | 3717 | }, |
| 3693 | .ptr_stack_offset => { | 3718 | .compare_flags_unsigned, |
| | 3719 | .compare_flags_signed, |
| | 3720 | .immediate, |
| | 3721 | .ptr_stack_offset, |
| | 3722 | .ptr_embedded_in_code, |
| | 3723 | => { |
| 3694 | const reg = try self.copyToTmpRegister(ty, mcv); | 3724 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3695 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); | 3725 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); |
| 3696 | }, | 3726 | }, |
| 3697 | .ptr_embedded_in_code => { | | |
| 3698 | return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); | | |
| 3699 | }, | | |
| 3700 | } | 3727 | } |
| 3701 | } | 3728 | } |
| 3702 | | 3729 | |
| ... | @@ -4114,9 +4141,13 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -4114,9 +4141,13 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4114 | var stack_offset: u32 = 0; | 4141 | var stack_offset: u32 = 0; |
| 4115 | | 4142 | |
| 4116 | for (param_types) |ty, i| { | 4143 | for (param_types) |ty, i| { |
| 4117 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)); | 4144 | if (ty.abiSize(self.target.*) > 0) { |
| 4118 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 4145 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)); |
| 4119 | stack_offset += @intCast(u32, ty.abiSize(self.target.*)); | 4146 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
| | 4147 | stack_offset += @intCast(u32, ty.abiSize(self.target.*)); |
| | 4148 | } else { |
| | 4149 | result.args[i] = .{ .none = {} }; |
| | 4150 | } |
| 4120 | } | 4151 | } |
| 4121 | | 4152 | |
| 4122 | result.stack_byte_count = stack_offset; | 4153 | result.stack_byte_count = stack_offset; |