authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-03-11 16:11:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-03-12 12:25:05-07:00
log22b7d0228261e040d64b2706918ee7582d4d2b6d
treef8f54a2b8a28b3a1df4ecabb0dd72b2989a003ec
parent623d5cc7f6b7ef84e8a465b5818e7c1e6060e8b5

Merge pull request #23188 from jacobly0/fix-23143

x86_64: fix crashes with symbols

3 files changed, 212 insertions(+), 71 deletions(-)

src/arch/x86_64/CodeGen.zig+159-45
...@@ -97909,16 +97909,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -97909,16 +97909,150 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
97909 switch (pred_mcv) {97909 switch (pred_mcv) {
97910 .register => |pred_reg| switch (pred_reg.class()) {97910 .register => |pred_reg| switch (pred_reg.class()) {
97911 .general_purpose => {},97911 .general_purpose => {},
97912 .sse => if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {97912 .sse => if (elem_ty.toIntern() == .bool_type)
97913 try self.register_manager.getKnownReg(.xmm0, null);97913 if (need_xmm0 and pred_reg.id() != comptime Register.xmm0.id()) {
97914 try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});97914 try self.register_manager.getKnownReg(.xmm0, null);
97915 break :mask .xmm0;97915 try self.genSetReg(.xmm0, pred_ty, pred_mcv, .{});
97916 } else break :mask if (has_blend)97916 break :mask .xmm0;
97917 pred_reg97917 } else break :mask if (has_blend)
97918 pred_reg
97919 else
97920 try self.copyToTmpRegister(pred_ty, pred_mcv)
97918 else97921 else
97919 try self.copyToTmpRegister(pred_ty, pred_mcv),97922 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)}),
97920 else => unreachable,97923 else => unreachable,
97921 },97924 },
97925 .register_mask => |pred_reg_mask| {
97926 if (pred_reg_mask.info.scalar.bitSize(self.target) != 8 * elem_abi_size)
97927 return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
97928
97929 const mask_reg: Register = if (need_xmm0 and pred_reg_mask.reg.id() != comptime Register.xmm0.id()) mask_reg: {
97930 try self.register_manager.getKnownReg(.xmm0, null);
97931 try self.genSetReg(.xmm0, ty, .{ .register = pred_reg_mask.reg }, .{});
97932 break :mask_reg .xmm0;
97933 } else pred_reg_mask.reg;
97934 const mask_alias = registerAlias(mask_reg, abi_size);
97935 const mask_lock = self.register_manager.lockRegAssumeUnused(mask_reg);
97936 defer self.register_manager.unlockReg(mask_lock);
97937
97938 const lhs_mcv = try self.resolveInst(extra.lhs);
97939 const lhs_lock = switch (lhs_mcv) {
97940 .register => |lhs_reg| self.register_manager.lockRegAssumeUnused(lhs_reg),
97941 else => null,
97942 };
97943 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
97944
97945 const rhs_mcv = try self.resolveInst(extra.rhs);
97946 const rhs_lock = switch (rhs_mcv) {
97947 .register => |rhs_reg| self.register_manager.lockReg(rhs_reg),
97948 else => null,
97949 };
97950 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
97951
97952 const order = has_blend != pred_reg_mask.info.inverted;
97953 const reuse_mcv, const other_mcv = if (order)
97954 .{ rhs_mcv, lhs_mcv }
97955 else
97956 .{ lhs_mcv, rhs_mcv };
97957 const dst_mcv: MCValue = if (reuse_mcv.isRegister() and self.reuseOperand(
97958 inst,
97959 if (order) extra.rhs else extra.lhs,
97960 @intFromBool(order),
97961 reuse_mcv,
97962 )) reuse_mcv else if (has_avx)
97963 .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) }
97964 else
97965 try self.copyToRegisterWithInstTracking(inst, ty, reuse_mcv);
97966 const dst_reg = dst_mcv.getReg().?;
97967 const dst_alias = registerAlias(dst_reg, abi_size);
97968 const dst_lock = self.register_manager.lockReg(dst_reg);
97969 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
97970
97971 const mir_tag = @as(?Mir.Inst.FixedTag, if ((pred_reg_mask.info.kind == .all and
97972 elem_ty.toIntern() != .f32_type and elem_ty.toIntern() != .f64_type) or pred_reg_mask.info.scalar == .byte)
97973 if (has_avx)
97974 .{ .vp_b, .blendv }
97975 else if (has_blend)
97976 .{ .p_b, .blendv }
97977 else if (pred_reg_mask.info.kind == .all)
97978 .{ .p_, undefined }
97979 else
97980 null
97981 else if ((pred_reg_mask.info.kind == .all and (elem_ty.toIntern() != .f64_type or !self.hasFeature(.sse2))) or
97982 pred_reg_mask.info.scalar == .dword)
97983 if (has_avx)
97984 .{ .v_ps, .blendv }
97985 else if (has_blend)
97986 .{ ._ps, .blendv }
97987 else if (pred_reg_mask.info.kind == .all)
97988 .{ ._ps, undefined }
97989 else
97990 null
97991 else if (pred_reg_mask.info.kind == .all or pred_reg_mask.info.scalar == .qword)
97992 if (has_avx)
97993 .{ .v_pd, .blendv }
97994 else if (has_blend)
97995 .{ ._pd, .blendv }
97996 else if (pred_reg_mask.info.kind == .all)
97997 .{ ._pd, undefined }
97998 else
97999 null
98000 else
98001 null) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
98002 if (has_avx) {
98003 const rhs_alias = if (reuse_mcv.isRegister())
98004 registerAlias(reuse_mcv.getReg().?, abi_size)
98005 else rhs: {
98006 try self.genSetReg(dst_reg, ty, reuse_mcv, .{});
98007 break :rhs dst_alias;
98008 };
98009 if (other_mcv.isBase()) try self.asmRegisterRegisterMemoryRegister(
98010 mir_tag,
98011 dst_alias,
98012 rhs_alias,
98013 try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
98014 mask_alias,
98015 ) else try self.asmRegisterRegisterRegisterRegister(
98016 mir_tag,
98017 dst_alias,
98018 rhs_alias,
98019 registerAlias(if (other_mcv.isRegister())
98020 other_mcv.getReg().?
98021 else
98022 try self.copyToTmpRegister(ty, other_mcv), abi_size),
98023 mask_alias,
98024 );
98025 } else if (has_blend) if (other_mcv.isBase()) try self.asmRegisterMemoryRegister(
98026 mir_tag,
98027 dst_alias,
98028 try other_mcv.mem(self, .{ .size = self.memSize(ty) }),
98029 mask_alias,
98030 ) else try self.asmRegisterRegisterRegister(
98031 mir_tag,
98032 dst_alias,
98033 registerAlias(if (other_mcv.isRegister())
98034 other_mcv.getReg().?
98035 else
98036 try self.copyToTmpRegister(ty, other_mcv), abi_size),
98037 mask_alias,
98038 ) else {
98039 try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
98040 if (other_mcv.isBase()) try self.asmRegisterMemory(
98041 .{ mir_tag[0], .andn },
98042 mask_alias,
98043 try other_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
98044 ) else try self.asmRegisterRegister(
98045 .{ mir_tag[0], .andn },
98046 mask_alias,
98047 if (other_mcv.isRegister())
98048 other_mcv.getReg().?
98049 else
98050 try self.copyToTmpRegister(ty, other_mcv),
98051 );
98052 try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
98053 }
98054 break :result dst_mcv;
98055 },
97922 else => {},98056 else => {},
97923 }98057 }
97924 const mask_reg: Register = if (need_xmm0) mask_reg: {98058 const mask_reg: Register = if (need_xmm0) mask_reg: {
...@@ -98121,7 +98255,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -98121,7 +98255,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
98121 const dst_lock = self.register_manager.lockReg(dst_reg);98255 const dst_lock = self.register_manager.lockReg(dst_reg);
98122 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);98256 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
9812398257
98124 const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.childType(zcu).zigTypeTag(zcu)) {98258 const mir_tag = @as(?Mir.Inst.FixedTag, switch (elem_ty.zigTypeTag(zcu)) {
98125 else => null,98259 else => null,
98126 .int => switch (abi_size) {98260 .int => switch (abi_size) {
98127 0 => unreachable,98261 0 => unreachable,
...@@ -98137,7 +98271,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -98137,7 +98271,7 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
98137 null,98271 null,
98138 else => null,98272 else => null,
98139 },98273 },
98140 .float => switch (ty.childType(zcu).floatBits(self.target.*)) {98274 .float => switch (elem_ty.floatBits(self.target.*)) {
98141 else => unreachable,98275 else => unreachable,
98142 16, 80, 128 => null,98276 16, 80, 128 => null,
98143 32 => switch (vec_len) {98277 32 => switch (vec_len) {
...@@ -98191,30 +98325,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {...@@ -98191,30 +98325,20 @@ fn airSelect(self: *CodeGen, inst: Air.Inst.Index) !void {
98191 try self.copyToTmpRegister(ty, lhs_mcv), abi_size),98325 try self.copyToTmpRegister(ty, lhs_mcv), abi_size),
98192 mask_alias,98326 mask_alias,
98193 ) else {98327 ) else {
98194 const mir_fixes = @as(?Mir.Inst.Fixes, switch (elem_ty.zigTypeTag(zcu)) {98328 try self.asmRegisterRegister(.{ mir_tag[0], .@"and" }, dst_alias, mask_alias);
98195 else => null,
98196 .int => .p_,
98197 .float => switch (elem_ty.floatBits(self.target.*)) {
98198 32 => ._ps,
98199 64 => ._pd,
98200 16, 80, 128 => null,
98201 else => unreachable,
98202 },
98203 }) orelse return self.fail("TODO implement airSelect for {}", .{ty.fmt(pt)});
98204 try self.asmRegisterRegister(.{ mir_fixes, .@"and" }, dst_alias, mask_alias);
98205 if (rhs_mcv.isBase()) try self.asmRegisterMemory(98329 if (rhs_mcv.isBase()) try self.asmRegisterMemory(
98206 .{ mir_fixes, .andn },98330 .{ mir_tag[0], .andn },
98207 mask_alias,98331 mask_alias,
98208 try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }),98332 try rhs_mcv.mem(self, .{ .size = .fromSize(abi_size) }),
98209 ) else try self.asmRegisterRegister(98333 ) else try self.asmRegisterRegister(
98210 .{ mir_fixes, .andn },98334 .{ mir_tag[0], .andn },
98211 mask_alias,98335 mask_alias,
98212 if (rhs_mcv.isRegister())98336 if (rhs_mcv.isRegister())
98213 rhs_mcv.getReg().?98337 rhs_mcv.getReg().?
98214 else98338 else
98215 try self.copyToTmpRegister(ty, rhs_mcv),98339 try self.copyToTmpRegister(ty, rhs_mcv),
98216 );98340 );
98217 try self.asmRegisterRegister(.{ mir_fixes, .@"or" }, dst_alias, mask_alias);98341 try self.asmRegisterRegister(.{ mir_tag[0], .@"or" }, dst_alias, mask_alias);
98218 }98342 }
98219 break :result dst_mcv;98343 break :result dst_mcv;
98220 };98344 };
...@@ -100753,11 +100877,11 @@ const Temp = struct {...@@ -100753,11 +100877,11 @@ const Temp = struct {
100753 const new_temp_index = cg.next_temp_index;100877 const new_temp_index = cg.next_temp_index;
100754 cg.temp_type[@intFromEnum(new_temp_index)] = .usize;100878 cg.temp_type[@intFromEnum(new_temp_index)] = .usize;
100755 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);100879 cg.next_temp_index = @enumFromInt(@intFromEnum(new_temp_index) + 1);
100756 switch (temp.tracking(cg).short) {100880 const mcv = temp.tracking(cg).short;
100757 else => |mcv| std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),100881 switch (mcv) {
100882 else => std.debug.panic("{s}: {}\n", .{ @src().fn_name, mcv }),
100758 .register => |reg| {100883 .register => |reg| {
100759 const new_reg =100884 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100760 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100761 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });100885 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
100762 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{100886 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
100763 .base = .{ .reg = reg.to64() },100887 .base = .{ .reg = reg.to64() },
...@@ -100765,33 +100889,22 @@ const Temp = struct {...@@ -100765,33 +100889,22 @@ const Temp = struct {
100765 });100889 });
100766 },100890 },
100767 .register_offset => |reg_off| {100891 .register_offset => |reg_off| {
100768 const new_reg =100892 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100769 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100770 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });100893 new_temp_index.tracking(cg).* = .init(.{ .register = new_reg });
100771 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{100894 try cg.asmRegisterMemory(.{ ._, .lea }, new_reg.to64(), .{
100772 .base = .{ .reg = reg_off.reg.to64() },100895 .base = .{ .reg = reg_off.reg.to64() },
100773 .mod = .{ .rm = .{ .disp = reg_off.off + off } },100896 .mod = .{ .rm = .{ .disp = reg_off.off + off } },
100774 });100897 });
100775 },100898 },
100899 .load_symbol, .load_frame => {
100900 const new_reg = try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100901 new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{ .reg = new_reg, .off = off } });
100902 try cg.genSetReg(new_reg, .usize, mcv, .{});
100903 },
100776 .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{100904 .lea_symbol => |sym_off| new_temp_index.tracking(cg).* = .init(.{ .lea_symbol = .{
100777 .sym_index = sym_off.sym_index,100905 .sym_index = sym_off.sym_index,
100778 .off = sym_off.off + off,100906 .off = sym_off.off + off,
100779 } }),100907 } }),
100780 .load_frame => |frame_addr| {
100781 const new_reg =
100782 try cg.register_manager.allocReg(new_temp_index.toIndex(), abi.RegisterClass.gp);
100783 new_temp_index.tracking(cg).* = .init(.{ .register_offset = .{
100784 .reg = new_reg,
100785 .off = off,
100786 } });
100787 try cg.asmRegisterMemory(.{ ._, .mov }, new_reg.to64(), .{
100788 .base = .{ .frame = frame_addr.index },
100789 .mod = .{ .rm = .{
100790 .size = .qword,
100791 .disp = frame_addr.off,
100792 } },
100793 });
100794 },
100795 .lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{100908 .lea_frame => |frame_addr| new_temp_index.tracking(cg).* = .init(.{ .lea_frame = .{
100796 .index = frame_addr.index,100909 .index = frame_addr.index,
100797 .off = frame_addr.off + off,100910 .off = frame_addr.off + off,
...@@ -101108,7 +101221,8 @@ const Temp = struct {...@@ -101108,7 +101221,8 @@ const Temp = struct {
101108 => return temp.toRegClass(true, .general_purpose, cg),101221 => return temp.toRegClass(true, .general_purpose, cg),
101109 .lea_symbol => |sym_off| {101222 .lea_symbol => |sym_off| {
101110 const off = sym_off.off;101223 const off = sym_off.off;
101111 if (off == 0) return false;101224 // hack around linker relocation bugs
101225 if (false and off == 0) return false;
101112 try temp.toOffset(-off, cg);101226 try temp.toOffset(-off, cg);
101113 while (try temp.toRegClass(true, .general_purpose, cg)) {}101227 while (try temp.toRegClass(true, .general_purpose, cg)) {}
101114 try temp.toOffset(off, cg);101228 try temp.toOffset(off, cg);
src/link/Dwarf.zig+33-26
...@@ -2008,9 +2008,9 @@ pub const WipNav = struct {...@@ -2008,9 +2008,9 @@ pub const WipNav = struct {
2008 .decl_const_runtime_bits,2008 .decl_const_runtime_bits,
2009 .decl_const_comptime_state,2009 .decl_const_comptime_state,
2010 .decl_const_runtime_bits_comptime_state,2010 .decl_const_runtime_bits_comptime_state,
2011 .decl_empty_func,2011 .decl_nullary_func,
2012 .decl_func,2012 .decl_func,
2013 .decl_empty_func_generic,2013 .decl_nullary_func_generic,
2014 .decl_func_generic,2014 .decl_func_generic,
2015 => false,2015 => false,
2016 .generic_decl_var,2016 .generic_decl_var,
...@@ -2626,8 +2626,8 @@ pub fn finishWipNavFunc(...@@ -2626,8 +2626,8 @@ pub fn finishWipNavFunc(
2626 abbrev_code_buf,2626 abbrev_code_buf,
2627 try dwarf.refAbbrevCode(switch (abbrev_code) {2627 try dwarf.refAbbrevCode(switch (abbrev_code) {
2628 else => unreachable,2628 else => unreachable,
2629 .decl_func => .decl_empty_func,2629 .decl_func => .decl_nullary_func,
2630 .decl_instance_func => .decl_instance_empty_func,2630 .decl_instance_func => .decl_instance_nullary_func,
2631 }),2631 }),
2632 );2632 );
2633 }2633 }
...@@ -3012,29 +3012,34 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo...@@ -3012,29 +3012,34 @@ fn updateComptimeNavInner(dwarf: *Dwarf, pt: Zcu.PerThread, nav_index: InternPoo
3012 if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) {3012 if (nav_gop.found_existing) switch (try dwarf.debug_info.declAbbrevCode(wip_nav.unit, nav_gop.value_ptr.*)) {
3013 .null => {},3013 .null => {},
3014 else => unreachable,3014 else => unreachable,
3015 .decl_empty_func, .decl_func, .decl_instance_empty_func, .decl_instance_func => return,3015 .decl_nullary_func, .decl_func, .decl_instance_nullary_func, .decl_instance_func => return,
3016 .decl_empty_func_generic,3016 .decl_nullary_func_generic,
3017 .decl_func_generic,3017 .decl_func_generic,
3018 .decl_instance_empty_func_generic,3018 .decl_instance_nullary_func_generic,
3019 .decl_instance_func_generic,3019 .decl_instance_func_generic,
3020 => dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(),3020 => dwarf.debug_info.section.getUnit(wip_nav.unit).getEntry(nav_gop.value_ptr.*).clear(),
3021 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);3021 } else nav_gop.value_ptr.* = try dwarf.addCommonEntry(wip_nav.unit);
3022 wip_nav.entry = nav_gop.value_ptr.*;3022 wip_nav.entry = nav_gop.value_ptr.*;
30233023
3024 const func_type = ip.indexToKey(func.ty).func_type;3024 const func_type = ip.indexToKey(func.ty).func_type;
3025 const is_nullary = !func_type.is_var_args and for (0..func_type.param_types.len) |param_index| {
3026 if (!func_type.paramIsComptime(std.math.cast(u5, param_index) orelse break false)) break false;
3027 } else true;
3025 const diw = wip_nav.debug_info.writer(dwarf.gpa);3028 const diw = wip_nav.debug_info.writer(dwarf.gpa);
3026 try wip_nav.declCommon(if (func_type.param_types.len > 0 or func_type.is_var_args) .{3029 try wip_nav.declCommon(if (is_nullary) .{
3027 .decl = .decl_func_generic,3030 .decl = .decl_nullary_func_generic,
3028 .generic_decl = .generic_decl_func,3031 .generic_decl = .generic_decl_func,
3029 .decl_instance = .decl_instance_func_generic,3032 .decl_instance = .decl_instance_nullary_func_generic,
3030 } else .{3033 } else .{
3031 .decl = .decl_empty_func_generic,3034 .decl = .decl_func_generic,
3032 .generic_decl = .generic_decl_func,3035 .generic_decl = .generic_decl_func,
3033 .decl_instance = .decl_instance_empty_func_generic,3036 .decl_instance = .decl_instance_func_generic,
3034 }, &nav, inst_info.file, &decl);3037 }, &nav, inst_info.file, &decl);
3035 try wip_nav.refType(.fromInterned(func_type.return_type));3038 try wip_nav.refType(.fromInterned(func_type.return_type));
3036 if (func_type.param_types.len > 0 or func_type.is_var_args) {3039 if (!is_nullary) {
3037 for (0..func_type.param_types.len) |param_index| {3040 for (0..func_type.param_types.len) |param_index| {
3041 if (std.math.cast(u5, param_index)) |small_param_index|
3042 if (func_type.paramIsComptime(small_param_index)) continue;
3038 try wip_nav.abbrevCode(.func_type_param);3043 try wip_nav.abbrevCode(.func_type_param);
3039 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));3044 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3040 }3045 }
...@@ -3568,12 +3573,14 @@ fn updateLazyType(...@@ -3568,12 +3573,14 @@ fn updateLazyType(
3568 };3573 };
3569 try diw.writeByte(@intFromEnum(cc));3574 try diw.writeByte(@intFromEnum(cc));
3570 try wip_nav.refType(.fromInterned(func_type.return_type));3575 try wip_nav.refType(.fromInterned(func_type.return_type));
3571 for (0..func_type.param_types.len) |param_index| {3576 if (!is_nullary) {
3572 try wip_nav.abbrevCode(.func_type_param);3577 for (0..func_type.param_types.len) |param_index| {
3573 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));3578 try wip_nav.abbrevCode(.func_type_param);
3579 try wip_nav.refType(.fromInterned(func_type.param_types.get(ip)[param_index]));
3580 }
3581 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3582 try uleb128(diw, @intFromEnum(AbbrevCode.null));
3574 }3583 }
3575 if (func_type.is_var_args) try wip_nav.abbrevCode(.is_var_args);
3576 if (!is_nullary) try uleb128(diw, @intFromEnum(AbbrevCode.null));
3577 },3584 },
3578 .error_set_type => |error_set_type| {3585 .error_set_type => |error_set_type| {
3579 try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);3586 try wip_nav.abbrevCode(if (error_set_type.names.len == 0) .generated_empty_enum_type else .generated_enum_type);
...@@ -4787,9 +4794,9 @@ const AbbrevCode = enum {...@@ -4787,9 +4794,9 @@ const AbbrevCode = enum {
4787 decl_const_runtime_bits,4794 decl_const_runtime_bits,
4788 decl_const_comptime_state,4795 decl_const_comptime_state,
4789 decl_const_runtime_bits_comptime_state,4796 decl_const_runtime_bits_comptime_state,
4790 decl_empty_func,4797 decl_nullary_func,
4791 decl_func,4798 decl_func,
4792 decl_empty_func_generic,4799 decl_nullary_func_generic,
4793 decl_func_generic,4800 decl_func_generic,
4794 generic_decl_var,4801 generic_decl_var,
4795 generic_decl_const,4802 generic_decl_const,
...@@ -4806,9 +4813,9 @@ const AbbrevCode = enum {...@@ -4806,9 +4813,9 @@ const AbbrevCode = enum {
4806 decl_instance_const_runtime_bits,4813 decl_instance_const_runtime_bits,
4807 decl_instance_const_comptime_state,4814 decl_instance_const_comptime_state,
4808 decl_instance_const_runtime_bits_comptime_state,4815 decl_instance_const_runtime_bits_comptime_state,
4809 decl_instance_empty_func,4816 decl_instance_nullary_func,
4810 decl_instance_func,4817 decl_instance_func,
4811 decl_instance_empty_func_generic,4818 decl_instance_nullary_func_generic,
4812 decl_instance_func_generic,4819 decl_instance_func_generic,
4813 // the rest are unrestricted other than empty variants must not be longer4820 // the rest are unrestricted other than empty variants must not be longer
4814 // than the non-empty variant, and so should appear first4821 // than the non-empty variant, and so should appear first
...@@ -5019,7 +5026,7 @@ const AbbrevCode = enum {...@@ -5019,7 +5026,7 @@ const AbbrevCode = enum {
5019 .{ .ZIG_comptime_value, .ref_addr },5026 .{ .ZIG_comptime_value, .ref_addr },
5020 },5027 },
5021 },5028 },
5022 .decl_empty_func = .{5029 .decl_nullary_func = .{
5023 .tag = .subprogram,5030 .tag = .subprogram,
5024 .attrs = decl_abbrev_common_attrs ++ .{5031 .attrs = decl_abbrev_common_attrs ++ .{
5025 .{ .linkage_name, .strp },5032 .{ .linkage_name, .strp },
...@@ -5044,7 +5051,7 @@ const AbbrevCode = enum {...@@ -5044,7 +5051,7 @@ const AbbrevCode = enum {
5044 .{ .noreturn, .flag },5051 .{ .noreturn, .flag },
5045 },5052 },
5046 },5053 },
5047 .decl_empty_func_generic = .{5054 .decl_nullary_func_generic = .{
5048 .tag = .subprogram,5055 .tag = .subprogram,
5049 .attrs = decl_abbrev_common_attrs ++ .{5056 .attrs = decl_abbrev_common_attrs ++ .{
5050 .{ .type, .ref_addr },5057 .{ .type, .ref_addr },
...@@ -5167,7 +5174,7 @@ const AbbrevCode = enum {...@@ -5167,7 +5174,7 @@ const AbbrevCode = enum {
5167 .{ .ZIG_comptime_value, .ref_addr },5174 .{ .ZIG_comptime_value, .ref_addr },
5168 },5175 },
5169 },5176 },
5170 .decl_instance_empty_func = .{5177 .decl_instance_nullary_func = .{
5171 .tag = .subprogram,5178 .tag = .subprogram,
5172 .attrs = decl_instance_abbrev_common_attrs ++ .{5179 .attrs = decl_instance_abbrev_common_attrs ++ .{
5173 .{ .linkage_name, .strp },5180 .{ .linkage_name, .strp },
...@@ -5192,7 +5199,7 @@ const AbbrevCode = enum {...@@ -5192,7 +5199,7 @@ const AbbrevCode = enum {
5192 .{ .noreturn, .flag },5199 .{ .noreturn, .flag },
5193 },5200 },
5194 },5201 },
5195 .decl_instance_empty_func_generic = .{5202 .decl_instance_nullary_func_generic = .{
5196 .tag = .subprogram,5203 .tag = .subprogram,
5197 .attrs = decl_instance_abbrev_common_attrs ++ .{5204 .attrs = decl_instance_abbrev_common_attrs ++ .{
5198 .{ .type, .ref_addr },5205 .{ .type, .ref_addr },
test/behavior/select.zig+20
...@@ -66,3 +66,23 @@ fn selectArrays() !void {...@@ -66,3 +66,23 @@ fn selectArrays() !void {
66 const xyz = @select(f32, x, y, z);66 const xyz = @select(f32, x, y, z);
67 try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));67 try expect(mem.eql(f32, &@as([4]f32, xyz), &[4]f32{ 0.0, 312.1, -145.9, -3381.233 }));
68}68}
69
70test "@select compare result" {
71 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
72 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
73 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest;
74
75 const S = struct {
76 fn min(comptime V: type, lhs: V, rhs: V) V {
77 return @select(@typeInfo(V).vector.child, lhs < rhs, lhs, rhs);
78 }
79
80 fn doTheTest() !void {
81 try expect(@reduce(.And, min(@Vector(4, f32), .{ -1, 2, -3, 4 }, .{ 1, -2, 3, -4 }) == @Vector(4, f32){ -1, -2, -3, -4 }));
82 try expect(@reduce(.And, min(@Vector(2, f64), .{ -1, 2 }, .{ 1, -2 }) == @Vector(2, f64){ -1, -2 }));
83 }
84 };
85
86 try S.doTheTest();
87 try comptime S.doTheTest();
88}