authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-27 22:51:58-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-27 23:31:20-04:00
loga440cf6d4454d3febfe07b6235745120d104cfa0
treea8c74967623411292b22b574956df98b97f43423
parentaecdf6ad50fef3ef68d699c2ef72b5904fdd3553

x86_64: fix c abi test failures


8 files changed, 489 insertions(+), 404 deletions(-)

lib/compiler_rt/tan.zig-2
......@@ -144,8 +144,6 @@ test "tan32" {
144144}
145145
146146test "tan64" {
147 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
148
149147 const epsilon = 0.000001;
150148
151149 try expect(math.approxEqAbs(f64, tan(0.0), 0.0, epsilon));
lib/std/atomic/Atomic.zig-2
......@@ -374,8 +374,6 @@ const atomic_rmw_orderings = [_]Ordering{
374374};
375375
376376test "Atomic.swap" {
377 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
378
379377 inline for (atomic_rmw_orderings) |ordering| {
380378 var x = Atomic(usize).init(5);
381379 try testing.expectEqual(x.swap(10, ordering), 5);
lib/std/debug.zig-2
......@@ -2513,8 +2513,6 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void {
25132513}
25142514
25152515test "manage resources correctly" {
2516 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2517
25182516 if (builtin.os.tag == .wasi) return error.SkipZigTest;
25192517
25202518 if (builtin.os.tag == .windows) {
lib/std/fmt/parse_float.zig+1-12
......@@ -2,7 +2,6 @@ pub const parseFloat = @import("parse_float/parse_float.zig").parseFloat;
22pub const ParseFloatError = @import("parse_float/parse_float.zig").ParseFloatError;
33
44const std = @import("std");
5const builtin = @import("builtin");
65const math = std.math;
76const testing = std.testing;
87const expect = testing.expect;
......@@ -14,8 +13,6 @@ const epsilon = 1e-7;
1413// See https://github.com/tiehuis/parse-number-fxx-test-data for a wider-selection of test-data.
1514
1615test "fmt.parseFloat" {
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
18
1916 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
2017 try testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
2118 try testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
......@@ -72,8 +69,6 @@ test "fmt.parseFloat" {
7269}
7370
7471test "fmt.parseFloat nan and inf" {
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
76
7772 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
7873 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
7974
......@@ -88,7 +83,7 @@ test "fmt.parseFloat #11169" {
8883}
8984
9085test "fmt.parseFloat hex.special" {
91 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
86 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
9287
9388 try testing.expect(math.isNan(try parseFloat(f32, "nAn")));
9489 try testing.expect(math.isPositiveInf(try parseFloat(f32, "iNf")));
......@@ -96,8 +91,6 @@ test "fmt.parseFloat hex.special" {
9691 try testing.expect(math.isNegativeInf(try parseFloat(f32, "-iNf")));
9792}
9893test "fmt.parseFloat hex.zero" {
99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
100
10194 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0"));
10295 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "-0x0"));
10396 try testing.expectEqual(@as(f32, 0.0), try parseFloat(f32, "0x0p42"));
......@@ -106,8 +99,6 @@ test "fmt.parseFloat hex.zero" {
10699}
107100
108101test "fmt.parseFloat hex.f16" {
109 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
110
111102 try testing.expectEqual(try parseFloat(f16, "0x1p0"), 1.0);
112103 try testing.expectEqual(try parseFloat(f16, "-0x1p-1"), -0.5);
113104 try testing.expectEqual(try parseFloat(f16, "0x10p+10"), 16384.0);
......@@ -124,8 +115,6 @@ test "fmt.parseFloat hex.f16" {
124115}
125116
126117test "fmt.parseFloat hex.f32" {
127 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
128
129118 try testing.expectError(error.InvalidCharacter, parseFloat(f32, "0x"));
130119 try testing.expectEqual(try parseFloat(f32, "0x1p0"), 1.0);
131120 try testing.expectEqual(try parseFloat(f32, "-0x1p-1"), -0.5);
lib/std/json/static_test.zig-2
......@@ -785,8 +785,6 @@ test "max_value_len" {
785785}
786786
787787test "parse into vector" {
788 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
789
790788 const T = struct {
791789 vec_i32: @Vector(4, i32),
792790 vec_f32: @Vector(2, f32),
src/arch/x86_64/CodeGen.zig+480-291
......@@ -6587,12 +6587,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
65876587 const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg);
65886588 defer self.register_manager.unlockReg(src_reg_lock);
65896589
6590 const dst_reg = if (field_rc.supersetOf(container_rc) and
6591 self.reuseOperand(inst, operand, 0, src_mcv))
6590 const src_in_field_rc =
6591 field_rc.isSet(RegisterManager.indexOfRegIntoTracked(src_reg).?);
6592 const dst_reg = if (src_in_field_rc and self.reuseOperand(inst, operand, 0, src_mcv))
65926593 src_reg
6594 else if (field_off == 0)
6595 (try self.copyToRegisterWithInstTracking(inst, field_ty, src_mcv)).register
65936596 else
65946597 try self.copyToTmpRegister(Type.usize, .{ .register = src_reg });
6595 const dst_mcv = MCValue{ .register = dst_reg };
6598 const dst_mcv: MCValue = .{ .register = dst_reg };
65966599 const dst_lock = self.register_manager.lockReg(dst_reg);
65976600 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
65986601
......@@ -6602,9 +6605,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
66026605 dst_mcv,
66036606 .{ .immediate = field_off },
66046607 );
6605 if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg);
6608 if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and
6609 container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod))
6610 try self.truncateRegister(field_ty, dst_reg);
66066611
6607 break :result if (field_rc.supersetOf(abi.RegisterClass.gp))
6612 break :result if (field_off == 0 or field_rc.supersetOf(abi.RegisterClass.gp))
66086613 dst_mcv
66096614 else
66106615 try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv);
......@@ -9674,17 +9679,25 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
96749679 self.arg_index = arg_index + 1;
96759680
96769681 const result: MCValue = if (self.liveness.isUnused(inst)) .unreach else result: {
9677 const dst_mcv = self.args[arg_index];
9678 switch (dst_mcv) {
9679 .register, .register_pair, .load_frame => for (dst_mcv.getRegs()) |reg|
9680 self.register_manager.getRegAssumeFree(reg, inst),
9681 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),
9682 }
9682 const arg_ty = self.typeOfIndex(inst);
9683 const src_mcv = self.args[arg_index];
9684 const dst_mcv = switch (src_mcv) {
9685 .register, .register_pair, .load_frame => dst: {
9686 for (src_mcv.getRegs()) |reg| self.register_manager.getRegAssumeFree(reg, inst);
9687 break :dst src_mcv;
9688 },
9689 .indirect => |reg_off| dst: {
9690 self.register_manager.getRegAssumeFree(reg_off.reg, inst);
9691 const dst_mcv = try self.allocRegOrMem(inst, false);
9692 try self.genCopy(arg_ty, dst_mcv, src_mcv);
9693 break :dst dst_mcv;
9694 },
9695 else => return self.fail("TODO implement arg for {}", .{src_mcv}),
9696 };
96839697
9684 const ty = self.typeOfIndex(inst);
96859698 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
96869699 const name = mod.getParamName(self.owner.func_index, src_index);
9687 try self.genArgDbgInfo(ty, name, dst_mcv);
9700 try self.genArgDbgInfo(arg_ty, name, src_mcv);
96889701
96899702 break :result dst_mcv;
96909703 };
......@@ -9863,7 +9876,8 @@ fn genCall(self: *Self, info: union(enum) {
98639876
98649877 const ExpectedContents = extern struct {
98659878 var_args: [16][@sizeOf(Type)]u8 align(@alignOf(Type)),
9866 arg_regs: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
9879 frame_indices: [16]FrameIndex,
9880 reg_locks: [16][@sizeOf(?RegisterLock)]u8 align(@alignOf(?RegisterLock)),
98679881 };
98689882 var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) =
98699883 std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa);
......@@ -9873,10 +9887,13 @@ fn genCall(self: *Self, info: union(enum) {
98739887 defer allocator.free(var_args);
98749888 for (var_args, arg_types[fn_info.param_types.len..]) |*var_arg, arg_ty| var_arg.* = arg_ty;
98759889
9876 var arg_locks = std.ArrayList(?RegisterLock).init(allocator);
9877 defer arg_locks.deinit();
9878 try arg_locks.ensureTotalCapacity(16);
9879 defer for (arg_locks.items) |arg_lock| if (arg_lock) |lock| self.register_manager.unlockReg(lock);
9890 const frame_indices = try allocator.alloc(FrameIndex, args.len);
9891 defer allocator.free(frame_indices);
9892
9893 var reg_locks = std.ArrayList(?RegisterLock).init(allocator);
9894 defer reg_locks.deinit();
9895 try reg_locks.ensureTotalCapacity(16);
9896 defer for (reg_locks.items) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
98809897
98819898 var call_info = try self.resolveCallingConventionValues(fn_info, var_args, .call_frame);
98829899 defer call_info.deinit(self);
......@@ -9908,44 +9925,69 @@ fn genCall(self: *Self, info: union(enum) {
99089925 .indirect => |reg_off| try self.spillRegisters(&.{reg_off.reg}),
99099926 else => unreachable,
99109927 }
9911 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
9912 .none => {},
9913 .register => |reg| {
9914 try self.spillRegisters(&.{reg});
9915 try arg_locks.append(self.register_manager.lockReg(reg));
9916 },
9917 .register_pair => |regs| {
9918 try self.spillRegisters(&regs);
9919 try arg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
9920 },
9921 .load_frame => {
9922 try self.genCopy(arg_ty, dst_arg, src_arg);
9923 try self.freeValue(src_arg);
9924 },
9925 else => unreachable,
9926 };
9928 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, *frame_index|
9929 switch (dst_arg) {
9930 .none => {},
9931 .register => |reg| {
9932 try self.spillRegisters(&.{reg});
9933 try reg_locks.append(self.register_manager.lockReg(reg));
9934 },
9935 .register_pair => |regs| {
9936 try self.spillRegisters(&regs);
9937 try reg_locks.appendSlice(&self.register_manager.lockRegs(2, regs));
9938 },
9939 .indirect => |reg_off| {
9940 frame_index.* = try self.allocFrameIndex(FrameAlloc.initType(arg_ty, mod));
9941 try self.genSetMem(.{ .frame = frame_index.* }, 0, arg_ty, src_arg);
9942 try self.spillRegisters(&.{reg_off.reg});
9943 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
9944 },
9945 .load_frame => {
9946 try self.genCopy(arg_ty, dst_arg, src_arg);
9947 try self.freeValue(src_arg);
9948 },
9949 else => unreachable,
9950 };
99279951
99289952 // now we are free to set register arguments
9929 const ret_lock = switch (call_info.return_value.long) {
9930 .none, .unreach => null,
9931 .indirect => |reg_off| lock: {
9953 switch (call_info.return_value.long) {
9954 .none, .unreach => {},
9955 .indirect => |reg_off| {
99329956 const ret_ty = fn_info.return_type.toType();
99339957 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
99349958 try self.genSetReg(reg_off.reg, Type.usize, .{
99359959 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
99369960 });
99379961 call_info.return_value.short = .{ .load_frame = .{ .index = frame_index } };
9938 break :lock self.register_manager.lockRegAssumeUnused(reg_off.reg);
9962 try reg_locks.append(self.register_manager.lockReg(reg_off.reg));
99399963 },
99409964 else => unreachable,
9941 };
9942 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
9965 }
99439966
9944 for (call_info.args, arg_types, args) |dst_arg, arg_ty, src_arg| switch (dst_arg) {
9945 .none, .load_frame => {},
9946 .register, .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),
9947 else => unreachable,
9948 };
9967 for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index|
9968 switch (dst_arg) {
9969 .none, .load_frame => {},
9970 .register => |dst_reg| switch (fn_info.cc) {
9971 else => try self.genSetReg(
9972 registerAlias(dst_reg, @intCast(arg_ty.abiSize(mod))),
9973 arg_ty,
9974 src_arg,
9975 ),
9976 .C, .SysV, .Win64 => {
9977 const promoted_ty = self.promoteInt(arg_ty);
9978 const promoted_abi_size: u32 = @intCast(promoted_ty.abiSize(mod));
9979 const dst_alias = registerAlias(dst_reg, promoted_abi_size);
9980 try self.genSetReg(dst_alias, promoted_ty, src_arg);
9981 if (promoted_ty.toIntern() != arg_ty.toIntern())
9982 try self.truncateRegister(arg_ty, dst_alias);
9983 },
9984 },
9985 .register_pair => try self.genCopy(arg_ty, dst_arg, src_arg),
9986 .indirect => |reg_off| try self.genSetReg(reg_off.reg, Type.usize, .{
9987 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
9988 }),
9989 else => unreachable,
9990 };
99499991
99509992 if (fn_info.is_var_args)
99519993 try self.asmRegisterImmediate(.{ ._, .mov }, .al, Immediate.u(call_info.fp_count));
......@@ -10054,7 +10096,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
1005410096 const ptr_ty = self.typeOf(un_op);
1005510097 switch (self.ret_mcv.short) {
1005610098 .none => {},
10057 .register => try self.load(self.ret_mcv.short, ptr_ty, ptr),
10099 .register, .register_pair => try self.load(self.ret_mcv.short, ptr_ty, ptr),
1005810100 .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr),
1005910101 else => unreachable,
1006010102 }
......@@ -10115,20 +10157,28 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1011510157 try self.spillEflagsIfOccupied();
1011610158
1011710159 const lhs_mcv = try self.resolveInst(bin_op.lhs);
10118 const lhs_lock = switch (lhs_mcv) {
10119 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
10120 .register_offset => |ro| self.register_manager.lockRegAssumeUnused(ro.reg),
10121 else => null,
10160 const lhs_locks: [2]?RegisterLock = switch (lhs_mcv) {
10161 .register => |lhs_reg| .{ self.register_manager.lockRegAssumeUnused(lhs_reg), null },
10162 .register_pair => |lhs_regs| locks: {
10163 const locks = self.register_manager.lockRegsAssumeUnused(2, lhs_regs);
10164 break :locks .{ locks[0], locks[1] };
10165 },
10166 .register_offset => |lhs_ro| .{
10167 self.register_manager.lockRegAssumeUnused(lhs_ro.reg),
10168 null,
10169 },
10170 else => .{null} ** 2,
1012210171 };
10123 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
10172 defer for (lhs_locks) |lhs_lock| if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
1012410173
1012510174 const rhs_mcv = try self.resolveInst(bin_op.rhs);
10126 const rhs_lock = switch (rhs_mcv) {
10127 .register => |reg| self.register_manager.lockReg(reg),
10128 .register_offset => |ro| self.register_manager.lockReg(ro.reg),
10129 else => null,
10175 const rhs_locks: [2]?RegisterLock = switch (rhs_mcv) {
10176 .register => |rhs_reg| .{ self.register_manager.lockReg(rhs_reg), null },
10177 .register_pair => |rhs_regs| self.register_manager.lockRegs(2, rhs_regs),
10178 .register_offset => |rhs_ro| .{ self.register_manager.lockReg(rhs_ro.reg), null },
10179 else => .{null} ** 2,
1013010180 };
10131 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
10181 defer for (rhs_locks) |rhs_lock| if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
1013210182
1013310183 switch (ty.zigTypeTag(mod)) {
1013410184 else => {
......@@ -10159,7 +10209,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1015910209 if (dst_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1016010210 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
1016110211
10162 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
10212 const src_mcv = try self.resolveInst(if (flipped) bin_op.lhs else bin_op.rhs);
1016310213 const src_lock =
1016410214 if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
1016510215 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
......@@ -10350,13 +10400,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
1035010400 },
1035110401 );
1035210402
10353 if (limb_i > 0) try self.asmRegisterRegister(
10354 .{ ._, .@"or" },
10355 acc_reg,
10356 tmp_reg,
10357 );
10403 if (limb_i > 0)
10404 try self.asmRegisterRegister(.{ ._, .@"or" }, acc_reg, tmp_reg);
1035810405 }
10359 try self.asmRegisterRegister(.{ ._, .@"test" }, acc_reg, acc_reg);
10406 assert(limbs_len >= 2); // use flags from or
1036010407 break :result_op flipped_op;
1036110408 },
1036210409 };
......@@ -11798,6 +11845,7 @@ const MoveStrategy = union(enum) {
1179811845 .move => |tag| try self.asmRegisterMemory(tag, dst_reg, src_mem),
1179911846 .x87_load_store => {
1180011847 try self.asmMemory(.{ .f_, .ld }, src_mem);
11848 assert(dst_reg != .st7);
1180111849 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
1180211850 },
1180311851 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
......@@ -11831,188 +11879,284 @@ const MoveStrategy = union(enum) {
1183111879 }
1183211880 }
1183311881};
11834fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
11882fn moveStrategy(self: *Self, ty: Type, class: Register.Class, aligned: bool) !MoveStrategy {
1183511883 const mod = self.bin_file.options.module.?;
11836 switch (ty.zigTypeTag(mod)) {
11837 else => return .{ .move = .{ ._, .mov } },
11838 .Float => switch (ty.floatBits(self.target.*)) {
11839 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11840 .insert = .{ .vp_w, .insr },
11841 .extract = .{ .vp_w, .extr },
11842 } } else .{ .insert_extract = .{
11843 .insert = .{ .p_w, .insr },
11844 .extract = .{ .p_w, .extr },
11845 } },
11846 32 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_ss, .mov } else .{ ._ss, .mov } },
11847 64 => return .{ .move = if (self.hasFeature(.avx)) .{ .v_sd, .mov } else .{ ._sd, .mov } },
11848 80 => return .x87_load_store,
11849 128 => return .{ .move = if (self.hasFeature(.avx))
11850 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11851 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11852 else => {},
11853 },
11854 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11855 .Bool => return .{ .move = .{ ._, .mov } },
11856 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
11857 8 => switch (ty.vectorLen(mod)) {
11858 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
11859 .insert = .{ .vp_b, .insr },
11860 .extract = .{ .vp_b, .extr },
11861 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
11862 .insert = .{ .p_b, .insr },
11863 .extract = .{ .p_b, .extr },
11864 } },
11865 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11866 .insert = .{ .vp_w, .insr },
11867 .extract = .{ .vp_w, .extr },
11868 } } else .{ .insert_extract = .{
11869 .insert = .{ .p_w, .insr },
11870 .extract = .{ .p_w, .extr },
11871 } },
11872 3...4 => return .{ .move = if (self.hasFeature(.avx))
11873 .{ .v_d, .mov }
11874 else
11875 .{ ._d, .mov } },
11876 5...8 => return .{ .move = if (self.hasFeature(.avx))
11877 .{ .v_q, .mov }
11878 else
11879 .{ ._q, .mov } },
11880 9...16 => return .{ .move = if (self.hasFeature(.avx))
11881 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11882 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11883 17...32 => if (self.hasFeature(.avx))
11884 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11885 else => {},
11886 },
11887 16 => switch (ty.vectorLen(mod)) {
11888 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11889 .insert = .{ .vp_w, .insr },
11890 .extract = .{ .vp_w, .extr },
11891 } } else .{ .insert_extract = .{
11892 .insert = .{ .p_w, .insr },
11893 .extract = .{ .p_w, .extr },
11894 } },
11895 2 => return .{ .move = if (self.hasFeature(.avx))
11896 .{ .v_d, .mov }
11897 else
11898 .{ ._d, .mov } },
11899 3...4 => return .{ .move = if (self.hasFeature(.avx))
11900 .{ .v_q, .mov }
11901 else
11902 .{ ._q, .mov } },
11903 5...8 => return .{ .move = if (self.hasFeature(.avx))
11904 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11905 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11906 9...16 => if (self.hasFeature(.avx))
11907 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11908 else => {},
11909 },
11910 32 => switch (ty.vectorLen(mod)) {
11911 1 => return .{ .move = if (self.hasFeature(.avx))
11912 .{ .v_d, .mov }
11913 else
11914 .{ ._d, .mov } },
11915 2 => return .{ .move = if (self.hasFeature(.avx))
11916 .{ .v_q, .mov }
11917 else
11918 .{ ._q, .mov } },
11919 3...4 => return .{ .move = if (self.hasFeature(.avx))
11920 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11921 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11922 5...8 => if (self.hasFeature(.avx))
11923 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11924 else => {},
11925 },
11926 64 => switch (ty.vectorLen(mod)) {
11927 1 => return .{ .move = if (self.hasFeature(.avx))
11928 .{ .v_q, .mov }
11929 else
11930 .{ ._q, .mov } },
11931 2 => return .{ .move = if (self.hasFeature(.avx))
11932 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11933 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11934 3...4 => if (self.hasFeature(.avx))
11935 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11936 else => {},
11937 },
11938 128 => switch (ty.vectorLen(mod)) {
11939 1 => return .{ .move = if (self.hasFeature(.avx))
11940 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11941 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11942 2 => if (self.hasFeature(.avx))
11943 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11944 else => {},
11945 },
11946 256 => switch (ty.vectorLen(mod)) {
11947 1 => if (self.hasFeature(.avx))
11948 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11949 else => {},
11884 switch (class) {
11885 .general_purpose, .segment => return .{ .move = .{ ._, .mov } },
11886 .x87 => return .x87_load_store,
11887 .mmx => {},
11888 .sse => {
11889 switch (ty.zigTypeTag(mod)) {
11890 else => {
11891 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
11892 assert(std.mem.indexOfNone(abi.Class, classes, &.{
11893 .integer, .sse, .float, .float_combine,
11894 }) == null);
11895 const abi_size = ty.abiSize(mod);
11896 if (abi_size < 4 or
11897 std.mem.indexOfScalar(abi.Class, classes, .integer) != null) switch (abi_size) {
11898 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
11899 .insert = .{ .vp_b, .insr },
11900 .extract = .{ .vp_b, .extr },
11901 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
11902 .insert = .{ .p_b, .insr },
11903 .extract = .{ .p_b, .extr },
11904 } },
11905 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11906 .insert = .{ .vp_w, .insr },
11907 .extract = .{ .vp_w, .extr },
11908 } } else .{ .insert_extract = .{
11909 .insert = .{ .p_w, .insr },
11910 .extract = .{ .p_w, .extr },
11911 } },
11912 3...4 => return .{ .move = if (self.hasFeature(.avx))
11913 .{ .v_d, .mov }
11914 else
11915 .{ ._d, .mov } },
11916 5...8 => return .{ .move = if (self.hasFeature(.avx))
11917 .{ .v_q, .mov }
11918 else
11919 .{ ._q, .mov } },
11920 9...16 => return .{ .move = if (self.hasFeature(.avx))
11921 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11922 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11923 17...32 => if (self.hasFeature(.avx))
11924 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11925 else => {},
11926 } else switch (abi_size) {
11927 4 => return .{ .move = if (self.hasFeature(.avx))
11928 .{ .v_ss, .mov }
11929 else
11930 .{ ._ss, .mov } },
11931 5...8 => return .{ .move = if (self.hasFeature(.avx))
11932 .{ .v_sd, .mov }
11933 else
11934 .{ ._sd, .mov } },
11935 9...16 => return .{ .move = if (self.hasFeature(.avx))
11936 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
11937 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
11938 17...32 => if (self.hasFeature(.avx)) return .{ .move = if (aligned)
11939 .{ .v_pd, .mova }
11940 else
11941 .{ .v_pd, .movu } },
11942 else => {},
11943 }
1195011944 },
11951 else => {},
11952 },
11953 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11954 16 => switch (ty.vectorLen(mod)) {
11955 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11945 .Float => switch (ty.floatBits(self.target.*)) {
11946 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
1195611947 .insert = .{ .vp_w, .insr },
1195711948 .extract = .{ .vp_w, .extr },
1195811949 } } else .{ .insert_extract = .{
1195911950 .insert = .{ .p_w, .insr },
1196011951 .extract = .{ .p_w, .extr },
1196111952 } },
11962 2 => return .{ .move = if (self.hasFeature(.avx))
11963 .{ .v_d, .mov }
11964 else
11965 .{ ._d, .mov } },
11966 3...4 => return .{ .move = if (self.hasFeature(.avx))
11967 .{ .v_q, .mov }
11968 else
11969 .{ ._q, .mov } },
11970 5...8 => return .{ .move = if (self.hasFeature(.avx))
11971 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11972 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11973 9...16 => if (self.hasFeature(.avx))
11974 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
11975 else => {},
11976 },
11977 32 => switch (ty.vectorLen(mod)) {
11978 1 => return .{ .move = if (self.hasFeature(.avx))
11953 32 => return .{ .move = if (self.hasFeature(.avx))
1197911954 .{ .v_ss, .mov }
1198011955 else
1198111956 .{ ._ss, .mov } },
11982 2 => return .{ .move = if (self.hasFeature(.avx))
11957 64 => return .{ .move = if (self.hasFeature(.avx))
1198311958 .{ .v_sd, .mov }
1198411959 else
1198511960 .{ ._sd, .mov } },
11986 3...4 => return .{ .move = if (self.hasFeature(.avx))
11987 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
11988 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
11989 5...8 => if (self.hasFeature(.avx))
11990 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },
11991 else => {},
11992 },
11993 64 => switch (ty.vectorLen(mod)) {
11994 1 => return .{ .move = if (self.hasFeature(.avx))
11995 .{ .v_sd, .mov }
11996 else
11997 .{ ._sd, .mov } },
11998 2 => return .{ .move = if (self.hasFeature(.avx))
11999 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12000 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12001 3...4 => if (self.hasFeature(.avx))
12002 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },
12003 else => {},
12004 },
12005 128 => switch (ty.vectorLen(mod)) {
12006 1 => return .{ .move = if (self.hasFeature(.avx))
11961 128 => return .{ .move = if (self.hasFeature(.avx))
1200711962 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
1200811963 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12009 2 => if (self.hasFeature(.avx))
12010 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
1201111964 else => {},
1201211965 },
12013 else => {},
12014 },
12015 else => {},
11966 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11967 .Bool => return .{ .move = .{ ._, .mov } },
11968 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
11969 8 => switch (ty.vectorLen(mod)) {
11970 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
11971 .insert = .{ .vp_b, .insr },
11972 .extract = .{ .vp_b, .extr },
11973 } } else if (self.hasFeature(.sse4_2)) return .{ .insert_extract = .{
11974 .insert = .{ .p_b, .insr },
11975 .extract = .{ .p_b, .extr },
11976 } },
11977 2 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
11978 .insert = .{ .vp_w, .insr },
11979 .extract = .{ .vp_w, .extr },
11980 } } else .{ .insert_extract = .{
11981 .insert = .{ .p_w, .insr },
11982 .extract = .{ .p_w, .extr },
11983 } },
11984 3...4 => return .{ .move = if (self.hasFeature(.avx))
11985 .{ .v_d, .mov }
11986 else
11987 .{ ._d, .mov } },
11988 5...8 => return .{ .move = if (self.hasFeature(.avx))
11989 .{ .v_q, .mov }
11990 else
11991 .{ ._q, .mov } },
11992 9...16 => return .{ .move = if (self.hasFeature(.avx))
11993 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
11994 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
11995 17...32 => if (self.hasFeature(.avx))
11996 return .{ .move = if (aligned)
11997 .{ .v_, .movdqa }
11998 else
11999 .{ .v_, .movdqu } },
12000 else => {},
12001 },
12002 16 => switch (ty.vectorLen(mod)) {
12003 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12004 .insert = .{ .vp_w, .insr },
12005 .extract = .{ .vp_w, .extr },
12006 } } else .{ .insert_extract = .{
12007 .insert = .{ .p_w, .insr },
12008 .extract = .{ .p_w, .extr },
12009 } },
12010 2 => return .{ .move = if (self.hasFeature(.avx))
12011 .{ .v_d, .mov }
12012 else
12013 .{ ._d, .mov } },
12014 3...4 => return .{ .move = if (self.hasFeature(.avx))
12015 .{ .v_q, .mov }
12016 else
12017 .{ ._q, .mov } },
12018 5...8 => return .{ .move = if (self.hasFeature(.avx))
12019 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12020 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12021 9...16 => if (self.hasFeature(.avx))
12022 return .{ .move = if (aligned)
12023 .{ .v_, .movdqa }
12024 else
12025 .{ .v_, .movdqu } },
12026 else => {},
12027 },
12028 32 => switch (ty.vectorLen(mod)) {
12029 1 => return .{ .move = if (self.hasFeature(.avx))
12030 .{ .v_d, .mov }
12031 else
12032 .{ ._d, .mov } },
12033 2 => return .{ .move = if (self.hasFeature(.avx))
12034 .{ .v_q, .mov }
12035 else
12036 .{ ._q, .mov } },
12037 3...4 => return .{ .move = if (self.hasFeature(.avx))
12038 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12039 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12040 5...8 => if (self.hasFeature(.avx))
12041 return .{ .move = if (aligned)
12042 .{ .v_, .movdqa }
12043 else
12044 .{ .v_, .movdqu } },
12045 else => {},
12046 },
12047 64 => switch (ty.vectorLen(mod)) {
12048 1 => return .{ .move = if (self.hasFeature(.avx))
12049 .{ .v_q, .mov }
12050 else
12051 .{ ._q, .mov } },
12052 2 => return .{ .move = if (self.hasFeature(.avx))
12053 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12054 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12055 3...4 => if (self.hasFeature(.avx))
12056 return .{ .move = if (aligned)
12057 .{ .v_, .movdqa }
12058 else
12059 .{ .v_, .movdqu } },
12060 else => {},
12061 },
12062 128 => switch (ty.vectorLen(mod)) {
12063 1 => return .{ .move = if (self.hasFeature(.avx))
12064 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12065 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12066 2 => if (self.hasFeature(.avx))
12067 return .{ .move = if (aligned)
12068 .{ .v_, .movdqa }
12069 else
12070 .{ .v_, .movdqu } },
12071 else => {},
12072 },
12073 256 => switch (ty.vectorLen(mod)) {
12074 1 => if (self.hasFeature(.avx))
12075 return .{ .move = if (aligned)
12076 .{ .v_, .movdqa }
12077 else
12078 .{ .v_, .movdqu } },
12079 else => {},
12080 },
12081 else => {},
12082 },
12083 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
12084 16 => switch (ty.vectorLen(mod)) {
12085 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
12086 .insert = .{ .vp_w, .insr },
12087 .extract = .{ .vp_w, .extr },
12088 } } else .{ .insert_extract = .{
12089 .insert = .{ .p_w, .insr },
12090 .extract = .{ .p_w, .extr },
12091 } },
12092 2 => return .{ .move = if (self.hasFeature(.avx))
12093 .{ .v_d, .mov }
12094 else
12095 .{ ._d, .mov } },
12096 3...4 => return .{ .move = if (self.hasFeature(.avx))
12097 .{ .v_q, .mov }
12098 else
12099 .{ ._q, .mov } },
12100 5...8 => return .{ .move = if (self.hasFeature(.avx))
12101 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12102 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12103 9...16 => if (self.hasFeature(.avx))
12104 return .{ .move = if (aligned)
12105 .{ .v_, .movdqa }
12106 else
12107 .{ .v_, .movdqu } },
12108 else => {},
12109 },
12110 32 => switch (ty.vectorLen(mod)) {
12111 1 => return .{ .move = if (self.hasFeature(.avx))
12112 .{ .v_ss, .mov }
12113 else
12114 .{ ._ss, .mov } },
12115 2 => return .{ .move = if (self.hasFeature(.avx))
12116 .{ .v_sd, .mov }
12117 else
12118 .{ ._sd, .mov } },
12119 3...4 => return .{ .move = if (self.hasFeature(.avx))
12120 if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu }
12121 else if (aligned) .{ ._ps, .mova } else .{ ._ps, .movu } },
12122 5...8 => if (self.hasFeature(.avx))
12123 return .{ .move = if (aligned)
12124 .{ .v_ps, .mova }
12125 else
12126 .{ .v_ps, .movu } },
12127 else => {},
12128 },
12129 64 => switch (ty.vectorLen(mod)) {
12130 1 => return .{ .move = if (self.hasFeature(.avx))
12131 .{ .v_sd, .mov }
12132 else
12133 .{ ._sd, .mov } },
12134 2 => return .{ .move = if (self.hasFeature(.avx))
12135 if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu }
12136 else if (aligned) .{ ._pd, .mova } else .{ ._pd, .movu } },
12137 3...4 => if (self.hasFeature(.avx))
12138 return .{ .move = if (aligned)
12139 .{ .v_pd, .mova }
12140 else
12141 .{ .v_pd, .movu } },
12142 else => {},
12143 },
12144 128 => switch (ty.vectorLen(mod)) {
12145 1 => return .{ .move = if (self.hasFeature(.avx))
12146 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
12147 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
12148 2 => if (self.hasFeature(.avx))
12149 return .{ .move = if (aligned)
12150 .{ .v_, .movdqa }
12151 else
12152 .{ .v_, .movdqu } },
12153 else => {},
12154 },
12155 else => {},
12156 },
12157 else => {},
12158 },
12159 }
1201612160 },
1201712161 }
1201812162 return self.fail("TODO moveStrategy for {}", .{ty.fmt(mod)});
......@@ -12060,28 +12204,49 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
1206012204 } },
1206112205 }),
1206212206 .register_pair => |dst_regs| {
12063 switch (src_mcv) {
12207 const src_info: ?struct { addr_reg: Register, addr_lock: RegisterLock } = switch (src_mcv) {
12208 .register_pair, .memory, .indirect, .load_frame => null,
12209 .load_direct, .load_got, .load_extern_got, .load_tlv => src: {
12210 const src_addr_reg =
12211 (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64();
12212 const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
12213 errdefer self.register_manager.unlockReg(src_addr_lock);
12214
12215 try self.genSetReg(src_addr_reg, Type.usize, src_mcv.address());
12216 break :src .{ .addr_reg = src_addr_reg, .addr_lock = src_addr_lock };
12217 },
1206412218 .air_ref => |src_ref| return self.genCopy(ty, dst_mcv, try self.resolveInst(src_ref)),
12065 else => {},
12066 }
12219 else => return self.fail("TODO implement genCopy for {s} of {}", .{
12220 @tagName(src_mcv), ty.fmt(mod),
12221 }),
12222 };
12223 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
12224
1206712225 const classes = mem.sliceTo(&abi.classifySystemV(ty, mod, .other), .none);
1206812226 for (dst_regs, classes, 0..) |dst_reg, class, dst_reg_i| {
1206912227 const class_ty = switch (class) {
1207012228 .integer => Type.usize,
12071 .sse => Type.f64,
12229 .sse, .float, .float_combine => Type.f64,
1207212230 else => unreachable,
1207312231 };
12232 const off: i32 = @intCast(dst_reg_i * 8);
1207412233 switch (src_mcv) {
1207512234 .register_pair => |src_regs| try self.genSetReg(
1207612235 dst_reg,
1207712236 class_ty,
1207812237 .{ .register = src_regs[dst_reg_i] },
1207912238 ),
12080 else => try self.genSetReg(
12239 .memory, .indirect, .load_frame => try self.genSetReg(
12240 dst_reg,
12241 class_ty,
12242 src_mcv.address().offset(off).deref(),
12243 ),
12244 .load_direct, .load_got, .load_extern_got, .load_tlv => try self.genSetReg(
1208112245 dst_reg,
1208212246 class_ty,
12083 src_mcv.address().offset(@intCast(dst_reg_i * 8)).deref(),
12247 .{ .indirect = .{ .reg = src_info.?.addr_reg, .off = off } },
1208412248 ),
12249 else => unreachable,
1208512250 }
1208612251 }
1208712252 },
......@@ -12157,6 +12322,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1215712322 registerAlias(dst_reg, abi_size),
1215812323 src_reg,
1215912324 ),
12325 .x87, .mmx => unreachable,
1216012326 .sse => try self.asmRegisterRegister(
1216112327 switch (abi_size) {
1216212328 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
......@@ -12166,17 +12332,30 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1216612332 registerAlias(dst_reg, @max(abi_size, 4)),
1216712333 src_reg.to128(),
1216812334 ),
12169 .x87, .mmx => unreachable,
1217012335 },
1217112336 .segment => try self.asmRegisterRegister(
1217212337 .{ ._, .mov },
1217312338 dst_reg,
1217412339 switch (src_reg.class()) {
1217512340 .general_purpose, .segment => registerAlias(src_reg, abi_size),
12176 .sse => try self.copyToTmpRegister(ty, src_mcv),
1217712341 .x87, .mmx => unreachable,
12342 .sse => try self.copyToTmpRegister(ty, src_mcv),
1217812343 },
1217912344 ),
12345 .x87 => switch (src_reg.class()) {
12346 .general_purpose, .segment => unreachable,
12347 .x87 => switch (src_reg) {
12348 .st0 => try self.asmRegister(.{ .f_, .st }, dst_reg),
12349 .st1, .st2, .st3, .st4, .st5, .st6 => {
12350 try self.asmRegister(.{ .f_, .ld }, src_reg);
12351 assert(dst_reg != .st7);
12352 try self.asmRegister(.{ .f_p, .st }, @enumFromInt(@intFromEnum(dst_reg) + 1));
12353 },
12354 else => unreachable,
12355 },
12356 .mmx, .sse => unreachable,
12357 },
12358 .mmx => unreachable,
1218012359 .sse => switch (src_reg.class()) {
1218112360 .general_purpose => try self.asmRegisterRegister(
1218212361 switch (abi_size) {
......@@ -12192,6 +12371,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1219212371 ty,
1219312372 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
1219412373 ),
12374 .x87, .mmx => unreachable,
1219512375 .sse => try self.asmRegisterRegister(
1219612376 @as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) {
1219712377 else => switch (abi_size) {
......@@ -12217,9 +12397,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1221712397 registerAlias(dst_reg, abi_size),
1221812398 registerAlias(src_reg, abi_size),
1221912399 ),
12220 .x87, .mmx => unreachable,
1222112400 },
12222 .x87, .mmx => unreachable,
1222312401 },
1222412402 .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }),
1222512403 .register_offset,
......@@ -12231,9 +12409,10 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1223112409 0 => return self.genSetReg(dst_reg, ty, .{ .register = reg_off.reg }),
1223212410 else => .{ .move = .{ ._, .lea } },
1223312411 },
12234 .indirect => try self.moveStrategy(ty, false),
12412 .indirect => try self.moveStrategy(ty, dst_reg.class(), false),
1223512413 .load_frame => |frame_addr| try self.moveStrategy(
1223612414 ty,
12415 dst_reg.class(),
1223712416 self.getFrameAddrAlignment(frame_addr).compare(.gte, ty.abiAlignment(mod)),
1223812417 ),
1223912418 .lea_frame => .{ .move = .{ ._, .lea } },
......@@ -12257,13 +12436,14 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1225712436 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |small_addr|
1225812437 return (try self.moveStrategy(
1225912438 ty,
12439 dst_reg.class(),
1226012440 ty.abiAlignment(mod).check(@as(u32, @bitCast(small_addr))),
1226112441 )).read(self, registerAlias(dst_reg, abi_size), Memory.sib(
1226212442 self.memPtrSize(ty),
1226312443 .{ .base = .{ .reg = .ds }, .disp = small_addr },
1226412444 )),
12265 .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) {
12266 else => {
12445 .load_direct => |sym_index| switch (dst_reg.class()) {
12446 .general_purpose => {
1226712447 const atom_index = try self.owner.getSymbolIndex(self);
1226812448 _ = try self.addInst(.{
1226912449 .tag = .mov,
......@@ -12278,7 +12458,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1227812458 });
1227912459 return;
1228012460 },
12281 .Float, .Vector => {},
12461 .segment, .mmx => unreachable,
12462 .x87, .sse => {},
1228212463 },
1228312464 .load_got, .load_extern_got, .load_tlv => {},
1228412465 else => unreachable,
......@@ -12288,7 +12469,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
1228812469 const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
1228912470 defer self.register_manager.unlockReg(addr_lock);
1229012471
12291 try (try self.moveStrategy(ty, false)).read(
12472 try (try self.moveStrategy(ty, dst_reg.class(), false)).read(
1229212473 self,
1229312474 registerAlias(dst_reg, abi_size),
1229412475 Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ .base = .{ .reg = addr_reg } }),
......@@ -12393,7 +12574,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1239312574 },
1239412575 },
1239512576 .eflags => |cc| try self.asmSetccMemory(cc, Memory.sib(.byte, .{ .base = base, .disp = disp })),
12396 .register => |src_reg| try (try self.moveStrategy(ty, switch (base) {
12577 .register => |src_reg| try (try self.moveStrategy(ty, src_reg.class(), switch (base) {
1239712578 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
1239812579 .reg => |reg| switch (reg) {
1239912580 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
......@@ -12408,17 +12589,21 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1240812589 registerAlias(src_reg, abi_size),
1240912590 ),
1241012591 .register_pair => |src_regs| for (src_regs, 0..) |src_reg, src_reg_i| {
12411 const part_size = @min(abi_size - src_reg_i * 8, 8);
12412 try (try self.moveStrategy(ty, switch (base) {
12413 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12414 .reg => |reg| switch (reg) {
12415 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12416 else => false,
12592 const part_size: u16 = @min(abi_size - src_reg_i * 8, 8);
12593 try (try self.moveStrategy(
12594 try mod.intType(.unsigned, part_size * 8),
12595 src_reg.class(),
12596 switch (base) {
12597 .none => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12598 .reg => |reg| switch (reg) {
12599 .es, .cs, .ss, .ds => ty.abiAlignment(mod).check(@as(u32, @bitCast(disp))),
12600 else => false,
12601 },
12602 .frame => |frame_index| self.getFrameAddrAlignment(
12603 .{ .index = frame_index, .off = disp },
12604 ).compare(.gte, ty.abiAlignment(mod)),
1241712605 },
12418 .frame => |frame_index| self.getFrameAddrAlignment(
12419 .{ .index = frame_index, .off = disp },
12420 ).compare(.gte, ty.abiAlignment(mod)),
12421 })).write(self, Memory.sib(
12606 )).write(self, Memory.sib(
1242212607 Memory.PtrSize.fromSize(part_size),
1242312608 .{ .base = base, .disp = disp + @as(i32, @intCast(src_reg_i * 8)) },
1242412609 ), registerAlias(src_reg, part_size));
......@@ -12482,9 +12667,9 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1248212667}
1248312668
1248412669fn genInlineMemcpy(self: *Self, dst_ptr: MCValue, src_ptr: MCValue, len: MCValue) InnerError!void {
12485 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
12486 try self.genSetReg(.rdi, Type.usize, dst_ptr);
12670 try self.spillRegisters(&.{ .rsi, .rdi, .rcx });
1248712671 try self.genSetReg(.rsi, Type.usize, src_ptr);
12672 try self.genSetReg(.rdi, Type.usize, dst_ptr);
1248812673 try self.genSetReg(.rcx, Type.usize, len);
1248912674 try self.asmOpOnly(.{ .@"rep _sb", .mov });
1249012675}
......@@ -14730,16 +14915,22 @@ fn resolveCallingConventionValues(
1473014915 arg_mcv_i += 1;
1473114916 },
1473214917 .sseup => assert(arg_mcv[arg_mcv_i - 1].register.class() == .sse),
14733 .x87, .x87up, .complex_x87, .memory => break,
14734 .none => unreachable,
14735 .win_i128 => {
14736 const param_int_reg =
14737 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
14738 param_int_reg_i += 1;
14739
14740 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
14741 arg_mcv_i += 1;
14918 .x87, .x87up, .complex_x87, .memory, .win_i128 => switch (resolved_cc) {
14919 .SysV => switch (class) {
14920 .x87, .x87up, .complex_x87, .memory => break,
14921 else => unreachable,
14922 },
14923 .Win64 => if (ty.abiSize(mod) > 8) {
14924 const param_int_reg =
14925 abi.getCAbiIntParamRegs(resolved_cc)[param_int_reg_i].to64();
14926 param_int_reg_i += 1;
14927
14928 arg_mcv[arg_mcv_i] = .{ .indirect = .{ .reg = param_int_reg } };
14929 arg_mcv_i += 1;
14930 } else break,
14931 else => unreachable,
1474214932 },
14933 .none => unreachable,
1474314934 } else {
1474414935 arg.* = switch (arg_mcv_i) {
1474514936 else => unreachable,
......@@ -15017,34 +15208,32 @@ fn floatLibcAbiSuffix(ty: Type) []const u8 {
1501715208 };
1501815209}
1501915210
15020fn promoteVarArg(self: *Self, ty: Type) Type {
15211fn promoteInt(self: *Self, ty: Type) Type {
1502115212 const mod = self.bin_file.options.module.?;
15022 switch (ty.zigTypeTag(mod)) {
15023 .Bool => return Type.c_int,
15024 else => {
15025 const int_info = ty.intInfo(mod);
15026 for ([_]Type{
15027 Type.c_int, Type.c_uint,
15028 Type.c_long, Type.c_ulong,
15029 Type.c_longlong, Type.c_ulonglong,
15030 }) |promote_ty| {
15031 const promote_info = promote_ty.intInfo(mod);
15032 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
15033 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
15034 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
15035 }
15036 unreachable;
15037 },
15038 .Float => switch (ty.floatBits(self.target.*)) {
15039 32, 64 => return Type.f64,
15040 else => |float_bits| {
15041 assert(float_bits == self.target.c_type_bit_size(.longdouble));
15042 return Type.c_longdouble;
15043 },
15044 },
15045 .Pointer => {
15046 assert(!ty.isSlice(mod));
15047 return ty;
15213 const int_info: InternPool.Key.IntType = switch (ty.toIntern()) {
15214 .bool_type => .{ .signedness = .unsigned, .bits = 1 },
15215 else => if (ty.isAbiInt(mod)) ty.intInfo(mod) else return ty,
15216 };
15217 for ([_]Type{
15218 Type.c_int, Type.c_uint,
15219 Type.c_long, Type.c_ulong,
15220 Type.c_longlong, Type.c_ulonglong,
15221 }) |promote_ty| {
15222 const promote_info = promote_ty.intInfo(mod);
15223 if (int_info.signedness == .signed and promote_info.signedness == .unsigned) continue;
15224 if (int_info.bits + @intFromBool(int_info.signedness == .unsigned and
15225 promote_info.signedness == .signed) <= promote_info.bits) return promote_ty;
15226 }
15227 return ty;
15228}
15229
15230fn promoteVarArg(self: *Self, ty: Type) Type {
15231 if (!ty.isRuntimeFloat()) return self.promoteInt(ty);
15232 switch (ty.floatBits(self.target.*)) {
15233 32, 64 => return Type.f64,
15234 else => |float_bits| {
15235 assert(float_bits == self.target.c_type_bit_size(.longdouble));
15236 return Type.c_longdouble;
1504815237 },
1504915238 }
1505015239}
test/c_abi/cfuncs.c+3-7
......@@ -73,10 +73,6 @@ static void assert_or_panic(bool ok) {
7373#define ZIG_NO_RAW_F16
7474#endif
7575
76#ifdef ZIG_BACKEND_STAGE2_X86_64
77#define ZIG_NO_COMPLEX
78#endif
79
8076#ifdef __i386__
8177#define ZIG_NO_RAW_F16
8278#endif
......@@ -278,7 +274,7 @@ void run_c_tests(void) {
278274 zig_u32(0xfffffffd);
279275 zig_u64(0xfffffffffffffffc);
280276
281#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
277#ifndef ZIG_NO_I128
282278 {
283279 struct u128 s = {0xfffffffffffffffc};
284280 zig_struct_u128(s);
......@@ -292,7 +288,7 @@ void run_c_tests(void) {
292288 zig_i32(-3);
293289 zig_i64(-4);
294290
295#if !defined ZIG_NO_I128 && !defined ZIG_BACKEND_STAGE2_X86_64
291#ifndef ZIG_NO_I128
296292 {
297293 struct i128 s = {-6};
298294 zig_struct_i128(s);
......@@ -433,7 +429,7 @@ void run_c_tests(void) {
433429 }
434430#endif
435431
436#if !defined __mips__ && !defined ZIG_PPC32 && !defined ZIG_BACKEND_STAGE2_X86_64
432#if !defined __mips__ && !defined ZIG_PPC32
437433 {
438434 struct FloatRect r1 = {1, 21, 16, 4};
439435 struct FloatRect r2 = {178, 189, 21, 15};
test/c_abi/main.zig+5-86
......@@ -49,8 +49,6 @@ export fn zig_five_integers(a: i32, b: i32, c: i32, d: i32, e: i32) void {
4949}
5050
5151test "C ABI integers" {
52 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
53
5452 c_u8(0xff);
5553 c_u16(0xfffe);
5654 c_u32(0xfffffffd);
......@@ -187,10 +185,8 @@ const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.is
187185 !builtin.cpu.arch.isARM() and !builtin.cpu.arch.isPPC() and !builtin.cpu.arch.isRISCV();
188186
189187test "C ABI complex float" {
190 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
191
192188 if (!complex_abi_compatible) return error.SkipZigTest;
193 if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
189 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) return error.SkipZigTest; // See https://github.com/ziglang/zig/issues/8465
194190
195191 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
196192 const b = ComplexFloat{ .real = 11.3, .imag = -1.5 };
......@@ -201,8 +197,6 @@ test "C ABI complex float" {
201197}
202198
203199test "C ABI complex float by component" {
204 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
205
206200 if (!complex_abi_compatible) return error.SkipZigTest;
207201
208202 const a = ComplexFloat{ .real = 1.25, .imag = 2.6 };
......@@ -214,8 +208,6 @@ test "C ABI complex float by component" {
214208}
215209
216210test "C ABI complex double" {
217 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
218
219211 if (!complex_abi_compatible) return error.SkipZigTest;
220212
221213 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
......@@ -227,8 +219,6 @@ test "C ABI complex double" {
227219}
228220
229221test "C ABI complex double by component" {
230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
231
232222 if (!complex_abi_compatible) return error.SkipZigTest;
233223
234224 const a = ComplexDouble{ .real = 1.25, .imag = 2.6 };
......@@ -240,8 +230,6 @@ test "C ABI complex double by component" {
240230}
241231
242232export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
243 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
244
245233 expect(a.real == 1.25) catch @panic("test failure: zig_cmultf 1");
246234 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultf 2");
247235 expect(b.real == 11.3) catch @panic("test failure: zig_cmultf 3");
......@@ -251,8 +239,6 @@ export fn zig_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat {
251239}
252240
253241export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
254 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
255
256242 expect(a.real == 1.25) catch @panic("test failure: zig_cmultd 1");
257243 expect(a.imag == 2.6) catch @panic("test failure: zig_cmultd 2");
258244 expect(b.real == 11.3) catch @panic("test failure: zig_cmultd 3");
......@@ -262,8 +248,6 @@ export fn zig_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble {
262248}
263249
264250export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
265 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
266
267251 expect(a_r == 1.25) catch @panic("test failure: zig_cmultf_comp 1");
268252 expect(a_i == 2.6) catch @panic("test failure: zig_cmultf_comp 2");
269253 expect(b_r == 11.3) catch @panic("test failure: zig_cmultf_comp 3");
......@@ -273,8 +257,6 @@ export fn zig_cmultf_comp(a_r: f32, a_i: f32, b_r: f32, b_i: f32) ComplexFloat {
273257}
274258
275259export fn zig_cmultd_comp(a_r: f64, a_i: f64, b_r: f64, b_i: f64) ComplexDouble {
276 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
277
278260 expect(a_r == 1.25) catch @panic("test failure: zig_cmultd_comp 1");
279261 expect(a_i == 2.6) catch @panic("test failure: zig_cmultd_comp 2");
280262 expect(b_r == 11.3) catch @panic("test failure: zig_cmultd_comp 3");
......@@ -352,8 +334,6 @@ extern fn c_med_struct_mixed(MedStructMixed) void;
352334extern fn c_ret_med_struct_mixed() MedStructMixed;
353335
354336test "C ABI medium struct of ints and floats" {
355 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
356
357337 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
358338 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
359339 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -422,8 +402,6 @@ extern fn c_med_struct_ints(MedStructInts) void;
422402extern fn c_ret_med_struct_ints() MedStructInts;
423403
424404test "C ABI medium struct of ints" {
425 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
426
427405 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
428406 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
429407 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -531,8 +509,6 @@ extern fn c_split_struct_mixed(SplitStructMixed) void;
531509extern fn c_ret_split_struct_mixed() SplitStructMixed;
532510
533511test "C ABI split struct of ints and floats" {
534 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
535
536512 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
537513 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
538514 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -614,8 +590,6 @@ const Vector5 = extern struct {
614590extern fn c_big_struct_floats(Vector5) void;
615591
616592test "C ABI structs of floats as parameter" {
617 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
618
619593 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
620594 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
621595 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
......@@ -683,8 +657,6 @@ const FloatRect = extern struct {
683657};
684658
685659export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
686 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
687
688660 expect(x.left == 1) catch @panic("test failure");
689661 expect(x.right == 21) catch @panic("test failure");
690662 expect(x.top == 16) catch @panic("test failure");
......@@ -696,8 +668,6 @@ export fn zig_multiple_struct_floats(x: FloatRect, y: FloatRect) void {
696668}
697669
698670test "C ABI structs of floats as multiple parameters" {
699 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
700
701671 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
702672 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
703673
......@@ -754,8 +724,6 @@ export fn zig_ret_small_struct_ints() SmallStructInts {
754724}
755725
756726export fn zig_ret_med_struct_ints() MedStructInts {
757 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
758
759727 return .{
760728 .x = 1,
761729 .y = 2,
......@@ -764,8 +732,6 @@ export fn zig_ret_med_struct_ints() MedStructInts {
764732}
765733
766734export fn zig_ret_med_struct_mixed() MedStructMixed {
767 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
768
769735 return .{
770736 .a = 1234,
771737 .b = 100.0,
......@@ -774,8 +740,6 @@ export fn zig_ret_med_struct_mixed() MedStructMixed {
774740}
775741
776742export fn zig_ret_split_struct_mixed() SplitStructMixed {
777 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
778
779743 return .{
780744 .a = 1234,
781745 .b = 100,
......@@ -816,8 +780,6 @@ extern fn c_struct_with_array(StructWithArray) void;
816780extern fn c_ret_struct_with_array() StructWithArray;
817781
818782test "Struct with array as padding." {
819 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
820
821783 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
822784 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
823785 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -889,7 +851,8 @@ extern fn c_medium_vec(MediumVec) void;
889851extern fn c_ret_medium_vec() MediumVec;
890852
891853test "medium simd vector" {
892 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
854 if (builtin.zig_backend == .stage2_x86_64 and
855 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .avx)) return error.SkipZigTest;
893856
894857 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
895858
......@@ -912,7 +875,7 @@ test "big simd vector" {
912875
913876 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
914877 if (comptime builtin.cpu.arch.isPPC64()) return error.SkipZigTest;
915 if (builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;
878 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64 and builtin.os.tag == .macos and builtin.mode != .Debug) return error.SkipZigTest;
916879
917880 c_big_vec(.{ 1, 2, 3, 4, 5, 6, 7, 8 });
918881
......@@ -933,8 +896,6 @@ extern fn c_ptr_size_float_struct(Vector2) void;
933896extern fn c_ret_ptr_size_float_struct() Vector2;
934897
935898test "C ABI pointer sized float struct" {
936 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
937
938899 if (builtin.cpu.arch == .x86) return error.SkipZigTest;
939900 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
940901 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -958,8 +919,6 @@ pub inline fn expectOk(c_err: c_int) !void {
958919/// Tests for Double + Char struct
959920const DC = extern struct { v1: f64, v2: u8 };
960921test "DC: Zig passes to C" {
961 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
962
963922 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
964923 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
965924 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -967,8 +926,6 @@ test "DC: Zig passes to C" {
967926 try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 }));
968927}
969928test "DC: Zig returns to C" {
970 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
971
972929 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
973930 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
974931 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -977,8 +934,6 @@ test "DC: Zig returns to C" {
977934 try expectOk(c_assert_ret_DC());
978935}
979936test "DC: C passes to Zig" {
980 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
981
982937 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
983938 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
984939 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -986,8 +941,6 @@ test "DC: C passes to Zig" {
986941 try expectOk(c_send_DC());
987942}
988943test "DC: C returns to Zig" {
989 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
990
991944 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
992945 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
993946 if (comptime builtin.cpu.arch.isRISCV()) return error.SkipZigTest;
......@@ -1001,8 +954,6 @@ pub extern fn c_assert_ret_DC() c_int;
1001954pub extern fn c_send_DC() c_int;
1002955pub extern fn c_ret_DC() DC;
1003956pub export fn zig_assert_DC(lv: DC) c_int {
1004 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1005
1006957 var err: c_int = 0;
1007958 if (lv.v1 != -0.25) err = 1;
1008959 if (lv.v2 != 15) err = 2;
......@@ -1010,8 +961,6 @@ pub export fn zig_assert_DC(lv: DC) c_int {
1010961 return err;
1011962}
1012963pub export fn zig_ret_DC() DC {
1013 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1014
1015964 return .{ .v1 = -0.25, .v2 = 15 };
1016965}
1017966
......@@ -1019,8 +968,6 @@ pub export fn zig_ret_DC() DC {
1019968const CFF = extern struct { v1: u8, v2: f32, v3: f32 };
1020969
1021970test "CFF: Zig passes to C" {
1022 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1023
1024971 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1025972 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1026973 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1028,8 +975,6 @@ test "CFF: Zig passes to C" {
1028975 try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }));
1029976}
1030977test "CFF: Zig returns to C" {
1031 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1032
1033978 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1034979 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
1035980 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1037,8 +982,6 @@ test "CFF: Zig returns to C" {
1037982 try expectOk(c_assert_ret_CFF());
1038983}
1039984test "CFF: C passes to Zig" {
1040 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1041
1042985 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1043986 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
1044987 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
......@@ -1049,8 +992,6 @@ test "CFF: C passes to Zig" {
1049992 try expectOk(c_send_CFF());
1050993}
1051994test "CFF: C returns to Zig" {
1052 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1053
1054995 if (builtin.cpu.arch == .x86 and builtin.mode != .Debug) return error.SkipZigTest;
1055996 if (builtin.cpu.arch == .aarch64 and builtin.mode != .Debug) return error.SkipZigTest;
1056997 if (comptime builtin.cpu.arch.isRISCV() and builtin.mode != .Debug) return error.SkipZigTest;
......@@ -1064,8 +1005,6 @@ pub extern fn c_assert_ret_CFF() c_int;
10641005pub extern fn c_send_CFF() c_int;
10651006pub extern fn c_ret_CFF() CFF;
10661007pub export fn zig_assert_CFF(lv: CFF) c_int {
1067 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1068
10691008 var err: c_int = 0;
10701009 if (lv.v1 != 39) err = 1;
10711010 if (lv.v2 != 0.875) err = 2;
......@@ -1074,8 +1013,6 @@ pub export fn zig_assert_CFF(lv: CFF) c_int {
10741013 return err;
10751014}
10761015pub export fn zig_ret_CFF() CFF {
1077 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1078
10791016 return .{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 };
10801017}
10811018
......@@ -1083,8 +1020,6 @@ pub export fn zig_ret_CFF() CFF {
10831020const PD = extern struct { v1: ?*anyopaque, v2: f64 };
10841021
10851022test "PD: Zig passes to C" {
1086 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1087
10881023 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
10891024 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
10901025 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1092,8 +1027,6 @@ test "PD: Zig passes to C" {
10921027 try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 }));
10931028}
10941029test "PD: Zig returns to C" {
1095 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1096
10971030 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
10981031 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
10991032 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1101,8 +1034,6 @@ test "PD: Zig returns to C" {
11011034 try expectOk(c_assert_ret_PD());
11021035}
11031036test "PD: C passes to Zig" {
1104 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1105
11061037 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
11071038 if (comptime builtin.cpu.arch.isMIPS()) return error.SkipZigTest;
11081039 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1110,8 +1041,6 @@ test "PD: C passes to Zig" {
11101041 try expectOk(c_send_PD());
11111042}
11121043test "PD: C returns to Zig" {
1113 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1114
11151044 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
11161045 if (comptime builtin.cpu.arch.isMIPS() and builtin.mode != .Debug) return error.SkipZigTest;
11171046 if (comptime builtin.cpu.arch.isPPC()) return error.SkipZigTest;
......@@ -1123,8 +1052,6 @@ pub extern fn c_assert_ret_PD() c_int;
11231052pub extern fn c_send_PD() c_int;
11241053pub extern fn c_ret_PD() PD;
11251054pub export fn zig_c_assert_PD(lv: PD) c_int {
1126 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1127
11281055 var err: c_int = 0;
11291056 if (lv.v1 != null) err = 1;
11301057 if (lv.v2 != 0.5) err = 2;
......@@ -1132,13 +1059,9 @@ pub export fn zig_c_assert_PD(lv: PD) c_int {
11321059 return err;
11331060}
11341061pub export fn zig_ret_PD() PD {
1135 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1136
11371062 return .{ .v1 = null, .v2 = 0.5 };
11381063}
11391064pub export fn zig_assert_PD(lv: PD) c_int {
1140 if (builtin.zig_backend == .stage2_x86_64) @panic("error.SkipZigTest");
1141
11421065 var err: c_int = 0;
11431066 if (lv.v1 != null) err = 1;
11441067 if (lv.v2 != 0.5) err = 2;
......@@ -1228,11 +1151,9 @@ const f80_struct = extern struct {
12281151};
12291152extern fn c_f80_struct(f80_struct) f80_struct;
12301153test "f80 struct" {
1231 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1232
12331154 if (!has_f80) return error.SkipZigTest;
12341155 if (builtin.target.cpu.arch == .x86) return error.SkipZigTest;
1235 if (builtin.mode != .Debug) return error.SkipZigTest;
1156 if (builtin.zig_backend == .stage2_llvm and builtin.mode != .Debug) return error.SkipZigTest;
12361157
12371158 const a = c_f80_struct(.{ .a = 12.34 });
12381159 try expect(@as(f64, @floatCast(a.a)) == 56.78);
......@@ -1317,8 +1238,6 @@ test "Stdcall ABI big union" {
13171238
13181239extern fn c_explict_win64(ByRef) callconv(.Win64) ByRef;
13191240test "explicit SysV calling convention" {
1320 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1321
13221241 if (builtin.cpu.arch != .x86_64) return error.SkipZigTest;
13231242
13241243 const res = c_explict_win64(.{ .val = 1, .arr = undefined });