| ... | @@ -122,9 +122,10 @@ const MCValue = union(enum) { | ... | @@ -122,9 +122,10 @@ const MCValue = union(enum) { |
| 122 | /// A pointer-sized integer that fits in a register. | 122 | /// A pointer-sized integer that fits in a register. |
| 123 | /// If the type is a pointer, this is the pointer address in virtual address space. | 123 | /// If the type is a pointer, this is the pointer address in virtual address space. |
| 124 | immediate: u64, | 124 | immediate: u64, |
| 125 | /// The value is in memory at an address not-yet-allocated by the linker. | 125 | /// The value doesn't exist in memory yet. |
| 126 | /// This traditionally corresponds to a relocation emitted in a relocatable object file. | | |
| 127 | load_symbol: SymbolOffset, | 126 | load_symbol: SymbolOffset, |
| | 127 | /// The address of the memory location not-yet-allocated by the linker. |
| | 128 | addr_symbol: SymbolOffset, |
| 128 | /// The value is in a target-specific register. | 129 | /// The value is in a target-specific register. |
| 129 | register: Register, | 130 | register: Register, |
| 130 | /// The value is split across two registers | 131 | /// The value is split across two registers |
| ... | @@ -169,6 +170,7 @@ const MCValue = union(enum) { | ... | @@ -169,6 +170,7 @@ const MCValue = union(enum) { |
| 169 | .indirect, | 170 | .indirect, |
| 170 | .undef, | 171 | .undef, |
| 171 | .load_symbol, | 172 | .load_symbol, |
| | 173 | .addr_symbol, |
| 172 | .air_ref, | 174 | .air_ref, |
| 173 | => false, | 175 | => false, |
| 174 | | 176 | |
| ... | @@ -188,10 +190,14 @@ const MCValue = union(enum) { | ... | @@ -188,10 +190,14 @@ const MCValue = union(enum) { |
| 188 | .immediate, | 190 | .immediate, |
| 189 | .ptr_stack_offset, | 191 | .ptr_stack_offset, |
| 190 | .register_offset, | 192 | .register_offset, |
| | 193 | .register_pair, |
| | 194 | .register, |
| 191 | .undef, | 195 | .undef, |
| 192 | .air_ref, | 196 | .air_ref, |
| | 197 | .addr_symbol, |
| 193 | => unreachable, // not in memory | 198 | => unreachable, // not in memory |
| 194 | | 199 | |
| | 200 | .load_symbol => |sym_off| .{ .addr_symbol = sym_off }, |
| 195 | .memory => |addr| .{ .immediate = addr }, | 201 | .memory => |addr| .{ .immediate = addr }, |
| 196 | .stack_offset => |off| .{ .ptr_stack_offset = off }, | 202 | .stack_offset => |off| .{ .ptr_stack_offset = off }, |
| 197 | .indirect => |reg_off| switch (reg_off.off) { | 203 | .indirect => |reg_off| switch (reg_off.off) { |
| ... | @@ -219,6 +225,7 @@ const MCValue = union(enum) { | ... | @@ -219,6 +225,7 @@ const MCValue = union(enum) { |
| 219 | .ptr_stack_offset => |off| .{ .stack_offset = off }, | 225 | .ptr_stack_offset => |off| .{ .stack_offset = off }, |
| 220 | .register => |reg| .{ .indirect = .{ .reg = reg } }, | 226 | .register => |reg| .{ .indirect = .{ .reg = reg } }, |
| 221 | .register_offset => |reg_off| .{ .indirect = reg_off }, | 227 | .register_offset => |reg_off| .{ .indirect = reg_off }, |
| | 228 | .addr_symbol => |sym_off| .{ .load_symbol = sym_off }, |
| 222 | }; | 229 | }; |
| 223 | } | 230 | } |
| 224 | | 231 | |
| ... | @@ -235,6 +242,7 @@ const MCValue = union(enum) { | ... | @@ -235,6 +242,7 @@ const MCValue = union(enum) { |
| 235 | .indirect, | 242 | .indirect, |
| 236 | .stack_offset, | 243 | .stack_offset, |
| 237 | .load_symbol, | 244 | .load_symbol, |
| | 245 | .addr_symbol, |
| 238 | => switch (off) { | 246 | => switch (off) { |
| 239 | 0 => mcv, | 247 | 0 => mcv, |
| 240 | else => unreachable, // not offsettable | 248 | else => unreachable, // not offsettable |
| ... | @@ -801,6 +809,43 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { | ... | @@ -801,6 +809,43 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 801 | try table.ensureUnusedCapacity(self.gpa, additional_count); | 809 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 802 | } | 810 | } |
| 803 | | 811 | |
| | 812 | fn splitType(self: *Self, ty: Type) ![2]Type { |
| | 813 | const mod = self.bin_file.comp.module.?; |
| | 814 | const classes = mem.sliceTo(&abi.classifySystemV(ty, mod), .none); |
| | 815 | var parts: [2]Type = undefined; |
| | 816 | if (classes.len == 2) for (&parts, classes, 0..) |*part, class, part_i| { |
| | 817 | part.* = switch (class) { |
| | 818 | .integer => switch (part_i) { |
| | 819 | 0 => Type.u64, |
| | 820 | 1 => part: { |
| | 821 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?; |
| | 822 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); |
| | 823 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { |
| | 824 | 1 => elem_ty, |
| | 825 | else => |len| try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() }), |
| | 826 | }; |
| | 827 | }, |
| | 828 | else => unreachable, |
| | 829 | }, |
| | 830 | else => break, |
| | 831 | }; |
| | 832 | } else if (parts[0].abiSize(mod) + parts[1].abiSize(mod) == ty.abiSize(mod)) return parts; |
| | 833 | return std.debug.panic("TODO implement splitType for {}", .{ty.fmt(mod)}); |
| | 834 | } |
| | 835 | |
| | 836 | fn symbolIndex(self: *Self) !u32 { |
| | 837 | const mod = self.bin_file.comp.module.?; |
| | 838 | const decl_index = mod.funcOwnerDeclIndex(self.func_index); |
| | 839 | return switch (self.bin_file.tag) { |
| | 840 | .elf => blk: { |
| | 841 | const elf_file = self.bin_file.cast(link.File.Elf).?; |
| | 842 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); |
| | 843 | break :blk atom_index; |
| | 844 | }, |
| | 845 | else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}), |
| | 846 | }; |
| | 847 | } |
| | 848 | |
| 804 | fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignment) !u32 { | 849 | fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: Alignment) !u32 { |
| 805 | self.stack_align = self.stack_align.max(abi_align); | 850 | self.stack_align = self.stack_align.max(abi_align); |
| 806 | // TODO find a free slot instead of always appending | 851 | // TODO find a free slot instead of always appending |
| ... | @@ -1610,40 +1655,41 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1610,40 +1655,41 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1610 | | 1655 | |
| 1611 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { | 1656 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1612 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 1657 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1613 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1658 | const result = result: { |
| 1614 | const mcv = try self.resolveInst(ty_op.operand); | 1659 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 1615 | break :result try self.slicePtr(mcv); | 1660 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv; |
| | 1661 | |
| | 1662 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| | 1663 | const dst_ty = self.typeOfIndex(inst); |
| | 1664 | try self.genCopy(dst_ty, dst_mcv, src_mcv); |
| | 1665 | break :result dst_mcv; |
| 1616 | }; | 1666 | }; |
| 1617 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1667 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1618 | } | 1668 | } |
| 1619 | | 1669 | |
| 1620 | fn slicePtr(self: *Self, mcv: MCValue) !MCValue { | | |
| 1621 | switch (mcv) { | | |
| 1622 | .dead, .unreach, .none => unreachable, | | |
| 1623 | .register => unreachable, // a slice doesn't fit in one register | | |
| 1624 | .stack_offset => |off| { | | |
| 1625 | return MCValue{ .stack_offset = off }; | | |
| 1626 | }, | | |
| 1627 | .memory => |addr| { | | |
| 1628 | return MCValue{ .memory = addr }; | | |
| 1629 | }, | | |
| 1630 | else => return self.fail("TODO slicePtr {s}", .{@tagName(mcv)}), | | |
| 1631 | } | | |
| 1632 | } | | |
| 1633 | | | |
| 1634 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | 1670 | fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1635 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 1671 | const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 1636 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1672 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1637 | const ptr_bits = 64; | 1673 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 1638 | const ptr_bytes = @divExact(ptr_bits, 8); | 1674 | switch (src_mcv) { |
| 1639 | const mcv = try self.resolveInst(ty_op.operand); | | |
| 1640 | switch (mcv) { | | |
| 1641 | .dead, .unreach, .none => unreachable, | | |
| 1642 | .register => unreachable, // a slice doesn't fit in one register | | |
| 1643 | .stack_offset => |off| { | 1675 | .stack_offset => |off| { |
| 1644 | break :result MCValue{ .stack_offset = off + ptr_bytes }; | 1676 | const len_mcv: MCValue = .{ .stack_offset = off + 8 }; |
| | 1677 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv; |
| | 1678 | |
| | 1679 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| | 1680 | try self.genCopy(Type.usize, dst_mcv, len_mcv); |
| | 1681 | break :result dst_mcv; |
| | 1682 | }, |
| | 1683 | .register_pair => |pair| { |
| | 1684 | const len_mcv: MCValue = .{ .register = pair[1] }; |
| | 1685 | |
| | 1686 | if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result len_mcv; |
| | 1687 | |
| | 1688 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| | 1689 | try self.genCopy(Type.usize, dst_mcv, len_mcv); |
| | 1690 | break :result dst_mcv; |
| 1645 | }, | 1691 | }, |
| 1646 | else => return self.fail("TODO airSliceLen for {}", .{mcv}), | 1692 | else => return self.fail("TODO airSliceLen for {}", .{src_mcv}), |
| 1647 | } | 1693 | } |
| 1648 | }; | 1694 | }; |
| 1649 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1695 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | @@ -1978,6 +2024,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro | ... | @@ -1978,6 +2024,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_mcv: MCValue, ptr_ty: Type) InnerErro |
| 1978 | .register, | 2024 | .register, |
| 1979 | .register_offset, | 2025 | .register_offset, |
| 1980 | .ptr_stack_offset, | 2026 | .ptr_stack_offset, |
| | 2027 | .addr_symbol, |
| 1981 | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), | 2028 | => try self.genCopy(dst_ty, dst_mcv, ptr_mcv.deref()), |
| 1982 | | 2029 | |
| 1983 | .memory, | 2030 | .memory, |
| ... | @@ -2019,11 +2066,6 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: | ... | @@ -2019,11 +2066,6 @@ fn store(self: *Self, pointer: MCValue, value: MCValue, ptr_ty: Type, value_ty: |
| 2019 | | 2066 | |
| 2020 | log.debug("storing {}:{} in {}:{}", .{ value, value_ty.fmt(mod), pointer, ptr_ty.fmt(mod) }); | 2067 | log.debug("storing {}:{} in {}:{}", .{ value, value_ty.fmt(mod), pointer, ptr_ty.fmt(mod) }); |
| 2021 | | 2068 | |
| 2022 | if (value_ty.isSlice(mod)) { | | |
| 2023 | // cheat a bit by loading in two parts | | |
| 2024 | | | |
| 2025 | } | | |
| 2026 | | | |
| 2027 | switch (pointer) { | 2069 | switch (pointer) { |
| 2028 | .none => unreachable, | 2070 | .none => unreachable, |
| 2029 | .undef => unreachable, | 2071 | .undef => unreachable, |
| ... | @@ -2192,7 +2234,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2192,7 +2234,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 2192 | | 2234 | |
| 2193 | const dst_mcv = switch (src_mcv) { | 2235 | const dst_mcv = switch (src_mcv) { |
| 2194 | .register => |src_reg| dst: { | 2236 | .register => |src_reg| dst: { |
| 2195 | try self.register_manager.getReg(src_reg, null); | 2237 | self.register_manager.getRegAssumeFree(src_reg, null); |
| | 2238 | break :dst src_mcv; |
| | 2239 | }, |
| | 2240 | .register_pair => |pair| dst: { |
| | 2241 | for (pair) |reg| self.register_manager.getRegAssumeFree(reg, null); |
| 2196 | break :dst src_mcv; | 2242 | break :dst src_mcv; |
| 2197 | }, | 2243 | }, |
| 2198 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), | 2244 | else => return self.fail("TODO: airArg {s}", .{@tagName(src_mcv)}), |
| ... | @@ -3056,6 +3102,8 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT | ... | @@ -3056,6 +3102,8 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT |
| 3056 | | 3102 | |
| 3057 | /// Sets the value without any modifications to register allocation metadata or stack allocation metadata. | 3103 | /// Sets the value without any modifications to register allocation metadata or stack allocation metadata. |
| 3058 | fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { | 3104 | fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| | 3105 | const mod = self.bin_file.comp.module.?; |
| | 3106 | |
| 3059 | // There isn't anything to store | 3107 | // There isn't anything to store |
| 3060 | if (dst_mcv == .none) return; | 3108 | if (dst_mcv == .none) return; |
| 3061 | | 3109 | |
| ... | @@ -3066,7 +3114,6 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { | ... | @@ -3066,7 +3114,6 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| 3066 | | 3114 | |
| 3067 | switch (dst_mcv) { | 3115 | switch (dst_mcv) { |
| 3068 | .register => |reg| return self.genSetReg(ty, reg, src_mcv), | 3116 | .register => |reg| return self.genSetReg(ty, reg, src_mcv), |
| 3069 | .register_pair => |pair| return self.genSetRegPair(ty, pair, src_mcv), | | |
| 3070 | .register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) { | 3117 | .register_offset => |dst_reg_off| try self.genSetReg(ty, dst_reg_off.reg, switch (src_mcv) { |
| 3071 | .none, | 3118 | .none, |
| 3072 | .unreach, | 3119 | .unreach, |
| ... | @@ -3084,7 +3131,47 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { | ... | @@ -3084,7 +3131,47 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void { |
| 3084 | }), | 3131 | }), |
| 3085 | .stack_offset => |off| return self.genSetStack(ty, off, src_mcv), | 3132 | .stack_offset => |off| return self.genSetStack(ty, off, src_mcv), |
| 3086 | .memory => |addr| return self.genSetMem(ty, addr, src_mcv), | 3133 | .memory => |addr| return self.genSetMem(ty, addr, src_mcv), |
| 3087 | else => return self.fail("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }), | 3134 | .register_pair => |dst_regs| { |
| | 3135 | const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) { |
| | 3136 | .register_pair, .memory, .indirect, .stack_offset => null, |
| | 3137 | .load_symbol => src: { |
| | 3138 | const src_addr_reg, const src_addr_lock = try self.allocReg(); |
| | 3139 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| | 3140 | |
| | 3141 | try self.genSetReg(Type.usize, src_addr_reg, src_mcv.address()); |
| | 3142 | break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock }; |
| | 3143 | }, |
| | 3144 | .air_ref => |src_ref| return self.genCopy( |
| | 3145 | ty, |
| | 3146 | dst_mcv, |
| | 3147 | try self.resolveInst(src_ref), |
| | 3148 | ), |
| | 3149 | else => return self.fail("TODO implement genCopy for {s} of {}", .{ |
| | 3150 | @tagName(src_mcv), ty.fmt(mod), |
| | 3151 | }), |
| | 3152 | }; |
| | 3153 | defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock); |
| | 3154 | |
| | 3155 | switch (ty.zigTypeTag(mod)) { |
| | 3156 | .Optional => return, |
| | 3157 | else => {}, |
| | 3158 | } |
| | 3159 | |
| | 3160 | var part_disp: i32 = 0; |
| | 3161 | for (dst_regs, try self.splitType(ty), 0..) |dst_reg, dst_ty, part_i| { |
| | 3162 | try self.genSetReg(dst_ty, dst_reg, switch (src_mcv) { |
| | 3163 | .register_pair => |src_regs| .{ .register = src_regs[part_i] }, |
| | 3164 | .memory, .indirect, .stack_offset => src_mcv.address().offset(part_disp).deref(), |
| | 3165 | .load_symbol => .{ .indirect = .{ |
| | 3166 | .reg = src_info.?.addr_reg, |
| | 3167 | .off = part_disp, |
| | 3168 | } }, |
| | 3169 | else => unreachable, |
| | 3170 | }); |
| | 3171 | part_disp += @intCast(dst_ty.abiSize(mod)); |
| | 3172 | } |
| | 3173 | }, |
| | 3174 | else => return std.debug.panic("TODO: genCopy {s} with {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }), |
| 3088 | } | 3175 | } |
| 3089 | } | 3176 | } |
| 3090 | | 3177 | |
| ... | @@ -3168,14 +3255,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_mcv: MCValue) Inner | ... | @@ -3168,14 +3255,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_mcv: MCValue) Inner |
| 3168 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); | 3255 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = offset }); |
| 3169 | }, | 3256 | }, |
| 3170 | .load_symbol => |sym_off| { | 3257 | .load_symbol => |sym_off| { |
| 3171 | const atom_index = atom: { | 3258 | const atom_index = try self.symbolIndex(); |
| 3172 | const decl_index = mod.funcOwnerDeclIndex(self.func_index); | | |
| 3173 | | | |
| 3174 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | | |
| 3175 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | | |
| 3176 | break :atom atom_index; | | |
| 3177 | } else return self.fail("TODO genSetStack for {s}", .{@tagName(self.bin_file.tag)}); | | |
| 3178 | }; | | |
| 3179 | | 3259 | |
| 3180 | // setup the src pointer | 3260 | // setup the src pointer |
| 3181 | _ = try self.addInst(.{ | 3261 | _ = try self.addInst(.{ |
| ... | @@ -3443,16 +3523,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -3443,16 +3523,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 3443 | .load_symbol => |sym_off| { | 3523 | .load_symbol => |sym_off| { |
| 3444 | assert(sym_off.off == 0); | 3524 | assert(sym_off.off == 0); |
| 3445 | | 3525 | |
| 3446 | const decl_index = mod.funcOwnerDeclIndex(self.func_index); | 3526 | const atom_index = try self.symbolIndex(); |
| 3447 | | 3527 | |
| 3448 | const atom_index = switch (self.bin_file.tag) { | | |
| 3449 | .elf => blk: { | | |
| 3450 | const elf_file = self.bin_file.cast(link.File.Elf).?; | | |
| 3451 | const atom_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index); | | |
| 3452 | break :blk atom_index; | | |
| 3453 | }, | | |
| 3454 | else => return self.fail("TODO genSetReg load_symbol for {s}", .{@tagName(self.bin_file.tag)}), | | |
| 3455 | }; | | |
| 3456 | _ = try self.addInst(.{ | 3528 | _ = try self.addInst(.{ |
| 3457 | .tag = .load_symbol, | 3529 | .tag = .load_symbol, |
| 3458 | .data = .{ | 3530 | .data = .{ |
| ... | @@ -3485,27 +3557,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -3485,27 +3557,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 3485 | }, | 3557 | }, |
| 3486 | }); | 3558 | }); |
| 3487 | }, | 3559 | }, |
| 3488 | else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), | 3560 | .addr_symbol => |sym_off| { |
| 3489 | } | 3561 | assert(sym_off.off == 0); |
| 3490 | } | | |
| 3491 | | | |
| 3492 | fn genSetRegPair(self: *Self, ty: Type, pair: [2]Register, src_mcv: MCValue) InnerError!void { | | |
| 3493 | const mod = self.bin_file.comp.module.?; | | |
| 3494 | const abi_size: u32 = @intCast(ty.abiSize(mod)); | | |
| 3495 | | | |
| 3496 | assert(abi_size > 8 and abi_size <= 16); // must fit only fit into two registers | | |
| 3497 | | 3562 | |
| 3498 | switch (src_mcv) { | 3563 | const atom_index = try self.symbolIndex(); |
| 3499 | .air_ref => |ref| return self.genSetRegPair(ty, pair, try self.resolveInst(ref)), | | |
| 3500 | .load_symbol => |sym_off| { | | |
| 3501 | _ = sym_off; | | |
| 3502 | // return self.fail("TODO: genSetRegPair load_symbol", .{}); | | |
| 3503 | // commented out just for testing. | | |
| 3504 | | 3564 | |
| 3505 | // plan here is to load the address into a temporary register and | 3565 | _ = try self.addInst(.{ |
| 3506 | // copy into the pair. | 3566 | .tag = .load_symbol, |
| | 3567 | .data = .{ |
| | 3568 | .payload = try self.addExtra(Mir.LoadSymbolPayload{ |
| | 3569 | .register = reg.id(), |
| | 3570 | .atom_index = atom_index, |
| | 3571 | .sym_index = sym_off.sym, |
| | 3572 | }), |
| | 3573 | }, |
| | 3574 | }); |
| 3507 | }, | 3575 | }, |
| 3508 | else => return self.fail("TODO: genSetRegPair {s}", .{@tagName(src_mcv)}), | 3576 | else => return self.fail("TODO: genSetReg {s}", .{@tagName(src_mcv)}), |
| 3509 | } | 3577 | } |
| 3510 | } | 3578 | } |
| 3511 | | 3579 | |