| ... | ... | @@ -329,7 +329,7 @@ pub const MCValue = union(enum) { |
| 329 | 329 | .load_frame, |
| 330 | 330 | .reserved_frame, |
| 331 | 331 | => unreachable, // not offsettable |
| 332 | | .immediate => |imm| .{ .immediate = @as(u64, @bitCast(@as(i64, @bitCast(imm)) +% off)) }, |
| 332 | .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) }, |
| 333 | 333 | .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } }, |
| 334 | 334 | .register_offset => |reg_off| .{ |
| 335 | 335 | .register_offset = .{ .reg = reg_off.reg, .off = reg_off.off + off }, |
| ... | ... | @@ -606,7 +606,7 @@ const FrameAlloc = struct { |
| 606 | 606 | fn init(alloc_abi: struct { size: u64, alignment: u32 }) FrameAlloc { |
| 607 | 607 | assert(math.isPowerOfTwo(alloc_abi.alignment)); |
| 608 | 608 | return .{ |
| 609 | | .abi_size = @as(u31, @intCast(alloc_abi.size)), |
| 609 | .abi_size = @intCast(alloc_abi.size), |
| 610 | 610 | .abi_align = math.log2_int(u32, alloc_abi.alignment), |
| 611 | 611 | .ref_count = 0, |
| 612 | 612 | }; |
| ... | ... | @@ -694,7 +694,7 @@ pub fn generate( |
| 694 | 694 | FrameAlloc.init(.{ |
| 695 | 695 | .size = 0, |
| 696 | 696 | .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack| |
| 697 | | @as(u32, @intCast(set_align_stack.alignment.toByteUnitsOptional().?)) |
| 697 | @intCast(set_align_stack.alignment.toByteUnitsOptional().?) |
| 698 | 698 | else |
| 699 | 699 | 1, |
| 700 | 700 | }), |
| ... | ... | @@ -979,7 +979,7 @@ fn fmtTracking(self: *Self) std.fmt.Formatter(formatTracking) { |
| 979 | 979 | fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index { |
| 980 | 980 | const gpa = self.gpa; |
| 981 | 981 | try self.mir_instructions.ensureUnusedCapacity(gpa, 1); |
| 982 | | const result_index = @as(Mir.Inst.Index, @intCast(self.mir_instructions.len)); |
| 982 | const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 983 | 983 | self.mir_instructions.appendAssumeCapacity(inst); |
| 984 | 984 | if (inst.tag != .pseudo or switch (inst.ops) { |
| 985 | 985 | else => true, |
| ... | ... | @@ -1000,11 +1000,11 @@ fn addExtra(self: *Self, extra: anytype) Allocator.Error!u32 { |
| 1000 | 1000 | |
| 1001 | 1001 | fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 { |
| 1002 | 1002 | const fields = std.meta.fields(@TypeOf(extra)); |
| 1003 | | const result = @as(u32, @intCast(self.mir_extra.items.len)); |
| 1003 | const result: u32 = @intCast(self.mir_extra.items.len); |
| 1004 | 1004 | inline for (fields) |field| { |
| 1005 | 1005 | self.mir_extra.appendAssumeCapacity(switch (field.type) { |
| 1006 | 1006 | u32 => @field(extra, field.name), |
| 1007 | | i32 => @as(u32, @bitCast(@field(extra, field.name))), |
| 1007 | i32 => @bitCast(@field(extra, field.name)), |
| 1008 | 1008 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), |
| 1009 | 1009 | }); |
| 1010 | 1010 | } |
| ... | ... | @@ -1214,8 +1214,8 @@ fn asmImmediate(self: *Self, tag: Mir.Inst.FixedTag, imm: Immediate) !void { |
| 1214 | 1214 | .data = .{ .i = .{ |
| 1215 | 1215 | .fixes = tag[0], |
| 1216 | 1216 | .i = switch (imm) { |
| 1217 | | .signed => |s| @as(u32, @bitCast(s)), |
| 1218 | | .unsigned => |u| @as(u32, @intCast(u)), |
| 1217 | .signed => |s| @bitCast(s), |
| 1218 | .unsigned => |u| @intCast(u), |
| 1219 | 1219 | }, |
| 1220 | 1220 | } }, |
| 1221 | 1221 | }); |
| ... | ... | @@ -1246,8 +1246,8 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.FixedTag, reg: Register, imm: |
| 1246 | 1246 | .fixes = tag[0], |
| 1247 | 1247 | .r1 = reg, |
| 1248 | 1248 | .i = switch (imm) { |
| 1249 | | .signed => |s| @as(u32, @bitCast(s)), |
| 1250 | | .unsigned => |u| @as(u32, @intCast(u)), |
| 1249 | .signed => |s| @bitCast(s), |
| 1250 | .unsigned => |u| @intCast(u), |
| 1251 | 1251 | }, |
| 1252 | 1252 | } }, |
| 1253 | 1253 | .ri64 => .{ .rx = .{ |
| ... | ... | @@ -1339,8 +1339,8 @@ fn asmRegisterRegisterImmediate( |
| 1339 | 1339 | .r1 = reg1, |
| 1340 | 1340 | .r2 = reg2, |
| 1341 | 1341 | .i = switch (imm) { |
| 1342 | | .signed => |s| @as(u32, @bitCast(s)), |
| 1343 | | .unsigned => |u| @as(u32, @intCast(u)), |
| 1342 | .signed => |s| @bitCast(s), |
| 1343 | .unsigned => |u| @intCast(u), |
| 1344 | 1344 | }, |
| 1345 | 1345 | } }, |
| 1346 | 1346 | }); |
| ... | ... | @@ -1458,7 +1458,7 @@ fn asmRegisterRegisterMemoryImmediate( |
| 1458 | 1458 | .fixes = tag[0], |
| 1459 | 1459 | .r1 = reg1, |
| 1460 | 1460 | .r2 = reg2, |
| 1461 | | .i = @as(u8, @intCast(imm.unsigned)), |
| 1461 | .i = @intCast(imm.unsigned), |
| 1462 | 1462 | .payload = switch (m) { |
| 1463 | 1463 | .sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| 1464 | 1464 | .rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| ... | ... | @@ -1490,8 +1490,8 @@ fn asmMemoryRegister(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, reg: Regist |
| 1490 | 1490 | |
| 1491 | 1491 | fn asmMemoryImmediate(self: *Self, tag: Mir.Inst.FixedTag, m: Memory, imm: Immediate) !void { |
| 1492 | 1492 | const payload = try self.addExtra(Mir.Imm32{ .imm = switch (imm) { |
| 1493 | | .signed => |s| @as(u32, @bitCast(s)), |
| 1494 | | .unsigned => |u| @as(u32, @intCast(u)), |
| 1493 | .signed => |s| @bitCast(s), |
| 1494 | .unsigned => |u| @intCast(u), |
| 1495 | 1495 | } }); |
| 1496 | 1496 | assert(payload + 1 == switch (m) { |
| 1497 | 1497 | .sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| ... | ... | @@ -1562,7 +1562,7 @@ fn asmMemoryRegisterImmediate( |
| 1562 | 1562 | .data = .{ .rix = .{ |
| 1563 | 1563 | .fixes = tag[0], |
| 1564 | 1564 | .r1 = reg, |
| 1565 | | .i = @as(u8, @intCast(imm.unsigned)), |
| 1565 | .i = @intCast(imm.unsigned), |
| 1566 | 1566 | .payload = switch (m) { |
| 1567 | 1567 | .sib => try self.addExtra(Mir.MemorySib.encode(m)), |
| 1568 | 1568 | .rip => try self.addExtra(Mir.MemoryRip.encode(m)), |
| ... | ... | @@ -1617,7 +1617,7 @@ fn gen(self: *Self) InnerError!void { |
| 1617 | 1617 | // Eliding the reloc will cause a miscompilation in this case. |
| 1618 | 1618 | for (self.exitlude_jump_relocs.items) |jmp_reloc| { |
| 1619 | 1619 | self.mir_instructions.items(.data)[jmp_reloc].inst.inst = |
| 1620 | | @as(u32, @intCast(self.mir_instructions.len)); |
| 1620 | @intCast(self.mir_instructions.len); |
| 1621 | 1621 | } |
| 1622 | 1622 | |
| 1623 | 1623 | try self.asmPseudo(.pseudo_dbg_epilogue_begin_none); |
| ... | ... | @@ -1739,7 +1739,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1739 | 1739 | |
| 1740 | 1740 | for (body) |inst| { |
| 1741 | 1741 | if (builtin.mode == .Debug) { |
| 1742 | | const mir_inst = @as(Mir.Inst.Index, @intCast(self.mir_instructions.len)); |
| 1742 | const mir_inst: Mir.Inst.Index = @intCast(self.mir_instructions.len); |
| 1743 | 1743 | try self.mir_to_air_map.put(self.gpa, mir_inst, inst); |
| 1744 | 1744 | } |
| 1745 | 1745 | |
| ... | ... | @@ -2034,7 +2034,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2034 | 2034 | |
| 2035 | 2035 | var data_off: i32 = 0; |
| 2036 | 2036 | for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| { |
| 2037 | | const index = @as(u32, @intCast(index_usize)); |
| 2037 | const index: u32 = @intCast(index_usize); |
| 2038 | 2038 | const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]); |
| 2039 | 2039 | const tag_val = try mod.enumValueFieldIndex(enum_ty, index); |
| 2040 | 2040 | const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val }); |
| ... | ... | @@ -2052,7 +2052,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2052 | 2052 | exitlude_jump_reloc.* = try self.asmJmpReloc(undefined); |
| 2053 | 2053 | try self.performReloc(skip_reloc); |
| 2054 | 2054 | |
| 2055 | | data_off += @as(i32, @intCast(tag_name.len + 1)); |
| 2055 | data_off += @intCast(tag_name.len + 1); |
| 2056 | 2056 | } |
| 2057 | 2057 | |
| 2058 | 2058 | try self.airTrap(); |
| ... | ... | @@ -2169,7 +2169,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout { |
| 2169 | 2169 | const frame_offset = self.frame_locs.items(.disp); |
| 2170 | 2170 | |
| 2171 | 2171 | for (stack_frame_order, FrameIndex.named_count..) |*frame_order, frame_index| |
| 2172 | | frame_order.* = @as(FrameIndex, @enumFromInt(frame_index)); |
| 2172 | frame_order.* = @enumFromInt(frame_index); |
| 2173 | 2173 | { |
| 2174 | 2174 | const SortContext = struct { |
| 2175 | 2175 | frame_align: @TypeOf(frame_align), |
| ... | ... | @@ -2197,7 +2197,7 @@ fn computeFrameLayout(self: *Self) !FrameLayout { |
| 2197 | 2197 | } |
| 2198 | 2198 | } |
| 2199 | 2199 | |
| 2200 | | var rbp_offset = @as(i32, @intCast(save_reg_list.count() * 8)); |
| 2200 | var rbp_offset: i32 = @intCast(save_reg_list.count() * 8); |
| 2201 | 2201 | self.setFrameLoc(.base_ptr, .rbp, &rbp_offset, false); |
| 2202 | 2202 | self.setFrameLoc(.ret_addr, .rbp, &rbp_offset, false); |
| 2203 | 2203 | self.setFrameLoc(.args_frame, .rbp, &rbp_offset, false); |
| ... | ... | @@ -2212,11 +2212,11 @@ fn computeFrameLayout(self: *Self) !FrameLayout { |
| 2212 | 2212 | rsp_offset = mem.alignForward(i32, rsp_offset, @as(i32, 1) << needed_align); |
| 2213 | 2213 | rsp_offset -= stack_frame_align_offset; |
| 2214 | 2214 | frame_size[@intFromEnum(FrameIndex.call_frame)] = |
| 2215 | | @as(u31, @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.stack_frame)])); |
| 2215 | @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.stack_frame)]); |
| 2216 | 2216 | |
| 2217 | 2217 | return .{ |
| 2218 | 2218 | .stack_mask = @as(u32, math.maxInt(u32)) << (if (need_align_stack) needed_align else 0), |
| 2219 | | .stack_adjust = @as(u32, @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.call_frame)])), |
| 2219 | .stack_adjust = @intCast(rsp_offset - frame_offset[@intFromEnum(FrameIndex.call_frame)]), |
| 2220 | 2220 | .save_reg_list = save_reg_list, |
| 2221 | 2221 | }; |
| 2222 | 2222 | } |
| ... | ... | @@ -2247,7 +2247,7 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex { |
| 2247 | 2247 | _ = self.free_frame_indices.swapRemoveAt(free_i); |
| 2248 | 2248 | return frame_index; |
| 2249 | 2249 | } |
| 2250 | | const frame_index = @as(FrameIndex, @enumFromInt(self.frame_allocs.len)); |
| 2250 | const frame_index: FrameIndex = @enumFromInt(self.frame_allocs.len); |
| 2251 | 2251 | try self.frame_allocs.append(self.gpa, alloc); |
| 2252 | 2252 | return frame_index; |
| 2253 | 2253 | } |
| ... | ... | @@ -2323,7 +2323,7 @@ const State = struct { |
| 2323 | 2323 | |
| 2324 | 2324 | fn initRetroactiveState(self: *Self) State { |
| 2325 | 2325 | var state: State = undefined; |
| 2326 | | state.inst_tracking_len = @as(u32, @intCast(self.inst_tracking.count())); |
| 2326 | state.inst_tracking_len = @intCast(self.inst_tracking.count()); |
| 2327 | 2327 | state.scope_generation = self.scope_generation; |
| 2328 | 2328 | return state; |
| 2329 | 2329 | } |
| ... | ... | @@ -2394,9 +2394,7 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 2394 | 2394 | self.inst_tracking.getPtr(current_inst).?.trackSpill(self, current_inst); |
| 2395 | 2395 | } |
| 2396 | 2396 | { |
| 2397 | | const reg = RegisterManager.regAtTrackedIndex( |
| 2398 | | @as(RegisterManager.RegisterBitSet.ShiftInt, @intCast(index)), |
| 2399 | | ); |
| 2397 | const reg = RegisterManager.regAtTrackedIndex(@intCast(index)); |
| 2400 | 2398 | self.register_manager.freeReg(reg); |
| 2401 | 2399 | self.register_manager.getRegAssumeFree(reg, target_maybe_inst); |
| 2402 | 2400 | } |
| ... | ... | @@ -2630,7 +2628,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2630 | 2628 | |
| 2631 | 2629 | const dst_ty = self.typeOfIndex(inst); |
| 2632 | 2630 | const dst_int_info = dst_ty.intInfo(mod); |
| 2633 | | const abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 2631 | const abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 2634 | 2632 | |
| 2635 | 2633 | const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty; |
| 2636 | 2634 | const extend = switch (src_int_info.signedness) { |
| ... | ... | @@ -2708,9 +2706,9 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2708 | 2706 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2709 | 2707 | |
| 2710 | 2708 | const dst_ty = self.typeOfIndex(inst); |
| 2711 | | const dst_abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 2709 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 2712 | 2710 | const src_ty = self.typeOf(ty_op.operand); |
| 2713 | | const src_abi_size = @as(u32, @intCast(src_ty.abiSize(mod))); |
| 2711 | const src_abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 2714 | 2712 | |
| 2715 | 2713 | const result = result: { |
| 2716 | 2714 | const src_mcv = try self.resolveInst(ty_op.operand); |
| ... | ... | @@ -2727,7 +2725,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2727 | 2725 | assert(src_ty.zigTypeTag(mod) == .Vector and dst_ty.vectorLen(mod) == src_ty.vectorLen(mod)); |
| 2728 | 2726 | const dst_info = dst_ty.childType(mod).intInfo(mod); |
| 2729 | 2727 | const src_info = src_ty.childType(mod).intInfo(mod); |
| 2730 | | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) { |
| 2728 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (dst_info.bits) { |
| 2731 | 2729 | 8 => switch (src_info.bits) { |
| 2732 | 2730 | 16 => switch (dst_ty.vectorLen(mod)) { |
| 2733 | 2731 | 1...8 => if (self.hasFeature(.avx)) .{ .vp_b, .ackusw } else .{ .p_b, .ackusw }, |
| ... | ... | @@ -2750,18 +2748,18 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 2750 | 2748 | else => null, |
| 2751 | 2749 | }, |
| 2752 | 2750 | else => null, |
| 2753 | | })) |tag| tag else return self.fail("TODO implement airTrunc for {}", .{ |
| 2751 | }) orelse return self.fail("TODO implement airTrunc for {}", .{ |
| 2754 | 2752 | dst_ty.fmt(self.bin_file.options.module.?), |
| 2755 | 2753 | }); |
| 2756 | 2754 | |
| 2757 | 2755 | const elem_ty = src_ty.childType(mod); |
| 2758 | | const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - dst_info.bits))); |
| 2756 | const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(64 - dst_info.bits)); |
| 2759 | 2757 | |
| 2760 | 2758 | const splat_ty = try mod.vectorType(.{ |
| 2761 | | .len = @as(u32, @intCast(@divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits))), |
| 2759 | .len = @intCast(@divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)), |
| 2762 | 2760 | .child = elem_ty.ip_index, |
| 2763 | 2761 | }); |
| 2764 | | const splat_abi_size = @as(u32, @intCast(splat_ty.abiSize(mod))); |
| 2762 | const splat_abi_size: u32 = @intCast(splat_ty.abiSize(mod)); |
| 2765 | 2763 | |
| 2766 | 2764 | const splat_val = try mod.intern(.{ .aggregate = .{ |
| 2767 | 2765 | .ty = splat_ty.ip_index, |
| ... | ... | @@ -2836,7 +2834,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 2836 | 2834 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); |
| 2837 | 2835 | try self.genSetMem( |
| 2838 | 2836 | .{ .frame = frame_index }, |
| 2839 | | @as(i32, @intCast(ptr_ty.abiSize(mod))), |
| 2837 | @intCast(ptr_ty.abiSize(mod)), |
| 2840 | 2838 | len_ty, |
| 2841 | 2839 | len, |
| 2842 | 2840 | ); |
| ... | ... | @@ -2935,6 +2933,10 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2935 | 2933 | const mod = self.bin_file.options.module.?; |
| 2936 | 2934 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 2937 | 2935 | const ty = self.typeOf(bin_op.lhs); |
| 2936 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 2937 | "TODO implement addMulSat for {}", |
| 2938 | .{ty.fmt(mod)}, |
| 2939 | ); |
| 2938 | 2940 | |
| 2939 | 2941 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 2940 | 2942 | const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv)) |
| ... | ... | @@ -2966,7 +2968,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2966 | 2968 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 2967 | 2969 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 2968 | 2970 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 2969 | | .immediate = (@as(u64, 1) << @as(u6, @intCast(reg_bits - 1))) - 1, |
| 2971 | .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1, |
| 2970 | 2972 | }); |
| 2971 | 2973 | if (reg_extra_bits > 0) { |
| 2972 | 2974 | const shifted_rhs_reg = try self.copyToTmpRegister(ty, rhs_mcv); |
| ... | ... | @@ -2985,7 +2987,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 2985 | 2987 | break :cc .o; |
| 2986 | 2988 | } else cc: { |
| 2987 | 2989 | try self.genSetReg(limit_reg, ty, .{ |
| 2988 | | .immediate = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - ty.bitSize(mod))), |
| 2990 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - ty.bitSize(mod)), |
| 2989 | 2991 | }); |
| 2990 | 2992 | |
| 2991 | 2993 | try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv); |
| ... | ... | @@ -3014,6 +3016,10 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3014 | 3016 | const mod = self.bin_file.options.module.?; |
| 3015 | 3017 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3016 | 3018 | const ty = self.typeOf(bin_op.lhs); |
| 3019 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 3020 | "TODO implement addMulSat for {}", |
| 3021 | .{ty.fmt(mod)}, |
| 3022 | ); |
| 3017 | 3023 | |
| 3018 | 3024 | const lhs_mcv = try self.resolveInst(bin_op.lhs); |
| 3019 | 3025 | const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv)) |
| ... | ... | @@ -3045,7 +3051,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3045 | 3051 | try self.genSetReg(limit_reg, ty, dst_mcv); |
| 3046 | 3052 | try self.genShiftBinOpMir(.{ ._r, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3047 | 3053 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3048 | | .immediate = (@as(u64, 1) << @as(u6, @intCast(reg_bits - 1))) - 1, |
| 3054 | .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1, |
| 3049 | 3055 | }); |
| 3050 | 3056 | if (reg_extra_bits > 0) { |
| 3051 | 3057 | const shifted_rhs_reg = try self.copyToTmpRegister(ty, rhs_mcv); |
| ... | ... | @@ -3086,6 +3092,10 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3086 | 3092 | const mod = self.bin_file.options.module.?; |
| 3087 | 3093 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3088 | 3094 | const ty = self.typeOf(bin_op.lhs); |
| 3095 | if (ty.zigTypeTag(mod) == .Vector or ty.abiSize(mod) > 8) return self.fail( |
| 3096 | "TODO implement addMulSat for {}", |
| 3097 | .{ty.fmt(mod)}, |
| 3098 | ); |
| 3089 | 3099 | |
| 3090 | 3100 | try self.spillRegisters(&.{ .rax, .rdx }); |
| 3091 | 3101 | const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx }); |
| ... | ... | @@ -3116,12 +3126,12 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3116 | 3126 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv); |
| 3117 | 3127 | try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 }); |
| 3118 | 3128 | try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, .{ |
| 3119 | | .immediate = (@as(u64, 1) << @as(u6, @intCast(reg_bits - 1))) - 1, |
| 3129 | .immediate = (@as(u64, 1) << @intCast(reg_bits - 1)) - 1, |
| 3120 | 3130 | }); |
| 3121 | 3131 | break :cc .o; |
| 3122 | 3132 | } else cc: { |
| 3123 | 3133 | try self.genSetReg(limit_reg, ty, .{ |
| 3124 | | .immediate = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - reg_bits)), |
| 3134 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - reg_bits), |
| 3125 | 3135 | }); |
| 3126 | 3136 | break :cc .c; |
| 3127 | 3137 | }; |
| ... | ... | @@ -3174,13 +3184,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3174 | 3184 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3175 | 3185 | try self.genSetMem( |
| 3176 | 3186 | .{ .frame = frame_index }, |
| 3177 | | @as(i32, @intCast(tuple_ty.structFieldOffset(1, mod))), |
| 3187 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3178 | 3188 | Type.u1, |
| 3179 | 3189 | .{ .eflags = cc }, |
| 3180 | 3190 | ); |
| 3181 | 3191 | try self.genSetMem( |
| 3182 | 3192 | .{ .frame = frame_index }, |
| 3183 | | @as(i32, @intCast(tuple_ty.structFieldOffset(0, mod))), |
| 3193 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 3184 | 3194 | ty, |
| 3185 | 3195 | partial_mcv, |
| 3186 | 3196 | ); |
| ... | ... | @@ -3247,13 +3257,13 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3247 | 3257 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| 3248 | 3258 | try self.genSetMem( |
| 3249 | 3259 | .{ .frame = frame_index }, |
| 3250 | | @as(i32, @intCast(tuple_ty.structFieldOffset(1, mod))), |
| 3260 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3251 | 3261 | tuple_ty.structFieldType(1, mod), |
| 3252 | 3262 | .{ .eflags = cc }, |
| 3253 | 3263 | ); |
| 3254 | 3264 | try self.genSetMem( |
| 3255 | 3265 | .{ .frame = frame_index }, |
| 3256 | | @as(i32, @intCast(tuple_ty.structFieldOffset(0, mod))), |
| 3266 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 3257 | 3267 | tuple_ty.structFieldType(0, mod), |
| 3258 | 3268 | partial_mcv, |
| 3259 | 3269 | ); |
| ... | ... | @@ -3321,7 +3331,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3321 | 3331 | ); |
| 3322 | 3332 | } |
| 3323 | 3333 | |
| 3324 | | const payload_off = @as(i32, @intCast(tuple_ty.structFieldOffset(0, mod))); |
| 3334 | const payload_off: i32 = @intCast(tuple_ty.structFieldOffset(0, mod)); |
| 3325 | 3335 | if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv); |
| 3326 | 3336 | try self.genSetMem( |
| 3327 | 3337 | .{ .frame = frame_index }, |
| ... | ... | @@ -3331,7 +3341,7 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3331 | 3341 | ); |
| 3332 | 3342 | try self.genSetMem( |
| 3333 | 3343 | .{ .frame = frame_index }, |
| 3334 | | @as(i32, @intCast(tuple_ty.structFieldOffset(1, mod))), |
| 3344 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3335 | 3345 | tuple_ty.structFieldType(1, mod), |
| 3336 | 3346 | if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne }, |
| 3337 | 3347 | ); |
| ... | ... | @@ -3388,13 +3398,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3388 | 3398 | if (dst_info.bits >= lhs_active_bits + rhs_active_bits) { |
| 3389 | 3399 | try self.genSetMem( |
| 3390 | 3400 | .{ .frame = frame_index }, |
| 3391 | | @as(i32, @intCast(tuple_ty.structFieldOffset(0, mod))), |
| 3401 | @intCast(tuple_ty.structFieldOffset(0, mod)), |
| 3392 | 3402 | tuple_ty.structFieldType(0, mod), |
| 3393 | 3403 | partial_mcv, |
| 3394 | 3404 | ); |
| 3395 | 3405 | try self.genSetMem( |
| 3396 | 3406 | .{ .frame = frame_index }, |
| 3397 | | @as(i32, @intCast(tuple_ty.structFieldOffset(1, mod))), |
| 3407 | @intCast(tuple_ty.structFieldOffset(1, mod)), |
| 3398 | 3408 | tuple_ty.structFieldType(1, mod), |
| 3399 | 3409 | .{ .immediate = 0 }, // cc being set is impossible |
| 3400 | 3410 | ); |
| ... | ... | @@ -3418,7 +3428,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3418 | 3428 | /// Quotient is saved in .rax and remainder in .rdx. |
| 3419 | 3429 | fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void { |
| 3420 | 3430 | const mod = self.bin_file.options.module.?; |
| 3421 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 3431 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 3422 | 3432 | if (abi_size > 8) { |
| 3423 | 3433 | return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{}); |
| 3424 | 3434 | } |
| ... | ... | @@ -3458,7 +3468,7 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue |
| 3458 | 3468 | /// Clobbers .rax and .rdx registers. |
| 3459 | 3469 | fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue { |
| 3460 | 3470 | const mod = self.bin_file.options.module.?; |
| 3461 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 3471 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 3462 | 3472 | const int_info = ty.intInfo(mod); |
| 3463 | 3473 | const dividend: Register = switch (lhs) { |
| 3464 | 3474 | .register => |reg| reg, |
| ... | ... | @@ -3597,7 +3607,7 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3597 | 3607 | try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv); |
| 3598 | 3608 | |
| 3599 | 3609 | const pl_ty = dst_ty.childType(mod); |
| 3600 | | const pl_abi_size = @as(i32, @intCast(pl_ty.abiSize(mod))); |
| 3610 | const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod)); |
| 3601 | 3611 | try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 }); |
| 3602 | 3612 | break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv; |
| 3603 | 3613 | }; |
| ... | ... | @@ -3629,17 +3639,12 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3629 | 3639 | defer if (eu_lock) |lock| self.register_manager.unlockReg(lock); |
| 3630 | 3640 | |
| 3631 | 3641 | const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand); |
| 3632 | | if (err_off > 0) { |
| 3633 | | const shift = @as(u6, @intCast(err_off * 8)); |
| 3634 | | try self.genShiftBinOpMir( |
| 3635 | | .{ ._r, .sh }, |
| 3636 | | err_union_ty, |
| 3637 | | result, |
| 3638 | | .{ .immediate = shift }, |
| 3639 | | ); |
| 3640 | | } else { |
| 3641 | | try self.truncateRegister(Type.anyerror, result.register); |
| 3642 | | } |
| 3642 | if (err_off > 0) try self.genShiftBinOpMir( |
| 3643 | .{ ._r, .sh }, |
| 3644 | err_union_ty, |
| 3645 | result, |
| 3646 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 3647 | ) else try self.truncateRegister(Type.anyerror, result.register); |
| 3643 | 3648 | break :result result; |
| 3644 | 3649 | }, |
| 3645 | 3650 | .load_frame => |frame_addr| break :result .{ .load_frame = .{ |
| ... | ... | @@ -3687,17 +3692,12 @@ fn genUnwrapErrorUnionPayloadMir( |
| 3687 | 3692 | try self.copyToRegisterWithInstTracking(inst, err_union_ty, err_union) |
| 3688 | 3693 | else |
| 3689 | 3694 | .{ .register = try self.copyToTmpRegister(err_union_ty, err_union) }; |
| 3690 | | if (payload_off > 0) { |
| 3691 | | const shift = @as(u6, @intCast(payload_off * 8)); |
| 3692 | | try self.genShiftBinOpMir( |
| 3693 | | .{ ._r, .sh }, |
| 3694 | | err_union_ty, |
| 3695 | | result_mcv, |
| 3696 | | .{ .immediate = shift }, |
| 3697 | | ); |
| 3698 | | } else { |
| 3699 | | try self.truncateRegister(payload_ty, result_mcv.register); |
| 3700 | | } |
| 3695 | if (payload_off > 0) try self.genShiftBinOpMir( |
| 3696 | .{ ._r, .sh }, |
| 3697 | err_union_ty, |
| 3698 | result_mcv, |
| 3699 | .{ .immediate = @as(u6, @intCast(payload_off * 8)) }, |
| 3700 | ) else try self.truncateRegister(payload_ty, result_mcv.register); |
| 3701 | 3701 | break :result result_mcv; |
| 3702 | 3702 | }, |
| 3703 | 3703 | else => return self.fail("TODO implement genUnwrapErrorUnionPayloadMir for {}", .{err_union}), |
| ... | ... | @@ -3729,8 +3729,8 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3729 | 3729 | const eu_ty = src_ty.childType(mod); |
| 3730 | 3730 | const pl_ty = eu_ty.errorUnionPayload(mod); |
| 3731 | 3731 | const err_ty = eu_ty.errorUnionSet(mod); |
| 3732 | | const err_off = @as(i32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 3733 | | const err_abi_size = @as(u32, @intCast(err_ty.abiSize(mod))); |
| 3732 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 3733 | const err_abi_size: u32 = @intCast(err_ty.abiSize(mod)); |
| 3734 | 3734 | try self.asmRegisterMemory( |
| 3735 | 3735 | .{ ._, .mov }, |
| 3736 | 3736 | registerAlias(dst_reg, err_abi_size), |
| ... | ... | @@ -3768,8 +3768,8 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3768 | 3768 | |
| 3769 | 3769 | const eu_ty = src_ty.childType(mod); |
| 3770 | 3770 | const pl_ty = eu_ty.errorUnionPayload(mod); |
| 3771 | | const pl_off = @as(i32, @intCast(errUnionPayloadOffset(pl_ty, mod))); |
| 3772 | | const dst_abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 3771 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 3772 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 3773 | 3773 | try self.asmRegisterMemory( |
| 3774 | 3774 | .{ ._, .lea }, |
| 3775 | 3775 | registerAlias(dst_reg, dst_abi_size), |
| ... | ... | @@ -3795,8 +3795,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3795 | 3795 | const eu_ty = src_ty.childType(mod); |
| 3796 | 3796 | const pl_ty = eu_ty.errorUnionPayload(mod); |
| 3797 | 3797 | const err_ty = eu_ty.errorUnionSet(mod); |
| 3798 | | const err_off = @as(i32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 3799 | | const err_abi_size = @as(u32, @intCast(err_ty.abiSize(mod))); |
| 3798 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 3799 | const err_abi_size: u32 = @intCast(err_ty.abiSize(mod)); |
| 3800 | 3800 | try self.asmMemoryImmediate( |
| 3801 | 3801 | .{ ._, .mov }, |
| 3802 | 3802 | Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{ |
| ... | ... | @@ -3816,8 +3816,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3816 | 3816 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3817 | 3817 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 3818 | 3818 | |
| 3819 | | const pl_off = @as(i32, @intCast(errUnionPayloadOffset(pl_ty, mod))); |
| 3820 | | const dst_abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 3819 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 3820 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 3821 | 3821 | try self.asmRegisterMemory( |
| 3822 | 3822 | .{ ._, .lea }, |
| 3823 | 3823 | registerAlias(dst_reg, dst_abi_size), |
| ... | ... | @@ -3866,7 +3866,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 3866 | 3866 | try self.genCopy(pl_ty, opt_mcv, pl_mcv); |
| 3867 | 3867 | |
| 3868 | 3868 | if (!same_repr) { |
| 3869 | | const pl_abi_size = @as(i32, @intCast(pl_ty.abiSize(mod))); |
| 3869 | const pl_abi_size: i32 = @intCast(pl_ty.abiSize(mod)); |
| 3870 | 3870 | switch (opt_mcv) { |
| 3871 | 3871 | else => unreachable, |
| 3872 | 3872 | |
| ... | ... | @@ -3905,8 +3905,8 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 3905 | 3905 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .{ .immediate = 0 }; |
| 3906 | 3906 | |
| 3907 | 3907 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod)); |
| 3908 | | const pl_off = @as(i32, @intCast(errUnionPayloadOffset(pl_ty, mod))); |
| 3909 | | const err_off = @as(i32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 3908 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 3909 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 3910 | 3910 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand); |
| 3911 | 3911 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 }); |
| 3912 | 3912 | break :result .{ .load_frame = .{ .index = frame_index } }; |
| ... | ... | @@ -3927,8 +3927,8 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 3927 | 3927 | if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand); |
| 3928 | 3928 | |
| 3929 | 3929 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod)); |
| 3930 | | const pl_off = @as(i32, @intCast(errUnionPayloadOffset(pl_ty, mod))); |
| 3931 | | const err_off = @as(i32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 3930 | const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, mod)); |
| 3931 | const err_off: i32 = @intCast(errUnionErrorOffset(pl_ty, mod)); |
| 3932 | 3932 | try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef); |
| 3933 | 3933 | const operand = try self.resolveInst(ty_op.operand); |
| 3934 | 3934 | try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand); |
| ... | ... | @@ -3990,7 +3990,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3990 | 3990 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3991 | 3991 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 3992 | 3992 | |
| 3993 | | const dst_abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 3993 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 3994 | 3994 | try self.asmRegisterMemory( |
| 3995 | 3995 | .{ ._, .lea }, |
| 3996 | 3996 | registerAlias(dst_reg, dst_abi_size), |
| ... | ... | @@ -4167,7 +4167,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4167 | 4167 | // additional `mov` is needed at the end to get the actual value |
| 4168 | 4168 | |
| 4169 | 4169 | const elem_ty = ptr_ty.elemType2(mod); |
| 4170 | | const elem_abi_size = @as(u32, @intCast(elem_ty.abiSize(mod))); |
| 4170 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 4171 | 4171 | const index_ty = self.typeOf(bin_op.rhs); |
| 4172 | 4172 | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 4173 | 4173 | const index_lock = switch (index_mcv) { |
| ... | ... | @@ -4307,7 +4307,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4307 | 4307 | .load_frame => |frame_addr| { |
| 4308 | 4308 | if (tag_abi_size <= 8) { |
| 4309 | 4309 | const off: i32 = if (layout.tag_align < layout.payload_align) |
| 4310 | | @as(i32, @intCast(layout.payload_size)) |
| 4310 | @intCast(layout.payload_size) |
| 4311 | 4311 | else |
| 4312 | 4312 | 0; |
| 4313 | 4313 | break :blk try self.copyToRegisterWithInstTracking(inst, tag_ty, .{ |
| ... | ... | @@ -4319,13 +4319,13 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void { |
| 4319 | 4319 | }, |
| 4320 | 4320 | .register => { |
| 4321 | 4321 | const shift: u6 = if (layout.tag_align < layout.payload_align) |
| 4322 | | @as(u6, @intCast(layout.payload_size * 8)) |
| 4322 | @intCast(layout.payload_size * 8) |
| 4323 | 4323 | else |
| 4324 | 4324 | 0; |
| 4325 | 4325 | const result = try self.copyToRegisterWithInstTracking(inst, union_ty, operand); |
| 4326 | 4326 | try self.genShiftBinOpMir(.{ ._r, .sh }, Type.usize, result, .{ .immediate = shift }); |
| 4327 | 4327 | break :blk MCValue{ |
| 4328 | | .register = registerAlias(result.register, @as(u32, @intCast(layout.tag_size))), |
| 4328 | .register = registerAlias(result.register, @intCast(layout.tag_size)), |
| 4329 | 4329 | }; |
| 4330 | 4330 | }, |
| 4331 | 4331 | else => return self.fail("TODO implement get_union_tag for {}", .{operand}), |
| ... | ... | @@ -4341,6 +4341,9 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4341 | 4341 | const result = result: { |
| 4342 | 4342 | const dst_ty = self.typeOfIndex(inst); |
| 4343 | 4343 | const src_ty = self.typeOf(ty_op.operand); |
| 4344 | if (src_ty.zigTypeTag(mod) == .Vector) return self.fail("TODO implement airClz for {}", .{ |
| 4345 | src_ty.fmt(mod), |
| 4346 | }); |
| 4344 | 4347 | |
| 4345 | 4348 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4346 | 4349 | const mat_src_mcv = switch (src_mcv) { |
| ... | ... | @@ -4432,7 +4435,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4432 | 4435 | try self.genBinOpMir(.{ ._, .xor }, dst_ty, dst_mcv, .{ .immediate = src_bits - 1 }); |
| 4433 | 4436 | } else { |
| 4434 | 4437 | const imm_reg = try self.copyToTmpRegister(dst_ty, .{ |
| 4435 | | .immediate = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - self.regBitSize(dst_ty))), |
| 4438 | .immediate = @as(u64, math.maxInt(u64)) >> @intCast(64 - self.regBitSize(dst_ty)), |
| 4436 | 4439 | }); |
| 4437 | 4440 | const imm_lock = self.register_manager.lockRegAssumeUnused(imm_reg); |
| 4438 | 4441 | defer self.register_manager.unlockReg(imm_lock); |
| ... | ... | @@ -4503,8 +4506,8 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4503 | 4506 | .{ ._, .@"or" }, |
| 4504 | 4507 | wide_ty, |
| 4505 | 4508 | tmp_mcv, |
| 4506 | | .{ .immediate = (@as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - extra_bits))) << |
| 4507 | | @as(u6, @intCast(src_bits)) }, |
| 4509 | .{ .immediate = (@as(u64, math.maxInt(u64)) >> @intCast(64 - extra_bits)) << |
| 4510 | @intCast(src_bits) }, |
| 4508 | 4511 | ); |
| 4509 | 4512 | break :masked tmp_mcv; |
| 4510 | 4513 | } else mat_src_mcv; |
| ... | ... | @@ -4521,7 +4524,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4521 | 4524 | .{ ._, .@"or" }, |
| 4522 | 4525 | Type.u64, |
| 4523 | 4526 | dst_mcv, |
| 4524 | | .{ .immediate = @as(u64, math.maxInt(u64)) << @as(u6, @intCast(src_bits - 64)) }, |
| 4527 | .{ .immediate = @as(u64, math.maxInt(u64)) << @intCast(src_bits - 64) }, |
| 4525 | 4528 | ); |
| 4526 | 4529 | break :masked dst_mcv; |
| 4527 | 4530 | } else mat_src_mcv.address().offset(8).deref(); |
| ... | ... | @@ -4565,7 +4568,9 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4565 | 4568 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4566 | 4569 | const result: MCValue = result: { |
| 4567 | 4570 | const src_ty = self.typeOf(ty_op.operand); |
| 4568 | | const src_abi_size = @as(u32, @intCast(src_ty.abiSize(mod))); |
| 4571 | const src_abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 4572 | if (src_ty.zigTypeTag(mod) == .Vector or src_abi_size > 8) |
| 4573 | return self.fail("TODO implement airPopcount for {}", .{src_ty.fmt(mod)}); |
| 4569 | 4574 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4570 | 4575 | |
| 4571 | 4576 | if (self.hasFeature(.popcnt)) { |
| ... | ... | @@ -4590,7 +4595,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4590 | 4595 | break :result dst_mcv; |
| 4591 | 4596 | } |
| 4592 | 4597 | |
| 4593 | | const mask = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - src_abi_size * 8)); |
| 4598 | const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8); |
| 4594 | 4599 | const imm_0_1 = Immediate.u(mask / 0b1_1); |
| 4595 | 4600 | const imm_00_11 = Immediate.u(mask / 0b01_01); |
| 4596 | 4601 | const imm_0000_1111 = Immediate.u(mask / 0b0001_0001); |
| ... | ... | @@ -4674,8 +4679,13 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4674 | 4679 | } |
| 4675 | 4680 | |
| 4676 | 4681 | fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, mem_ok: bool) !MCValue { |
| 4682 | const mod = self.bin_file.options.module.?; |
| 4677 | 4683 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4678 | 4684 | |
| 4685 | if (src_ty.zigTypeTag(mod) == .Vector or src_ty.abiSize(mod) > 8) return self.fail( |
| 4686 | "TODO implement byteSwap for {}", |
| 4687 | .{src_ty.fmt(mod)}, |
| 4688 | ); |
| 4679 | 4689 | const src_bits = self.regBitSize(src_ty); |
| 4680 | 4690 | const src_lock = switch (src_mcv) { |
| 4681 | 4691 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| ... | ... | @@ -4684,7 +4694,9 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4684 | 4694 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4685 | 4695 | |
| 4686 | 4696 | switch (src_bits) { |
| 4687 | | else => unreachable, |
| 4697 | else => return self.fail("TODO implement byteSwap for {}", .{ |
| 4698 | src_ty.fmt(mod), |
| 4699 | }), |
| 4688 | 4700 | 8 => return if ((mem_ok or src_mcv.isRegister()) and |
| 4689 | 4701 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 4690 | 4702 | src_mcv |
| ... | ... | @@ -4756,7 +4768,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4756 | 4768 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 4757 | 4769 | |
| 4758 | 4770 | const src_ty = self.typeOf(ty_op.operand); |
| 4759 | | const src_abi_size = @as(u32, @intCast(src_ty.abiSize(mod))); |
| 4771 | const src_abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 4760 | 4772 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 4761 | 4773 | |
| 4762 | 4774 | const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false); |
| ... | ... | @@ -4776,7 +4788,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4776 | 4788 | else |
| 4777 | 4789 | undefined; |
| 4778 | 4790 | |
| 4779 | | const mask = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - src_abi_size * 8)); |
| 4791 | const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - src_abi_size * 8); |
| 4780 | 4792 | const imm_0000_1111 = Immediate.u(mask / 0b0001_0001); |
| 4781 | 4793 | const imm_00_11 = Immediate.u(mask / 0b01_01); |
| 4782 | 4794 | const imm_0_1 = Immediate.u(mask / 0b1_1); |
| ... | ... | @@ -4874,6 +4886,9 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| 4874 | 4886 | }), |
| 4875 | 4887 | }; |
| 4876 | 4888 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 4889 | if (scalar_bits == 80) return self.fail("TODO implement airFloatSign for {}", .{ |
| 4890 | ty.fmt(mod), |
| 4891 | }); |
| 4877 | 4892 | |
| 4878 | 4893 | const src_mcv = try self.resolveInst(un_op); |
| 4879 | 4894 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | ... | @@ -4989,7 +5004,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 |
| 4989 | 5004 | if (!self.hasFeature(.sse4_1)) |
| 4990 | 5005 | return self.fail("TODO implement genRound without sse4_1 feature", .{}); |
| 4991 | 5006 | |
| 4992 | | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5007 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 4993 | 5008 | .Float => switch (ty.floatBits(self.target.*)) { |
| 4994 | 5009 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round }, |
| 4995 | 5010 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round }, |
| ... | ... | @@ -5016,10 +5031,10 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4 |
| 5016 | 5031 | else => null, |
| 5017 | 5032 | }, |
| 5018 | 5033 | else => unreachable, |
| 5019 | | })) |tag| tag else return self.fail("TODO implement genRound for {}", .{ |
| 5034 | }) orelse return self.fail("TODO implement genRound for {}", .{ |
| 5020 | 5035 | ty.fmt(self.bin_file.options.module.?), |
| 5021 | 5036 | }); |
| 5022 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 5037 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 5023 | 5038 | const dst_alias = registerAlias(dst_reg, abi_size); |
| 5024 | 5039 | switch (mir_tag[0]) { |
| 5025 | 5040 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate( |
| ... | ... | @@ -5059,7 +5074,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5059 | 5074 | const mod = self.bin_file.options.module.?; |
| 5060 | 5075 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 5061 | 5076 | const ty = self.typeOf(un_op); |
| 5062 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 5077 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 5063 | 5078 | |
| 5064 | 5079 | const src_mcv = try self.resolveInst(un_op); |
| 5065 | 5080 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| ... | ... | @@ -5071,7 +5086,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5071 | 5086 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5072 | 5087 | |
| 5073 | 5088 | const result: MCValue = result: { |
| 5074 | | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5089 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5075 | 5090 | .Float => switch (ty.floatBits(self.target.*)) { |
| 5076 | 5091 | 16 => if (self.hasFeature(.f16c)) { |
| 5077 | 5092 | const mat_src_reg = if (src_mcv.isRegister()) |
| ... | ... | @@ -5125,7 +5140,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5125 | 5140 | .{ .v_ps, .cvtph2 }, |
| 5126 | 5141 | wide_reg, |
| 5127 | 5142 | src_mcv.mem(Memory.PtrSize.fromSize( |
| 5128 | | @as(u32, @intCast(@divExact(wide_reg.bitSize(), 16))), |
| 5143 | @intCast(@divExact(wide_reg.bitSize(), 16)), |
| 5129 | 5144 | )), |
| 5130 | 5145 | ) else try self.asmRegisterRegister( |
| 5131 | 5146 | .{ .v_ps, .cvtph2 }, |
| ... | ... | @@ -5164,7 +5179,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5164 | 5179 | else => unreachable, |
| 5165 | 5180 | }, |
| 5166 | 5181 | else => unreachable, |
| 5167 | | })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{ |
| 5182 | }) orelse return self.fail("TODO implement airSqrt for {}", .{ |
| 5168 | 5183 | ty.fmt(mod), |
| 5169 | 5184 | }); |
| 5170 | 5185 | switch (mir_tag[0]) { |
| ... | ... | @@ -5257,10 +5272,10 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5257 | 5272 | const ptr_info = ptr_ty.ptrInfo(mod); |
| 5258 | 5273 | |
| 5259 | 5274 | const val_ty = ptr_info.child.toType(); |
| 5260 | | const val_abi_size = @as(u32, @intCast(val_ty.abiSize(mod))); |
| 5275 | const val_abi_size: u32 = @intCast(val_ty.abiSize(mod)); |
| 5261 | 5276 | const limb_abi_size: u32 = @min(val_abi_size, 8); |
| 5262 | 5277 | const limb_abi_bits = limb_abi_size * 8; |
| 5263 | | const val_byte_off = @as(i32, @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size)); |
| 5278 | const val_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size); |
| 5264 | 5279 | const val_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits; |
| 5265 | 5280 | const val_extra_bits = self.regExtraBits(val_ty); |
| 5266 | 5281 | |
| ... | ... | @@ -5404,9 +5419,10 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5404 | 5419 | |
| 5405 | 5420 | const limb_abi_size: u16 = @min(ptr_info.packed_offset.host_size, 8); |
| 5406 | 5421 | const limb_abi_bits = limb_abi_size * 8; |
| 5422 | const limb_ty = try mod.intType(.unsigned, limb_abi_bits); |
| 5407 | 5423 | |
| 5408 | 5424 | const src_bit_size = src_ty.bitSize(mod); |
| 5409 | | const src_byte_off = @as(i32, @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size)); |
| 5425 | const src_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size); |
| 5410 | 5426 | const src_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits; |
| 5411 | 5427 | |
| 5412 | 5428 | const ptr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv); |
| ... | ... | @@ -5423,10 +5439,9 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5423 | 5439 | .disp = src_byte_off + limb_i * limb_abi_bits, |
| 5424 | 5440 | }); |
| 5425 | 5441 | |
| 5426 | | const part_mask = (@as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - part_bit_size))) << |
| 5427 | | @as(u6, @intCast(part_bit_off)); |
| 5428 | | const part_mask_not = part_mask ^ |
| 5429 | | (@as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - limb_abi_bits))); |
| 5442 | const part_mask = (@as(u64, math.maxInt(u64)) >> @intCast(64 - part_bit_size)) << |
| 5443 | @intCast(part_bit_off); |
| 5444 | const part_mask_not = part_mask ^ (@as(u64, math.maxInt(u64)) >> @intCast(64 - limb_abi_bits)); |
| 5430 | 5445 | if (limb_abi_size <= 4) { |
| 5431 | 5446 | try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.u(part_mask_not)); |
| 5432 | 5447 | } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| { |
| ... | ... | @@ -5443,23 +5458,23 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5443 | 5458 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 5444 | 5459 | defer self.register_manager.unlockReg(tmp_lock); |
| 5445 | 5460 | |
| 5446 | | try self.genSetReg(tmp_reg, src_ty, src_mcv); |
| 5461 | try self.genSetReg(tmp_reg, limb_ty, src_mcv); |
| 5447 | 5462 | switch (limb_i) { |
| 5448 | 5463 | 0 => try self.genShiftBinOpMir( |
| 5449 | 5464 | .{ ._l, .sh }, |
| 5450 | | src_ty, |
| 5465 | limb_ty, |
| 5451 | 5466 | tmp_mcv, |
| 5452 | 5467 | .{ .immediate = src_bit_off }, |
| 5453 | 5468 | ), |
| 5454 | 5469 | 1 => try self.genShiftBinOpMir( |
| 5455 | 5470 | .{ ._r, .sh }, |
| 5456 | | src_ty, |
| 5471 | limb_ty, |
| 5457 | 5472 | tmp_mcv, |
| 5458 | 5473 | .{ .immediate = limb_abi_bits - src_bit_off }, |
| 5459 | 5474 | ), |
| 5460 | 5475 | else => unreachable, |
| 5461 | 5476 | } |
| 5462 | | try self.genBinOpMir(.{ ._, .@"and" }, src_ty, tmp_mcv, .{ .immediate = part_mask }); |
| 5477 | try self.genBinOpMir(.{ ._, .@"and" }, limb_ty, tmp_mcv, .{ .immediate = part_mask }); |
| 5463 | 5478 | try self.asmMemoryRegister( |
| 5464 | 5479 | .{ ._, .@"or" }, |
| 5465 | 5480 | limb_mem, |
| ... | ... | @@ -5544,14 +5559,14 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32 |
| 5544 | 5559 | const ptr_field_ty = self.typeOfIndex(inst); |
| 5545 | 5560 | const ptr_container_ty = self.typeOf(operand); |
| 5546 | 5561 | const container_ty = ptr_container_ty.childType(mod); |
| 5547 | | const field_offset = @as(i32, @intCast(switch (container_ty.containerLayout(mod)) { |
| 5562 | const field_offset: i32 = @intCast(switch (container_ty.containerLayout(mod)) { |
| 5548 | 5563 | .Auto, .Extern => container_ty.structFieldOffset(index, mod), |
| 5549 | 5564 | .Packed => if (container_ty.zigTypeTag(mod) == .Struct and |
| 5550 | 5565 | ptr_field_ty.ptrInfo(mod).packed_offset.host_size == 0) |
| 5551 | 5566 | container_ty.packedStructFieldByteOffset(index, mod) |
| 5552 | 5567 | else |
| 5553 | 5568 | 0, |
| 5554 | | })); |
| 5569 | }); |
| 5555 | 5570 | |
| 5556 | 5571 | const src_mcv = try self.resolveInst(operand); |
| 5557 | 5572 | const dst_mcv = if (switch (src_mcv) { |
| ... | ... | @@ -5578,8 +5593,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5578 | 5593 | const field_is_gp = field_rc.supersetOf(gp); |
| 5579 | 5594 | |
| 5580 | 5595 | const src_mcv = try self.resolveInst(operand); |
| 5581 | | const field_off = switch (container_ty.containerLayout(mod)) { |
| 5582 | | .Auto, .Extern => @as(u32, @intCast(container_ty.structFieldOffset(index, mod) * 8)), |
| 5596 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { |
| 5597 | .Auto, .Extern => @intCast(container_ty.structFieldOffset(index, mod) * 8), |
| 5583 | 5598 | .Packed => if (mod.typeToStruct(container_ty)) |struct_obj| |
| 5584 | 5599 | struct_obj.packedFieldBitOffset(mod, index) |
| 5585 | 5600 | else |
| ... | ... | @@ -5588,9 +5603,31 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5588 | 5603 | |
| 5589 | 5604 | switch (src_mcv) { |
| 5590 | 5605 | .load_frame => |frame_addr| { |
| 5606 | const field_abi_size: u32 = @intCast(field_ty.abiSize(mod)); |
| 5591 | 5607 | if (field_off % 8 == 0) { |
| 5592 | 5608 | const off_mcv = |
| 5593 | | src_mcv.address().offset(@as(i32, @intCast(@divExact(field_off, 8)))).deref(); |
| 5609 | src_mcv.address().offset(@intCast(@divExact(field_off, 8))).deref(); |
| 5610 | |
| 5611 | if (field_abi_size <= 8) { |
| 5612 | const int_ty = try mod.intType( |
| 5613 | if (field_ty.isAbiInt(mod)) field_ty.intInfo(mod).signedness else .unsigned, |
| 5614 | @intCast(field_ty.bitSize(mod)), |
| 5615 | ); |
| 5616 | |
| 5617 | const dst_reg = |
| 5618 | try self.register_manager.allocReg(if (field_is_gp) inst else null, gp); |
| 5619 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 5620 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 5621 | defer self.register_manager.unlockReg(dst_lock); |
| 5622 | |
| 5623 | try self.genCopy(int_ty, dst_mcv, off_mcv); |
| 5624 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(int_ty, dst_reg); |
| 5625 | break :result if (field_is_gp) |
| 5626 | dst_mcv |
| 5627 | else |
| 5628 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 5629 | } |
| 5630 | |
| 5594 | 5631 | if (self.reuseOperand(inst, operand, 0, src_mcv)) break :result off_mcv; |
| 5595 | 5632 | |
| 5596 | 5633 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| ... | ... | @@ -5598,10 +5635,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5598 | 5635 | break :result dst_mcv; |
| 5599 | 5636 | } |
| 5600 | 5637 | |
| 5601 | | const field_abi_size = @as(u32, @intCast(field_ty.abiSize(mod))); |
| 5602 | 5638 | const limb_abi_size: u32 = @min(field_abi_size, 8); |
| 5603 | 5639 | const limb_abi_bits = limb_abi_size * 8; |
| 5604 | | const field_byte_off = @as(i32, @intCast(field_off / limb_abi_bits * limb_abi_size)); |
| 5640 | const field_byte_off: i32 = @intCast(field_off / limb_abi_bits * limb_abi_size); |
| 5605 | 5641 | const field_bit_off = field_off % limb_abi_bits; |
| 5606 | 5642 | |
| 5607 | 5643 | if (field_abi_size > 8) { |
| ... | ... | @@ -5726,7 +5762,7 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 5726 | 5762 | |
| 5727 | 5763 | const inst_ty = self.typeOfIndex(inst); |
| 5728 | 5764 | const parent_ty = inst_ty.childType(mod); |
| 5729 | | const field_offset = @as(i32, @intCast(parent_ty.structFieldOffset(extra.field_index, mod))); |
| 5765 | const field_offset: i32 = @intCast(parent_ty.structFieldOffset(extra.field_index, mod)); |
| 5730 | 5766 | |
| 5731 | 5767 | const src_mcv = try self.resolveInst(extra.field_ptr); |
| 5732 | 5768 | const dst_mcv = if (src_mcv.isRegisterOffset() and |
| ... | ... | @@ -5775,14 +5811,14 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 5775 | 5811 | |
| 5776 | 5812 | switch (tag) { |
| 5777 | 5813 | .not => { |
| 5778 | | const limb_abi_size = @as(u16, @intCast(@min(src_ty.abiSize(mod), 8))); |
| 5814 | const limb_abi_size: u16 = @intCast(@min(src_ty.abiSize(mod), 8)); |
| 5779 | 5815 | const int_info = if (src_ty.ip_index == .bool_type) |
| 5780 | 5816 | std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 } |
| 5781 | 5817 | else |
| 5782 | 5818 | src_ty.intInfo(mod); |
| 5783 | 5819 | var byte_off: i32 = 0; |
| 5784 | 5820 | while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) { |
| 5785 | | const limb_bits = @as(u16, @intCast(@min(int_info.bits - byte_off * 8, limb_abi_size * 8))); |
| 5821 | const limb_bits: u16 = @intCast(@min(int_info.bits - byte_off * 8, limb_abi_size * 8)); |
| 5786 | 5822 | const limb_ty = try mod.intType(int_info.signedness, limb_bits); |
| 5787 | 5823 | const limb_mcv = switch (byte_off) { |
| 5788 | 5824 | 0 => dst_mcv, |
| ... | ... | @@ -5790,7 +5826,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 5790 | 5826 | }; |
| 5791 | 5827 | |
| 5792 | 5828 | if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) { |
| 5793 | | const mask = @as(u64, math.maxInt(u64)) >> @as(u6, @intCast(64 - limb_bits)); |
| 5829 | const mask = @as(u64, math.maxInt(u64)) >> @intCast(64 - limb_bits); |
| 5794 | 5830 | try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask }); |
| 5795 | 5831 | } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv); |
| 5796 | 5832 | } |
| ... | ... | @@ -5803,7 +5839,7 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: |
| 5803 | 5839 | |
| 5804 | 5840 | fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void { |
| 5805 | 5841 | const mod = self.bin_file.options.module.?; |
| 5806 | | const abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 5842 | const abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 5807 | 5843 | if (abi_size > 8) return self.fail("TODO implement {} for {}", .{ |
| 5808 | 5844 | mir_tag, |
| 5809 | 5845 | dst_ty.fmt(self.bin_file.options.module.?), |
| ... | ... | @@ -5865,7 +5901,7 @@ fn genShiftBinOpMir( |
| 5865 | 5901 | break :rhs .{ .register = .rcx }; |
| 5866 | 5902 | }; |
| 5867 | 5903 | |
| 5868 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 5904 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 5869 | 5905 | if (abi_size <= 8) { |
| 5870 | 5906 | switch (lhs_mcv) { |
| 5871 | 5907 | .register => |lhs_reg| switch (rhs_mcv) { |
| ... | ... | @@ -6085,16 +6121,16 @@ fn genShiftBinOp( |
| 6085 | 6121 | rhs_ty: Type, |
| 6086 | 6122 | ) !MCValue { |
| 6087 | 6123 | const mod = self.bin_file.options.module.?; |
| 6088 | | if (lhs_ty.zigTypeTag(mod) == .Vector) { |
| 6089 | | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); |
| 6090 | | } |
| 6124 | if (lhs_ty.zigTypeTag(mod) == .Vector) return self.fail("TODO implement genShiftBinOp for {}", .{ |
| 6125 | lhs_ty.fmt(mod), |
| 6126 | }); |
| 6091 | 6127 | |
| 6092 | 6128 | assert(rhs_ty.abiSize(mod) == 1); |
| 6093 | 6129 | |
| 6094 | 6130 | const lhs_abi_size = lhs_ty.abiSize(mod); |
| 6095 | | if (lhs_abi_size > 16) { |
| 6096 | | return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()}); |
| 6097 | | } |
| 6131 | if (lhs_abi_size > 16) return self.fail("TODO implement genShiftBinOp for {}", .{ |
| 6132 | lhs_ty.fmt(mod), |
| 6133 | }); |
| 6098 | 6134 | |
| 6099 | 6135 | try self.register_manager.getReg(.rcx, null); |
| 6100 | 6136 | const rcx_lock = self.register_manager.lockRegAssumeUnused(.rcx); |
| ... | ... | @@ -6150,11 +6186,12 @@ fn genMulDivBinOp( |
| 6150 | 6186 | rhs: MCValue, |
| 6151 | 6187 | ) !MCValue { |
| 6152 | 6188 | const mod = self.bin_file.options.module.?; |
| 6153 | | if (dst_ty.zigTypeTag(mod) == .Vector or dst_ty.zigTypeTag(mod) == .Float) { |
| 6154 | | return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()}); |
| 6155 | | } |
| 6156 | | const dst_abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 6157 | | const src_abi_size = @as(u32, @intCast(src_ty.abiSize(mod))); |
| 6189 | if (dst_ty.zigTypeTag(mod) == .Vector or dst_ty.zigTypeTag(mod) == .Float) return self.fail( |
| 6190 | "TODO implement genMulDivBinOp for {}", |
| 6191 | .{dst_ty.fmt(mod)}, |
| 6192 | ); |
| 6193 | const dst_abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 6194 | const src_abi_size: u32 = @intCast(src_ty.abiSize(mod)); |
| 6158 | 6195 | if (switch (tag) { |
| 6159 | 6196 | else => unreachable, |
| 6160 | 6197 | .mul, .mul_wrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2, |
| ... | ... | @@ -6328,7 +6365,13 @@ fn genBinOp( |
| 6328 | 6365 | const mod = self.bin_file.options.module.?; |
| 6329 | 6366 | const lhs_ty = self.typeOf(lhs_air); |
| 6330 | 6367 | const rhs_ty = self.typeOf(rhs_air); |
| 6331 | | const abi_size = @as(u32, @intCast(lhs_ty.abiSize(mod))); |
| 6368 | const abi_size: u32 = @intCast(lhs_ty.abiSize(mod)); |
| 6369 | if ((lhs_ty.scalarType(mod).isRuntimeFloat() and |
| 6370 | lhs_ty.scalarType(mod).floatBits(self.target.*) == 80) or |
| 6371 | lhs_ty.abiSize(mod) > @as(u6, if (self.hasFeature(.avx)) 32 else 16)) |
| 6372 | return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 6373 | @tagName(air_tag), lhs_ty.fmt(mod), |
| 6374 | }); |
| 6332 | 6375 | |
| 6333 | 6376 | const maybe_mask_reg = switch (air_tag) { |
| 6334 | 6377 | else => null, |
| ... | ... | @@ -6339,6 +6382,9 @@ fn genBinOp( |
| 6339 | 6382 | } else try self.register_manager.allocReg(null, sse), |
| 6340 | 6383 | abi_size, |
| 6341 | 6384 | ) else null, |
| 6385 | .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 6386 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 6387 | }), |
| 6342 | 6388 | }; |
| 6343 | 6389 | const mask_lock = |
| 6344 | 6390 | if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null; |
| ... | ... | @@ -6543,7 +6589,7 @@ fn genBinOp( |
| 6543 | 6589 | Memory.sib(Memory.PtrSize.fromSize(cmov_abi_size), switch (mat_src_mcv) { |
| 6544 | 6590 | .memory => |addr| .{ |
| 6545 | 6591 | .base = .{ .reg = .ds }, |
| 6546 | | .disp = @as(i32, @intCast(@as(i64, @bitCast(addr)))), |
| 6592 | .disp = @intCast(@as(i64, @bitCast(addr))), |
| 6547 | 6593 | }, |
| 6548 | 6594 | .indirect => |reg_off| .{ |
| 6549 | 6595 | .base = .{ .reg = reg_off.reg }, |
| ... | ... | @@ -6569,7 +6615,7 @@ fn genBinOp( |
| 6569 | 6615 | } |
| 6570 | 6616 | |
| 6571 | 6617 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 6572 | | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 6618 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 6573 | 6619 | else => unreachable, |
| 6574 | 6620 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 6575 | 6621 | 16 => if (self.hasFeature(.f16c)) { |
| ... | ... | @@ -7131,7 +7177,7 @@ fn genBinOp( |
| 7131 | 7177 | else => unreachable, |
| 7132 | 7178 | }, |
| 7133 | 7179 | }, |
| 7134 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7180 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7135 | 7181 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7136 | 7182 | }); |
| 7137 | 7183 | |
| ... | ... | @@ -7194,7 +7240,7 @@ fn genBinOp( |
| 7194 | 7240 | const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size); |
| 7195 | 7241 | |
| 7196 | 7242 | try self.asmRegisterRegisterRegisterImmediate( |
| 7197 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7243 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7198 | 7244 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7199 | 7245 | 32 => .{ .v_ss, .cmp }, |
| 7200 | 7246 | 64 => .{ .v_sd, .cmp }, |
| ... | ... | @@ -7219,7 +7265,7 @@ fn genBinOp( |
| 7219 | 7265 | else => unreachable, |
| 7220 | 7266 | }, |
| 7221 | 7267 | else => unreachable, |
| 7222 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7268 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7223 | 7269 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7224 | 7270 | }), |
| 7225 | 7271 | mask_reg, |
| ... | ... | @@ -7228,7 +7274,7 @@ fn genBinOp( |
| 7228 | 7274 | Immediate.u(3), // unord |
| 7229 | 7275 | ); |
| 7230 | 7276 | try self.asmRegisterRegisterRegisterRegister( |
| 7231 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7277 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7232 | 7278 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7233 | 7279 | 32 => .{ .v_ps, .blendv }, |
| 7234 | 7280 | 64 => .{ .v_pd, .blendv }, |
| ... | ... | @@ -7251,7 +7297,7 @@ fn genBinOp( |
| 7251 | 7297 | else => unreachable, |
| 7252 | 7298 | }, |
| 7253 | 7299 | else => unreachable, |
| 7254 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7300 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7255 | 7301 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7256 | 7302 | }), |
| 7257 | 7303 | dst_reg, |
| ... | ... | @@ -7262,7 +7308,7 @@ fn genBinOp( |
| 7262 | 7308 | } else { |
| 7263 | 7309 | const has_blend = self.hasFeature(.sse4_1); |
| 7264 | 7310 | try self.asmRegisterRegisterImmediate( |
| 7265 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7311 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7266 | 7312 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7267 | 7313 | 32 => .{ ._ss, .cmp }, |
| 7268 | 7314 | 64 => .{ ._sd, .cmp }, |
| ... | ... | @@ -7287,7 +7333,7 @@ fn genBinOp( |
| 7287 | 7333 | else => unreachable, |
| 7288 | 7334 | }, |
| 7289 | 7335 | else => unreachable, |
| 7290 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7336 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7291 | 7337 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7292 | 7338 | }), |
| 7293 | 7339 | mask_reg, |
| ... | ... | @@ -7295,7 +7341,7 @@ fn genBinOp( |
| 7295 | 7341 | Immediate.u(if (has_blend) 3 else 7), // unord, ord |
| 7296 | 7342 | ); |
| 7297 | 7343 | if (has_blend) try self.asmRegisterRegisterRegister( |
| 7298 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7344 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7299 | 7345 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7300 | 7346 | 32 => .{ ._ps, .blendv }, |
| 7301 | 7347 | 64 => .{ ._pd, .blendv }, |
| ... | ... | @@ -7318,7 +7364,7 @@ fn genBinOp( |
| 7318 | 7364 | else => unreachable, |
| 7319 | 7365 | }, |
| 7320 | 7366 | else => unreachable, |
| 7321 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7367 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7322 | 7368 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7323 | 7369 | }), |
| 7324 | 7370 | dst_reg, |
| ... | ... | @@ -7326,7 +7372,7 @@ fn genBinOp( |
| 7326 | 7372 | mask_reg, |
| 7327 | 7373 | ) else { |
| 7328 | 7374 | try self.asmRegisterRegister( |
| 7329 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7375 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7330 | 7376 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7331 | 7377 | 32 => .{ ._ps, .@"and" }, |
| 7332 | 7378 | 64 => .{ ._pd, .@"and" }, |
| ... | ... | @@ -7349,14 +7395,14 @@ fn genBinOp( |
| 7349 | 7395 | else => unreachable, |
| 7350 | 7396 | }, |
| 7351 | 7397 | else => unreachable, |
| 7352 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7398 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7353 | 7399 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7354 | 7400 | }), |
| 7355 | 7401 | dst_reg, |
| 7356 | 7402 | mask_reg, |
| 7357 | 7403 | ); |
| 7358 | 7404 | try self.asmRegisterRegister( |
| 7359 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7405 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7360 | 7406 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7361 | 7407 | 32 => .{ ._ps, .andn }, |
| 7362 | 7408 | 64 => .{ ._pd, .andn }, |
| ... | ... | @@ -7379,14 +7425,14 @@ fn genBinOp( |
| 7379 | 7425 | else => unreachable, |
| 7380 | 7426 | }, |
| 7381 | 7427 | else => unreachable, |
| 7382 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7428 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7383 | 7429 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7384 | 7430 | }), |
| 7385 | 7431 | mask_reg, |
| 7386 | 7432 | lhs_copy_reg.?, |
| 7387 | 7433 | ); |
| 7388 | 7434 | try self.asmRegisterRegister( |
| 7389 | | if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7435 | @as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) { |
| 7390 | 7436 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 7391 | 7437 | 32 => .{ ._ps, .@"or" }, |
| 7392 | 7438 | 64 => .{ ._pd, .@"or" }, |
| ... | ... | @@ -7409,7 +7455,7 @@ fn genBinOp( |
| 7409 | 7455 | else => unreachable, |
| 7410 | 7456 | }, |
| 7411 | 7457 | else => unreachable, |
| 7412 | | })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7458 | }) orelse return self.fail("TODO implement genBinOp for {s} {}", .{ |
| 7413 | 7459 | @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?), |
| 7414 | 7460 | }), |
| 7415 | 7461 | dst_reg, |
| ... | ... | @@ -7431,7 +7477,7 @@ fn genBinOpMir( |
| 7431 | 7477 | src_mcv: MCValue, |
| 7432 | 7478 | ) !void { |
| 7433 | 7479 | const mod = self.bin_file.options.module.?; |
| 7434 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 7480 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 7435 | 7481 | switch (dst_mcv) { |
| 7436 | 7482 | .none, |
| 7437 | 7483 | .unreach, |
| ... | ... | @@ -7679,10 +7725,10 @@ fn genBinOpMir( |
| 7679 | 7725 | else => unreachable, |
| 7680 | 7726 | }, |
| 7681 | 7727 | .immediate => |src_imm| { |
| 7682 | | const imm = switch (off) { |
| 7728 | const imm: u64 = switch (off) { |
| 7683 | 7729 | 0 => src_imm, |
| 7684 | 7730 | else => switch (ty_signedness) { |
| 7685 | | .signed => @as(u64, @bitCast(@as(i64, @bitCast(src_imm)) >> 63)), |
| 7731 | .signed => @bitCast(@as(i64, @bitCast(src_imm)) >> 63), |
| 7686 | 7732 | .unsigned => 0, |
| 7687 | 7733 | }, |
| 7688 | 7734 | }; |
| ... | ... | @@ -7755,7 +7801,7 @@ fn genBinOpMir( |
| 7755 | 7801 | 0 => src_mcv, |
| 7756 | 7802 | else => .{ .immediate = 0 }, |
| 7757 | 7803 | }, |
| 7758 | | .memory => |addr| .{ .memory = @as(u64, @bitCast(@as(i64, @bitCast(addr)) + off)) }, |
| 7804 | .memory => |addr| .{ .memory = @bitCast(@as(i64, @bitCast(addr)) + off) }, |
| 7759 | 7805 | .indirect => |reg_off| .{ .indirect = .{ |
| 7760 | 7806 | .reg = reg_off.reg, |
| 7761 | 7807 | .off = reg_off.off + off, |
| ... | ... | @@ -7782,7 +7828,7 @@ fn genBinOpMir( |
| 7782 | 7828 | /// Does not support byte-size operands. |
| 7783 | 7829 | fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 7784 | 7830 | const mod = self.bin_file.options.module.?; |
| 7785 | | const abi_size = @as(u32, @intCast(dst_ty.abiSize(mod))); |
| 7831 | const abi_size: u32 = @intCast(dst_ty.abiSize(mod)); |
| 7786 | 7832 | switch (dst_mcv) { |
| 7787 | 7833 | .none, |
| 7788 | 7834 | .unreach, |
| ... | ... | @@ -8016,7 +8062,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8016 | 8062 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 8017 | 8063 | const callee = pl_op.operand; |
| 8018 | 8064 | const extra = self.air.extraData(Air.Call, pl_op.payload); |
| 8019 | | const args = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len])); |
| 8065 | const args: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra.end..][0..extra.data.args_len]); |
| 8020 | 8066 | const ty = self.typeOf(callee); |
| 8021 | 8067 | |
| 8022 | 8068 | const fn_ty = switch (ty.zigTypeTag(mod)) { |
| ... | ... | @@ -8109,7 +8155,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8109 | 8155 | const got_addr = atom.getOffsetTableAddress(elf_file); |
| 8110 | 8156 | try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{ |
| 8111 | 8157 | .base = .{ .reg = .ds }, |
| 8112 | | .disp = @as(i32, @intCast(got_addr)), |
| 8158 | .disp = @intCast(got_addr), |
| 8113 | 8159 | })); |
| 8114 | 8160 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { |
| 8115 | 8161 | const atom = try coff_file.getOrCreateAtomForDecl(owner_decl); |
| ... | ... | @@ -8126,7 +8172,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 8126 | 8172 | const atom = p9.getAtom(atom_index); |
| 8127 | 8173 | try self.asmMemory(.{ ._, .call }, Memory.sib(.qword, .{ |
| 8128 | 8174 | .base = .{ .reg = .ds }, |
| 8129 | | .disp = @as(i32, @intCast(atom.getOffsetTableAddress(p9))), |
| 8175 | .disp = @intCast(atom.getOffsetTableAddress(p9)), |
| 8130 | 8176 | })); |
| 8131 | 8177 | } else unreachable; |
| 8132 | 8178 | } else if (func_value.getExternFunc(mod)) |extern_func| { |
| ... | ... | @@ -8246,7 +8292,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8246 | 8292 | const result = MCValue{ |
| 8247 | 8293 | .eflags = switch (ty.zigTypeTag(mod)) { |
| 8248 | 8294 | else => result: { |
| 8249 | | const abi_size = @as(u16, @intCast(ty.abiSize(mod))); |
| 8295 | const abi_size: u16 = @intCast(ty.abiSize(mod)); |
| 8250 | 8296 | const may_flip: enum { |
| 8251 | 8297 | may_flip, |
| 8252 | 8298 | must_flip, |
| ... | ... | @@ -8443,7 +8489,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 8443 | 8489 | self.eflags_inst = inst; |
| 8444 | 8490 | |
| 8445 | 8491 | const op_ty = self.typeOf(un_op); |
| 8446 | | const op_abi_size = @as(u32, @intCast(op_ty.abiSize(mod))); |
| 8492 | const op_abi_size: u32 = @intCast(op_ty.abiSize(mod)); |
| 8447 | 8493 | const op_mcv = try self.resolveInst(un_op); |
| 8448 | 8494 | const dst_reg = switch (op_mcv) { |
| 8449 | 8495 | .register => |reg| reg, |
| ... | ... | @@ -8652,7 +8698,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8652 | 8698 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) |
| 8653 | 8699 | .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty } |
| 8654 | 8700 | else |
| 8655 | | .{ .off = @as(i32, @intCast(pl_ty.abiSize(mod))), .ty = Type.bool }; |
| 8701 | .{ .off = @intCast(pl_ty.abiSize(mod)), .ty = Type.bool }; |
| 8656 | 8702 | |
| 8657 | 8703 | switch (opt_mcv) { |
| 8658 | 8704 | .none, |
| ... | ... | @@ -8672,14 +8718,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8672 | 8718 | |
| 8673 | 8719 | .register => |opt_reg| { |
| 8674 | 8720 | if (some_info.off == 0) { |
| 8675 | | const some_abi_size = @as(u32, @intCast(some_info.ty.abiSize(mod))); |
| 8721 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod)); |
| 8676 | 8722 | const alias_reg = registerAlias(opt_reg, some_abi_size); |
| 8677 | 8723 | assert(some_abi_size * 8 == alias_reg.bitSize()); |
| 8678 | 8724 | try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg); |
| 8679 | 8725 | return .{ .eflags = .z }; |
| 8680 | 8726 | } |
| 8681 | 8727 | assert(some_info.ty.ip_index == .bool_type); |
| 8682 | | const opt_abi_size = @as(u32, @intCast(opt_ty.abiSize(mod))); |
| 8728 | const opt_abi_size: u32 = @intCast(opt_ty.abiSize(mod)); |
| 8683 | 8729 | try self.asmRegisterImmediate( |
| 8684 | 8730 | .{ ._, .bt }, |
| 8685 | 8731 | registerAlias(opt_reg, opt_abi_size), |
| ... | ... | @@ -8698,7 +8744,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8698 | 8744 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 8699 | 8745 | |
| 8700 | 8746 | try self.genSetReg(addr_reg, Type.usize, opt_mcv.address()); |
| 8701 | | const some_abi_size = @as(u32, @intCast(some_info.ty.abiSize(mod))); |
| 8747 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod)); |
| 8702 | 8748 | try self.asmMemoryImmediate( |
| 8703 | 8749 | .{ ._, .cmp }, |
| 8704 | 8750 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ |
| ... | ... | @@ -8711,7 +8757,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 8711 | 8757 | }, |
| 8712 | 8758 | |
| 8713 | 8759 | .indirect, .load_frame => { |
| 8714 | | const some_abi_size = @as(u32, @intCast(some_info.ty.abiSize(mod))); |
| 8760 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod)); |
| 8715 | 8761 | try self.asmMemoryImmediate( |
| 8716 | 8762 | .{ ._, .cmp }, |
| 8717 | 8763 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) { |
| ... | ... | @@ -8743,7 +8789,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 8743 | 8789 | const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) |
| 8744 | 8790 | .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty } |
| 8745 | 8791 | else |
| 8746 | | .{ .off = @as(i32, @intCast(pl_ty.abiSize(mod))), .ty = Type.bool }; |
| 8792 | .{ .off = @intCast(pl_ty.abiSize(mod)), .ty = Type.bool }; |
| 8747 | 8793 | |
| 8748 | 8794 | const ptr_reg = switch (ptr_mcv) { |
| 8749 | 8795 | .register => |reg| reg, |
| ... | ... | @@ -8752,7 +8798,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) |
| 8752 | 8798 | const ptr_lock = self.register_manager.lockReg(ptr_reg); |
| 8753 | 8799 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 8754 | 8800 | |
| 8755 | | const some_abi_size = @as(u32, @intCast(some_info.ty.abiSize(mod))); |
| 8801 | const some_abi_size: u32 = @intCast(some_info.ty.abiSize(mod)); |
| 8756 | 8802 | try self.asmMemoryImmediate( |
| 8757 | 8803 | .{ ._, .cmp }, |
| 8758 | 8804 | Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{ |
| ... | ... | @@ -8785,12 +8831,11 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) ! |
| 8785 | 8831 | |
| 8786 | 8832 | const tmp_reg = try self.copyToTmpRegister(ty, operand); |
| 8787 | 8833 | if (err_off > 0) { |
| 8788 | | const shift = @as(u6, @intCast(err_off * 8)); |
| 8789 | 8834 | try self.genShiftBinOpMir( |
| 8790 | 8835 | .{ ._r, .sh }, |
| 8791 | 8836 | ty, |
| 8792 | 8837 | .{ .register = tmp_reg }, |
| 8793 | | .{ .immediate = shift }, |
| 8838 | .{ .immediate = @as(u6, @intCast(err_off * 8)) }, |
| 8794 | 8839 | ); |
| 8795 | 8840 | } else { |
| 8796 | 8841 | try self.truncateRegister(Type.anyerror, tmp_reg); |
| ... | ... | @@ -8945,7 +8990,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 8945 | 8990 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 8946 | 8991 | const loop = self.air.extraData(Air.Block, ty_pl.payload); |
| 8947 | 8992 | const body = self.air.extra[loop.end..][0..loop.data.body_len]; |
| 8948 | | const jmp_target = @as(u32, @intCast(self.mir_instructions.len)); |
| 8993 | const jmp_target: u32 = @intCast(self.mir_instructions.len); |
| 8949 | 8994 | |
| 8950 | 8995 | self.scope_generation += 1; |
| 8951 | 8996 | const state = try self.saveState(); |
| ... | ... | @@ -9017,10 +9062,8 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 9017 | 9062 | |
| 9018 | 9063 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| 9019 | 9064 | const case = self.air.extraData(Air.SwitchBr.Case, extra_index); |
| 9020 | | const items = @as( |
| 9021 | | []const Air.Inst.Ref, |
| 9022 | | @ptrCast(self.air.extra[case.end..][0..case.data.items_len]), |
| 9023 | | ); |
| 9065 | const items: []const Air.Inst.Ref = |
| 9066 | @ptrCast(self.air.extra[case.end..][0..case.data.items_len]); |
| 9024 | 9067 | const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len]; |
| 9025 | 9068 | extra_index = case.end + items.len + case_body.len; |
| 9026 | 9069 | |
| ... | ... | @@ -9068,7 +9111,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 9068 | 9111 | } |
| 9069 | 9112 | |
| 9070 | 9113 | fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 9071 | | const next_inst = @as(u32, @intCast(self.mir_instructions.len)); |
| 9114 | const next_inst: u32 = @intCast(self.mir_instructions.len); |
| 9072 | 9115 | switch (self.mir_instructions.items(.tag)[reloc]) { |
| 9073 | 9116 | .j, .jmp => {}, |
| 9074 | 9117 | .pseudo => switch (self.mir_instructions.items(.ops)[reloc]) { |
| ... | ... | @@ -9143,11 +9186,12 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 9143 | 9186 | fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9144 | 9187 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 9145 | 9188 | const extra = self.air.extraData(Air.Asm, ty_pl.payload); |
| 9146 | | const clobbers_len = @as(u31, @truncate(extra.data.flags)); |
| 9189 | const clobbers_len: u31 = @truncate(extra.data.flags); |
| 9147 | 9190 | var extra_i: usize = extra.end; |
| 9148 | | const outputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len])); |
| 9191 | const outputs: []const Air.Inst.Ref = |
| 9192 | @ptrCast(self.air.extra[extra_i..][0..extra.data.outputs_len]); |
| 9149 | 9193 | extra_i += outputs.len; |
| 9150 | | const inputs = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len])); |
| 9194 | const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra[extra_i..][0..extra.data.inputs_len]); |
| 9151 | 9195 | extra_i += inputs.len; |
| 9152 | 9196 | |
| 9153 | 9197 | var result: MCValue = .none; |
| ... | ... | @@ -9282,16 +9326,14 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9282 | 9326 | } else if (mem.startsWith(u8, op_str, "$")) { |
| 9283 | 9327 | if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| { |
| 9284 | 9328 | if (mnem_size) |size| { |
| 9285 | | const max = @as(u64, math.maxInt(u64)) >> |
| 9286 | | @as(u6, @intCast(64 - (size.bitSize() - 1))); |
| 9329 | const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1)); |
| 9287 | 9330 | if ((if (s < 0) ~s else s) > max) |
| 9288 | 9331 | return self.fail("Invalid immediate size: '{s}'", .{op_str}); |
| 9289 | 9332 | } |
| 9290 | 9333 | op.* = .{ .imm = Immediate.s(s) }; |
| 9291 | 9334 | } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| { |
| 9292 | 9335 | if (mnem_size) |size| { |
| 9293 | | const max = @as(u64, math.maxInt(u64)) >> |
| 9294 | | @as(u6, @intCast(64 - size.bitSize())); |
| 9336 | const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize()); |
| 9295 | 9337 | if (u > max) |
| 9296 | 9338 | return self.fail("Invalid immediate size: '{s}'", .{op_str}); |
| 9297 | 9339 | } |
| ... | ... | @@ -9643,7 +9685,7 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError |
| 9643 | 9685 | |
| 9644 | 9686 | fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void { |
| 9645 | 9687 | const mod = self.bin_file.options.module.?; |
| 9646 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 9688 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 9647 | 9689 | if (abi_size * 8 > dst_reg.bitSize()) |
| 9648 | 9690 | return self.fail("genSetReg called with a value larger than dst_reg", .{}); |
| 9649 | 9691 | switch (src_mcv) { |
| ... | ... | @@ -9668,7 +9710,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9668 | 9710 | try self.asmRegisterImmediate( |
| 9669 | 9711 | .{ ._, .mov }, |
| 9670 | 9712 | registerAlias(dst_reg, abi_size), |
| 9671 | | Immediate.s(@as(i32, @intCast(@as(i64, @bitCast(imm))))), |
| 9713 | Immediate.s(@intCast(@as(i64, @bitCast(imm)))), |
| 9672 | 9714 | ); |
| 9673 | 9715 | } else { |
| 9674 | 9716 | try self.asmRegisterImmediate( |
| ... | ... | @@ -9726,7 +9768,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9726 | 9768 | .{ .register = try self.copyToTmpRegister(ty, src_mcv) }, |
| 9727 | 9769 | ), |
| 9728 | 9770 | .sse => try self.asmRegisterRegister( |
| 9729 | | if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 9771 | @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) { |
| 9730 | 9772 | else => switch (abi_size) { |
| 9731 | 9773 | 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov }, |
| 9732 | 9774 | 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov }, |
| ... | ... | @@ -9750,7 +9792,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9750 | 9792 | 80 => null, |
| 9751 | 9793 | else => unreachable, |
| 9752 | 9794 | }, |
| 9753 | | })) |tag| tag else return self.fail("TODO implement genSetReg for {}", .{ |
| 9795 | }) orelse return self.fail("TODO implement genSetReg for {}", .{ |
| 9754 | 9796 | ty.fmt(self.bin_file.options.module.?), |
| 9755 | 9797 | }), |
| 9756 | 9798 | registerAlias(dst_reg, abi_size), |
| ... | ... | @@ -9930,9 +9972,9 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 9930 | 9972 | |
| 9931 | 9973 | fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void { |
| 9932 | 9974 | const mod = self.bin_file.options.module.?; |
| 9933 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 9975 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 9934 | 9976 | const dst_ptr_mcv: MCValue = switch (base) { |
| 9935 | | .none => .{ .immediate = @as(u64, @bitCast(@as(i64, disp))) }, |
| 9977 | .none => .{ .immediate = @bitCast(@as(i64, disp)) }, |
| 9936 | 9978 | .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } }, |
| 9937 | 9979 | .frame => |base_frame_index| .{ .lea_frame = .{ .index = base_frame_index, .off = disp } }, |
| 9938 | 9980 | }; |
| ... | ... | @@ -9943,7 +9985,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 9943 | 9985 | .immediate => |imm| switch (abi_size) { |
| 9944 | 9986 | 1, 2, 4 => { |
| 9945 | 9987 | const immediate = if (ty.isSignedInt(mod)) |
| 9946 | | Immediate.s(@as(i32, @truncate(@as(i64, @bitCast(imm))))) |
| 9988 | Immediate.s(@truncate(@as(i64, @bitCast(imm)))) |
| 9947 | 9989 | else |
| 9948 | 9990 | Immediate.u(@as(u32, @intCast(imm))); |
| 9949 | 9991 | try self.asmMemoryImmediate( |
| ... | ... | @@ -9965,10 +10007,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal |
| 9965 | 10007 | .{ ._, .mov }, |
| 9966 | 10008 | Memory.sib(.dword, .{ .base = base, .disp = disp + offset }), |
| 9967 | 10009 | if (ty.isSignedInt(mod)) |
| 9968 | | Immediate.s(@as( |
| 9969 | | i32, |
| 10010 | Immediate.s( |
| 9970 | 10011 | @truncate(@as(i64, @bitCast(imm)) >> (math.cast(u6, offset * 8) orelse 63)), |
| 9971 | | )) |
| 10012 | ) |
| 9972 | 10013 | else |
| 9973 | 10014 | Immediate.u(@as( |
| 9974 | 10015 | u32, |
| ... | ... | @@ -10079,7 +10120,7 @@ fn genLazySymbolRef( |
| 10079 | 10120 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); |
| 10080 | 10121 | const got_addr = atom.getOffsetTableAddress(elf_file); |
| 10081 | 10122 | const got_mem = |
| 10082 | | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @as(i32, @intCast(got_addr)) }); |
| 10123 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(got_addr) }); |
| 10083 | 10124 | switch (tag) { |
| 10084 | 10125 | .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem), |
| 10085 | 10126 | .call => try self.asmMemory(.{ ._, .call }, got_mem), |
| ... | ... | @@ -10101,7 +10142,7 @@ fn genLazySymbolRef( |
| 10101 | 10142 | _ = atom.getOrCreateOffsetTableEntry(p9_file); |
| 10102 | 10143 | const got_addr = atom.getOffsetTableAddress(p9_file); |
| 10103 | 10144 | const got_mem = |
| 10104 | | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @as(i32, @intCast(got_addr)) }); |
| 10145 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(got_addr) }); |
| 10105 | 10146 | switch (tag) { |
| 10106 | 10147 | .lea, .mov => try self.asmRegisterMemory(.{ ._, .mov }, reg.to64(), got_mem), |
| 10107 | 10148 | .call => try self.asmMemory(.{ ._, .call }, got_mem), |
| ... | ... | @@ -10197,8 +10238,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10197 | 10238 | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; |
| 10198 | 10239 | if (dst_signedness == src_signedness) break :result dst_mcv; |
| 10199 | 10240 | |
| 10200 | | const abi_size = @as(u16, @intCast(dst_ty.abiSize(mod))); |
| 10201 | | const bit_size = @as(u16, @intCast(dst_ty.bitSize(mod))); |
| 10241 | const abi_size: u16 = @intCast(dst_ty.abiSize(mod)); |
| 10242 | const bit_size: u16 = @intCast(dst_ty.bitSize(mod)); |
| 10202 | 10243 | if (abi_size * 8 <= bit_size) break :result dst_mcv; |
| 10203 | 10244 | |
| 10204 | 10245 | const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable; |
| ... | ... | @@ -10239,7 +10280,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 10239 | 10280 | try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr); |
| 10240 | 10281 | try self.genSetMem( |
| 10241 | 10282 | .{ .frame = frame_index }, |
| 10242 | | @as(i32, @intCast(ptr_ty.abiSize(mod))), |
| 10283 | @intCast(ptr_ty.abiSize(mod)), |
| 10243 | 10284 | Type.usize, |
| 10244 | 10285 | .{ .immediate = array_len }, |
| 10245 | 10286 | ); |
| ... | ... | @@ -10253,7 +10294,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10253 | 10294 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 10254 | 10295 | |
| 10255 | 10296 | const src_ty = self.typeOf(ty_op.operand); |
| 10256 | | const src_bits = @as(u32, @intCast(src_ty.bitSize(mod))); |
| 10297 | const src_bits: u32 = @intCast(src_ty.bitSize(mod)); |
| 10257 | 10298 | const src_signedness = |
| 10258 | 10299 | if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned; |
| 10259 | 10300 | const dst_ty = self.typeOfIndex(inst); |
| ... | ... | @@ -10281,7 +10322,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10281 | 10322 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 10282 | 10323 | defer self.register_manager.unlockReg(dst_lock); |
| 10283 | 10324 | |
| 10284 | | const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) { |
| 10325 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) { |
| 10285 | 10326 | .Float => switch (dst_ty.floatBits(self.target.*)) { |
| 10286 | 10327 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 }, |
| 10287 | 10328 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 }, |
| ... | ... | @@ -10289,7 +10330,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 10289 | 10330 | else => unreachable, |
| 10290 | 10331 | }, |
| 10291 | 10332 | else => null, |
| 10292 | | })) |tag| tag else return self.fail("TODO implement airFloatFromInt from {} to {}", .{ |
| 10333 | }) orelse return self.fail("TODO implement airFloatFromInt from {} to {}", .{ |
| 10293 | 10334 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 10294 | 10335 | }); |
| 10295 | 10336 | const dst_alias = dst_reg.to128(); |
| ... | ... | @@ -10308,7 +10349,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10308 | 10349 | |
| 10309 | 10350 | const src_ty = self.typeOf(ty_op.operand); |
| 10310 | 10351 | const dst_ty = self.typeOfIndex(inst); |
| 10311 | | const dst_bits = @as(u32, @intCast(dst_ty.bitSize(mod))); |
| 10352 | const dst_bits: u32 = @intCast(dst_ty.bitSize(mod)); |
| 10312 | 10353 | const dst_signedness = |
| 10313 | 10354 | if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned; |
| 10314 | 10355 | |
| ... | ... | @@ -10334,7 +10375,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10334 | 10375 | defer self.register_manager.unlockReg(dst_lock); |
| 10335 | 10376 | |
| 10336 | 10377 | try self.asmRegisterRegister( |
| 10337 | | if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) { |
| 10378 | @as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) { |
| 10338 | 10379 | .Float => switch (src_ty.floatBits(self.target.*)) { |
| 10339 | 10380 | 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si }, |
| 10340 | 10381 | 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si }, |
| ... | ... | @@ -10342,7 +10383,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 10342 | 10383 | else => unreachable, |
| 10343 | 10384 | }, |
| 10344 | 10385 | else => null, |
| 10345 | | })) |tag| tag else return self.fail("TODO implement airIntFromFloat from {} to {}", .{ |
| 10386 | }) orelse return self.fail("TODO implement airIntFromFloat from {} to {}", .{ |
| 10346 | 10387 | src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?), |
| 10347 | 10388 | }), |
| 10348 | 10389 | registerAlias(dst_reg, dst_size), |
| ... | ... | @@ -10361,7 +10402,7 @@ fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| 10361 | 10402 | |
| 10362 | 10403 | const ptr_ty = self.typeOf(extra.ptr); |
| 10363 | 10404 | const val_ty = self.typeOf(extra.expected_value); |
| 10364 | | const val_abi_size = @as(u32, @intCast(val_ty.abiSize(mod))); |
| 10405 | const val_abi_size: u32 = @intCast(val_ty.abiSize(mod)); |
| 10365 | 10406 | |
| 10366 | 10407 | try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx }); |
| 10367 | 10408 | const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx }); |
| ... | ... | @@ -10463,7 +10504,7 @@ fn atomicOp( |
| 10463 | 10504 | }; |
| 10464 | 10505 | defer if (val_lock) |lock| self.register_manager.unlockReg(lock); |
| 10465 | 10506 | |
| 10466 | | const val_abi_size = @as(u32, @intCast(val_ty.abiSize(mod))); |
| 10507 | const val_abi_size: u32 = @intCast(val_ty.abiSize(mod)); |
| 10467 | 10508 | const ptr_size = Memory.PtrSize.fromSize(val_abi_size); |
| 10468 | 10509 | const ptr_mem = switch (ptr_mcv) { |
| 10469 | 10510 | .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size), |
| ... | ... | @@ -10541,7 +10582,7 @@ fn atomicOp( |
| 10541 | 10582 | defer self.register_manager.unlockReg(tmp_lock); |
| 10542 | 10583 | |
| 10543 | 10584 | try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem); |
| 10544 | | const loop = @as(u32, @intCast(self.mir_instructions.len)); |
| 10585 | const loop: u32 = @intCast(self.mir_instructions.len); |
| 10545 | 10586 | if (rmw_op != std.builtin.AtomicRmwOp.Xchg) { |
| 10546 | 10587 | try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax }); |
| 10547 | 10588 | } |
| ... | ... | @@ -10615,7 +10656,7 @@ fn atomicOp( |
| 10615 | 10656 | .scale_index = ptr_mem.scaleIndex(), |
| 10616 | 10657 | .disp = ptr_mem.sib.disp + 8, |
| 10617 | 10658 | })); |
| 10618 | | const loop = @as(u32, @intCast(self.mir_instructions.len)); |
| 10659 | const loop: u32 = @intCast(self.mir_instructions.len); |
| 10619 | 10660 | const val_mem_mcv: MCValue = switch (val_mcv) { |
| 10620 | 10661 | .memory, .indirect, .load_frame => val_mcv, |
| 10621 | 10662 | else => .{ .indirect = .{ |
| ... | ... | @@ -10771,7 +10812,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 10771 | 10812 | }; |
| 10772 | 10813 | defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock); |
| 10773 | 10814 | |
| 10774 | | const elem_abi_size = @as(u31, @intCast(elem_ty.abiSize(mod))); |
| 10815 | const elem_abi_size: u31 = @intCast(elem_ty.abiSize(mod)); |
| 10775 | 10816 | |
| 10776 | 10817 | if (elem_abi_size == 1) { |
| 10777 | 10818 | const ptr: MCValue = switch (dst_ptr_ty.ptrSize(mod)) { |
| ... | ... | @@ -11251,9 +11292,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 11251 | 11292 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11252 | 11293 | const mod = self.bin_file.options.module.?; |
| 11253 | 11294 | const result_ty = self.typeOfIndex(inst); |
| 11254 | | const len = @as(usize, @intCast(result_ty.arrayLen(mod))); |
| 11295 | const len: usize = @intCast(result_ty.arrayLen(mod)); |
| 11255 | 11296 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 11256 | | const elements = @as([]const Air.Inst.Ref, @ptrCast(self.air.extra[ty_pl.payload..][0..len])); |
| 11297 | const elements: []const Air.Inst.Ref = @ptrCast(self.air.extra[ty_pl.payload..][0..len]); |
| 11257 | 11298 | const result: MCValue = result: { |
| 11258 | 11299 | switch (result_ty.zigTypeTag(mod)) { |
| 11259 | 11300 | .Struct => { |
| ... | ... | @@ -11270,17 +11311,17 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11270 | 11311 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; |
| 11271 | 11312 | |
| 11272 | 11313 | const elem_ty = result_ty.structFieldType(elem_i, mod); |
| 11273 | | const elem_bit_size = @as(u32, @intCast(elem_ty.bitSize(mod))); |
| 11314 | const elem_bit_size: u32 = @intCast(elem_ty.bitSize(mod)); |
| 11274 | 11315 | if (elem_bit_size > 64) { |
| 11275 | 11316 | return self.fail( |
| 11276 | 11317 | "TODO airAggregateInit implement packed structs with large fields", |
| 11277 | 11318 | .{}, |
| 11278 | 11319 | ); |
| 11279 | 11320 | } |
| 11280 | | const elem_abi_size = @as(u32, @intCast(elem_ty.abiSize(mod))); |
| 11321 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 11281 | 11322 | const elem_abi_bits = elem_abi_size * 8; |
| 11282 | 11323 | const elem_off = struct_obj.packedFieldBitOffset(mod, elem_i); |
| 11283 | | const elem_byte_off = @as(i32, @intCast(elem_off / elem_abi_bits * elem_abi_size)); |
| 11324 | const elem_byte_off: i32 = @intCast(elem_off / elem_abi_bits * elem_abi_size); |
| 11284 | 11325 | const elem_bit_off = elem_off % elem_abi_bits; |
| 11285 | 11326 | const elem_mcv = try self.resolveInst(elem); |
| 11286 | 11327 | const mat_elem_mcv = switch (elem_mcv) { |
| ... | ... | @@ -11342,7 +11383,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11342 | 11383 | if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue; |
| 11343 | 11384 | |
| 11344 | 11385 | const elem_ty = result_ty.structFieldType(elem_i, mod); |
| 11345 | | const elem_off = @as(i32, @intCast(result_ty.structFieldOffset(elem_i, mod))); |
| 11386 | const elem_off: i32 = @intCast(result_ty.structFieldOffset(elem_i, mod)); |
| 11346 | 11387 | const elem_mcv = try self.resolveInst(elem); |
| 11347 | 11388 | const mat_elem_mcv = switch (elem_mcv) { |
| 11348 | 11389 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| ... | ... | @@ -11356,7 +11397,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11356 | 11397 | const frame_index = |
| 11357 | 11398 | try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod)); |
| 11358 | 11399 | const elem_ty = result_ty.childType(mod); |
| 11359 | | const elem_size = @as(u32, @intCast(elem_ty.abiSize(mod))); |
| 11400 | const elem_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 11360 | 11401 | |
| 11361 | 11402 | for (elements, 0..) |elem, elem_i| { |
| 11362 | 11403 | const elem_mcv = try self.resolveInst(elem); |
| ... | ... | @@ -11364,12 +11405,12 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11364 | 11405 | .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index }, |
| 11365 | 11406 | else => elem_mcv, |
| 11366 | 11407 | }; |
| 11367 | | const elem_off = @as(i32, @intCast(elem_size * elem_i)); |
| 11408 | const elem_off: i32 = @intCast(elem_size * elem_i); |
| 11368 | 11409 | try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv); |
| 11369 | 11410 | } |
| 11370 | 11411 | if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem( |
| 11371 | 11412 | .{ .frame = frame_index }, |
| 11372 | | @as(i32, @intCast(elem_size * elements.len)), |
| 11413 | @intCast(elem_size * elements.len), |
| 11373 | 11414 | elem_ty, |
| 11374 | 11415 | try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), |
| 11375 | 11416 | ); |
| ... | ... | @@ -11417,16 +11458,16 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void { |
| 11417 | 11458 | const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); |
| 11418 | 11459 | const tag_int_val = try tag_val.intFromEnum(tag_ty, mod); |
| 11419 | 11460 | const tag_int = tag_int_val.toUnsignedInt(mod); |
| 11420 | | const tag_off = if (layout.tag_align < layout.payload_align) |
| 11421 | | @as(i32, @intCast(layout.payload_size)) |
| 11461 | const tag_off: i32 = if (layout.tag_align < layout.payload_align) |
| 11462 | @intCast(layout.payload_size) |
| 11422 | 11463 | else |
| 11423 | 11464 | 0; |
| 11424 | 11465 | try self.genCopy(tag_ty, dst_mcv.address().offset(tag_off).deref(), .{ .immediate = tag_int }); |
| 11425 | 11466 | |
| 11426 | | const pl_off = if (layout.tag_align < layout.payload_align) |
| 11467 | const pl_off: i32 = if (layout.tag_align < layout.payload_align) |
| 11427 | 11468 | 0 |
| 11428 | 11469 | else |
| 11429 | | @as(i32, @intCast(layout.tag_size)); |
| 11470 | @intCast(layout.tag_size); |
| 11430 | 11471 | try self.genCopy(src_ty, dst_mcv.address().offset(pl_off).deref(), src_mcv); |
| 11431 | 11472 | |
| 11432 | 11473 | break :result dst_mcv; |
| ... | ... | @@ -11456,7 +11497,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11456 | 11497 | var order = [1]u2{0} ** 3; |
| 11457 | 11498 | var unused = std.StaticBitSet(3).initFull(); |
| 11458 | 11499 | for (ops, &mcvs, &locks, 0..) |op, *mcv, *lock, op_i| { |
| 11459 | | const op_index = @as(u2, @intCast(op_i)); |
| 11500 | const op_index: u2 = @intCast(op_i); |
| 11460 | 11501 | mcv.* = try self.resolveInst(op); |
| 11461 | 11502 | if (unused.isSet(0) and mcv.isRegister() and self.reuseOperand(inst, op, op_index, mcv.*)) { |
| 11462 | 11503 | order[op_index] = 1; |
| ... | ... | @@ -11480,99 +11521,97 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void { |
| 11480 | 11521 | lock.* = self.register_manager.lockRegAssumeUnused(reg); |
| 11481 | 11522 | } |
| 11482 | 11523 | |
| 11483 | | const mir_tag = if (@as( |
| 11484 | | ?Mir.Inst.FixedTag, |
| 11485 | | if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 })) |
| 11486 | | switch (ty.zigTypeTag(mod)) { |
| 11487 | | .Float => switch (ty.floatBits(self.target.*)) { |
| 11488 | | 32 => .{ .v_ss, .fmadd132 }, |
| 11489 | | 64 => .{ .v_sd, .fmadd132 }, |
| 11490 | | 16, 80, 128 => null, |
| 11491 | | else => unreachable, |
| 11492 | | }, |
| 11493 | | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11494 | | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11495 | | 32 => switch (ty.vectorLen(mod)) { |
| 11496 | | 1 => .{ .v_ss, .fmadd132 }, |
| 11497 | | 2...8 => .{ .v_ps, .fmadd132 }, |
| 11498 | | else => null, |
| 11499 | | }, |
| 11500 | | 64 => switch (ty.vectorLen(mod)) { |
| 11501 | | 1 => .{ .v_sd, .fmadd132 }, |
| 11502 | | 2...4 => .{ .v_pd, .fmadd132 }, |
| 11503 | | else => null, |
| 11504 | | }, |
| 11505 | | 16, 80, 128 => null, |
| 11506 | | else => unreachable, |
| 11507 | | }, |
| 11508 | | else => unreachable, |
| 11509 | | }, |
| 11524 | const mir_tag = @as(?Mir.Inst.FixedTag, if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or |
| 11525 | mem.eql(u2, &order, &.{ 3, 1, 2 })) |
| 11526 | switch (ty.zigTypeTag(mod)) { |
| 11527 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11528 | 32 => .{ .v_ss, .fmadd132 }, |
| 11529 | 64 => .{ .v_sd, .fmadd132 }, |
| 11530 | 16, 80, 128 => null, |
| 11510 | 11531 | else => unreachable, |
| 11511 | | } |
| 11512 | | else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 })) |
| 11513 | | switch (ty.zigTypeTag(mod)) { |
| 11514 | | .Float => switch (ty.floatBits(self.target.*)) { |
| 11515 | | 32 => .{ .v_ss, .fmadd213 }, |
| 11516 | | 64 => .{ .v_sd, .fmadd213 }, |
| 11517 | | 16, 80, 128 => null, |
| 11518 | | else => unreachable, |
| 11519 | | }, |
| 11520 | | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11521 | | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11522 | | 32 => switch (ty.vectorLen(mod)) { |
| 11523 | | 1 => .{ .v_ss, .fmadd213 }, |
| 11524 | | 2...8 => .{ .v_ps, .fmadd213 }, |
| 11525 | | else => null, |
| 11526 | | }, |
| 11527 | | 64 => switch (ty.vectorLen(mod)) { |
| 11528 | | 1 => .{ .v_sd, .fmadd213 }, |
| 11529 | | 2...4 => .{ .v_pd, .fmadd213 }, |
| 11530 | | else => null, |
| 11531 | | }, |
| 11532 | | 16, 80, 128 => null, |
| 11533 | | else => unreachable, |
| 11532 | }, |
| 11533 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11534 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11535 | 32 => switch (ty.vectorLen(mod)) { |
| 11536 | 1 => .{ .v_ss, .fmadd132 }, |
| 11537 | 2...8 => .{ .v_ps, .fmadd132 }, |
| 11538 | else => null, |
| 11539 | }, |
| 11540 | 64 => switch (ty.vectorLen(mod)) { |
| 11541 | 1 => .{ .v_sd, .fmadd132 }, |
| 11542 | 2...4 => .{ .v_pd, .fmadd132 }, |
| 11543 | else => null, |
| 11534 | 11544 | }, |
| 11545 | 16, 80, 128 => null, |
| 11535 | 11546 | else => unreachable, |
| 11536 | 11547 | }, |
| 11537 | 11548 | else => unreachable, |
| 11538 | | } |
| 11539 | | else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 })) |
| 11540 | | switch (ty.zigTypeTag(mod)) { |
| 11541 | | .Float => switch (ty.floatBits(self.target.*)) { |
| 11542 | | 32 => .{ .v_ss, .fmadd231 }, |
| 11543 | | 64 => .{ .v_sd, .fmadd231 }, |
| 11549 | }, |
| 11550 | else => unreachable, |
| 11551 | } |
| 11552 | else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 })) |
| 11553 | switch (ty.zigTypeTag(mod)) { |
| 11554 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11555 | 32 => .{ .v_ss, .fmadd213 }, |
| 11556 | 64 => .{ .v_sd, .fmadd213 }, |
| 11557 | 16, 80, 128 => null, |
| 11558 | else => unreachable, |
| 11559 | }, |
| 11560 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11561 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11562 | 32 => switch (ty.vectorLen(mod)) { |
| 11563 | 1 => .{ .v_ss, .fmadd213 }, |
| 11564 | 2...8 => .{ .v_ps, .fmadd213 }, |
| 11565 | else => null, |
| 11566 | }, |
| 11567 | 64 => switch (ty.vectorLen(mod)) { |
| 11568 | 1 => .{ .v_sd, .fmadd213 }, |
| 11569 | 2...4 => .{ .v_pd, .fmadd213 }, |
| 11570 | else => null, |
| 11571 | }, |
| 11544 | 11572 | 16, 80, 128 => null, |
| 11545 | 11573 | else => unreachable, |
| 11546 | 11574 | }, |
| 11547 | | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11548 | | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11549 | | 32 => switch (ty.vectorLen(mod)) { |
| 11550 | | 1 => .{ .v_ss, .fmadd231 }, |
| 11551 | | 2...8 => .{ .v_ps, .fmadd231 }, |
| 11552 | | else => null, |
| 11553 | | }, |
| 11554 | | 64 => switch (ty.vectorLen(mod)) { |
| 11555 | | 1 => .{ .v_sd, .fmadd231 }, |
| 11556 | | 2...4 => .{ .v_pd, .fmadd231 }, |
| 11557 | | else => null, |
| 11558 | | }, |
| 11559 | | 16, 80, 128 => null, |
| 11560 | | else => unreachable, |
| 11575 | else => unreachable, |
| 11576 | }, |
| 11577 | else => unreachable, |
| 11578 | } |
| 11579 | else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 })) |
| 11580 | switch (ty.zigTypeTag(mod)) { |
| 11581 | .Float => switch (ty.floatBits(self.target.*)) { |
| 11582 | 32 => .{ .v_ss, .fmadd231 }, |
| 11583 | 64 => .{ .v_sd, .fmadd231 }, |
| 11584 | 16, 80, 128 => null, |
| 11585 | else => unreachable, |
| 11586 | }, |
| 11587 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| 11588 | .Float => switch (ty.childType(mod).floatBits(self.target.*)) { |
| 11589 | 32 => switch (ty.vectorLen(mod)) { |
| 11590 | 1 => .{ .v_ss, .fmadd231 }, |
| 11591 | 2...8 => .{ .v_ps, .fmadd231 }, |
| 11592 | else => null, |
| 11561 | 11593 | }, |
| 11594 | 64 => switch (ty.vectorLen(mod)) { |
| 11595 | 1 => .{ .v_sd, .fmadd231 }, |
| 11596 | 2...4 => .{ .v_pd, .fmadd231 }, |
| 11597 | else => null, |
| 11598 | }, |
| 11599 | 16, 80, 128 => null, |
| 11562 | 11600 | else => unreachable, |
| 11563 | 11601 | }, |
| 11564 | 11602 | else => unreachable, |
| 11565 | | } |
| 11566 | | else |
| 11567 | | unreachable, |
| 11568 | | )) |tag| tag else return self.fail("TODO implement airMulAdd for {}", .{ |
| 11603 | }, |
| 11604 | else => unreachable, |
| 11605 | } |
| 11606 | else |
| 11607 | unreachable) orelse return self.fail("TODO implement airMulAdd for {}", .{ |
| 11569 | 11608 | ty.fmt(self.bin_file.options.module.?), |
| 11570 | 11609 | }); |
| 11571 | 11610 | |
| 11572 | 11611 | var mops: [3]MCValue = undefined; |
| 11573 | 11612 | for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv; |
| 11574 | 11613 | |
| 11575 | | const abi_size = @as(u32, @intCast(ty.abiSize(mod))); |
| 11614 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 11576 | 11615 | const mop1_reg = registerAlias(mops[0].getReg().?, abi_size); |
| 11577 | 11616 | const mop2_reg = registerAlias(mops[1].getReg().?, abi_size); |
| 11578 | 11617 | if (mops[2].isRegister()) try self.asmRegisterRegisterRegister( |
| ... | ... | @@ -11725,7 +11764,7 @@ fn resolveCallingConventionValues( |
| 11725 | 11764 | switch (self.target.os.tag) { |
| 11726 | 11765 | .windows => { |
| 11727 | 11766 | // Align the stack to 16bytes before allocating shadow stack space (if any). |
| 11728 | | result.stack_byte_count += @as(u31, @intCast(4 * Type.usize.abiSize(mod))); |
| 11767 | result.stack_byte_count += @intCast(4 * Type.usize.abiSize(mod)); |
| 11729 | 11768 | }, |
| 11730 | 11769 | else => {}, |
| 11731 | 11770 | } |
| ... | ... | @@ -11748,7 +11787,7 @@ fn resolveCallingConventionValues( |
| 11748 | 11787 | result.return_value = switch (classes[0]) { |
| 11749 | 11788 | .integer => InstTracking.init(.{ .register = registerAlias( |
| 11750 | 11789 | ret_reg, |
| 11751 | | @as(u32, @intCast(ret_ty.abiSize(mod))), |
| 11790 | @intCast(ret_ty.abiSize(mod)), |
| 11752 | 11791 | ) }), |
| 11753 | 11792 | .float, .sse => InstTracking.init(.{ .register = .xmm0 }), |
| 11754 | 11793 | .memory => ret: { |
| ... | ... | @@ -11784,18 +11823,16 @@ fn resolveCallingConventionValues( |
| 11784 | 11823 | }, |
| 11785 | 11824 | .float, .sse => switch (self.target.os.tag) { |
| 11786 | 11825 | .windows => if (param_reg_i < 4) { |
| 11787 | | arg.* = .{ .register = @as( |
| 11788 | | Register, |
| 11789 | | @enumFromInt(@intFromEnum(Register.xmm0) + param_reg_i), |
| 11790 | | ) }; |
| 11826 | arg.* = .{ |
| 11827 | .register = @enumFromInt(@intFromEnum(Register.xmm0) + param_reg_i), |
| 11828 | }; |
| 11791 | 11829 | param_reg_i += 1; |
| 11792 | 11830 | continue; |
| 11793 | 11831 | }, |
| 11794 | 11832 | else => if (param_sse_reg_i < 8) { |
| 11795 | | arg.* = .{ .register = @as( |
| 11796 | | Register, |
| 11797 | | @enumFromInt(@intFromEnum(Register.xmm0) + param_sse_reg_i), |
| 11798 | | ) }; |
| 11833 | arg.* = .{ |
| 11834 | .register = @enumFromInt(@intFromEnum(Register.xmm0) + param_sse_reg_i), |
| 11835 | }; |
| 11799 | 11836 | param_sse_reg_i += 1; |
| 11800 | 11837 | continue; |
| 11801 | 11838 | }, |
| ... | ... | @@ -11806,8 +11843,8 @@ fn resolveCallingConventionValues( |
| 11806 | 11843 | }), |
| 11807 | 11844 | } |
| 11808 | 11845 | |
| 11809 | | const param_size = @as(u31, @intCast(ty.abiSize(mod))); |
| 11810 | | const param_align = @as(u31, @intCast(ty.abiAlignment(mod))); |
| 11846 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 11847 | const param_align: u31 = @intCast(ty.abiAlignment(mod)); |
| 11811 | 11848 | result.stack_byte_count = |
| 11812 | 11849 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 11813 | 11850 | arg.* = .{ .load_frame = .{ |
| ... | ... | @@ -11827,7 +11864,7 @@ fn resolveCallingConventionValues( |
| 11827 | 11864 | result.return_value = InstTracking.init(.none); |
| 11828 | 11865 | } else { |
| 11829 | 11866 | const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0]; |
| 11830 | | const ret_ty_size = @as(u31, @intCast(ret_ty.abiSize(mod))); |
| 11867 | const ret_ty_size: u31 = @intCast(ret_ty.abiSize(mod)); |
| 11831 | 11868 | if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) { |
| 11832 | 11869 | const aliased_reg = registerAlias(ret_reg, ret_ty_size); |
| 11833 | 11870 | result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none }; |
| ... | ... | @@ -11846,8 +11883,8 @@ fn resolveCallingConventionValues( |
| 11846 | 11883 | arg.* = .none; |
| 11847 | 11884 | continue; |
| 11848 | 11885 | } |
| 11849 | | const param_size = @as(u31, @intCast(ty.abiSize(mod))); |
| 11850 | | const param_align = @as(u31, @intCast(ty.abiAlignment(mod))); |
| 11886 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 11887 | const param_align: u31 = @intCast(ty.abiAlignment(mod)); |
| 11851 | 11888 | result.stack_byte_count = |
| 11852 | 11889 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 11853 | 11890 | arg.* = .{ .load_frame = .{ |
| ... | ... | @@ -11934,12 +11971,12 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 11934 | 11971 | const mod = self.bin_file.options.module.?; |
| 11935 | 11972 | const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{ |
| 11936 | 11973 | .signedness = .unsigned, |
| 11937 | | .bits = @as(u16, @intCast(ty.bitSize(mod))), |
| 11974 | .bits = @intCast(ty.bitSize(mod)), |
| 11938 | 11975 | }; |
| 11939 | 11976 | const max_reg_bit_width = Register.rax.bitSize(); |
| 11940 | 11977 | switch (int_info.signedness) { |
| 11941 | 11978 | .signed => { |
| 11942 | | const shift = @as(u6, @intCast(max_reg_bit_width - int_info.bits)); |
| 11979 | const shift: u6 = @intCast(max_reg_bit_width - int_info.bits); |
| 11943 | 11980 | try self.genShiftBinOpMir( |
| 11944 | 11981 | .{ ._l, .sa }, |
| 11945 | 11982 | Type.isize, |
| ... | ... | @@ -11954,8 +11991,8 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void { |
| 11954 | 11991 | ); |
| 11955 | 11992 | }, |
| 11956 | 11993 | .unsigned => { |
| 11957 | | const shift = @as(u6, @intCast(max_reg_bit_width - int_info.bits)); |
| 11958 | | const mask = (~@as(u64, 0)) >> shift; |
| 11994 | const shift: u6 = @intCast(max_reg_bit_width - int_info.bits); |
| 11995 | const mask = ~@as(u64, 0) >> shift; |
| 11959 | 11996 | if (int_info.bits <= 32) { |
| 11960 | 11997 | try self.genBinOpMir( |
| 11961 | 11998 | .{ ._, .@"and" }, |