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