authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-12-04 18:37:39-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-12-04 18:37:39-05:00
logc357b902b0b76806970462ab3b274d8ade76e35a
tree8c63d76b33589df5aaa418b9c3ebc37dece594e8
parent8a8fd47d217eadb8a45ec6b9325acfe1d42704d7
parentc70c33359498bfe33a2f60cfcc5ea401a277d5bf
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #18179 from jacobly0/x86_64

x86_64: pass more behavior tests

14 files changed, 596 insertions(+), 328 deletions(-)

src/Sema.zig+13-17
......@@ -9069,7 +9069,7 @@ fn handleExternLibName(
90699069 block: *Block,
90709070 src_loc: LazySrcLoc,
90719071 lib_name: []const u8,
9072) CompileError![:0]u8 {
9072) CompileError!void {
90739073 blk: {
90749074 const mod = sema.mod;
90759075 const comp = mod.comp;
......@@ -9117,7 +9117,6 @@ fn handleExternLibName(
91179117 });
91189118 };
91199119 }
9120 return sema.gpa.dupeZ(u8, lib_name);
91219120}
91229121
91239122/// These are calling conventions that are confirmed to work with variadic functions.
......@@ -9422,15 +9421,13 @@ fn funcCommon(
94229421 assert(section != .generic);
94239422 assert(address_space != null);
94249423 assert(!is_generic);
9424 if (opt_lib_name) |lib_name| try sema.handleExternLibName(block, .{
9425 .node_offset_lib_name = src_node_offset,
9426 }, lib_name);
94259427 const func_index = try ip.getExternFunc(gpa, .{
94269428 .ty = func_ty,
94279429 .decl = sema.owner_decl_index,
9428 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9429 gpa,
9430 try sema.handleExternLibName(block, .{
9431 .node_offset_lib_name = src_node_offset,
9432 }, lib_name),
9433 )).toOptional() else .none,
9430 .lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, opt_lib_name),
94349431 });
94359432 return finishFunc(
94369433 sema,
......@@ -24688,10 +24685,11 @@ fn zirVarExtended(
2468824685
2468924686 var extra_index: usize = extra.end;
2469024687
24691 const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
24688 const lib_name = if (small.has_lib_name) lib_name: {
2469224689 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
2469324690 extra_index += 1;
24694 break :blk lib_name;
24691 try sema.handleExternLibName(block, ty_src, lib_name);
24692 break :lib_name lib_name;
2469524693 } else null;
2469624694
2469724695 // ZIR supports encoding this information but it is not used; the information
......@@ -24729,10 +24727,7 @@ fn zirVarExtended(
2472924727 .ty = var_ty.toIntern(),
2473024728 .init = init_val,
2473124729 .decl = sema.owner_decl_index,
24732 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
24733 sema.gpa,
24734 try sema.handleExternLibName(block, ty_src, lname),
24735 )).toOptional() else .none,
24730 .lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name),
2473624731 .is_extern = small.is_extern,
2473724732 .is_threadlocal = small.is_threadlocal,
2473824733 } })));
......@@ -25177,12 +25172,13 @@ fn resolveExternOptions(
2517725172 .needed_comptime_reason = "threadlocality of the extern symbol must be comptime-known",
2517825173 });
2517925174
25180 const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
25181 const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
25175 const library_name = if (library_name_val.optionalValue(mod)) |library_name_payload| library_name: {
25176 const library_name = try library_name_payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2518225177 if (library_name.len == 0) {
2518325178 return sema.fail(block, library_src, "library name cannot be empty", .{});
2518425179 }
25185 break :blk try sema.handleExternLibName(block, library_src, library_name);
25180 try sema.handleExternLibName(block, library_src, library_name);
25181 break :library_name library_name;
2518625182 } else null;
2518725183
2518825184 if (name.len == 0) {
src/arch/x86_64/CodeGen.zig+512-273
......@@ -2478,8 +2478,11 @@ fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet {
24782478 else => abi.RegisterClass.sse,
24792479 },
24802480 .Vector => switch (ty.childType(mod).toIntern()) {
2481 .bool_type => abi.RegisterClass.gp,
2482 else => abi.RegisterClass.sse,
2481 .bool_type, .u1_type => abi.RegisterClass.gp,
2482 else => if (ty.isAbiInt(mod) and ty.intInfo(mod).bits == 1)
2483 abi.RegisterClass.gp
2484 else
2485 abi.RegisterClass.sse,
24832486 },
24842487 else => abi.RegisterClass.gp,
24852488 };
......@@ -3104,18 +3107,17 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
31043107 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
31053108
31063109 const slice_ty = self.typeOfIndex(inst);
3107 const ptr = try self.resolveInst(bin_op.lhs);
3110 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
3111
31083112 const ptr_ty = self.typeOf(bin_op.lhs);
3109 const len = try self.resolveInst(bin_op.rhs);
3110 const len_ty = self.typeOf(bin_op.rhs);
3113 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, .{ .air_ref = bin_op.lhs });
31113114
3112 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(slice_ty, mod));
3113 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
3115 const len_ty = self.typeOf(bin_op.rhs);
31143116 try self.genSetMem(
31153117 .{ .frame = frame_index },
31163118 @intCast(ptr_ty.abiSize(mod)),
31173119 len_ty,
3118 len,
3120 .{ .air_ref = bin_op.rhs },
31193121 );
31203122
31213123 const result = MCValue{ .load_frame = .{ .index = frame_index } };
......@@ -5133,74 +5135,114 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
51335135 const mod = self.bin_file.options.module.?;
51345136 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
51355137
5136 const array_ty = self.typeOf(bin_op.lhs);
5137 const array = try self.resolveInst(bin_op.lhs);
5138 const array_lock: ?RegisterLock = switch (array) {
5139 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5140 else => null,
5141 };
5142 defer if (array_lock) |lock| self.register_manager.unlockReg(lock);
5138 const result: MCValue = result: {
5139 const array_ty = self.typeOf(bin_op.lhs);
5140 const elem_ty = array_ty.childType(mod);
51435141
5144 const elem_ty = array_ty.childType(mod);
5145 const elem_abi_size = elem_ty.abiSize(mod);
5142 const array_mcv = try self.resolveInst(bin_op.lhs);
5143 const array_lock: ?RegisterLock = switch (array_mcv) {
5144 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5145 else => null,
5146 };
5147 defer if (array_lock) |lock| self.register_manager.unlockReg(lock);
51465148
5147 const index_ty = self.typeOf(bin_op.rhs);
5148 const index = try self.resolveInst(bin_op.rhs);
5149 const index_lock: ?RegisterLock = switch (index) {
5150 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5151 else => null,
5152 };
5153 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
5149 const index_ty = self.typeOf(bin_op.rhs);
5150 const index_mcv = try self.resolveInst(bin_op.rhs);
5151 const index_lock: ?RegisterLock = switch (index_mcv) {
5152 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5153 else => null,
5154 };
5155 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
51545156
5155 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5156 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5157 defer self.register_manager.unlockReg(addr_lock);
5157 try self.spillEflagsIfOccupied();
5158 if (array_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) {
5159 const index_reg = switch (index_mcv) {
5160 .register => |reg| reg,
5161 else => try self.copyToTmpRegister(index_ty, index_mcv),
5162 };
5163 switch (array_mcv) {
5164 .register => |array_reg| try self.asmRegisterRegister(
5165 .{ ._, .bt },
5166 array_reg.to64(),
5167 index_reg.to64(),
5168 ),
5169 .load_frame => try self.asmMemoryRegister(
5170 .{ ._, .bt },
5171 try array_mcv.mem(self, .qword),
5172 index_reg.to64(),
5173 ),
5174 .memory, .load_symbol, .load_direct, .load_got, .load_tlv => try self.asmMemoryRegister(
5175 .{ ._, .bt },
5176 .{
5177 .base = .{
5178 .reg = try self.copyToTmpRegister(Type.usize, array_mcv.address()),
5179 },
5180 .mod = .{ .rm = .{ .size = .qword } },
5181 },
5182 index_reg.to64(),
5183 ),
5184 else => return self.fail("TODO airArrayElemVal for {s} of {}", .{
5185 @tagName(array_mcv), array_ty.fmt(mod),
5186 }),
5187 }
5188
5189 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
5190 try self.asmSetccRegister(.c, dst_reg.to8());
5191 break :result .{ .register = dst_reg };
5192 }
5193
5194 const elem_abi_size = elem_ty.abiSize(mod);
5195 const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
5196 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
5197 defer self.register_manager.unlockReg(addr_lock);
51585198
5159 switch (array) {
5160 .register => {
5161 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
5162 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array);
5163 try self.asmRegisterMemory(
5199 switch (array_mcv) {
5200 .register => {
5201 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
5202 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array_mcv);
5203 try self.asmRegisterMemory(
5204 .{ ._, .lea },
5205 addr_reg,
5206 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
5207 );
5208 },
5209 .load_frame => |frame_addr| try self.asmRegisterMemory(
51645210 .{ ._, .lea },
51655211 addr_reg,
5166 .{ .base = .{ .frame = frame_index }, .mod = .{ .rm = .{ .size = .qword } } },
5167 );
5168 },
5169 .load_frame => |frame_addr| try self.asmRegisterMemory(
5170 .{ ._, .lea },
5171 addr_reg,
5172 .{
5173 .base = .{ .frame = frame_addr.index },
5174 .mod = .{ .rm = .{ .size = .qword, .disp = frame_addr.off } },
5175 },
5176 ),
5177 .memory,
5178 .load_symbol,
5179 .load_direct,
5180 .load_got,
5181 .load_tlv,
5182 => try self.genSetReg(addr_reg, Type.usize, array.address()),
5183 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
5184 else => return self.fail("TODO implement array_elem_val when array is {}", .{array}),
5185 }
5186
5187 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
5188 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5189 defer self.register_manager.unlockReg(offset_lock);
5212 .{
5213 .base = .{ .frame = frame_addr.index },
5214 .mod = .{ .rm = .{ .size = .qword, .disp = frame_addr.off } },
5215 },
5216 ),
5217 .memory,
5218 .load_symbol,
5219 .load_direct,
5220 .load_got,
5221 .load_tlv,
5222 => try self.genSetReg(addr_reg, Type.usize, array_mcv.address()),
5223 .lea_symbol, .lea_direct, .lea_tlv => unreachable,
5224 else => return self.fail("TODO airArrayElemVal_val for {s} of {}", .{
5225 @tagName(array_mcv), array_ty.fmt(mod),
5226 }),
5227 }
51905228
5191 // TODO we could allocate register here, but need to expect addr register and potentially
5192 // offset register.
5193 try self.spillEflagsIfOccupied();
5194 const dst_mcv = try self.allocRegOrMem(inst, false);
5195 try self.genBinOpMir(
5196 .{ ._, .add },
5197 Type.usize,
5198 .{ .register = addr_reg },
5199 .{ .register = offset_reg },
5200 );
5201 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
5229 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);
5230 const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5231 defer self.register_manager.unlockReg(offset_lock);
52025232
5203 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
5233 // TODO we could allocate register here, but need to expect addr register and potentially
5234 // offset register.
5235 const dst_mcv = try self.allocRegOrMem(inst, false);
5236 try self.genBinOpMir(
5237 .{ ._, .add },
5238 Type.usize,
5239 .{ .register = addr_reg },
5240 .{ .register = offset_reg },
5241 );
5242 try self.genCopy(elem_ty, dst_mcv, .{ .indirect = .{ .reg = addr_reg } });
5243 break :result dst_mcv;
5244 };
5245 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
52045246}
52055247
52065248fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
......@@ -5258,32 +5300,44 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
52585300 const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
52595301 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
52605302
5261 const ptr_ty = self.typeOf(extra.lhs);
5262 const ptr = try self.resolveInst(extra.lhs);
5263 const ptr_lock: ?RegisterLock = switch (ptr) {
5264 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5265 else => null,
5266 };
5267 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
5303 const result = result: {
5304 const elem_ptr_ty = self.typeOfIndex(inst);
5305 const base_ptr_ty = self.typeOf(extra.lhs);
52685306
5269 const elem_ty = ptr_ty.elemType2(mod);
5270 const elem_abi_size = elem_ty.abiSize(mod);
5271 const index_ty = self.typeOf(extra.rhs);
5272 const index = try self.resolveInst(extra.rhs);
5273 const index_lock: ?RegisterLock = switch (index) {
5274 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5275 else => null,
5276 };
5277 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
5307 const base_ptr_mcv = try self.resolveInst(extra.lhs);
5308 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
5309 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5310 else => null,
5311 };
5312 defer if (base_ptr_lock) |lock| self.register_manager.unlockReg(lock);
52785313
5279 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
5280 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5281 defer self.register_manager.unlockReg(offset_reg_lock);
5314 if (elem_ptr_ty.ptrInfo(mod).flags.vector_index != .none) {
5315 break :result if (self.reuseOperand(inst, extra.lhs, 0, base_ptr_mcv))
5316 base_ptr_mcv
5317 else
5318 try self.copyToRegisterWithInstTracking(inst, elem_ptr_ty, base_ptr_mcv);
5319 }
52825320
5283 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
5284 try self.genBinOpMir(.{ ._, .add }, ptr_ty, dst_mcv, .{ .register = offset_reg });
5321 const elem_ty = base_ptr_ty.elemType2(mod);
5322 const elem_abi_size = elem_ty.abiSize(mod);
5323 const index_ty = self.typeOf(extra.rhs);
5324 const index_mcv = try self.resolveInst(extra.rhs);
5325 const index_lock: ?RegisterLock = switch (index_mcv) {
5326 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
5327 else => null,
5328 };
5329 defer if (index_lock) |lock| self.register_manager.unlockReg(lock);
52855330
5286 return self.finishAir(inst, dst_mcv, .{ extra.lhs, extra.rhs, .none });
5331 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size);
5332 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
5333 defer self.register_manager.unlockReg(offset_reg_lock);
5334
5335 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, elem_ptr_ty, base_ptr_mcv);
5336 try self.genBinOpMir(.{ ._, .add }, elem_ptr_ty, dst_mcv, .{ .register = offset_reg });
5337
5338 break :result dst_mcv;
5339 };
5340 return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none });
52875341}
52885342
52895343fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
......@@ -6712,19 +6766,20 @@ fn reuseOperandAdvanced(
67126766
67136767fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {
67146768 const mod = self.bin_file.options.module.?;
6715 const ptr_info = ptr_ty.ptrInfo(mod);
67166769
6770 const ptr_info = ptr_ty.ptrInfo(mod);
67176771 const val_ty = Type.fromInterned(ptr_info.child);
67186772 if (!val_ty.hasRuntimeBitsIgnoreComptime(mod)) return;
67196773 const val_abi_size: u32 = @intCast(val_ty.abiSize(mod));
67206774
6721 if (ptr_info.packed_offset.bit_offset % 8 == 0) {
6722 try self.load(
6723 dst_mcv,
6724 ptr_ty,
6725 ptr_mcv.offset(@intCast(@divExact(ptr_info.packed_offset.bit_offset, 8))),
6726 );
6727 const val_bit_size: u32 = @intCast(val_ty.bitSize(mod));
6775 const val_bit_size: u32 = @intCast(val_ty.bitSize(mod));
6776 const ptr_bit_off = ptr_info.packed_offset.bit_offset + switch (ptr_info.flags.vector_index) {
6777 .none => 0,
6778 .runtime => unreachable,
6779 else => |vector_index| @intFromEnum(vector_index) * val_bit_size,
6780 };
6781 if (ptr_bit_off % 8 == 0) {
6782 try self.load(dst_mcv, ptr_ty, ptr_mcv.offset(@intCast(@divExact(ptr_bit_off, 8))));
67286783 if (val_abi_size * 8 > val_bit_size) {
67296784 if (dst_mcv.isRegister()) {
67306785 try self.truncateRegister(val_ty, dst_mcv.getReg().?);
......@@ -6746,9 +6801,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
67466801
67476802 const limb_abi_size: u32 = @min(val_abi_size, 8);
67486803 const limb_abi_bits = limb_abi_size * 8;
6749 const val_byte_off: i32 =
6750 @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
6751 const val_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits;
6804 const val_byte_off: i32 = @intCast(ptr_bit_off / limb_abi_bits * limb_abi_size);
6805 const val_bit_off = ptr_bit_off % limb_abi_bits;
67526806 const val_extra_bits = self.regExtraBits(val_ty);
67536807
67546808 const ptr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
......@@ -6875,7 +6929,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
68756929 else
68766930 try self.allocRegOrMem(inst, true);
68776931
6878 if (ptr_ty.ptrInfo(mod).packed_offset.host_size > 0) {
6932 const ptr_info = ptr_ty.ptrInfo(mod);
6933 if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {
68796934 try self.packedLoad(dst_mcv, ptr_ty, ptr_mcv);
68806935 } else {
68816936 try self.load(dst_mcv, ptr_ty, ptr_mcv);
......@@ -6909,7 +6964,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
69096964fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {
69106965 const mod = self.bin_file.options.module.?;
69116966 const ptr_info = ptr_ty.ptrInfo(mod);
6912 const src_ty = ptr_ty.childType(mod);
6967 const src_ty = Type.fromInterned(ptr_info.child);
69136968 if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return;
69146969
69156970 const limb_abi_size: u16 = @min(ptr_info.packed_offset.host_size, 8);
......@@ -6917,8 +6972,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
69176972 const limb_ty = try mod.intType(.unsigned, limb_abi_bits);
69186973
69196974 const src_bit_size = src_ty.bitSize(mod);
6920 const src_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size);
6921 const src_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits;
6975 const ptr_bit_off = ptr_info.packed_offset.bit_offset + switch (ptr_info.flags.vector_index) {
6976 .none => 0,
6977 .runtime => unreachable,
6978 else => |vector_index| @intFromEnum(vector_index) * src_bit_size,
6979 };
6980 const src_byte_off: i32 = @intCast(ptr_bit_off / limb_abi_bits * limb_abi_size);
6981 const src_bit_off = ptr_bit_off % limb_abi_bits;
69226982
69236983 const ptr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv);
69246984 const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg);
......@@ -7041,24 +7101,25 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
70417101
70427102fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
70437103 const mod = self.bin_file.options.module.?;
7044 if (safety) {
7045 // TODO if the value is undef, write 0xaa bytes to dest
7046 } else {
7047 // TODO if the value is undef, don't lower this instruction
7048 }
7104 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
70497105
7050 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
7051 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
7052 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
7106 result: {
7107 if (!safety and (try self.resolveInst(bin_op.rhs)) == .undef) break :result;
70537108
7054 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
7055 const ptr_mcv = try self.resolveInst(bin_op.lhs);
7056 const ptr_ty = self.typeOf(bin_op.lhs);
7057 const src_mcv = try self.resolveInst(bin_op.rhs);
7058 if (ptr_ty.ptrInfo(mod).packed_offset.host_size > 0) {
7059 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
7060 } else {
7061 try self.store(ptr_ty, ptr_mcv, src_mcv);
7109 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
7110 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
7111 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
7112
7113 const src_mcv = try self.resolveInst(bin_op.rhs);
7114 const ptr_mcv = try self.resolveInst(bin_op.lhs);
7115 const ptr_ty = self.typeOf(bin_op.lhs);
7116
7117 const ptr_info = ptr_ty.ptrInfo(mod);
7118 if (ptr_info.flags.vector_index != .none or ptr_info.packed_offset.host_size > 0) {
7119 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
7120 } else {
7121 try self.store(ptr_ty, ptr_mcv, src_mcv);
7122 }
70627123 }
70637124 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
70647125}
......@@ -7263,8 +7324,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
72637324 .load_frame => |frame_addr| {
72647325 const field_abi_size: u32 = @intCast(field_ty.abiSize(mod));
72657326 if (field_off % 8 == 0) {
7266 const off_mcv =
7267 src_mcv.address().offset(@intCast(@divExact(field_off, 8))).deref();
7327 const field_byte_off = @divExact(field_off, 8);
7328 const off_mcv = src_mcv.address().offset(@intCast(field_byte_off)).deref();
72687329 const field_bit_size = field_ty.bitSize(mod);
72697330
72707331 if (field_abi_size <= 8) {
......@@ -7289,7 +7350,9 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
72897350 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
72907351 }
72917352
7292 const dst_mcv = if (self.reuseOperand(inst, operand, 0, src_mcv))
7353 const container_abi_size: u32 = @intCast(container_ty.abiSize(mod));
7354 const dst_mcv = if (field_byte_off + field_abi_size <= container_abi_size and
7355 self.reuseOperand(inst, operand, 0, src_mcv))
72937356 off_mcv
72947357 else dst: {
72957358 const dst_mcv = try self.allocRegOrMem(inst, true);
......@@ -8422,7 +8485,8 @@ fn genBinOp(
84228485 if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null;
84238486 defer if (mask_lock) |lock| self.register_manager.unlockReg(lock);
84248487
8425 const ordered_air = if (lhs_ty.isVector(mod) and switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
8488 const ordered_air: [2]Air.Inst.Ref = if (lhs_ty.isVector(mod) and
8489 switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
84268490 .Int => switch (air_tag) {
84278491 .cmp_lt, .cmp_gte => true,
84288492 else => false,
......@@ -8432,14 +8496,24 @@ fn genBinOp(
84328496 else => false,
84338497 },
84348498 else => unreachable,
8435 }) .{ .lhs = rhs_air, .rhs = lhs_air } else .{ .lhs = lhs_air, .rhs = rhs_air };
8499 }) .{ rhs_air, lhs_air } else .{ lhs_air, rhs_air };
8500
8501 if (lhs_ty.isAbiInt(mod)) for (ordered_air) |op_air| {
8502 switch (try self.resolveInst(op_air)) {
8503 .register => |op_reg| switch (op_reg.class()) {
8504 .sse => try self.register_manager.getReg(op_reg, null),
8505 else => {},
8506 },
8507 else => {},
8508 }
8509 };
84368510
8437 const lhs_mcv = try self.resolveInst(ordered_air.lhs);
8438 var rhs_mcv = try self.resolveInst(ordered_air.rhs);
8511 const lhs_mcv = try self.resolveInst(ordered_air[0]);
8512 var rhs_mcv = try self.resolveInst(ordered_air[1]);
84398513 switch (lhs_mcv) {
84408514 .immediate => |imm| switch (imm) {
84418515 0 => switch (air_tag) {
8442 .sub, .sub_wrap => return self.genUnOp(maybe_inst, .neg, ordered_air.rhs),
8516 .sub, .sub_wrap => return self.genUnOp(maybe_inst, .neg, ordered_air[1]),
84438517 else => {},
84448518 },
84458519 else => {},
......@@ -8491,10 +8565,10 @@ fn genBinOp(
84918565 };
84928566 if (maybe_inst) |inst| {
84938567 if ((!sse_op or lhs_mcv.isRegister()) and
8494 self.reuseOperandAdvanced(inst, ordered_air.lhs, 0, lhs_mcv, tracked_inst))
8568 self.reuseOperandAdvanced(inst, ordered_air[0], 0, lhs_mcv, tracked_inst))
84958569 break :dst lhs_mcv;
84968570 if (is_commutative and (!sse_op or rhs_mcv.isRegister()) and
8497 self.reuseOperandAdvanced(inst, ordered_air.rhs, 1, rhs_mcv, tracked_inst))
8571 self.reuseOperandAdvanced(inst, ordered_air[1], 1, rhs_mcv, tracked_inst))
84988572 {
84998573 flipped = true;
85008574 break :dst rhs_mcv;
......@@ -8505,7 +8579,7 @@ fn genBinOp(
85058579 copied_to_dst = false
85068580 else
85078581 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv);
8508 rhs_mcv = try self.resolveInst(ordered_air.rhs);
8582 rhs_mcv = try self.resolveInst(ordered_air[1]);
85098583 break :dst dst_mcv;
85108584 };
85118585 const dst_locks: [2]?RegisterLock = switch (dst_mcv) {
......@@ -9905,12 +9979,25 @@ fn genBinOp(
99059979 defer self.register_manager.unlockReg(gp_lock);
99069980
99079981 try self.asmRegisterRegister(switch (mir_tag[0]) {
9908 ._pd, ._sd => .{ ._pd, .movmsk },
9909 ._ps, ._ss => .{ ._ps, .movmsk },
9910 .p_b, .p_d, .p_q, .p_w => .{ .p_b, .movmsk },
9911 .v_pd, .v_sd => .{ .v_pd, .movmsk },
9912 .v_ps, .v_ss => .{ .v_ps, .movmsk },
9913 .vp_b, .vp_d, .vp_q, .vp_w => .{ .vp_b, .movmsk },
9982 ._pd, ._sd, .p_q => .{ ._pd, .movmsk },
9983 ._ps, ._ss, .p_d => .{ ._ps, .movmsk },
9984 .p_b => .{ .p_b, .movmsk },
9985 .p_w => movmsk: {
9986 try self.asmRegisterRegister(.{ .p_b, .ackssw }, dst_reg, dst_reg);
9987 break :movmsk .{ .p_b, .movmsk };
9988 },
9989 .v_pd, .v_sd, .vp_q => .{ .v_pd, .movmsk },
9990 .v_ps, .v_ss, .vp_d => .{ .v_ps, .movmsk },
9991 .vp_b => .{ .vp_b, .movmsk },
9992 .vp_w => movmsk: {
9993 try self.asmRegisterRegisterRegister(
9994 .{ .vp_b, .ackssw },
9995 dst_reg,
9996 dst_reg,
9997 dst_reg,
9998 );
9999 break :movmsk .{ .vp_b, .movmsk };
10000 },
991410001 else => unreachable,
991510002 }, gp_reg.to32(), dst_reg);
991610003 return .{ .register = gp_reg };
......@@ -11488,7 +11575,6 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !Mir.Inst.Index {
1148811575 },
1148911576 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
1149011577 }
11491 return 0; // TODO
1149211578}
1149311579
1149411580fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
......@@ -12275,7 +12361,18 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1227512361 // for the string, we still use the next u32 for the null terminator.
1227612362 extra_i += clobber.len / 4 + 1;
1227712363
12278 // TODO honor these
12364 if (std.mem.eql(u8, clobber, "") or std.mem.eql(u8, clobber, "memory")) {
12365 // ok, sure
12366 } else if (std.mem.eql(u8, clobber, "cc") or
12367 std.mem.eql(u8, clobber, "flags") or
12368 std.mem.eql(u8, clobber, "eflags") or
12369 std.mem.eql(u8, clobber, "rflags"))
12370 {
12371 try self.spillEflagsIfOccupied();
12372 } else {
12373 try self.register_manager.getReg(parseRegName(clobber) orelse
12374 return self.fail("invalid clobber: '{s}'", .{clobber}), null);
12375 }
1227912376 }
1228012377 }
1228112378
......@@ -12777,7 +12874,7 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1277712874 else => {
1277812875 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
1277912876 assert(std.mem.indexOfNone(abi.Class, classes, &.{
12780 .integer, .sse, .float, .float_combine,
12877 .integer, .sse, .memory, .float, .float_combine,
1278112878 }) == null);
1278212879 const abi_size = ty.abiSize(mod);
1278312880 if (abi_size < 4 or
......@@ -12967,6 +13064,24 @@ fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !Mo
1296713064 },
1296813065 else => {},
1296913066 },
13067 .Pointer, .Optional => if (ty.childType(mod).isPtrAtRuntime(mod))
13068 switch (ty.vectorLen(mod)) {
13069 1 => return .{ .move = if (self.hasFeature(.avx))
13070 .{ .v_q, .mov }
13071 else
13072 .{ ._q, .mov } },
13073 2 => return .{ .move = if (self.hasFeature(.avx))
13074 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
13075 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
13076 3...4 => if (self.hasFeature(.avx))
13077 return .{ .move = if (aligned)
13078 .{ .v_, .movdqa }
13079 else
13080 .{ .v_, .movdqu } },
13081 else => {},
13082 }
13083 else
13084 unreachable,
1297013085 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
1297113086 16 => switch (ty.vectorLen(mod)) {
1297213087 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
......@@ -13456,7 +13571,11 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1345613571 };
1345713572 switch (src_mcv) {
1345813573 .none, .unreach, .dead, .reserved_frame => unreachable,
13459 .undef => {},
13574 .undef => try self.genInlineMemset(
13575 dst_ptr_mcv,
13576 .{ .immediate = 0xaa },
13577 .{ .immediate = abi_size },
13578 ),
1346013579 .immediate => |imm| switch (abi_size) {
1346113580 1, 2, 4 => {
1346213581 const immediate = switch (if (ty.isAbiInt(mod))
......@@ -14162,9 +14281,8 @@ fn atomicOp(
1416214281 };
1416314282 defer if (mem_lock) |lock| self.register_manager.unlockReg(lock);
1416414283
14165 const method: enum { lock, loop, libcall } = if (val_ty.isRuntimeFloat())
14166 .loop
14167 else switch (rmw_op orelse .Xchg) {
14284 const use_sse = rmw_op orelse .Xchg != .Xchg and val_ty.isRuntimeFloat();
14285 const strat: enum { lock, loop, libcall } = if (use_sse) .loop else switch (rmw_op orelse .Xchg) {
1416814286 .Xchg,
1416914287 .Add,
1417014288 .Sub,
......@@ -14178,7 +14296,7 @@ fn atomicOp(
1417814296 .Min,
1417914297 => if (val_abi_size <= 16) .loop else .libcall,
1418014298 };
14181 switch (method) {
14299 switch (strat) {
1418214300 .lock => {
1418314301 const tag: Mir.Inst.Tag = if (rmw_op) |op| switch (op) {
1418414302 .Xchg => if (unused) .mov else .xchg,
......@@ -14216,6 +14334,14 @@ fn atomicOp(
1421614334 return if (unused) .unreach else dst_mcv;
1421714335 },
1421814336 .loop => _ = if (val_abi_size <= 8) {
14337 const sse_reg: Register = if (use_sse)
14338 try self.register_manager.allocReg(null, abi.RegisterClass.sse)
14339 else
14340 undefined;
14341 const sse_lock =
14342 if (use_sse) self.register_manager.lockRegAssumeUnused(sse_reg) else undefined;
14343 defer if (use_sse) self.register_manager.unlockReg(sse_lock);
14344
1421914345 const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
1422014346 const tmp_mcv = MCValue{ .register = tmp_reg };
1422114347 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -14223,10 +14349,67 @@ fn atomicOp(
1422314349
1422414350 try self.asmRegisterMemory(.{ ._, .mov }, registerAlias(.rax, val_abi_size), ptr_mem);
1422514351 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
14226 if (rmw_op != std.builtin.AtomicRmwOp.Xchg) {
14352 if (!use_sse and rmw_op orelse .Xchg != .Xchg) {
1422714353 try self.genSetReg(tmp_reg, val_ty, .{ .register = .rax });
1422814354 }
14229 if (rmw_op) |op| switch (op) {
14355 if (rmw_op) |op| if (use_sse) {
14356 const mir_tag = @as(?Mir.Inst.FixedTag, switch (op) {
14357 .Add => switch (val_ty.floatBits(self.target.*)) {
14358 32 => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
14359 64 => if (self.hasFeature(.avx)) .{ .v_sd, .add } else .{ ._sd, .add },
14360 else => null,
14361 },
14362 .Sub => switch (val_ty.floatBits(self.target.*)) {
14363 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },
14364 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sub } else .{ ._sd, .sub },
14365 else => null,
14366 },
14367 .Min => switch (val_ty.floatBits(self.target.*)) {
14368 32 => if (self.hasFeature(.avx)) .{ .v_ss, .min } else .{ ._ss, .min },
14369 64 => if (self.hasFeature(.avx)) .{ .v_sd, .min } else .{ ._sd, .min },
14370 else => null,
14371 },
14372 .Max => switch (val_ty.floatBits(self.target.*)) {
14373 32 => if (self.hasFeature(.avx)) .{ .v_ss, .max } else .{ ._ss, .max },
14374 64 => if (self.hasFeature(.avx)) .{ .v_sd, .max } else .{ ._sd, .max },
14375 else => null,
14376 },
14377 else => unreachable,
14378 }) orelse return self.fail("TODO implement atomicOp of {s} for {}", .{
14379 @tagName(op), val_ty.fmt(mod),
14380 });
14381 try self.genSetReg(sse_reg, val_ty, .{ .register = .rax });
14382 switch (mir_tag[0]) {
14383 .v_ss, .v_sd => if (val_mcv.isMemory()) try self.asmRegisterRegisterMemory(
14384 mir_tag,
14385 sse_reg.to128(),
14386 sse_reg.to128(),
14387 try val_mcv.mem(self, self.memSize(val_ty)),
14388 ) else try self.asmRegisterRegisterRegister(
14389 mir_tag,
14390 sse_reg.to128(),
14391 sse_reg.to128(),
14392 (if (val_mcv.isRegister())
14393 val_mcv.getReg().?
14394 else
14395 try self.copyToTmpRegister(val_ty, val_mcv)).to128(),
14396 ),
14397 ._ss, ._sd => if (val_mcv.isMemory()) try self.asmRegisterMemory(
14398 mir_tag,
14399 sse_reg.to128(),
14400 try val_mcv.mem(self, self.memSize(val_ty)),
14401 ) else try self.asmRegisterRegister(
14402 mir_tag,
14403 sse_reg.to128(),
14404 (if (val_mcv.isRegister())
14405 val_mcv.getReg().?
14406 else
14407 try self.copyToTmpRegister(val_ty, val_mcv)).to128(),
14408 ),
14409 else => unreachable,
14410 }
14411 try self.genSetReg(tmp_reg, val_ty, .{ .register = sse_reg });
14412 } else switch (op) {
1423014413 .Xchg => try self.genSetReg(tmp_reg, val_ty, val_mcv),
1423114414 .Add => try self.genBinOpMir(.{ ._, .add }, val_ty, tmp_mcv, val_mcv),
1423214415 .Sub => try self.genBinOpMir(.{ ._, .sub }, val_ty, tmp_mcv, val_mcv),
......@@ -14362,9 +14545,32 @@ fn atomicOp(
1436214545 try self.asmRegisterMemory(.{ ._, .xor }, .rbx, val_lo_mem);
1436314546 try self.asmRegisterMemory(.{ ._, .xor }, .rcx, val_hi_mem);
1436414547 },
14365 else => return self.fail("TODO implement x86 atomic loop for {} {s}", .{
14366 val_ty.fmt(mod), @tagName(op),
14367 }),
14548 .Min, .Max => {
14549 const cc: Condition = switch (if (val_ty.isAbiInt(mod))
14550 val_ty.intInfo(mod).signedness
14551 else
14552 .unsigned) {
14553 .unsigned => switch (op) {
14554 .Min => .a,
14555 .Max => .b,
14556 else => unreachable,
14557 },
14558 .signed => switch (op) {
14559 .Min => .g,
14560 .Max => .l,
14561 else => unreachable,
14562 },
14563 };
14564
14565 const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .register = .rcx });
14566 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
14567 defer self.register_manager.unlockReg(tmp_lock);
14568
14569 try self.asmRegisterMemory(.{ ._, .cmp }, .rbx, val_lo_mem);
14570 try self.asmRegisterMemory(.{ ._, .sbb }, tmp_reg, val_hi_mem);
14571 try self.asmCmovccRegisterMemory(cc, .rbx, val_lo_mem);
14572 try self.asmCmovccRegisterMemory(cc, .rcx, val_hi_mem);
14573 },
1436814574 };
1436914575 try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem);
1437014576 _ = try self.asmJccReloc(.ne, loop);
......@@ -14448,128 +14654,129 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr
1444814654
1444914655fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1445014656 const mod = self.bin_file.options.module.?;
14451 if (safety) {
14452 // TODO if the value is undef, write 0xaa bytes to dest
14453 } else {
14454 // TODO if the value is undef, don't lower this instruction
14455 }
14456
1445714657 const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
1445814658
14459 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
14460 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
14461 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
14462
14463 const dst_ptr = try self.resolveInst(bin_op.lhs);
14464 const dst_ptr_ty = self.typeOf(bin_op.lhs);
14465 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
14466 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
14467 else => null,
14468 };
14469 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
14470
14471 const src_val = try self.resolveInst(bin_op.rhs);
14472 const elem_ty = self.typeOf(bin_op.rhs);
14473 const src_val_lock: ?RegisterLock = switch (src_val) {
14474 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
14475 else => null,
14476 };
14477 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);
14659 result: {
14660 if (!safety and (try self.resolveInst(bin_op.rhs)) == .undef) break :result;
1447814661
14479 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(mod));
14662 try self.spillRegisters(&.{ .rax, .rdi, .rsi, .rcx });
14663 const reg_locks = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdi, .rsi, .rcx });
14664 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
1448014665
14481 if (elem_abi_size == 1) {
14482 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
14483 // TODO: this only handles slices stored in the stack
14484 .Slice => dst_ptr,
14485 .One => dst_ptr,
14486 .C, .Many => unreachable,
14487 };
14488 const len: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
14489 // TODO: this only handles slices stored in the stack
14490 .Slice => dst_ptr.address().offset(8).deref(),
14491 .One => .{ .immediate = dst_ptr_ty.childType(mod).arrayLen(mod) },
14492 .C, .Many => unreachable,
14493 };
14494 const len_lock: ?RegisterLock = switch (len) {
14666 const dst_ptr = try self.resolveInst(bin_op.lhs);
14667 const dst_ptr_ty = self.typeOf(bin_op.lhs);
14668 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
1449514669 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1449614670 else => null,
1449714671 };
14498 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
14499
14500 try self.genInlineMemset(ptr, src_val, len);
14501 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
14502 }
14672 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
1450314673
14504 // Store the first element, and then rely on memcpy copying forwards.
14505 // Length zero requires a runtime check - so we handle arrays specially
14506 // here to elide it.
14507 switch (dst_ptr_ty.ptrSize(mod)) {
14508 .Slice => {
14509 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(mod);
14510
14511 // TODO: this only handles slices stored in the stack
14512 const ptr = dst_ptr;
14513 const len = dst_ptr.address().offset(8).deref();
14514
14515 // Used to store the number of elements for comparison.
14516 // After comparison, updated to store number of bytes needed to copy.
14517 const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14518 const len_mcv: MCValue = .{ .register = len_reg };
14519 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
14520 defer self.register_manager.unlockReg(len_lock);
14521
14522 try self.genSetReg(len_reg, Type.usize, len);
14523 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
14674 const src_val = try self.resolveInst(bin_op.rhs);
14675 const elem_ty = self.typeOf(bin_op.rhs);
14676 const src_val_lock: ?RegisterLock = switch (src_val) {
14677 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
14678 else => null,
14679 };
14680 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);
1452414681
14525 const skip_reloc = try self.asmJccReloc(.z, undefined);
14526 try self.store(slice_ptr_ty, ptr, src_val);
14682 const elem_abi_size: u31 = @intCast(elem_ty.abiSize(mod));
1452714683
14528 const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14529 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
14530 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
14531 defer self.register_manager.unlockReg(second_elem_ptr_lock);
14684 if (elem_abi_size == 1) {
14685 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
14686 // TODO: this only handles slices stored in the stack
14687 .Slice => dst_ptr,
14688 .One => dst_ptr,
14689 .C, .Many => unreachable,
14690 };
14691 const len: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
14692 // TODO: this only handles slices stored in the stack
14693 .Slice => dst_ptr.address().offset(8).deref(),
14694 .One => .{ .immediate = dst_ptr_ty.childType(mod).arrayLen(mod) },
14695 .C, .Many => unreachable,
14696 };
14697 const len_lock: ?RegisterLock = switch (len) {
14698 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
14699 else => null,
14700 };
14701 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
1453214702
14533 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
14534 .reg = try self.copyToTmpRegister(Type.usize, ptr),
14535 .off = elem_abi_size,
14536 } });
14703 try self.genInlineMemset(ptr, src_val, len);
14704 break :result;
14705 }
1453714706
14538 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });
14539 try self.asmRegisterRegisterImmediate(
14540 .{ .i_, .mul },
14541 len_reg,
14542 len_reg,
14543 Immediate.s(elem_abi_size),
14544 );
14545 try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv);
14707 // Store the first element, and then rely on memcpy copying forwards.
14708 // Length zero requires a runtime check - so we handle arrays specially
14709 // here to elide it.
14710 switch (dst_ptr_ty.ptrSize(mod)) {
14711 .Slice => {
14712 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(mod);
14713
14714 // TODO: this only handles slices stored in the stack
14715 const ptr = dst_ptr;
14716 const len = dst_ptr.address().offset(8).deref();
14717
14718 // Used to store the number of elements for comparison.
14719 // After comparison, updated to store number of bytes needed to copy.
14720 const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14721 const len_mcv: MCValue = .{ .register = len_reg };
14722 const len_lock = self.register_manager.lockRegAssumeUnused(len_reg);
14723 defer self.register_manager.unlockReg(len_lock);
14724
14725 try self.genSetReg(len_reg, Type.usize, len);
14726 try self.asmRegisterRegister(.{ ._, .@"test" }, len_reg, len_reg);
14727
14728 const skip_reloc = try self.asmJccReloc(.z, undefined);
14729 try self.store(slice_ptr_ty, ptr, src_val);
14730
14731 const second_elem_ptr_reg =
14732 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14733 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
14734 const second_elem_ptr_lock =
14735 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
14736 defer self.register_manager.unlockReg(second_elem_ptr_lock);
14737
14738 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
14739 .reg = try self.copyToTmpRegister(Type.usize, ptr),
14740 .off = elem_abi_size,
14741 } });
14742
14743 try self.genBinOpMir(.{ ._, .sub }, Type.usize, len_mcv, .{ .immediate = 1 });
14744 try self.asmRegisterRegisterImmediate(
14745 .{ .i_, .mul },
14746 len_reg,
14747 len_reg,
14748 Immediate.s(elem_abi_size),
14749 );
14750 try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv);
1454614751
14547 try self.performReloc(skip_reloc);
14548 },
14549 .One => {
14550 const elem_ptr_ty = try mod.singleMutPtrType(elem_ty);
14752 try self.performReloc(skip_reloc);
14753 },
14754 .One => {
14755 const elem_ptr_ty = try mod.singleMutPtrType(elem_ty);
1455114756
14552 const len = dst_ptr_ty.childType(mod).arrayLen(mod);
14757 const len = dst_ptr_ty.childType(mod).arrayLen(mod);
1455314758
14554 assert(len != 0); // prevented by Sema
14555 try self.store(elem_ptr_ty, dst_ptr, src_val);
14759 assert(len != 0); // prevented by Sema
14760 try self.store(elem_ptr_ty, dst_ptr, src_val);
1455614761
14557 const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14558 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
14559 const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
14560 defer self.register_manager.unlockReg(second_elem_ptr_lock);
14762 const second_elem_ptr_reg =
14763 try self.register_manager.allocReg(null, abi.RegisterClass.gp);
14764 const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg };
14765 const second_elem_ptr_lock =
14766 self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg);
14767 defer self.register_manager.unlockReg(second_elem_ptr_lock);
1456114768
14562 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
14563 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
14564 .off = elem_abi_size,
14565 } });
14769 try self.genSetReg(second_elem_ptr_reg, Type.usize, .{ .register_offset = .{
14770 .reg = try self.copyToTmpRegister(Type.usize, dst_ptr),
14771 .off = elem_abi_size,
14772 } });
1456614773
14567 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
14568 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
14569 },
14570 .C, .Many => unreachable,
14774 const bytes_to_copy: MCValue = .{ .immediate = elem_abi_size * (len - 1) };
14775 try self.genInlineMemcpy(second_elem_ptr_mcv, dst_ptr, bytes_to_copy);
14776 },
14777 .C, .Many => unreachable,
14778 }
1457114779 }
14572
1457314780 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
1457414781}
1457514782
......@@ -15285,29 +15492,61 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1528515492 }
1528615493 break :result .{ .load_frame = .{ .index = frame_index } };
1528715494 },
15288 .Array => {
15289 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
15495 .Array, .Vector => {
1529015496 const elem_ty = result_ty.childType(mod);
15291 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));
15497 if (result_ty.isVector(mod) and elem_ty.bitSize(mod) == 1) {
15498 const result_size: u32 = @intCast(result_ty.abiSize(mod));
15499 const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp);
15500 try self.asmRegisterRegister(
15501 .{ ._, .xor },
15502 registerAlias(dst_reg, @min(result_size, 4)),
15503 registerAlias(dst_reg, @min(result_size, 4)),
15504 );
1529215505
15293 for (elements, 0..) |elem, elem_i| {
15294 const elem_mcv = try self.resolveInst(elem);
15295 const mat_elem_mcv = switch (elem_mcv) {
15296 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
15297 else => elem_mcv,
15298 };
15299 const elem_off: i32 = @intCast(elem_size * elem_i);
15300 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);
15506 for (elements, 0..) |elem, elem_i| {
15507 const elem_reg = try self.copyToTmpRegister(elem_ty, .{ .air_ref = elem });
15508 const elem_lock = self.register_manager.lockRegAssumeUnused(elem_reg);
15509 defer self.register_manager.unlockReg(elem_lock);
15510
15511 try self.asmRegisterImmediate(
15512 .{ ._, .@"and" },
15513 registerAlias(elem_reg, @min(result_size, 4)),
15514 Immediate.u(1),
15515 );
15516 if (elem_i > 0) try self.asmRegisterImmediate(
15517 .{ ._l, .sh },
15518 registerAlias(elem_reg, result_size),
15519 Immediate.u(@intCast(elem_i)),
15520 );
15521 try self.asmRegisterRegister(
15522 .{ ._, .@"or" },
15523 registerAlias(dst_reg, result_size),
15524 registerAlias(elem_reg, result_size),
15525 );
15526 }
15527 break :result .{ .register = dst_reg };
15528 } else {
15529 const frame_index = try self.allocFrameIndex(FrameAlloc.initSpill(result_ty, mod));
15530 const elem_size: u32 = @intCast(elem_ty.abiSize(mod));
15531
15532 for (elements, 0..) |elem, elem_i| {
15533 const elem_mcv = try self.resolveInst(elem);
15534 const mat_elem_mcv = switch (elem_mcv) {
15535 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
15536 else => elem_mcv,
15537 };
15538 const elem_off: i32 = @intCast(elem_size * elem_i);
15539 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);
15540 }
15541 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
15542 .{ .frame = frame_index },
15543 @intCast(elem_size * elements.len),
15544 elem_ty,
15545 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),
15546 );
15547 break :result .{ .load_frame = .{ .index = frame_index } };
1530115548 }
15302 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
15303 .{ .frame = frame_index },
15304 @intCast(elem_size * elements.len),
15305 elem_ty,
15306 try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }),
15307 );
15308 break :result .{ .load_frame = .{ .index = frame_index } };
1530915549 },
15310 .Vector => return self.fail("TODO implement aggregate_init for vectors", .{}),
1531115550 else => unreachable,
1531215551 }
1531315552 };
src/codegen.zig+50-5
......@@ -389,7 +389,47 @@ pub fn generateSymbol(
389389 },
390390 },
391391 .vector_type => |vector_type| {
392 switch (aggregate.storage) {
392 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
393 return error.Overflow;
394 if (Type.fromInterned(vector_type.child).bitSize(mod) == 1) {
395 const bytes = try code.addManyAsSlice(abi_size);
396 @memset(bytes, 0xaa);
397 var index: usize = 0;
398 const len = math.cast(usize, vector_type.len) orelse return error.Overflow;
399 while (index < len) : (index += 1) {
400 const bit_index = switch (endian) {
401 .big => len - 1 - index,
402 .little => index,
403 };
404 const byte = &bytes[bit_index / 8];
405 const mask = @as(u8, 1) << @truncate(bit_index);
406 if (switch (switch (aggregate.storage) {
407 .bytes => unreachable,
408 .elems => |elems| elems[index],
409 .repeated_elem => |elem| elem,
410 }) {
411 .bool_true => true,
412 .bool_false => false,
413 else => |elem| switch (mod.intern_pool.indexToKey(elem)) {
414 .undef => continue,
415 .int => |int| switch (int.storage) {
416 .u64 => |x| switch (x) {
417 0 => false,
418 1 => true,
419 else => unreachable,
420 },
421 .i64 => |x| switch (x) {
422 -1 => true,
423 0 => false,
424 else => unreachable,
425 },
426 else => unreachable,
427 },
428 else => unreachable,
429 },
430 }) byte.* |= mask else byte.* &= ~mask;
431 }
432 } else switch (aggregate.storage) {
393433 .bytes => |bytes| try code.appendSlice(bytes),
394434 .elems, .repeated_elem => {
395435 var index: u64 = 0;
......@@ -398,7 +438,9 @@ pub fn generateSymbol(
398438 .ty = Type.fromInterned(vector_type.child),
399439 .val = Value.fromInterned(switch (aggregate.storage) {
400440 .bytes => unreachable,
401 .elems => |elems| elems[@as(usize, @intCast(index))],
441 .elems => |elems| elems[
442 math.cast(usize, index) orelse return error.Overflow
443 ],
402444 .repeated_elem => |elem| elem,
403445 }),
404446 }, code, debug_output, reloc_info)) {
......@@ -409,11 +451,14 @@ pub fn generateSymbol(
409451 },
410452 }
411453
412 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
413 (math.divCeil(u64, Type.fromInterned(vector_type.child).bitSize(mod) * vector_type.len, 8) catch |err| switch (err) {
454 const padding = abi_size - (math.cast(usize, math.divCeil(
455 u64,
456 Type.fromInterned(vector_type.child).bitSize(mod) * vector_type.len,
457 8,
458 ) catch |err| switch (err) {
414459 error.DivisionByZero => unreachable,
415460 else => |e| return e,
416 })) orelse return error.Overflow;
461 }) orelse return error.Overflow);
417462 if (padding > 0) try code.appendNTimes(0, padding);
418463 },
419464 .anon_struct_type => |tuple| {
src/link/Coff.zig+2
......@@ -316,6 +316,8 @@ pub fn deinit(self: *Coff) void {
316316 }
317317 self.import_tables.deinit(gpa);
318318
319 self.lazy_syms.deinit(gpa);
320
319321 for (self.decls.values()) |*metadata| {
320322 metadata.deinit(gpa);
321323 }
src/link/msdos-stub.bin
Binary files a/src/link/msdos-stub.bin and b/src/link/msdos-stub.bin differ
src/print_air.zig+11-11
......@@ -97,7 +97,7 @@ const Writer = struct {
9797 const tag = w.air.instructions.items(.tag)[@intFromEnum(inst)];
9898 try s.writeByteNTimes(' ', w.indent);
9999 try s.print("%{d}{c}= {s}(", .{
100 inst,
100 @intFromEnum(inst),
101101 @as(u8, if (if (w.liveness) |liveness| liveness.isUnused(inst) else false) '!' else ' '),
102102 @tagName(tag),
103103 });
......@@ -388,7 +388,7 @@ const Writer = struct {
388388 try s.writeAll("}");
389389
390390 for (liveness_block.deaths) |operand| {
391 try s.print(" %{d}!", .{operand});
391 try s.print(" %{d}!", .{@intFromEnum(operand)});
392392 }
393393 }
394394
......@@ -715,7 +715,7 @@ const Writer = struct {
715715 try s.writeByteNTimes(' ', w.indent);
716716 for (liveness_condbr.else_deaths, 0..) |operand, i| {
717717 if (i != 0) try s.writeAll(" ");
718 try s.print("%{d}!", .{operand});
718 try s.print("%{d}!", .{@intFromEnum(operand)});
719719 }
720720 try s.writeAll("\n");
721721 }
......@@ -726,7 +726,7 @@ const Writer = struct {
726726 try s.writeAll("}");
727727
728728 for (liveness_condbr.then_deaths) |operand| {
729 try s.print(" %{d}!", .{operand});
729 try s.print(" %{d}!", .{@intFromEnum(operand)});
730730 }
731731 }
732732
......@@ -752,7 +752,7 @@ const Writer = struct {
752752 try s.writeByteNTimes(' ', w.indent);
753753 for (liveness_condbr.else_deaths, 0..) |operand, i| {
754754 if (i != 0) try s.writeAll(" ");
755 try s.print("%{d}!", .{operand});
755 try s.print("%{d}!", .{@intFromEnum(operand)});
756756 }
757757 try s.writeAll("\n");
758758 }
......@@ -763,7 +763,7 @@ const Writer = struct {
763763 try s.writeAll("}");
764764
765765 for (liveness_condbr.then_deaths) |operand| {
766 try s.print(" %{d}!", .{operand});
766 try s.print(" %{d}!", .{@intFromEnum(operand)});
767767 }
768768 }
769769
......@@ -787,7 +787,7 @@ const Writer = struct {
787787 try s.writeByteNTimes(' ', w.indent);
788788 for (liveness_condbr.then_deaths, 0..) |operand, i| {
789789 if (i != 0) try s.writeAll(" ");
790 try s.print("%{d}!", .{operand});
790 try s.print("%{d}!", .{@intFromEnum(operand)});
791791 }
792792 try s.writeAll("\n");
793793 }
......@@ -800,7 +800,7 @@ const Writer = struct {
800800 try s.writeByteNTimes(' ', w.indent);
801801 for (liveness_condbr.else_deaths, 0..) |operand, i| {
802802 if (i != 0) try s.writeAll(" ");
803 try s.print("%{d}!", .{operand});
803 try s.print("%{d}!", .{@intFromEnum(operand)});
804804 }
805805 try s.writeAll("\n");
806806 }
......@@ -852,7 +852,7 @@ const Writer = struct {
852852 try s.writeByteNTimes(' ', w.indent);
853853 for (deaths, 0..) |operand, i| {
854854 if (i != 0) try s.writeAll(" ");
855 try s.print("%{d}!", .{operand});
855 try s.print("%{d}!", .{@intFromEnum(operand)});
856856 }
857857 try s.writeAll("\n");
858858 }
......@@ -873,7 +873,7 @@ const Writer = struct {
873873 try s.writeByteNTimes(' ', w.indent);
874874 for (deaths, 0..) |operand, i| {
875875 if (i != 0) try s.writeAll(" ");
876 try s.print("%{d}!", .{operand});
876 try s.print("%{d}!", .{@intFromEnum(operand)});
877877 }
878878 try s.writeAll("\n");
879879 }
......@@ -957,7 +957,7 @@ const Writer = struct {
957957 dies: bool,
958958 ) @TypeOf(s).Error!void {
959959 _ = w;
960 try s.print("%{d}", .{inst});
960 try s.print("%{d}", .{@intFromEnum(inst)});
961961 if (dies) try s.writeByte('!');
962962 }
963963
test/behavior/atomics.zig-2
......@@ -208,7 +208,6 @@ fn testAtomicStore() !void {
208208}
209209
210210test "atomicrmw with floats" {
211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
212211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
213212 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
214213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -316,7 +315,6 @@ test "atomicrmw with 128-bit ints" {
316315 if (!supports_128_bit_atomics) return error.SkipZigTest;
317316
318317 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
319 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
320318
321319 // TODO "ld.lld: undefined symbol: __sync_lock_test_and_set_16" on -mcpu x86_64
322320 if (builtin.cpu.arch == .x86_64 and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
test/behavior/bitcast.zig-1
......@@ -393,7 +393,6 @@ test "bitcast vector to integer and back" {
393393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
394394 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
395395 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
396 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
397396 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
398397 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
399398
test/behavior/bugs/2114.zig+1-2
......@@ -9,8 +9,7 @@ fn ctz(x: anytype) usize {
99
1010test "fixed" {
1111 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_x86_64 and
13 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .bmi)) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
1413 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1514 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/cast.zig+3-9
......@@ -336,7 +336,6 @@ test "array coercion to undefined at runtime" {
336336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
337337 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
338338 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
339 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
340339
341340 @setRuntimeSafety(true);
342341
......@@ -1477,7 +1476,7 @@ test "coerce between pointers of compatible differently-named floats" {
14771476 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
14781477 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
14791478
1480 if (builtin.os.tag == .windows) {
1479 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
14811480 // https://github.com/ziglang/zig/issues/12396
14821481 return error.SkipZigTest;
14831482 }
......@@ -1724,7 +1723,6 @@ test "peer type resolution: array and vector with same child type" {
17241723test "peer type resolution: array with smaller child type and vector with larger child type" {
17251724 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17261725 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1727 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
17281726 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
17291727 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
17301728 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
......@@ -2312,11 +2310,11 @@ test "cast builtins can wrap result in error union and optional" {
23122310
23132311test "@floatCast on vector" {
23142312 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2315 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
23162313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23172314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23182315 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23192316 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2317 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
23202318
23212319 const S = struct {
23222320 fn doTheTest() !void {
......@@ -2333,7 +2331,6 @@ test "@floatCast on vector" {
23332331
23342332test "@ptrFromInt on vector" {
23352333 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2336 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
23372334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23382335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23392336 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -2358,7 +2355,6 @@ test "@ptrFromInt on vector" {
23582355
23592356test "@intFromPtr on vector" {
23602357 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2361 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
23622358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23632359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23642360 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -2383,11 +2379,11 @@ test "@intFromPtr on vector" {
23832379
23842380test "@floatFromInt on vector" {
23852381 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2386 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
23872382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
23882383 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
23892384 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
23902385 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
2386 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
23912387
23922388 const S = struct {
23932389 fn doTheTest() !void {
......@@ -2404,7 +2400,6 @@ test "@floatFromInt on vector" {
24042400
24052401test "@intFromFloat on vector" {
24062402 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2407 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
24082403 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
24092404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
24102405 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -2425,7 +2420,6 @@ test "@intFromFloat on vector" {
24252420
24262421test "@intFromBool on vector" {
24272422 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2428 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
24292423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
24302424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
24312425 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/int128.zig-1
......@@ -28,7 +28,6 @@ test "undefined 128 bit int" {
2828 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2929 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
3030 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3231
3332 @setRuntimeSafety(true);
3433
test/behavior/math.zig+3-3
......@@ -78,12 +78,11 @@ fn testClz() !void {
7878}
7979
8080test "@clz big ints" {
81 if (builtin.zig_backend == .stage2_x86_64 and
82 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .lzcnt)) return error.SkipZigTest; // TODO
8381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8482 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8583 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8684 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
8786
8887 try testClzBigInts();
8988 try comptime testClzBigInts();
......@@ -1610,8 +1609,9 @@ test "vector comparison" {
16101609 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16111610 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16121611 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
16141612 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1613 if (builtin.zig_backend == .stage2_x86_64 and
1614 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx2)) return error.SkipZigTest;
16151615
16161616 const S = struct {
16171617 fn doTheTest() !void {
test/behavior/packed-struct.zig-1
......@@ -804,7 +804,6 @@ test "nested packed struct at non-zero offset" {
804804}
805805
806806test "nested packed struct at non-zero offset 2" {
807 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
808807 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
809808 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
810809 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/vector.zig+1-3
......@@ -49,7 +49,6 @@ test "vector wrap operators" {
4949
5050test "vector bin compares with mem.eql" {
5151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5352 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5453 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5554 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -222,7 +221,7 @@ test "array to vector with element type coercion" {
222221 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
223222 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
224223 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
225 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf) return error.SkipZigTest;
226225
227226 const S = struct {
228227 fn doTheTest() !void {
......@@ -1234,7 +1233,6 @@ test "array of vectors is copied" {
12341233
12351234test "byte vector initialized in inline function" {
12361235 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1237 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12381236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12391237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12401238 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO