| ... | ... | @@ -1575,7 +1575,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 1575 | 1575 | .compare_flags_signed, .compare_flags_unsigned => unreachable, |
| 1576 | 1576 | .embedded_in_code => unreachable, |
| 1577 | 1577 | .register => |dst_reg| { |
| 1578 | | try self.genLdrRegister(dst_reg, reg, elem_size); |
| 1578 | try self.genLdrRegister(dst_reg, reg, elem_ty); |
| 1579 | 1579 | }, |
| 1580 | 1580 | .stack_offset => |off| { |
| 1581 | 1581 | if (elem_size <= 4) { |
| ... | ... | @@ -1676,7 +1676,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1676 | 1676 | |
| 1677 | 1677 | switch (value) { |
| 1678 | 1678 | .register => |value_reg| { |
| 1679 | | try self.genStrRegister(value_reg, addr_reg, @intCast(u32, value_ty.abiSize(self.target.*))); |
| 1679 | try self.genStrRegister(value_reg, addr_reg, value_ty); |
| 1680 | 1680 | }, |
| 1681 | 1681 | else => { |
| 1682 | 1682 | if (value_ty.abiSize(self.target.*) <= 4) { |
| ... | ... | @@ -2241,68 +2241,71 @@ fn binOp( |
| 2241 | 2241 | } |
| 2242 | 2242 | } |
| 2243 | 2243 | |
| 2244 | | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, abi_size: u32) !void { |
| 2245 | | switch (abi_size) { |
| 2246 | | 1, 3, 4 => { |
| 2247 | | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 2248 | | 1 => .ldrb, |
| 2249 | | 3, 4 => .ldr, |
| 2250 | | else => unreachable, |
| 2251 | | }; |
| 2244 | fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void { |
| 2245 | const abi_size = ty.abiSize(self.target.*); |
| 2252 | 2246 | |
| 2253 | | _ = try self.addInst(.{ |
| 2254 | | .tag = tag, |
| 2255 | | .data = .{ .rr_offset = .{ |
| 2256 | | .rt = dest_reg, |
| 2257 | | .rn = addr_reg, |
| 2258 | | .offset = .{ .offset = Instruction.Offset.none }, |
| 2259 | | } }, |
| 2260 | | }); |
| 2261 | | }, |
| 2262 | | 2 => { |
| 2263 | | _ = try self.addInst(.{ |
| 2264 | | .tag = .ldrh, |
| 2265 | | .data = .{ .rr_extra_offset = .{ |
| 2266 | | .rt = dest_reg, |
| 2267 | | .rn = addr_reg, |
| 2268 | | .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none }, |
| 2269 | | } }, |
| 2270 | | }); |
| 2271 | | }, |
| 2272 | | else => unreachable, // invalid abi_size for a register |
| 2273 | | } |
| 2247 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 2248 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb, |
| 2249 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh, |
| 2250 | 3, 4 => .ldr, |
| 2251 | else => unreachable, |
| 2252 | }; |
| 2253 | |
| 2254 | const rr_offset: Mir.Inst.Data = .{ .rr_offset = .{ |
| 2255 | .rt = dest_reg, |
| 2256 | .rn = addr_reg, |
| 2257 | .offset = .{ .offset = Instruction.Offset.none }, |
| 2258 | } }; |
| 2259 | const rr_extra_offset: Mir.Inst.Data = .{ .rr_extra_offset = .{ |
| 2260 | .rt = dest_reg, |
| 2261 | .rn = addr_reg, |
| 2262 | .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none }, |
| 2263 | } }; |
| 2264 | |
| 2265 | const data: Mir.Inst.Data = switch (abi_size) { |
| 2266 | 1 => if (ty.isSignedInt()) rr_extra_offset else rr_offset, |
| 2267 | 2 => rr_extra_offset, |
| 2268 | 3, 4 => rr_offset, |
| 2269 | else => unreachable, |
| 2270 | }; |
| 2271 | |
| 2272 | _ = try self.addInst(.{ |
| 2273 | .tag = tag, |
| 2274 | .data = data, |
| 2275 | }); |
| 2274 | 2276 | } |
| 2275 | 2277 | |
| 2276 | | fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, abi_size: u32) !void { |
| 2277 | | switch (abi_size) { |
| 2278 | | 1, 3, 4 => { |
| 2279 | | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 2280 | | 1 => .strb, |
| 2281 | | 3, 4 => .str, |
| 2282 | | else => unreachable, |
| 2283 | | }; |
| 2278 | fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void { |
| 2279 | const abi_size = ty.abiSize(self.target.*); |
| 2284 | 2280 | |
| 2285 | | _ = try self.addInst(.{ |
| 2286 | | .tag = tag, |
| 2287 | | .data = .{ .rr_offset = .{ |
| 2288 | | .rt = source_reg, |
| 2289 | | .rn = addr_reg, |
| 2290 | | .offset = .{ .offset = Instruction.Offset.none }, |
| 2291 | | } }, |
| 2292 | | }); |
| 2293 | | }, |
| 2294 | | 2 => { |
| 2295 | | _ = try self.addInst(.{ |
| 2296 | | .tag = .strh, |
| 2297 | | .data = .{ .rr_extra_offset = .{ |
| 2298 | | .rt = source_reg, |
| 2299 | | .rn = addr_reg, |
| 2300 | | .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none }, |
| 2301 | | } }, |
| 2302 | | }); |
| 2303 | | }, |
| 2304 | | else => unreachable, // invalid abi_size for a register |
| 2305 | | } |
| 2281 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 2282 | 1 => .strb, |
| 2283 | 2 => .strh, |
| 2284 | 3, 4 => .str, |
| 2285 | else => unreachable, |
| 2286 | }; |
| 2287 | |
| 2288 | const rr_offset: Mir.Inst.Data = .{ .rr_offset = .{ |
| 2289 | .rt = source_reg, |
| 2290 | .rn = addr_reg, |
| 2291 | .offset = .{ .offset = Instruction.Offset.none }, |
| 2292 | } }; |
| 2293 | const rr_extra_offset: Mir.Inst.Data = .{ .rr_extra_offset = .{ |
| 2294 | .rt = source_reg, |
| 2295 | .rn = addr_reg, |
| 2296 | .offset = .{ .offset = Instruction.ExtraLoadStoreOffset.none }, |
| 2297 | } }; |
| 2298 | |
| 2299 | const data: Mir.Inst.Data = switch (abi_size) { |
| 2300 | 1, 3, 4 => rr_offset, |
| 2301 | 2 => rr_extra_offset, |
| 2302 | else => unreachable, |
| 2303 | }; |
| 2304 | |
| 2305 | _ = try self.addInst(.{ |
| 2306 | .tag = tag, |
| 2307 | .data = data, |
| 2308 | }); |
| 2306 | 2309 | } |
| 2307 | 2310 | |
| 2308 | 2311 | fn genInlineMemcpy( |
| ... | ... | @@ -2895,8 +2898,6 @@ fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2895 | 2898 | } |
| 2896 | 2899 | |
| 2897 | 2900 | fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2898 | | _ = operand; |
| 2899 | | |
| 2900 | 2901 | const error_type = ty.errorUnionSet(); |
| 2901 | 2902 | const payload_type = ty.errorUnionPayload(); |
| 2902 | 2903 | |
| ... | ... | @@ -3630,55 +3631,59 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3630 | 3631 | // The value is in memory at a hard-coded address. |
| 3631 | 3632 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 3632 | 3633 | try self.genSetReg(ty, reg, .{ .immediate = @intCast(u32, addr) }); |
| 3633 | | try self.genLdrRegister(reg, reg, @intCast(u32, ty.abiSize(self.target.*))); |
| 3634 | try self.genLdrRegister(reg, reg, ty); |
| 3634 | 3635 | }, |
| 3635 | 3636 | .stack_offset => |unadjusted_off| { |
| 3636 | 3637 | // TODO: maybe addressing from sp instead of fp |
| 3637 | 3638 | const abi_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3638 | 3639 | const adj_off = unadjusted_off + abi_size; |
| 3639 | 3640 | |
| 3640 | | switch (abi_size) { |
| 3641 | | 1, 4 => { |
| 3642 | | const offset = if (adj_off <= math.maxInt(u12)) blk: { |
| 3643 | | break :blk Instruction.Offset.imm(@intCast(u12, adj_off)); |
| 3644 | | } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }), .none); |
| 3641 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3642 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb, |
| 3643 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh, |
| 3644 | 3, 4 => .ldr, |
| 3645 | else => unreachable, |
| 3646 | }; |
| 3645 | 3647 | |
| 3646 | | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3647 | | 1 => .ldrb, |
| 3648 | | 4 => .ldr, |
| 3649 | | else => unreachable, |
| 3650 | | }; |
| 3648 | const extra_offset = switch (abi_size) { |
| 3649 | 1 => ty.isSignedInt(), |
| 3650 | 2 => true, |
| 3651 | 3, 4 => false, |
| 3652 | else => unreachable, |
| 3653 | }; |
| 3651 | 3654 | |
| 3652 | | _ = try self.addInst(.{ |
| 3653 | | .tag = tag, |
| 3654 | | .data = .{ .rr_offset = .{ |
| 3655 | | .rt = reg, |
| 3656 | | .rn = .fp, |
| 3657 | | .offset = .{ |
| 3658 | | .offset = offset, |
| 3659 | | .positive = false, |
| 3660 | | }, |
| 3661 | | } }, |
| 3662 | | }); |
| 3663 | | }, |
| 3664 | | 2 => { |
| 3665 | | const offset = if (adj_off <= math.maxInt(u8)) blk: { |
| 3666 | | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); |
| 3667 | | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off })); |
| 3655 | if (extra_offset) { |
| 3656 | const offset = if (adj_off <= math.maxInt(u8)) blk: { |
| 3657 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); |
| 3658 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off })); |
| 3668 | 3659 | |
| 3669 | | _ = try self.addInst(.{ |
| 3670 | | .tag = .ldrh, |
| 3671 | | .data = .{ .rr_extra_offset = .{ |
| 3672 | | .rt = reg, |
| 3673 | | .rn = .fp, |
| 3674 | | .offset = .{ |
| 3675 | | .offset = offset, |
| 3676 | | .positive = false, |
| 3677 | | }, |
| 3678 | | } }, |
| 3679 | | }); |
| 3680 | | }, |
| 3681 | | else => return self.fail("TODO a type of size {} is not allowed in a register", .{abi_size}), |
| 3660 | _ = try self.addInst(.{ |
| 3661 | .tag = tag, |
| 3662 | .data = .{ .rr_extra_offset = .{ |
| 3663 | .rt = reg, |
| 3664 | .rn = .fp, |
| 3665 | .offset = .{ |
| 3666 | .offset = offset, |
| 3667 | .positive = false, |
| 3668 | }, |
| 3669 | } }, |
| 3670 | }); |
| 3671 | } else { |
| 3672 | const offset = if (adj_off <= math.maxInt(u12)) blk: { |
| 3673 | break :blk Instruction.Offset.imm(@intCast(u12, adj_off)); |
| 3674 | } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }), .none); |
| 3675 | |
| 3676 | _ = try self.addInst(.{ |
| 3677 | .tag = tag, |
| 3678 | .data = .{ .rr_offset = .{ |
| 3679 | .rt = reg, |
| 3680 | .rn = .fp, |
| 3681 | .offset = .{ |
| 3682 | .offset = offset, |
| 3683 | .positive = false, |
| 3684 | }, |
| 3685 | } }, |
| 3686 | }); |
| 3682 | 3687 | } |
| 3683 | 3688 | }, |
| 3684 | 3689 | .stack_argument_offset => |unadjusted_off| { |
| ... | ... | @@ -3686,9 +3691,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3686 | 3691 | const adj_off = unadjusted_off + abi_size; |
| 3687 | 3692 | |
| 3688 | 3693 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3689 | | 1 => .ldrb_stack_argument, |
| 3690 | | 2 => .ldrh_stack_argument, |
| 3691 | | 4 => .ldr_stack_argument, |
| 3694 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, |
| 3695 | 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument, |
| 3696 | 3, 4 => .ldr_stack_argument, |
| 3692 | 3697 | else => unreachable, |
| 3693 | 3698 | }; |
| 3694 | 3699 | |