| ... | @@ -1434,29 +1434,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1434,29 +1434,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1434 | break :result dst_mcv; | 1434 | break :result dst_mcv; |
| 1435 | }, | 1435 | }, |
| 1436 | else => { | 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( | 1441 | break :result dest; |
| 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; | | |
| 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,6 +1692,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1710 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); | 1692 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 1711 | | 1693 | |
| 1712 | switch (value) { | 1694 | switch (value) { |
| | 1695 | .dead => unreachable, |
| | 1696 | .undef => unreachable, |
| 1713 | .register => |value_reg| { | 1697 | .register => |value_reg| { |
| 1714 | try self.genStrRegister(value_reg, addr_reg, value_ty); | 1698 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 1715 | }, | 1699 | }, |
| ... | @@ -2140,7 +2124,7 @@ fn binOp( | ... | @@ -2140,7 +2124,7 @@ fn binOp( |
| 2140 | rhs: MCValue, | 2124 | rhs: MCValue, |
| 2141 | lhs_ty: Type, | 2125 | lhs_ty: Type, |
| 2142 | rhs_ty: Type, | 2126 | rhs_ty: Type, |
| 2143 | ) !MCValue { | 2127 | ) InnerError!MCValue { |
| 2144 | switch (tag) { | 2128 | switch (tag) { |
| 2145 | .add, | 2129 | .add, |
| 2146 | .sub, | 2130 | .sub, |
| ... | @@ -2281,16 +2265,21 @@ fn binOp( | ... | @@ -2281,16 +2265,21 @@ fn binOp( |
| 2281 | switch (lhs_ty.zigTypeTag()) { | 2265 | switch (lhs_ty.zigTypeTag()) { |
| 2282 | .Pointer => { | 2266 | .Pointer => { |
| 2283 | const ptr_ty = lhs_ty; | 2267 | const ptr_ty = lhs_ty; |
| 2284 | const pointee_ty = switch (ptr_ty.ptrSize()) { | 2268 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 2285 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 2269 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 2286 | else => ptr_ty.childType(), | 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) { | 2274 | if (elem_size == 1) { |
| 2290 | return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{}); | 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 | else => unreachable, | 2284 | else => unreachable, |
| 2296 | } | 2285 | } |
| ... | @@ -3494,6 +3483,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3494,6 +3483,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3494 | const reg = try self.copyToTmpRegister(ty, mcv); | 3483 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3495 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3484 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3496 | } else { | 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 | // TODO call extern memcpy | 3492 | // TODO call extern memcpy |
| 3498 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); | 3493 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3499 | const src_reg = regs[0]; | 3494 | const src_reg = regs[0]; |
| ... | @@ -3505,20 +3500,9 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3505,20 +3500,9 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3505 | switch (mcv) { | 3500 | switch (mcv) { |
| 3506 | .stack_offset => |off| { | 3501 | .stack_offset => |off| { |
| 3507 | // sub src_reg, fp, #off | 3502 | // sub src_reg, fp, #off |
| 3508 | const adj_src_offset = off + @intCast(u32, abi_size); | 3503 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 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 | }); | | |
| 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 | .embedded_in_code, | 3506 | .embedded_in_code, |
| 3523 | .stack_argument_offset, | 3507 | .stack_argument_offset, |
| 3524 | => return self.fail("TODO genSetStack with src={}", .{mcv}), | 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,18 +3510,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3526 | } | 3510 | } |
| 3527 | | 3511 | |
| 3528 | // sub dst_reg, fp, #stack_offset | 3512 | // sub dst_reg, fp, #stack_offset |
| 3529 | const adj_dst_offset = stack_offset + abi_size; | 3513 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); |
| 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 | }); | | |
| 3541 | | 3514 | |
| 3542 | // mov len, #abi_size | 3515 | // mov len, #abi_size |
| 3543 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size }); | 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,6 +3855,12 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3882 | const reg = try self.copyToTmpRegister(ty, mcv); | 3855 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3883 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); | 3856 | return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg }); |
| 3884 | } else { | 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 | // TODO call extern memcpy | 3864 | // TODO call extern memcpy |
| 3886 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); | 3865 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3887 | const src_reg = regs[0]; | 3866 | const src_reg = regs[0]; |
| ... | @@ -3893,20 +3872,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -3893,20 +3872,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3893 | switch (mcv) { | 3872 | switch (mcv) { |
| 3894 | .stack_offset => |off| { | 3873 | .stack_offset => |off| { |
| 3895 | // sub src_reg, fp, #off | 3874 | // sub src_reg, fp, #off |
| 3896 | const adj_src_offset = off + abi_size; | 3875 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 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 | }); | | |
| 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 | .stack_argument_offset, | 3878 | .stack_argument_offset, |
| 3911 | .embedded_in_code, | 3879 | .embedded_in_code, |
| 3912 | => return self.fail("TODO genSetStackArgument src={}", .{mcv}), | 3880 | => return self.fail("TODO genSetStackArgument src={}", .{mcv}), |