| ... | ... | @@ -1434,29 +1434,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1434 | 1434 | break :result dst_mcv; |
| 1435 | 1435 | }, |
| 1436 | 1436 | else => { |
| 1437 | | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1437 | const dest = try self.allocRegOrMem(inst, true); |
| 1438 | const addr = try self.binOp(.ptr_add, null, base_mcv, index_mcv, slice_ty, Type.usize); |
| 1439 | try self.load(dest, addr, slice_ptr_field_type); |
| 1438 | 1440 | |
| 1439 | | const offset_mcv = try self.binOp( |
| 1440 | | .mul, |
| 1441 | | null, |
| 1442 | | index_mcv, |
| 1443 | | .{ .immediate = elem_size }, |
| 1444 | | Type.usize, |
| 1445 | | Type.usize, |
| 1446 | | ); |
| 1447 | | assert(offset_mcv == .register); // result of multiplication should always be register |
| 1448 | | self.register_manager.freezeRegs(&.{offset_mcv.register}); |
| 1449 | | |
| 1450 | | const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize); |
| 1451 | | |
| 1452 | | // At this point in time, neither the base register |
| 1453 | | // nor the offset register contains any valuable data |
| 1454 | | // anymore. |
| 1455 | | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); |
| 1456 | | |
| 1457 | | try self.load(dst_mcv, addr_mcv, slice_ptr_field_type); |
| 1458 | | |
| 1459 | | break :result dst_mcv; |
| 1441 | break :result dest; |
| 1460 | 1442 | }, |
| 1461 | 1443 | } |
| 1462 | 1444 | }; |
| ... | ... | @@ -1710,6 +1692,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1710 | 1692 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1711 | 1693 | |
| 1712 | 1694 | switch (value) { |
| 1695 | .dead => unreachable, |
| 1696 | .undef => unreachable, |
| 1713 | 1697 | .register => |value_reg| { |
| 1714 | 1698 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 1715 | 1699 | }, |
| ... | ... | @@ -2140,7 +2124,7 @@ fn binOp( |
| 2140 | 2124 | rhs: MCValue, |
| 2141 | 2125 | lhs_ty: Type, |
| 2142 | 2126 | rhs_ty: Type, |
| 2143 | | ) !MCValue { |
| 2127 | ) InnerError!MCValue { |
| 2144 | 2128 | switch (tag) { |
| 2145 | 2129 | .add, |
| 2146 | 2130 | .sub, |
| ... | ... | @@ -2281,16 +2265,21 @@ fn binOp( |
| 2281 | 2265 | switch (lhs_ty.zigTypeTag()) { |
| 2282 | 2266 | .Pointer => { |
| 2283 | 2267 | const ptr_ty = lhs_ty; |
| 2284 | | const pointee_ty = switch (ptr_ty.ptrSize()) { |
| 2268 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 2285 | 2269 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 2286 | 2270 | else => ptr_ty.childType(), |
| 2287 | 2271 | }; |
| 2272 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); |
| 2288 | 2273 | |
| 2289 | | if (pointee_ty.abiSize(self.target.*) > 1) { |
| 2290 | | return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{}); |
| 2274 | if (elem_size == 1) { |
| 2275 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2276 | } else { |
| 2277 | // convert the offset into a byte offset by |
| 2278 | // multiplying it with elem_size |
| 2279 | const offset = try self.binOp(.mul, null, rhs, .{ .immediate = elem_size }, Type.usize, Type.usize); |
| 2280 | const addr = try self.binOp(tag, null, lhs, offset, Type.initTag(.manyptr_u8), Type.usize); |
| 2281 | return addr; |
| 2291 | 2282 | } |
| 2292 | | |
| 2293 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2294 | 2283 | }, |
| 2295 | 2284 | else => unreachable, |
| 2296 | 2285 | } |
| ... | ... | @@ -3494,6 +3483,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3494 | 3483 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3495 | 3484 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3496 | 3485 | } else { |
| 3486 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 3487 | .base = .{ .tag = .single_mut_pointer }, |
| 3488 | .data = ty, |
| 3489 | }; |
| 3490 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 3491 | |
| 3497 | 3492 | // TODO call extern memcpy |
| 3498 | 3493 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3499 | 3494 | const src_reg = regs[0]; |
| ... | ... | @@ -3505,20 +3500,9 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3505 | 3500 | switch (mcv) { |
| 3506 | 3501 | .stack_offset => |off| { |
| 3507 | 3502 | // sub src_reg, fp, #off |
| 3508 | | const adj_src_offset = off + @intCast(u32, abi_size); |
| 3509 | | const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else { |
| 3510 | | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 3511 | | }; |
| 3512 | | _ = try self.addInst(.{ |
| 3513 | | .tag = .sub, |
| 3514 | | .data = .{ .rr_op = .{ |
| 3515 | | .rd = src_reg, |
| 3516 | | .rn = .fp, |
| 3517 | | .op = src_offset_op, |
| 3518 | | } }, |
| 3519 | | }); |
| 3503 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3520 | 3504 | }, |
| 3521 | | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3505 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3522 | 3506 | .embedded_in_code, |
| 3523 | 3507 | .stack_argument_offset, |
| 3524 | 3508 | => return self.fail("TODO genSetStack with src={}", .{mcv}), |
| ... | ... | @@ -3526,18 +3510,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3526 | 3510 | } |
| 3527 | 3511 | |
| 3528 | 3512 | // sub dst_reg, fp, #stack_offset |
| 3529 | | const adj_dst_offset = stack_offset + abi_size; |
| 3530 | | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { |
| 3531 | | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 3532 | | }; |
| 3533 | | _ = try self.addInst(.{ |
| 3534 | | .tag = .sub, |
| 3535 | | .data = .{ .rr_op = .{ |
| 3536 | | .rd = dst_reg, |
| 3537 | | .rn = .fp, |
| 3538 | | .op = dst_offset_op, |
| 3539 | | } }, |
| 3540 | | }); |
| 3513 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); |
| 3541 | 3514 | |
| 3542 | 3515 | // mov len, #abi_size |
| 3543 | 3516 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size }); |
| ... | ... | @@ -3882,6 +3855,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3882 | 3855 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3883 | 3856 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); |
| 3884 | 3857 | } else { |
| 3858 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 3859 | .base = .{ .tag = .single_mut_pointer }, |
| 3860 | .data = ty, |
| 3861 | }; |
| 3862 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 3863 | |
| 3885 | 3864 | // TODO call extern memcpy |
| 3886 | 3865 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3887 | 3866 | const src_reg = regs[0]; |
| ... | ... | @@ -3893,20 +3872,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3893 | 3872 | switch (mcv) { |
| 3894 | 3873 | .stack_offset => |off| { |
| 3895 | 3874 | // sub src_reg, fp, #off |
| 3896 | | const adj_src_offset = off + abi_size; |
| 3897 | | const src_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_src_offset)) |x| x else { |
| 3898 | | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 3899 | | }; |
| 3900 | | _ = try self.addInst(.{ |
| 3901 | | .tag = .sub, |
| 3902 | | .data = .{ .rr_op = .{ |
| 3903 | | .rd = src_reg, |
| 3904 | | .rn = .fp, |
| 3905 | | .op = src_offset_op, |
| 3906 | | } }, |
| 3907 | | }); |
| 3875 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3908 | 3876 | }, |
| 3909 | | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3877 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3910 | 3878 | .stack_argument_offset, |
| 3911 | 3879 | .embedded_in_code, |
| 3912 | 3880 | => return self.fail("TODO genSetStackArgument src={}", .{mcv}), |