| ... | ... | @@ -1359,7 +1359,7 @@ fn binOp( |
| 1359 | 1359 | rhs: MCValue, |
| 1360 | 1360 | lhs_ty: Type, |
| 1361 | 1361 | rhs_ty: Type, |
| 1362 | | ) !MCValue { |
| 1362 | ) InnerError!MCValue { |
| 1363 | 1363 | switch (tag) { |
| 1364 | 1364 | // Arithmetic operations on integers and floats |
| 1365 | 1365 | .add, |
| ... | ... | @@ -1481,16 +1481,21 @@ fn binOp( |
| 1481 | 1481 | switch (lhs_ty.zigTypeTag()) { |
| 1482 | 1482 | .Pointer => { |
| 1483 | 1483 | const ptr_ty = lhs_ty; |
| 1484 | | const pointee_ty = switch (ptr_ty.ptrSize()) { |
| 1484 | const elem_ty = switch (ptr_ty.ptrSize()) { |
| 1485 | 1485 | .One => ptr_ty.childType().childType(), // ptr to array, so get array element type |
| 1486 | 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 | | return self.fail("TODO ptr_add, ptr_sub with more element sizes", .{}); |
| 1490 | if (elem_size == 1) { |
| 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 | 1500 | else => unreachable, |
| 1496 | 1501 | } |
| ... | ... | @@ -1800,29 +1805,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1800 | 1805 | |
| 1801 | 1806 | switch (elem_size) { |
| 1802 | 1807 | else => { |
| 1803 | | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 1804 | | |
| 1805 | | const offset_mcv = try self.binOp( |
| 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); |
| 1808 | const dest = try self.allocRegOrMem(inst, true); |
| 1809 | const addr = try self.binOp(.ptr_add, null, base_mcv, index_mcv, slice_ty, Type.usize); |
| 1810 | try self.load(dest, addr, slice_ptr_field_type); |
| 1817 | 1811 | |
| 1818 | | // At this point in time, neither the base register |
| 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; |
| 1812 | break :result dest; |
| 1826 | 1813 | }, |
| 1827 | 1814 | } |
| 1828 | 1815 | }; |
| ... | ... | @@ -3414,7 +3401,13 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3414 | 3401 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3415 | 3402 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3416 | 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 | 3411 | const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }); |
| 3419 | 3412 | self.register_manager.freezeRegs(&regs); |
| 3420 | 3413 | defer self.register_manager.unfreezeRegs(&regs); |
| ... | ... | @@ -3428,16 +3421,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3428 | 3421 | switch (mcv) { |
| 3429 | 3422 | .stack_offset => |off| { |
| 3430 | 3423 | // sub src_reg, fp, #off |
| 3431 | | const adj_src_offset = off + abi_size; |
| 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 | | }); |
| 3424 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3441 | 3425 | }, |
| 3442 | 3426 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = addr }), |
| 3443 | 3427 | .got_load, |
| ... | ... | @@ -3463,16 +3447,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3463 | 3447 | } |
| 3464 | 3448 | |
| 3465 | 3449 | // sub dst_reg, fp, #stack_offset |
| 3466 | | const adj_dst_off = stack_offset + abi_size; |
| 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 | | }); |
| 3450 | try self.genSetReg(ptr_ty, dst_reg, .{ .ptr_stack_offset = stack_offset }); |
| 3476 | 3451 | |
| 3477 | 3452 | // mov len, #abi_size |
| 3478 | 3453 | try self.genSetReg(Type.usize, len_reg, .{ .immediate = abi_size }); |