| ... | @@ -1359,7 +1359,7 @@ fn binOp( | ... | @@ -1359,7 +1359,7 @@ fn binOp( |
| 1359 | rhs: MCValue, | 1359 | rhs: MCValue, |
| 1360 | lhs_ty: Type, | 1360 | lhs_ty: Type, |
| 1361 | rhs_ty: Type, | 1361 | rhs_ty: Type, |
| 1362 | ) !MCValue { | 1362 | ) InnerError!MCValue { |
| 1363 | switch (tag) { | 1363 | switch (tag) { |
| 1364 | // Arithmetic operations on integers and floats | 1364 | // Arithmetic operations on integers and floats |
| 1365 | .add, | 1365 | .add, |
| ... | @@ -1481,16 +1481,21 @@ fn binOp( | ... | @@ -1481,16 +1481,21 @@ fn binOp( |
| 1481 | switch (lhs_ty.zigTypeTag()) { | 1481 | switch (lhs_ty.zigTypeTag()) { |
| 1482 | .Pointer => { | 1482 | .Pointer => { |
| 1483 | const ptr_ty = lhs_ty; | 1483 | const ptr_ty = lhs_ty; |
| 1484 | const pointee_ty = switch (ptr_ty.ptrSize()) { | 1484 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 1485 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type | 1485 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 1486 | else => ptr_ty.childType(), | 1486 | else => ptr_ty.childType(), |
| 1487 | }; | 1487 | }; |
| | 1488 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1488 | | 1489 | |
| 1489 | if (pointee_ty.abiSize(self.target.*) > 1) { | 1490 | if (elem_size == 1) { |
| 1490 | return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{}); | 1491 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| | 1492 | } else { |
| | 1493 | // convert the offset into a byte offset by |
| | 1494 | // multiplying it with elem_size |
| | 1495 | const offset = try self.binOp(.mul, null, rhs, .{ .immediate = elem_size }, Type.usize, Type.usize); |
| | 1496 | const addr = try self.binOp(tag, null, lhs, offset, Type.initTag(.manyptr_u8), Type.usize); |
| | 1497 | return addr; |
| 1491 | } | 1498 | } |
| 1492 | | | |
| 1493 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); | | |
| 1494 | }, | 1499 | }, |
| 1495 | else => unreachable, | 1500 | else => unreachable, |
| 1496 | } | 1501 | } |
| ... | @@ -1800,29 +1805,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1800,29 +1805,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1800 | | 1805 | |
| 1801 | switch (elem_size) { | 1806 | switch (elem_size) { |
| 1802 | else => { | 1807 | else => { |
| 1803 | const dst_mcv = try self.allocRegOrMem(inst, true); | 1808 | const dest = try self.allocRegOrMem(inst, true); |
| 1804 | | 1809 | const addr = try self.binOp(.ptr_add, null, base_mcv, index_mcv, slice_ty, Type.usize); |
| 1805 | const offset_mcv = try self.binOp( | 1810 | try self.load(dest, addr, slice_ptr_field_type); |
| 1806 | .mul, | | |
| 1807 | null, | | |
| 1808 | index_mcv, | | |
| 1809 | .{ .immediate = elem_size }, | | |
| 1810 | Type.usize, | | |
| 1811 | Type.usize, | | |
| 1812 | ); | | |
| 1813 | assert(offset_mcv == .register); // result of multiplication should always be register | | |
| 1814 | self.register_manager.freezeRegs(&.{offset_mcv.register}); | | |
| 1815 | | | |
| 1816 | const addr_mcv = try self.binOp(.add, null, base_mcv, offset_mcv, Type.usize, Type.usize); | | |
| 1817 | | 1811 | |
| 1818 | // At this point in time, neither the base register | 1812 | break :result dest; |
| 1819 | // nor the offset register contains any valuable data | | |
| 1820 | // anymore. | | |
| 1821 | self.register_manager.unfreezeRegs(&.{ base_mcv.register, offset_mcv.register }); | | |
| 1822 | | | |
| 1823 | try self.load(dst_mcv, addr_mcv, slice_ptr_field_type); | | |
| 1824 | | | |
| 1825 | break :result dst_mcv; | | |
| 1826 | }, | 1813 | }, |
| 1827 | } | 1814 | } |
| 1828 | }; | 1815 | }; |
| ... | @@ -3414,7 +3401,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3414,7 +3401,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3414 | const reg = try self.copyToTmpRegister(ty, mcv); | 3401 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3415 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3402 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3416 | } else { | 3403 | } else { |
| 3417 | // TODO optimize the register allocation | 3404 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| | 3405 | .base = .{ .tag = .single_mut_pointer }, |
| | 3406 | .data = ty, |
| | 3407 | }; |
| | 3408 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| | 3409 | |
| | 3410 | // TODO call extern memcpy |
| 3418 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); | 3411 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3419 | self.register_manager.freezeRegs(&regs); | 3412 | self.register_manager.freezeRegs(&regs); |
| 3420 | defer self.register_manager.unfreezeRegs(&regs); | 3413 | defer self.register_manager.unfreezeRegs(&regs); |
| ... | @@ -3428,16 +3421,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3428,16 +3421,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3428 | switch (mcv) { | 3421 | switch (mcv) { |
| 3429 | .stack_offset => |off| { | 3422 | .stack_offset => |off| { |
| 3430 | // sub src_reg, fp, #off | 3423 | // sub src_reg, fp, #off |
| 3431 | const adj_src_offset = off + abi_size; | 3424 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3432 | const src_offset = math.cast(u12, adj_src_offset) catch return self.fail("TODO load: larger stack offsets", .{}); | | |
| 3433 | _ = try self.addInst(.{ | | |
| 3434 | .tag = .sub_immediate, | | |
| 3435 | .data = .{ .rr_imm12_sh = .{ | | |
| 3436 | .rd = src_reg, | | |
| 3437 | .rn = .x29, | | |
| 3438 | .imm12 = src_offset, | | |
| 3439 | } }, | | |
| 3440 | }); | | |
| 3441 | }, | 3425 | }, |
| 3442 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), | 3426 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), |
| 3443 | .got_load, | 3427 | .got_load, |
| ... | @@ -3463,16 +3447,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3463,16 +3447,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3463 | } | 3447 | } |
| 3464 | | 3448 | |
| 3465 | // sub dst_reg, fp, #stack_offset | 3449 | // sub dst_reg, fp, #stack_offset |
| 3466 | const adj_dst_off = stack_offset + abi_size; | 3450 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); |
| 3467 | const dst_offset = math.cast(u12, adj_dst_off) catch return self.fail("TODO load: larger stack offsets", .{}); | | |
| 3468 | _ = try self.addInst(.{ | | |
| 3469 | .tag = .sub_immediate, | | |
| 3470 | .data = .{ .rr_imm12_sh = .{ | | |
| 3471 | .rd = dst_reg, | | |
| 3472 | .rn = .x29, | | |
| 3473 | .imm12 = dst_offset, | | |
| 3474 | } }, | | |
| 3475 | }); | | |
| 3476 | | 3451 | |
| 3477 | // mov len, #abi_size | 3452 | // mov len, #abi_size |
| 3478 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size }); | 3453 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size }); |