authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-22 23:06:07+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-02-22 23:06:07+01:00
loge5c30eef1f338ed65325ddbfd4d631baef0d9b81
treefe3707565525f342ce0aa6c86e58c828809ae600
parentb23f10b42403406f40158ec11de95a3f80ce5879
parentc64d3b0a96a854b093fbedc976397f225ea964fa
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10949 from ziglang/x64-print-results

stage2,x64: print test_runner results

50 files changed, 1717 insertions(+), 319 deletions(-)

lib/std/special/c.zig+19
...@@ -46,6 +46,10 @@ comptime {...@@ -46,6 +46,10 @@ comptime {
4646
47 @export(log10, .{ .name = "log10", .linkage = .Strong });47 @export(log10, .{ .name = "log10", .linkage = .Strong });
48 @export(log10f, .{ .name = "log10f", .linkage = .Strong });48 @export(log10f, .{ .name = "log10f", .linkage = .Strong });
49
50 @export(ceil, .{ .name = "ceil", .linkage = .Strong });
51 @export(ceilf, .{ .name = "ceilf", .linkage = .Strong });
52 @export(ceill, .{ .name = "ceill", .linkage = .Strong });
49}53}
5054
51// Avoid dragging in the runtime safety mechanisms into this .o file,55// Avoid dragging in the runtime safety mechanisms into this .o file,
...@@ -179,3 +183,18 @@ fn log10(a: f64) callconv(.C) f64 {...@@ -179,3 +183,18 @@ fn log10(a: f64) callconv(.C) f64 {
179fn log10f(a: f32) callconv(.C) f32 {183fn log10f(a: f32) callconv(.C) f32 {
180 return math.log10(a);184 return math.log10(a);
181}185}
186
187fn ceilf(x: f32) callconv(.C) f32 {
188 return math.ceil(x);
189}
190
191fn ceil(x: f64) callconv(.C) f64 {
192 return math.ceil(x);
193}
194
195fn ceill(x: c_longdouble) callconv(.C) c_longdouble {
196 if (!long_double_is_f128) {
197 @panic("TODO implement this");
198 }
199 return math.ceil(x);
200}
lib/std/special/c_stage1.zig-13
...@@ -613,19 +613,6 @@ export fn fmod(x: f64, y: f64) f64 {...@@ -613,19 +613,6 @@ export fn fmod(x: f64, y: f64) f64 {
613 return generic_fmod(f64, x, y);613 return generic_fmod(f64, x, y);
614}614}
615615
616export fn ceilf(x: f32) f32 {
617 return math.ceil(x);
618}
619export fn ceil(x: f64) f64 {
620 return math.ceil(x);
621}
622export fn ceill(x: c_longdouble) c_longdouble {
623 if (!long_double_is_f128) {
624 @panic("TODO implement this");
625 }
626 return math.ceil(x);
627}
628
629export fn fmaf(a: f32, b: f32, c: f32) f32 {616export fn fmaf(a: f32, b: f32, c: f32) f32 {
630 return math.fma(f32, a, b, c);617 return math.fma(f32, a, b, c);
631}618}
lib/std/special/test_runner.zig+4-1
...@@ -141,7 +141,10 @@ pub fn main2() anyerror!void {...@@ -141,7 +141,10 @@ pub fn main2() anyerror!void {
141 }141 }
142 };142 };
143 }143 }
144 if (builtin.zig_backend == .stage2_llvm or builtin.zig_backend == .stage2_wasm) {144 if (builtin.zig_backend == .stage2_llvm or
145 builtin.zig_backend == .stage2_wasm or
146 (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag != .macos))
147 {
145 const passed = builtin.test_functions.len - skipped - failed;148 const passed = builtin.test_functions.len - skipped - failed;
146 const stderr = std.io.getStdErr();149 const stderr = std.io.getStdErr();
147 writeInt(stderr, passed) catch {};150 writeInt(stderr, passed) catch {};
src/Liveness.zig+36
...@@ -135,6 +135,42 @@ pub fn getCondBr(l: Liveness, inst: Air.Inst.Index) CondBrSlices {...@@ -135,6 +135,42 @@ pub fn getCondBr(l: Liveness, inst: Air.Inst.Index) CondBrSlices {
135 };135 };
136}136}
137137
138/// Indexed by case number as they appear in AIR.
139/// Else is the last element.
140pub const SwitchBrTable = struct {
141 deaths: []const []const Air.Inst.Index,
142};
143
144/// Caller owns the memory.
145pub fn getSwitchBr(l: Liveness, gpa: Allocator, inst: Air.Inst.Index, cases_len: u32) Allocator.Error!SwitchBrTable {
146 var index: usize = l.special.get(inst) orelse return SwitchBrTable{
147 .deaths = &.{},
148 };
149 const else_death_count = l.extra[index];
150 index += 1;
151
152 var deaths = std.ArrayList([]const Air.Inst.Index).init(gpa);
153 defer deaths.deinit();
154 try deaths.ensureTotalCapacity(cases_len + 1);
155
156 var case_i: u32 = 0;
157 while (case_i < cases_len - 1) : (case_i += 1) {
158 const case_death_count: u32 = l.extra[index];
159 index += 1;
160 const case_deaths = l.extra[index..][0..case_death_count];
161 index += case_death_count;
162 deaths.appendAssumeCapacity(case_deaths);
163 }
164 {
165 // Else
166 const else_deaths = l.extra[index..][0..else_death_count];
167 deaths.appendAssumeCapacity(else_deaths);
168 }
169 return SwitchBrTable{
170 .deaths = deaths.toOwnedSlice(),
171 };
172}
173
138pub fn deinit(l: *Liveness, gpa: Allocator) void {174pub fn deinit(l: *Liveness, gpa: Allocator) void {
139 gpa.free(l.tomb_bits);175 gpa.free(l.tomb_bits);
140 gpa.free(l.extra);176 gpa.free(l.extra);
src/arch/x86_64/CodeGen.zig+646-161
...@@ -49,6 +49,9 @@ arg_index: u32,...@@ -49,6 +49,9 @@ arg_index: u32,
49src_loc: Module.SrcLoc,49src_loc: Module.SrcLoc,
50stack_align: u32,50stack_align: u32,
5151
52ret_backpatch: ?Mir.Inst.Index = null,
53compare_flags_inst: ?Air.Inst.Index = null,
54
52/// MIR Instructions55/// MIR Instructions
53mir_instructions: std.MultiArrayList(Mir.Inst) = .{},56mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
54/// MIR extra data57/// MIR extra data
...@@ -470,6 +473,20 @@ fn gen(self: *Self) InnerError!void {...@@ -470,6 +473,20 @@ fn gen(self: *Self) InnerError!void {
470 };473 };
471 inline for (callee_preserved_regs) |reg, i| {474 inline for (callee_preserved_regs) |reg, i| {
472 if (self.register_manager.isRegAllocated(reg)) {475 if (self.register_manager.isRegAllocated(reg)) {
476 if (self.ret_backpatch) |inst| {
477 if (reg.to64() == .rdi) {
478 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
479 self.mir_instructions.set(inst, Mir.Inst{
480 .tag = .mov,
481 .ops = (Mir.Ops{
482 .reg1 = ops.reg1,
483 .reg2 = .rbp,
484 .flags = 0b01,
485 }).encode(),
486 .data = .{ .imm = @bitCast(u32, -@intCast(i32, self.max_end_stack + 8)) },
487 });
488 }
489 }
473 data.regs |= 1 << @intCast(u5, i);490 data.regs |= 1 << @intCast(u5, i);
474 self.max_end_stack += 8;491 self.max_end_stack += 8;
475 }492 }
...@@ -758,6 +775,9 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {...@@ -758,6 +775,9 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void {
758 const canon_reg = reg.to64();775 const canon_reg = reg.to64();
759 self.register_manager.freeReg(canon_reg);776 self.register_manager.freeReg(canon_reg);
760 },777 },
778 .compare_flags_signed, .compare_flags_unsigned => {
779 self.compare_flags_inst = null;
780 },
761 else => {}, // TODO process stack allocation death781 else => {}, // TODO process stack allocation death
762 }782 }
763}783}
...@@ -870,7 +890,23 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -870,7 +890,23 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
870 assert(reg.to64() == reg_mcv.register.to64());890 assert(reg.to64() == reg_mcv.register.to64());
871 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];891 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
872 try branch.inst_table.put(self.gpa, inst, stack_mcv);892 try branch.inst_table.put(self.gpa, inst, stack_mcv);
873 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);893 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{});
894}
895
896pub fn spillCompareFlagsIfOccupied(self: *Self) !void {
897 if (self.compare_flags_inst) |inst_to_save| {
898 const mcv = self.getResolvedInstValue(inst_to_save);
899 assert(mcv == .compare_flags_signed or mcv == .compare_flags_unsigned);
900
901 const new_mcv = try self.allocRegOrMem(inst_to_save, true);
902 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
903 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
904
905 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
906 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
907
908 self.compare_flags_inst = null;
909 }
874}910}
875911
876/// Copies a value to a register without tracking the register. The register is not considered912/// Copies a value to a register without tracking the register. The register is not considered
...@@ -925,8 +961,6 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -925,8 +961,6 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
925 const operand = try self.resolveInst(ty_op.operand);961 const operand = try self.resolveInst(ty_op.operand);
926 const info_a = operand_ty.intInfo(self.target.*);962 const info_a = operand_ty.intInfo(self.target.*);
927 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);963 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);
928 if (info_a.signedness != info_b.signedness)
929 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
930964
931 const operand_abi_size = operand_ty.abiSize(self.target.*);965 const operand_abi_size = operand_ty.abiSize(self.target.*);
932 const dest_ty = self.air.typeOfIndex(inst);966 const dest_ty = self.air.typeOfIndex(inst);
...@@ -1058,10 +1092,44 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1058,10 +1092,44 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
10581092
1059fn airMin(self: *Self, inst: Air.Inst.Index) !void {1093fn airMin(self: *Self, inst: Air.Inst.Index) !void {
1060 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1094 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1061 const result: MCValue = if (self.liveness.isUnused(inst))1095 if (self.liveness.isUnused(inst)) {
1062 .dead1096 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1063 else1097 }
1064 return self.fail("TODO implement min for {}", .{self.target.cpu.arch});1098
1099 const ty = self.air.typeOfIndex(inst);
1100 if (ty.zigTypeTag() != .Int) {
1101 return self.fail("TODO implement min for type {}", .{ty});
1102 }
1103 const signedness = ty.intInfo(self.target.*).signedness;
1104 const result: MCValue = result: {
1105 // TODO improve by checking if any operand can be reused.
1106 // TODO audit register allocation
1107 const lhs = try self.resolveInst(bin_op.lhs);
1108 lhs.freezeIfRegister(&self.register_manager);
1109 defer lhs.unfreezeIfRegister(&self.register_manager);
1110
1111 const lhs_reg = try self.copyToTmpRegister(ty, lhs);
1112 self.register_manager.freezeRegs(&.{lhs_reg});
1113 defer self.register_manager.unfreezeRegs(&.{lhs_reg});
1114
1115 const rhs_mcv = try self.limitImmediateType(bin_op.rhs, i32);
1116 rhs_mcv.freezeIfRegister(&self.register_manager);
1117 defer rhs_mcv.unfreezeIfRegister(&self.register_manager);
1118
1119 try self.genBinMathOpMir(.cmp, ty, .{ .register = lhs_reg }, rhs_mcv);
1120
1121 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, rhs_mcv);
1122 _ = try self.addInst(.{
1123 .tag = if (signedness == .signed) .cond_mov_lt else .cond_mov_below,
1124 .ops = (Mir.Ops{
1125 .reg1 = dst_mcv.register,
1126 .reg2 = lhs_reg,
1127 }).encode(),
1128 .data = undefined,
1129 });
1130
1131 break :result dst_mcv;
1132 };
1065 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1133 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1066}1134}
10671135
...@@ -1081,9 +1149,6 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1081,9 +1149,6 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1081 const offset = try self.resolveInst(op_rhs);1149 const offset = try self.resolveInst(op_rhs);
1082 const offset_ty = self.air.typeOf(op_rhs);1150 const offset_ty = self.air.typeOf(op_rhs);
10831151
1084 ptr.freezeIfRegister(&self.register_manager);
1085 defer ptr.unfreezeIfRegister(&self.register_manager);
1086
1087 offset.freezeIfRegister(&self.register_manager);1152 offset.freezeIfRegister(&self.register_manager);
1088 defer offset.unfreezeIfRegister(&self.register_manager);1153 defer offset.unfreezeIfRegister(&self.register_manager);
10891154
...@@ -1091,9 +1156,12 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1091,9 +1156,12 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1091 if (self.reuseOperand(inst, op_lhs, 0, ptr)) {1156 if (self.reuseOperand(inst, op_lhs, 0, ptr)) {
1092 if (ptr.isMemory() or ptr.isRegister()) break :blk ptr;1157 if (ptr.isMemory() or ptr.isRegister()) break :blk ptr;
1093 }1158 }
1094 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, ptr);1159 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, ptr) };
1095 };1160 };
10961161
1162 dst_mcv.freezeIfRegister(&self.register_manager);
1163 defer dst_mcv.unfreezeIfRegister(&self.register_manager);
1164
1097 const offset_mcv = blk: {1165 const offset_mcv = blk: {
1098 if (self.reuseOperand(inst, op_rhs, 1, offset)) {1166 if (self.reuseOperand(inst, op_rhs, 1, offset)) {
1099 if (offset.isRegister()) break :blk offset;1167 if (offset.isRegister()) break :blk offset;
...@@ -1101,6 +1169,9 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1101,6 +1169,9 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1101 break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) };1169 break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) };
1102 };1170 };
11031171
1172 offset_mcv.freezeIfRegister(&self.register_manager);
1173 defer offset_mcv.unfreezeIfRegister(&self.register_manager);
1174
1104 try self.genIMulOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size });1175 try self.genIMulOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size });
11051176
1106 const tag = self.air.instructions.items(.tag)[inst];1177 const tag = self.air.instructions.items(.tag)[inst];
...@@ -1145,8 +1216,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -1145,8 +1216,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
1145 const len_ty = self.air.typeOf(bin_op.rhs);1216 const len_ty = self.air.typeOf(bin_op.rhs);
11461217
1147 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));1218 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
1148 try self.genSetStack(ptr_ty, stack_offset, ptr);1219 try self.genSetStack(ptr_ty, stack_offset, ptr, .{});
1149 try self.genSetStack(len_ty, stack_offset - 8, len);1220 try self.genSetStack(len_ty, stack_offset - 8, len, .{});
1150 const result = MCValue{ .stack_offset = stack_offset };1221 const result = MCValue{ .stack_offset = stack_offset };
11511222
1152 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1223 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
...@@ -1179,12 +1250,43 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {...@@ -1179,12 +1250,43 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
1179 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1250 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1180}1251}
11811252
1253fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air.Inst.Ref) !MCValue {
1254 const dst_ty = self.air.typeOfIndex(inst);
1255 const lhs = try self.resolveInst(op_lhs);
1256 const rhs = try self.resolveInst(op_rhs);
1257
1258 rhs.freezeIfRegister(&self.register_manager);
1259 defer rhs.unfreezeIfRegister(&self.register_manager);
1260
1261 const dst_mcv = blk: {
1262 if (self.reuseOperand(inst, op_lhs, 0, lhs)) {
1263 if (lhs.isMemory() or lhs.isRegister()) break :blk lhs;
1264 }
1265 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);
1266 };
1267
1268 dst_mcv.freezeIfRegister(&self.register_manager);
1269 defer dst_mcv.unfreezeIfRegister(&self.register_manager);
1270
1271 const rhs_mcv = blk: {
1272 if (rhs.isRegister()) break :blk rhs;
1273 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, rhs) };
1274 };
1275
1276 rhs_mcv.freezeIfRegister(&self.register_manager);
1277 defer rhs_mcv.unfreezeIfRegister(&self.register_manager);
1278
1279 try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, rhs_mcv);
1280
1281 return dst_mcv;
1282}
1283
1182fn airSub(self: *Self, inst: Air.Inst.Index) !void {1284fn airSub(self: *Self, inst: Air.Inst.Index) !void {
1183 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1285 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1184 const result: MCValue = if (self.liveness.isUnused(inst))1286 const result: MCValue = if (self.liveness.isUnused(inst))
1185 .dead1287 .dead
1186 else1288 else
1187 try self.genBinMathOp(inst, bin_op.lhs, bin_op.rhs);1289 try self.genSubOp(inst, bin_op.lhs, bin_op.rhs);
1188 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1290 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1189}1291}
11901292
...@@ -1523,11 +1625,58 @@ fn airXor(self: *Self, inst: Air.Inst.Index) !void {...@@ -1523,11 +1625,58 @@ fn airXor(self: *Self, inst: Air.Inst.Index) !void {
15231625
1524fn airShl(self: *Self, inst: Air.Inst.Index) !void {1626fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1525 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1627 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1526 const result: MCValue = if (self.liveness.isUnused(inst))1628 if (self.liveness.isUnused(inst)) {
1527 .dead1629 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1528 else1630 }
1529 return self.fail("TODO implement shl for {}", .{self.target.cpu.arch});1631
1530 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1632 const ty = self.air.typeOfIndex(inst);
1633 const tag = self.air.instructions.items(.tag)[inst];
1634 switch (tag) {
1635 .shl_exact => return self.fail("TODO implement {} for type {}", .{ tag, ty }),
1636 .shl => {},
1637 else => unreachable,
1638 }
1639
1640 if (ty.zigTypeTag() != .Int) {
1641 return self.fail("TODO implement .shl for type {}", .{ty});
1642 }
1643 if (ty.abiSize(self.target.*) > 8) {
1644 return self.fail("TODO implement .shl for integers larger than 8 bytes", .{});
1645 }
1646
1647 // TODO look into reusing the operands
1648 // TODO audit register allocation mechanics
1649 const shift = try self.resolveInst(bin_op.rhs);
1650 const shift_ty = self.air.typeOf(bin_op.rhs);
1651
1652 blk: {
1653 switch (shift) {
1654 .register => |reg| {
1655 if (reg.to64() == .rcx) break :blk;
1656 },
1657 else => {},
1658 }
1659 try self.register_manager.getReg(.rcx, null);
1660 try self.genSetReg(shift_ty, .rcx, shift);
1661 }
1662 self.register_manager.freezeRegs(&.{.rcx});
1663 defer self.register_manager.unfreezeRegs(&.{.rcx});
1664
1665 const value = try self.resolveInst(bin_op.lhs);
1666 value.freezeIfRegister(&self.register_manager);
1667 defer value.unfreezeIfRegister(&self.register_manager);
1668
1669 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, value);
1670 _ = try self.addInst(.{
1671 .tag = .sal,
1672 .ops = (Mir.Ops{
1673 .reg1 = dst_mcv.register,
1674 .flags = 0b01,
1675 }).encode(),
1676 .data = undefined,
1677 });
1678
1679 return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none });
1531}1680}
15321681
1533fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {1682fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
...@@ -1580,23 +1729,44 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -1580,23 +1729,44 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
15801729
1581fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {1730fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1582 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1731 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1583 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1732 if (self.liveness.isUnused(inst)) {
1584 const err_union_ty = self.air.typeOf(ty_op.operand);1733 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1585 const payload_ty = err_union_ty.errorUnionPayload();1734 }
1586 const mcv = try self.resolveInst(ty_op.operand);1735 const err_union_ty = self.air.typeOf(ty_op.operand);
1587 if (!payload_ty.hasRuntimeBits()) break :result mcv;1736 const payload_ty = err_union_ty.errorUnionPayload();
1588 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});1737 const operand = try self.resolveInst(ty_op.operand);
1738 const result: MCValue = result: {
1739 if (!payload_ty.hasRuntimeBits()) break :result operand;
1740 switch (operand) {
1741 .stack_offset => |off| {
1742 break :result MCValue{ .stack_offset = off };
1743 },
1744 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),
1745 }
1589 };1746 };
1590 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1747 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1591}1748}
15921749
1593fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {1750fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
1594 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1751 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1595 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1752 if (self.liveness.isUnused(inst)) {
1596 const err_union_ty = self.air.typeOf(ty_op.operand);1753 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1597 const payload_ty = err_union_ty.errorUnionPayload();1754 }
1755 const err_union_ty = self.air.typeOf(ty_op.operand);
1756 const payload_ty = err_union_ty.errorUnionPayload();
1757 const result: MCValue = result: {
1598 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;1758 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
1599 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});1759
1760 const operand = try self.resolveInst(ty_op.operand);
1761 const err_ty = err_union_ty.errorUnionSet();
1762 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
1763 switch (operand) {
1764 .stack_offset => |off| {
1765 const offset = off - @intCast(i32, err_abi_size);
1766 break :result MCValue{ .stack_offset = offset };
1767 },
1768 else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
1769 }
1600 };1770 };
1601 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1771 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1602}1772}
...@@ -1647,24 +1817,47 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -1647,24 +1817,47 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1647/// T to E!T1817/// T to E!T
1648fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {1818fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
1649 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1819 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1650 const result: MCValue = if (self.liveness.isUnused(inst))1820 if (self.liveness.isUnused(inst)) {
1651 .dead1821 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1652 else1822 }
1653 return self.fail("TODO implement wrap errunion payload for {}", .{self.target.cpu.arch});1823 const error_union_ty = self.air.getRefType(ty_op.ty);
1654 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1824 const error_ty = error_union_ty.errorUnionSet();
1825 const payload_ty = error_union_ty.errorUnionPayload();
1826 const operand = try self.resolveInst(ty_op.operand);
1827 assert(payload_ty.hasRuntimeBits());
1828
1829 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
1830 const abi_align = error_union_ty.abiAlignment(self.target.*);
1831 const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*));
1832 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
1833 try self.genSetStack(error_ty, stack_offset, .{ .immediate = 0 }, .{});
1834 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, err_abi_size), operand, .{});
1835
1836 return self.finishAir(inst, .{ .stack_offset = stack_offset }, .{ ty_op.operand, .none, .none });
1655}1837}
16561838
1657/// E to E!T1839/// E to E!T
1658fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {1840fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1659 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1841 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1660 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1842 if (self.liveness.isUnused(inst)) {
1661 const error_union_ty = self.air.getRefType(ty_op.ty);1843 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1662 const payload_ty = error_union_ty.errorUnionPayload();1844 }
1663 const mcv = try self.resolveInst(ty_op.operand);1845 const error_union_ty = self.air.getRefType(ty_op.ty);
1664 if (!payload_ty.hasRuntimeBits()) break :result mcv;1846 const error_ty = error_union_ty.errorUnionSet();
16651847 const payload_ty = error_union_ty.errorUnionPayload();
1666 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});1848 const err = try self.resolveInst(ty_op.operand);
1849 const result: MCValue = result: {
1850 if (!payload_ty.hasRuntimeBits()) break :result err;
1851
1852 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
1853 const abi_align = error_union_ty.abiAlignment(self.target.*);
1854 const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*));
1855 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
1856 try self.genSetStack(error_ty, stack_offset, err, .{});
1857 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, err_abi_size), .undef, .{});
1858 break :result MCValue{ .stack_offset = stack_offset };
1667 };1859 };
1860
1668 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1861 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1669}1862}
16701863
...@@ -1824,7 +2017,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1824,7 +2017,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
1824 @intCast(u32, array_ty.abiSize(self.target.*)),2017 @intCast(u32, array_ty.abiSize(self.target.*)),
1825 array_ty.abiAlignment(self.target.*),2018 array_ty.abiAlignment(self.target.*),
1826 ));2019 ));
1827 try self.genSetStack(array_ty, off, array);2020 try self.genSetStack(array_ty, off, array, .{});
1828 break :inner off;2021 break :inner off;
1829 },2022 },
1830 .stack_offset => |off| {2023 .stack_offset => |off| {
...@@ -2057,10 +2250,10 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2057,10 +2250,10 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2057 if (abi_size <= 8) {2250 if (abi_size <= 8) {
2058 const tmp_reg = try self.register_manager.allocReg(null);2251 const tmp_reg = try self.register_manager.allocReg(null);
2059 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);2252 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
2060 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2253 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{});
2061 }2254 }
20622255
2063 try self.genInlineMemcpy(off, .rbp, elem_ty, ptr);2256 try self.genInlineMemcpy(off, elem_ty, ptr, .{});
2064 },2257 },
2065 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),2258 else => return self.fail("TODO implement loading from register into {}", .{dst_mcv}),
2066 }2259 }
...@@ -2155,7 +2348,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2155,7 +2348,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2155 try self.store(.{ .register = reg }, value, ptr_ty, value_ty);2348 try self.store(.{ .register = reg }, value, ptr_ty, value_ty);
2156 },2349 },
2157 .ptr_stack_offset => |off| {2350 .ptr_stack_offset => |off| {
2158 try self.genSetStack(value_ty, off, value);2351 try self.genSetStack(value_ty, off, value, .{});
2159 },2352 },
2160 .ptr_embedded_in_code => |off| {2353 .ptr_embedded_in_code => |off| {
2161 try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value);2354 try self.setRegOrMem(value_ty, .{ .embedded_in_code = off }, value);
...@@ -2590,6 +2783,8 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -2590,6 +2783,8 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
2590 .memory,2783 .memory,
2591 .got_load,2784 .got_load,
2592 .direct_load,2785 .direct_load,
2786 .compare_flags_signed,
2787 .compare_flags_unsigned,
2593 => {2788 => {
2594 assert(abi_size <= 8);2789 assert(abi_size <= 8);
2595 self.register_manager.freezeRegs(&.{dst_reg});2790 self.register_manager.freezeRegs(&.{dst_reg});
...@@ -2611,12 +2806,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -2611,12 +2806,6 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
2611 .data = .{ .imm = @bitCast(u32, -off) },2806 .data = .{ .imm = @bitCast(u32, -off) },
2612 });2807 });
2613 },2808 },
2614 .compare_flags_unsigned => {
2615 return self.fail("TODO implement x86 ADD/SUB/CMP source compare flag (unsigned)", .{});
2616 },
2617 .compare_flags_signed => {
2618 return self.fail("TODO implement x86 ADD/SUB/CMP source compare flag (signed)", .{});
2619 },
2620 }2809 }
2621 },2810 },
2622 .stack_offset => |off| {2811 .stack_offset => |off| {
...@@ -2629,7 +2818,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -2629,7 +2818,7 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
26292818
2630 switch (src_mcv) {2819 switch (src_mcv) {
2631 .none => unreachable,2820 .none => unreachable,
2632 .undef => return self.genSetStack(dst_ty, off, .undef),2821 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
2633 .dead, .unreach => unreachable,2822 .dead, .unreach => unreachable,
2634 .ptr_stack_offset => unreachable,2823 .ptr_stack_offset => unreachable,
2635 .ptr_embedded_in_code => unreachable,2824 .ptr_embedded_in_code => unreachable,
...@@ -2772,7 +2961,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !...@@ -2772,7 +2961,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !
2772 .stack_offset => |off| {2961 .stack_offset => |off| {
2773 switch (src_mcv) {2962 switch (src_mcv) {
2774 .none => unreachable,2963 .none => unreachable,
2775 .undef => return self.genSetStack(dst_ty, off, .undef),2964 .undef => return self.genSetStack(dst_ty, off, .undef, .{}),
2776 .dead, .unreach => unreachable,2965 .dead, .unreach => unreachable,
2777 .ptr_stack_offset => unreachable,2966 .ptr_stack_offset => unreachable,
2778 .ptr_embedded_in_code => unreachable,2967 .ptr_embedded_in_code => unreachable,
...@@ -2790,7 +2979,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !...@@ -2790,7 +2979,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !
2790 .data = undefined,2979 .data = undefined,
2791 });2980 });
2792 // copy dst_reg back out2981 // copy dst_reg back out
2793 return self.genSetStack(dst_ty, off, MCValue{ .register = dst_reg });2982 return self.genSetStack(dst_ty, off, MCValue{ .register = dst_reg }, .{});
2794 },2983 },
2795 .immediate => |imm| {2984 .immediate => |imm| {
2796 _ = imm;2985 _ = imm;
...@@ -2888,6 +3077,20 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2888,6 +3077,20 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2888 var info = try self.resolveCallingConventionValues(fn_ty);3077 var info = try self.resolveCallingConventionValues(fn_ty);
2889 defer info.deinit(self);3078 defer info.deinit(self);
28903079
3080 try self.spillCompareFlagsIfOccupied();
3081
3082 if (info.return_value == .stack_offset) {
3083 const ret_ty = fn_ty.fnReturnType();
3084 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
3085 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
3086 const stack_offset = @intCast(i32, try self.allocMem(inst, ret_abi_size, ret_abi_align));
3087
3088 try self.register_manager.getReg(.rdi, inst);
3089 try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });
3090
3091 info.return_value.stack_offset = stack_offset;
3092 }
3093
2891 for (args) |arg, arg_i| {3094 for (args) |arg, arg_i| {
2892 const mc_arg = info.args[arg_i];3095 const mc_arg = info.args[arg_i];
2893 const arg_ty = self.air.typeOf(arg);3096 const arg_ty = self.air.typeOf(arg);
...@@ -3099,9 +3302,33 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -3099,9 +3302,33 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
3099 return bt.finishAir(result);3302 return bt.finishAir(result);
3100}3303}
31013304
3102fn ret(self: *Self, mcv: MCValue) !void {3305fn airRet(self: *Self, inst: Air.Inst.Index) !void {
3306 const un_op = self.air.instructions.items(.data)[inst].un_op;
3307 const operand = try self.resolveInst(un_op);
3103 const ret_ty = self.fn_type.fnReturnType();3308 const ret_ty = self.fn_type.fnReturnType();
3104 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);3309 switch (self.ret_mcv) {
3310 .stack_offset => {
3311 // TODO audit register allocation!
3312 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });
3313 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });
3314 const reg = try self.register_manager.allocReg(null);
3315 self.ret_backpatch = try self.addInst(.{
3316 .tag = .mov,
3317 .ops = (Mir.Ops{
3318 .reg1 = reg,
3319 .reg2 = .rdi,
3320 }).encode(),
3321 .data = undefined,
3322 });
3323 try self.genSetStack(ret_ty, 0, operand, .{
3324 .source_stack_base = .rbp,
3325 .dest_stack_base = reg,
3326 });
3327 },
3328 else => {
3329 try self.setRegOrMem(ret_ty, self.ret_mcv, operand);
3330 },
3331 }
3105 // TODO when implementing defer, this will need to jump to the appropriate defer expression.3332 // TODO when implementing defer, this will need to jump to the appropriate defer expression.
3106 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction3333 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
3107 // which is available if the jump is 127 bytes or less forward.3334 // which is available if the jump is 127 bytes or less forward.
...@@ -3113,21 +3340,49 @@ fn ret(self: *Self, mcv: MCValue) !void {...@@ -3113,21 +3340,49 @@ fn ret(self: *Self, mcv: MCValue) !void {
3113 .data = .{ .inst = undefined },3340 .data = .{ .inst = undefined },
3114 });3341 });
3115 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);3342 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
3116}
3117
3118fn airRet(self: *Self, inst: Air.Inst.Index) !void {
3119 const un_op = self.air.instructions.items(.data)[inst].un_op;
3120 const operand = try self.resolveInst(un_op);
3121 try self.ret(operand);
3122 return self.finishAir(inst, .dead, .{ un_op, .none, .none });3343 return self.finishAir(inst, .dead, .{ un_op, .none, .none });
3123}3344}
31243345
3125fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {3346fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
3126 const un_op = self.air.instructions.items(.data)[inst].un_op;3347 const un_op = self.air.instructions.items(.data)[inst].un_op;
3127 const ptr = try self.resolveInst(un_op);3348 const ptr = try self.resolveInst(un_op);
3128 // we can reuse self.ret_mcv because it just gets returned3349 const ptr_ty = self.air.typeOf(un_op);
3129 try self.load(self.ret_mcv, ptr, self.air.typeOf(un_op));3350 const elem_ty = ptr_ty.elemType();
3130 try self.ret(self.ret_mcv);3351 switch (self.ret_mcv) {
3352 .stack_offset => {
3353 // TODO audit register allocation!
3354 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rdi });
3355 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rdi });
3356 const reg = try self.register_manager.allocReg(null);
3357 self.ret_backpatch = try self.addInst(.{
3358 .tag = .mov,
3359 .ops = (Mir.Ops{
3360 .reg1 = reg,
3361 .reg2 = .rdi,
3362 }).encode(),
3363 .data = undefined,
3364 });
3365 try self.genInlineMemcpy(0, elem_ty, ptr, .{
3366 .source_stack_base = .rbp,
3367 .dest_stack_base = reg,
3368 });
3369 },
3370 else => {
3371 try self.load(self.ret_mcv, ptr, ptr_ty);
3372 try self.setRegOrMem(elem_ty, self.ret_mcv, self.ret_mcv);
3373 },
3374 }
3375 // TODO when implementing defer, this will need to jump to the appropriate defer expression.
3376 // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction
3377 // which is available if the jump is 127 bytes or less forward.
3378 const jmp_reloc = try self.addInst(.{
3379 .tag = .jmp,
3380 .ops = (Mir.Ops{
3381 .flags = 0b00,
3382 }).encode(),
3383 .data = .{ .inst = undefined },
3384 });
3385 try self.exitlude_jump_relocs.append(self.gpa, jmp_reloc);
3131 return self.finishAir(inst, .dead, .{ un_op, .none, .none });3386 return self.finishAir(inst, .dead, .{ un_op, .none, .none });
3132}3387}
31333388
...@@ -3147,16 +3402,24 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3147,16 +3402,24 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3147 break :blk ty.intInfo(self.target.*).signedness;3402 break :blk ty.intInfo(self.target.*).signedness;
3148 };3403 };
31493404
3150 const lhs = try self.resolveInst(bin_op.lhs);3405 try self.spillCompareFlagsIfOccupied();
3151 const rhs = try self.resolveInst(bin_op.rhs);3406 self.compare_flags_inst = inst;
3407
3152 const result: MCValue = result: {3408 const result: MCValue = result: {
3153 // There are 2 operands, destination and source.3409 // There are 2 operands, destination and source.
3154 // Either one, but not both, can be a memory operand.3410 // Either one, but not both, can be a memory operand.
3155 // Source operand can be an immediate, 8 bits or 32 bits.3411 // Source operand can be an immediate, 8 bits or 32 bits.
3156 const dst_mcv = if (lhs.isImmediate() or (lhs.isMemory() and rhs.isMemory()))3412 // TODO look into reusing the operand
3157 MCValue{ .register = try self.copyToTmpRegister(ty, lhs) }3413 const lhs = try self.resolveInst(bin_op.lhs);
3158 else3414 lhs.freezeIfRegister(&self.register_manager);
3159 lhs;3415 defer lhs.unfreezeIfRegister(&self.register_manager);
3416
3417 const dst_reg = try self.copyToTmpRegister(ty, lhs);
3418 self.register_manager.freezeRegs(&.{dst_reg});
3419 defer self.register_manager.unfreezeRegs(&.{dst_reg});
3420
3421 const dst_mcv = MCValue{ .register = dst_reg };
3422
3160 // This instruction supports only signed 32-bit immediates at most.3423 // This instruction supports only signed 32-bit immediates at most.
3161 const src_mcv = try self.limitImmediateType(bin_op.rhs, i32);3424 const src_mcv = try self.limitImmediateType(bin_op.rhs, i32);
31623425
...@@ -3166,6 +3429,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3166,6 +3429,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3166 .unsigned => MCValue{ .compare_flags_unsigned = op },3429 .unsigned => MCValue{ .compare_flags_unsigned = op },
3167 };3430 };
3168 };3431 };
3432
3169 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });3433 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
3170}3434}
31713435
...@@ -3213,6 +3477,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {...@@ -3213,6 +3477,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
3213 });3477 });
3214 },3478 },
3215 .register => |reg| {3479 .register => |reg| {
3480 try self.spillCompareFlagsIfOccupied();
3216 _ = try self.addInst(.{3481 _ = try self.addInst(.{
3217 .tag = .@"test",3482 .tag = .@"test",
3218 .ops = (Mir.Ops{3483 .ops = (Mir.Ops{
...@@ -3229,19 +3494,15 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {...@@ -3229,19 +3494,15 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
3229 .data = .{ .inst = undefined },3494 .data = .{ .inst = undefined },
3230 });3495 });
3231 },3496 },
3232 .immediate => {3497 .immediate,
3233 if (abi_size <= 8) {3498 .stack_offset,
3234 const reg = try self.copyToTmpRegister(ty, mcv);3499 => {
3235 return self.genCondBrMir(ty, .{ .register = reg });3500 try self.spillCompareFlagsIfOccupied();
3236 }
3237 return self.fail("TODO implement condbr when condition is immediate larger than 4 bytes", .{});
3238 },
3239 .stack_offset => {
3240 if (abi_size <= 8) {3501 if (abi_size <= 8) {
3241 const reg = try self.copyToTmpRegister(ty, mcv);3502 const reg = try self.copyToTmpRegister(ty, mcv);
3242 return self.genCondBrMir(ty, .{ .register = reg });3503 return self.genCondBrMir(ty, .{ .register = reg });
3243 }3504 }
3244 return self.fail("TODO implement condbr when condition is stack offset with abi larger than 8 bytes", .{});3505 return self.fail("TODO implement condbr when condition is {} with abi larger than 8 bytes", .{mcv});
3245 },3506 },
3246 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),3507 else => return self.fail("TODO implement condbr when condition is {s}", .{@tagName(mcv)}),
3247 }3508 }
...@@ -3258,9 +3519,23 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3258,9 +3519,23 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
32583519
3259 const reloc = try self.genCondBrMir(cond_ty, cond);3520 const reloc = try self.genCondBrMir(cond_ty, cond);
32603521
3522 // If the condition dies here in this condbr instruction, process
3523 // that death now instead of later as this has an effect on
3524 // whether it needs to be spilled in the branches
3525 // TODO I need investigate how to make this work without removing
3526 // an assertion from getResolvedInstValue()
3527 if (self.liveness.operandDies(inst, 0)) {
3528 const op_int = @enumToInt(pl_op.operand);
3529 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
3530 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
3531 self.processDeath(op_index);
3532 }
3533 }
3534
3261 // Capture the state of register and stack allocation state so that we can revert to it.3535 // Capture the state of register and stack allocation state so that we can revert to it.
3262 const parent_next_stack_offset = self.next_stack_offset;3536 const parent_next_stack_offset = self.next_stack_offset;
3263 const parent_free_registers = self.register_manager.free_registers;3537 const parent_free_registers = self.register_manager.free_registers;
3538 const parent_compare_flags_inst = self.compare_flags_inst;
3264 var parent_stack = try self.stack.clone(self.gpa);3539 var parent_stack = try self.stack.clone(self.gpa);
3265 defer parent_stack.deinit(self.gpa);3540 defer parent_stack.deinit(self.gpa);
3266 const parent_registers = self.register_manager.registers;3541 const parent_registers = self.register_manager.registers;
...@@ -3282,6 +3557,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3282,6 +3557,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3282 defer saved_then_branch.deinit(self.gpa);3557 defer saved_then_branch.deinit(self.gpa);
32833558
3284 self.register_manager.registers = parent_registers;3559 self.register_manager.registers = parent_registers;
3560 self.compare_flags_inst = parent_compare_flags_inst;
32853561
3286 self.stack.deinit(self.gpa);3562 self.stack.deinit(self.gpa);
3287 self.stack = parent_stack;3563 self.stack = parent_stack;
...@@ -3352,6 +3628,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3352,6 +3628,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3352 // We already deleted the items from this table that matched the else_branch.3628 // We already deleted the items from this table that matched the else_branch.
3353 // So these are all instructions that are only overridden in the then branch.3629 // So these are all instructions that are only overridden in the then branch.
3354 parent_branch.inst_table.putAssumeCapacity(then_key, then_value);3630 parent_branch.inst_table.putAssumeCapacity(then_key, then_value);
3631 log.debug("then_value = {}", .{then_value});
3355 if (then_value == .dead)3632 if (then_value == .dead)
3356 continue;3633 continue;
3357 const parent_mcv = blk: {3634 const parent_mcv = blk: {
...@@ -3376,23 +3653,31 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3376,23 +3653,31 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3376 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });3653 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
3377}3654}
33783655
3379fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue {3656fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
3657 try self.spillCompareFlagsIfOccupied();
3658 self.compare_flags_inst = inst;
3659
3380 try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 });3660 try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 });
3381 return MCValue{ .compare_flags_unsigned = .eq };3661 return MCValue{ .compare_flags_unsigned = .eq };
3382}3662}
33833663
3384fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue {3664fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
3385 const is_null_res = try self.isNull(ty, operand);3665 const is_null_res = try self.isNull(inst, ty, operand);
3386 assert(is_null_res.compare_flags_unsigned == .eq);3666 assert(is_null_res.compare_flags_unsigned == .eq);
3387 return MCValue{ .compare_flags_unsigned = .neq };3667 return MCValue{ .compare_flags_unsigned = .neq };
3388}3668}
33893669
3390fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3670fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
3391 const err_type = ty.errorUnionSet();3671 const err_type = ty.errorUnionSet();
3392 const payload_type = ty.errorUnionPayload();3672 const payload_type = ty.errorUnionPayload();
3393 if (!err_type.hasRuntimeBits()) {3673 if (!err_type.hasRuntimeBits()) {
3394 return MCValue{ .immediate = 0 }; // always false3674 return MCValue{ .immediate = 0 }; // always false
3395 } else if (!payload_type.hasRuntimeBits()) {3675 }
3676
3677 try self.spillCompareFlagsIfOccupied();
3678 self.compare_flags_inst = inst;
3679
3680 if (!payload_type.hasRuntimeBits()) {
3396 if (err_type.abiSize(self.target.*) <= 8) {3681 if (err_type.abiSize(self.target.*) <= 8) {
3397 try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });3682 try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });
3398 return MCValue{ .compare_flags_unsigned = .gt };3683 return MCValue{ .compare_flags_unsigned = .gt };
...@@ -3400,12 +3685,13 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3400,12 +3685,13 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3400 return self.fail("TODO isErr for errors with size larger than register size", .{});3685 return self.fail("TODO isErr for errors with size larger than register size", .{});
3401 }3686 }
3402 } else {3687 } else {
3403 return self.fail("TODO isErr for non-empty payloads", .{});3688 try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });
3689 return MCValue{ .compare_flags_unsigned = .gt };
3404 }3690 }
3405}3691}
34063692
3407fn isNonErr(self: *Self, ty: Type, operand: MCValue) !MCValue {3693fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
3408 const is_err_res = try self.isErr(ty, operand);3694 const is_err_res = try self.isErr(inst, ty, operand);
3409 switch (is_err_res) {3695 switch (is_err_res) {
3410 .compare_flags_unsigned => |op| {3696 .compare_flags_unsigned => |op| {
3411 assert(op == .gt);3697 assert(op == .gt);
...@@ -3424,7 +3710,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -3424,7 +3710,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
3424 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3710 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3425 const operand = try self.resolveInst(un_op);3711 const operand = try self.resolveInst(un_op);
3426 const ty = self.air.typeOf(un_op);3712 const ty = self.air.typeOf(un_op);
3427 break :result try self.isNull(ty, operand);3713 break :result try self.isNull(inst, ty, operand);
3428 };3714 };
3429 return self.finishAir(inst, result, .{ un_op, .none, .none });3715 return self.finishAir(inst, result, .{ un_op, .none, .none });
3430}3716}
...@@ -3445,7 +3731,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3445,7 +3731,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
3445 };3731 };
3446 const ptr_ty = self.air.typeOf(un_op);3732 const ptr_ty = self.air.typeOf(un_op);
3447 try self.load(operand, operand_ptr, ptr_ty);3733 try self.load(operand, operand_ptr, ptr_ty);
3448 break :result try self.isNull(ptr_ty.elemType(), operand);3734 break :result try self.isNull(inst, ptr_ty.elemType(), operand);
3449 };3735 };
3450 return self.finishAir(inst, result, .{ un_op, .none, .none });3736 return self.finishAir(inst, result, .{ un_op, .none, .none });
3451}3737}
...@@ -3455,7 +3741,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {...@@ -3455,7 +3741,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
3455 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3741 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3456 const operand = try self.resolveInst(un_op);3742 const operand = try self.resolveInst(un_op);
3457 const ty = self.air.typeOf(un_op);3743 const ty = self.air.typeOf(un_op);
3458 break :result try self.isNonNull(ty, operand);3744 break :result try self.isNonNull(inst, ty, operand);
3459 };3745 };
3460 return self.finishAir(inst, result, .{ un_op, .none, .none });3746 return self.finishAir(inst, result, .{ un_op, .none, .none });
3461}3747}
...@@ -3476,7 +3762,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3476,7 +3762,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
3476 };3762 };
3477 const ptr_ty = self.air.typeOf(un_op);3763 const ptr_ty = self.air.typeOf(un_op);
3478 try self.load(operand, operand_ptr, ptr_ty);3764 try self.load(operand, operand_ptr, ptr_ty);
3479 break :result try self.isNonNull(ptr_ty.elemType(), operand);3765 break :result try self.isNonNull(inst, ptr_ty.elemType(), operand);
3480 };3766 };
3481 return self.finishAir(inst, result, .{ un_op, .none, .none });3767 return self.finishAir(inst, result, .{ un_op, .none, .none });
3482}3768}
...@@ -3486,7 +3772,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3486,7 +3772,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
3486 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3772 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3487 const operand = try self.resolveInst(un_op);3773 const operand = try self.resolveInst(un_op);
3488 const ty = self.air.typeOf(un_op);3774 const ty = self.air.typeOf(un_op);
3489 break :result try self.isErr(ty, operand);3775 break :result try self.isErr(inst, ty, operand);
3490 };3776 };
3491 return self.finishAir(inst, result, .{ un_op, .none, .none });3777 return self.finishAir(inst, result, .{ un_op, .none, .none });
3492}3778}
...@@ -3507,7 +3793,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3507,7 +3793,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3507 };3793 };
3508 const ptr_ty = self.air.typeOf(un_op);3794 const ptr_ty = self.air.typeOf(un_op);
3509 try self.load(operand, operand_ptr, ptr_ty);3795 try self.load(operand, operand_ptr, ptr_ty);
3510 break :result try self.isErr(ptr_ty.elemType(), operand);3796 break :result try self.isErr(inst, ptr_ty.elemType(), operand);
3511 };3797 };
3512 return self.finishAir(inst, result, .{ un_op, .none, .none });3798 return self.finishAir(inst, result, .{ un_op, .none, .none });
3513}3799}
...@@ -3517,7 +3803,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3517,7 +3803,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
3517 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {3803 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3518 const operand = try self.resolveInst(un_op);3804 const operand = try self.resolveInst(un_op);
3519 const ty = self.air.typeOf(un_op);3805 const ty = self.air.typeOf(un_op);
3520 break :result try self.isNonErr(ty, operand);3806 break :result try self.isNonErr(inst, ty, operand);
3521 };3807 };
3522 return self.finishAir(inst, result, .{ un_op, .none, .none });3808 return self.finishAir(inst, result, .{ un_op, .none, .none });
3523}3809}
...@@ -3538,7 +3824,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3538,7 +3824,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3538 };3824 };
3539 const ptr_ty = self.air.typeOf(un_op);3825 const ptr_ty = self.air.typeOf(un_op);
3540 try self.load(operand, operand_ptr, ptr_ty);3826 try self.load(operand, operand_ptr, ptr_ty);
3541 break :result try self.isNonErr(ptr_ty.elemType(), operand);3827 break :result try self.isNonErr(inst, ptr_ty.elemType(), operand);
3542 };3828 };
3543 return self.finishAir(inst, result, .{ un_op, .none, .none });3829 return self.finishAir(inst, result, .{ un_op, .none, .none });
3544}3830}
...@@ -3584,12 +3870,185 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {...@@ -3584,12 +3870,185 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
3584 return self.finishAir(inst, result, .{ .none, .none, .none });3870 return self.finishAir(inst, result, .{ .none, .none, .none });
3585}3871}
35863872
3873fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u32 {
3874 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3875 switch (condition) {
3876 .none => unreachable,
3877 .undef => unreachable,
3878 .dead, .unreach => unreachable,
3879 .compare_flags_signed => unreachable,
3880 .compare_flags_unsigned => unreachable,
3881 .register => |cond_reg| {
3882 try self.spillCompareFlagsIfOccupied();
3883
3884 self.register_manager.freezeRegs(&.{cond_reg});
3885 defer self.register_manager.unfreezeRegs(&.{cond_reg});
3886
3887 switch (case) {
3888 .none => unreachable,
3889 .undef => unreachable,
3890 .dead, .unreach => unreachable,
3891 .immediate => |imm| {
3892 _ = try self.addInst(.{
3893 .tag = .@"test",
3894 .ops = (Mir.Ops{
3895 .reg1 = registerAlias(cond_reg, abi_size),
3896 }).encode(),
3897 .data = .{ .imm = @intCast(u32, imm) },
3898 });
3899 return self.addInst(.{
3900 .tag = .cond_jmp_eq_ne,
3901 .ops = (Mir.Ops{
3902 .flags = 0b00,
3903 }).encode(),
3904 .data = .{ .inst = undefined },
3905 });
3906 },
3907 .register => |reg| {
3908 _ = try self.addInst(.{
3909 .tag = .@"test",
3910 .ops = (Mir.Ops{
3911 .reg1 = registerAlias(cond_reg, abi_size),
3912 .reg2 = registerAlias(reg, abi_size),
3913 }).encode(),
3914 .data = undefined,
3915 });
3916 return self.addInst(.{
3917 .tag = .cond_jmp_eq_ne,
3918 .ops = (Mir.Ops{
3919 .flags = 0b00,
3920 }).encode(),
3921 .data = .{ .inst = undefined },
3922 });
3923 },
3924 .stack_offset => {
3925 if (abi_size <= 8) {
3926 const reg = try self.copyToTmpRegister(ty, case);
3927 return self.genCondSwitchMir(ty, condition, .{ .register = reg });
3928 }
3929
3930 return self.fail("TODO implement switch mir when case is stack offset with abi larger than 8 bytes", .{});
3931 },
3932 else => {
3933 return self.fail("TODO implement switch mir when case is {}", .{case});
3934 },
3935 }
3936 },
3937 .stack_offset => {
3938 try self.spillCompareFlagsIfOccupied();
3939
3940 if (abi_size <= 8) {
3941 const reg = try self.copyToTmpRegister(ty, condition);
3942 self.register_manager.freezeRegs(&.{reg});
3943 defer self.register_manager.unfreezeRegs(&.{reg});
3944 return self.genCondSwitchMir(ty, .{ .register = reg }, case);
3945 }
3946
3947 return self.fail("TODO implement switch mir when condition is stack offset with abi larger than 8 bytes", .{});
3948 },
3949 else => {
3950 return self.fail("TODO implemenent switch mir when condition is {}", .{condition});
3951 },
3952 }
3953}
3954
3587fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {3955fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
3588 const pl_op = self.air.instructions.items(.data)[inst].pl_op;3956 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
3589 const condition = pl_op.operand;3957 const condition = try self.resolveInst(pl_op.operand);
3590 _ = condition;3958 const condition_ty = self.air.typeOf(pl_op.operand);
3591 return self.fail("TODO airSwitch for {}", .{self.target.cpu.arch});3959 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
3592 // return self.finishAir(inst, .dead, .{ condition, .none, .none });3960 var extra_index: usize = switch_br.end;
3961 var case_i: u32 = 0;
3962 const liveness = try self.liveness.getSwitchBr(
3963 self.gpa,
3964 inst,
3965 switch_br.data.cases_len + 1,
3966 );
3967 defer self.gpa.free(liveness.deaths);
3968
3969 while (case_i < switch_br.data.cases_len) : (case_i += 1) {
3970 const case = self.air.extraData(Air.SwitchBr.Case, extra_index);
3971 const items = @bitCast([]const Air.Inst.Ref, self.air.extra[case.end..][0..case.data.items_len]);
3972 const case_body = self.air.extra[case.end + items.len ..][0..case.data.body_len];
3973 extra_index = case.end + items.len + case_body.len;
3974
3975 var relocs = try self.gpa.alloc(u32, items.len);
3976 defer self.gpa.free(relocs);
3977
3978 for (items) |item, item_i| {
3979 const item_mcv = try self.resolveInst(item);
3980 relocs[item_i] = try self.genCondSwitchMir(condition_ty, condition, item_mcv);
3981 }
3982
3983 // If the condition dies here in this condbr instruction, process
3984 // that death now instead of later as this has an effect on
3985 // whether it needs to be spilled in the branches
3986 // TODO I need investigate how to make this work without removing
3987 // an assertion from getResolvedInstValue()
3988 if (self.liveness.operandDies(inst, 0)) {
3989 const op_int = @enumToInt(pl_op.operand);
3990 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
3991 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
3992 self.processDeath(op_index);
3993 }
3994 }
3995
3996 // Capture the state of register and stack allocation state so that we can revert to it.
3997 const parent_next_stack_offset = self.next_stack_offset;
3998 const parent_free_registers = self.register_manager.free_registers;
3999 const parent_compare_flags_inst = self.compare_flags_inst;
4000 var parent_stack = try self.stack.clone(self.gpa);
4001 defer parent_stack.deinit(self.gpa);
4002 const parent_registers = self.register_manager.registers;
4003
4004 try self.branch_stack.append(.{});
4005 errdefer {
4006 _ = self.branch_stack.pop();
4007 }
4008
4009 try self.ensureProcessDeathCapacity(liveness.deaths[case_i].len);
4010 for (liveness.deaths[case_i]) |operand| {
4011 self.processDeath(operand);
4012 }
4013
4014 try self.genBody(case_body);
4015
4016 // Revert to the previous register and stack allocation state.
4017 var saved_case_branch = self.branch_stack.pop();
4018 defer saved_case_branch.deinit(self.gpa);
4019
4020 self.register_manager.registers = parent_registers;
4021 self.compare_flags_inst = parent_compare_flags_inst;
4022 self.stack.deinit(self.gpa);
4023 self.stack = parent_stack;
4024 parent_stack = .{};
4025
4026 self.next_stack_offset = parent_next_stack_offset;
4027 self.register_manager.free_registers = parent_free_registers;
4028
4029 for (relocs) |reloc| {
4030 try self.performReloc(reloc);
4031 }
4032 }
4033
4034 if (switch_br.data.else_body_len > 0) {
4035 const else_body = self.air.extra[extra_index..][0..switch_br.data.else_body_len];
4036 try self.branch_stack.append(.{});
4037 defer self.branch_stack.pop().deinit(self.gpa);
4038
4039 const else_deaths = liveness.deaths.len - 1;
4040 try self.ensureProcessDeathCapacity(liveness.deaths[else_deaths].len);
4041 for (liveness.deaths[else_deaths]) |operand| {
4042 self.processDeath(operand);
4043 }
4044
4045 try self.genBody(else_body);
4046
4047 // TODO consolidate returned MCValues between prongs and else branch like we do
4048 // in airCondBr.
4049 }
4050
4051 return self.finishAir(inst, .unreach, .{ pl_op.operand, .none, .none });
3593}4052}
35944053
3595fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {4054fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {
...@@ -3628,7 +4087,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {...@@ -3628,7 +4087,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
3628 block_data.mcv = switch (operand_mcv) {4087 block_data.mcv = switch (operand_mcv) {
3629 .none, .dead, .unreach => unreachable,4088 .none, .dead, .unreach => unreachable,
3630 .register, .stack_offset, .memory => operand_mcv,4089 .register, .stack_offset, .memory => operand_mcv,
3631 .immediate => blk: {4090 .compare_flags_signed, .compare_flags_unsigned, .immediate => blk: {
3632 const new_mcv = try self.allocRegOrMem(block, true);4091 const new_mcv = try self.allocRegOrMem(block, true);
3633 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);4092 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
3634 break :blk new_mcv;4093 break :blk new_mcv;
...@@ -3828,7 +4287,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {...@@ -3828,7 +4287,7 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
3828 .none => return,4287 .none => return,
3829 .immediate => unreachable,4288 .immediate => unreachable,
3830 .register => |reg| return self.genSetReg(ty, reg, val),4289 .register => |reg| return self.genSetReg(ty, reg, val),
3831 .stack_offset => |off| return self.genSetStack(ty, off, val),4290 .stack_offset => |off| return self.genSetStack(ty, off, val, .{}),
3832 .memory => {4291 .memory => {
3833 return self.fail("TODO implement setRegOrMem for memory", .{});4292 return self.fail("TODO implement setRegOrMem for memory", .{});
3834 },4293 },
...@@ -3849,7 +4308,9 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3849,7 +4308,9 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3849 const reg = try self.copyToTmpRegister(ty, mcv);4308 const reg = try self.copyToTmpRegister(ty, mcv);
3850 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });4309 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3851 }4310 }
3852 try self.genInlineMemset(stack_offset, .rsp, ty, .{ .immediate = 0xaa });4311 try self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, .{
4312 .dest_stack_base = .rsp,
4313 });
3853 },4314 },
3854 .compare_flags_unsigned,4315 .compare_flags_unsigned,
3855 .compare_flags_signed,4316 .compare_flags_signed,
...@@ -3904,7 +4365,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3904,7 +4365,10 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3904 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });4365 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3905 }4366 }
39064367
3907 try self.genInlineMemcpy(stack_offset, .rsp, ty, mcv);4368 try self.genInlineMemcpy(stack_offset, ty, mcv, .{
4369 .source_stack_base = .rbp,
4370 .dest_stack_base = .rsp,
4371 });
3908 },4372 },
3909 .register => |reg| {4373 .register => |reg| {
3910 _ = try self.addInst(.{4374 _ = try self.addInst(.{
...@@ -3927,12 +4391,15 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE...@@ -3927,12 +4391,15 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
3927 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });4391 return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
3928 }4392 }
39294393
3930 try self.genInlineMemcpy(stack_offset, .rsp, ty, mcv);4394 try self.genInlineMemcpy(stack_offset, ty, mcv, .{
4395 .source_stack_base = .rbp,
4396 .dest_stack_base = .rsp,
4397 });
3931 },4398 },
3932 }4399 }
3933}4400}
39344401
3935fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerError!void {4402fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: InlineMemcpyOpts) InnerError!void {
3936 const abi_size = ty.abiSize(self.target.*);4403 const abi_size = ty.abiSize(self.target.*);
3937 switch (mcv) {4404 switch (mcv) {
3938 .dead => unreachable,4405 .dead => unreachable,
...@@ -3943,23 +4410,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3943,23 +4410,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3943 return; // The already existing value will do just fine.4410 return; // The already existing value will do just fine.
3944 // TODO Upgrade this to a memset call when we have that available.4411 // TODO Upgrade this to a memset call when we have that available.
3945 switch (ty.abiSize(self.target.*)) {4412 switch (ty.abiSize(self.target.*)) {
3946 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),4413 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }, opts),
3947 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),4414 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }, opts),
3948 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),4415 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }, opts),
3949 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),4416 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }, opts),
3950 else => return self.genInlineMemset(stack_offset, .rbp, ty, .{ .immediate = 0xaa }),4417 else => return self.genInlineMemset(stack_offset, ty, .{ .immediate = 0xaa }, opts),
3951 }4418 }
3952 },4419 },
3953 .compare_flags_unsigned,4420 .compare_flags_unsigned,
3954 .compare_flags_signed,4421 .compare_flags_signed,
3955 => {4422 => {
3956 const reg = try self.copyToTmpRegister(ty, mcv);4423 const reg = try self.copyToTmpRegister(ty, mcv);
3957 return self.genSetStack(ty, stack_offset, .{ .register = reg });4424 return self.genSetStack(ty, stack_offset, .{ .register = reg }, opts);
3958 },4425 },
3959 .immediate => |x_big| {4426 .immediate => |x_big| {
3960 if (stack_offset > 128) {4427 const base_reg = opts.dest_stack_base orelse .rbp;
3961 return self.fail("TODO implement set stack variable with large stack offset", .{});
3962 }
3963 switch (abi_size) {4428 switch (abi_size) {
3964 1, 2, 4 => {4429 1, 2, 4 => {
3965 const payload = try self.addExtra(Mir.ImmPair{4430 const payload = try self.addExtra(Mir.ImmPair{
...@@ -3969,7 +4434,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3969,7 +4434,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3969 _ = try self.addInst(.{4434 _ = try self.addInst(.{
3970 .tag = .mov_mem_imm,4435 .tag = .mov_mem_imm,
3971 .ops = (Mir.Ops{4436 .ops = (Mir.Ops{
3972 .reg1 = .rbp,4437 .reg1 = base_reg,
3973 .flags = switch (abi_size) {4438 .flags = switch (abi_size) {
3974 1 => 0b00,4439 1 => 0b00,
3975 2 => 0b01,4440 2 => 0b01,
...@@ -3991,7 +4456,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -3991,7 +4456,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
3991 _ = try self.addInst(.{4456 _ = try self.addInst(.{
3992 .tag = .mov_mem_imm,4457 .tag = .mov_mem_imm,
3993 .ops = (Mir.Ops{4458 .ops = (Mir.Ops{
3994 .reg1 = .rbp,4459 .reg1 = base_reg,
3995 .flags = 0b10,4460 .flags = 0b10,
3996 }).encode(),4461 }).encode(),
3997 .data = .{ .payload = payload },4462 .data = .{ .payload = payload },
...@@ -4005,7 +4470,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4005,7 +4470,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
4005 _ = try self.addInst(.{4470 _ = try self.addInst(.{
4006 .tag = .mov_mem_imm,4471 .tag = .mov_mem_imm,
4007 .ops = (Mir.Ops{4472 .ops = (Mir.Ops{
4008 .reg1 = .rbp,4473 .reg1 = base_reg,
4009 .flags = 0b10,4474 .flags = 0b10,
4010 }).encode(),4475 }).encode(),
4011 .data = .{ .payload = payload },4476 .data = .{ .payload = payload },
...@@ -4022,6 +4487,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4022,6 +4487,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
4022 return self.fail("stack offset too large", .{});4487 return self.fail("stack offset too large", .{});
4023 }4488 }
40244489
4490 const base_reg = opts.dest_stack_base orelse .rbp;
4025 const is_power_of_two = (abi_size % 2) == 0;4491 const is_power_of_two = (abi_size % 2) == 0;
4026 if (!is_power_of_two) {4492 if (!is_power_of_two) {
4027 self.register_manager.freezeRegs(&.{reg});4493 self.register_manager.freezeRegs(&.{reg});
...@@ -4037,7 +4503,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4037,7 +4503,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
4037 _ = try self.addInst(.{4503 _ = try self.addInst(.{
4038 .tag = .mov,4504 .tag = .mov,
4039 .ops = (Mir.Ops{4505 .ops = (Mir.Ops{
4040 .reg1 = .rbp,4506 .reg1 = base_reg,
4041 .reg2 = registerAlias(tmp_reg, closest_power_of_two),4507 .reg2 = registerAlias(tmp_reg, closest_power_of_two),
4042 .flags = 0b10,4508 .flags = 0b10,
4043 }).encode(),4509 }).encode(),
...@@ -4062,7 +4528,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4062,7 +4528,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
4062 _ = try self.addInst(.{4528 _ = try self.addInst(.{
4063 .tag = .mov,4529 .tag = .mov,
4064 .ops = (Mir.Ops{4530 .ops = (Mir.Ops{
4065 .reg1 = .rbp,4531 .reg1 = base_reg,
4066 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),4532 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
4067 .flags = 0b10,4533 .flags = 0b10,
4068 }).encode(),4534 }).encode(),
...@@ -4077,14 +4543,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4077,14 +4543,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
4077 => {4543 => {
4078 if (abi_size <= 8) {4544 if (abi_size <= 8) {
4079 const reg = try self.copyToTmpRegister(ty, mcv);4545 const reg = try self.copyToTmpRegister(ty, mcv);
4080 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });4546 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
4081 }4547 }
40824548
4083 try self.genInlineMemcpy(stack_offset, .rbp, ty, mcv);4549 try self.genInlineMemcpy(stack_offset, ty, mcv, opts);
4084 },4550 },
4085 .ptr_stack_offset => {4551 .ptr_stack_offset => {
4086 const reg = try self.copyToTmpRegister(ty, mcv);4552 const reg = try self.copyToTmpRegister(ty, mcv);
4087 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });4553 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
4088 },4554 },
4089 .stack_offset => |off| {4555 .stack_offset => |off| {
4090 if (stack_offset == off) {4556 if (stack_offset == off) {
...@@ -4094,22 +4560,35 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro...@@ -4094,22 +4560,35 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerErro
40944560
4095 if (abi_size <= 8) {4561 if (abi_size <= 8) {
4096 const reg = try self.copyToTmpRegister(ty, mcv);4562 const reg = try self.copyToTmpRegister(ty, mcv);
4097 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });4563 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }, opts);
4098 }4564 }
40994565
4100 try self.genInlineMemcpy(stack_offset, .rbp, ty, mcv);4566 try self.genInlineMemcpy(stack_offset, ty, mcv, opts);
4101 },4567 },
4102 }4568 }
4103}4569}
41044570
4105fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type, val: MCValue) InnerError!void {4571const InlineMemcpyOpts = struct {
4572 source_stack_base: ?Register = null,
4573 dest_stack_base: ?Register = null,
4574};
4575
4576fn genInlineMemcpy(self: *Self, stack_offset: i32, ty: Type, val: MCValue, opts: InlineMemcpyOpts) InnerError!void {
4106 const abi_size = ty.abiSize(self.target.*);4577 const abi_size = ty.abiSize(self.target.*);
41074578
4579 // TODO this is wrong. We should check first if any of the operands is in `.rax` or `.rcx` before
4580 // spilling. Consolidate with other TODOs regarding register allocation mechanics.
4108 try self.register_manager.getReg(.rax, null);4581 try self.register_manager.getReg(.rax, null);
4109 try self.register_manager.getReg(.rcx, null);4582 try self.register_manager.getReg(.rcx, null);
41104583
4111 self.register_manager.freezeRegs(&.{ .rax, .rcx, .rbp });4584 self.register_manager.freezeRegs(&.{ .rax, .rcx });
4112 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx, .rbp });4585 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
4586
4587 if (opts.source_stack_base) |reg| self.register_manager.freezeRegs(&.{reg});
4588 defer if (opts.source_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg});
4589
4590 if (opts.dest_stack_base) |reg| self.register_manager.freezeRegs(&.{reg});
4591 defer if (opts.dest_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg});
41134592
4114 const addr_reg: Register = blk: {4593 const addr_reg: Register = blk: {
4115 switch (val) {4594 switch (val) {
...@@ -4119,13 +4598,13 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type...@@ -4119,13 +4598,13 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type
4119 => {4598 => {
4120 break :blk try self.loadMemPtrIntoRegister(Type.usize, val);4599 break :blk try self.loadMemPtrIntoRegister(Type.usize, val);
4121 },4600 },
4122 .stack_offset => |off| {4601 .ptr_stack_offset, .stack_offset => |off| {
4123 const addr_reg = (try self.register_manager.allocReg(null)).to64();4602 const addr_reg = (try self.register_manager.allocReg(null)).to64();
4124 _ = try self.addInst(.{4603 _ = try self.addInst(.{
4125 .tag = .lea,4604 .tag = .lea,
4126 .ops = (Mir.Ops{4605 .ops = (Mir.Ops{
4127 .reg1 = addr_reg,4606 .reg1 = addr_reg,
4128 .reg2 = .rbp,4607 .reg2 = opts.source_stack_base orelse .rbp,
4129 }).encode(),4608 }).encode(),
4130 .data = .{ .imm = @bitCast(u32, -off) },4609 .data = .{ .imm = @bitCast(u32, -off) },
4131 });4610 });
...@@ -4207,7 +4686,7 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type...@@ -4207,7 +4686,7 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type
4207 _ = try self.addInst(.{4686 _ = try self.addInst(.{
4208 .tag = .mov_scale_dst,4687 .tag = .mov_scale_dst,
4209 .ops = (Mir.Ops{4688 .ops = (Mir.Ops{
4210 .reg1 = stack_reg,4689 .reg1 = opts.dest_stack_base orelse .rbp,
4211 .reg2 = tmp_reg.to8(),4690 .reg2 = tmp_reg.to8(),
4212 }).encode(),4691 }).encode(),
4213 .data = .{ .imm = @bitCast(u32, -stack_offset) },4692 .data = .{ .imm = @bitCast(u32, -stack_offset) },
...@@ -4254,9 +4733,9 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type...@@ -4254,9 +4733,9 @@ fn genInlineMemcpy(self: *Self, stack_offset: i32, stack_reg: Register, ty: Type
4254fn genInlineMemset(4733fn genInlineMemset(
4255 self: *Self,4734 self: *Self,
4256 stack_offset: i32,4735 stack_offset: i32,
4257 stack_register: Register,
4258 ty: Type,4736 ty: Type,
4259 value: MCValue,4737 value: MCValue,
4738 opts: InlineMemcpyOpts,
4260) InnerError!void {4739) InnerError!void {
4261 try self.register_manager.getReg(.rax, null);4740 try self.register_manager.getReg(.rax, null);
42624741
...@@ -4321,7 +4800,7 @@ fn genInlineMemset(...@@ -4321,7 +4800,7 @@ fn genInlineMemset(
4321 _ = try self.addInst(.{4800 _ = try self.addInst(.{
4322 .tag = .mov_mem_index_imm,4801 .tag = .mov_mem_index_imm,
4323 .ops = (Mir.Ops{4802 .ops = (Mir.Ops{
4324 .reg1 = stack_register.to64(),4803 .reg1 = opts.dest_stack_base orelse .rbp,
4325 }).encode(),4804 }).encode(),
4326 .data = .{ .payload = payload },4805 .data = .{ .payload = payload },
4327 });4806 });
...@@ -4653,8 +5132,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {...@@ -4653,8 +5132,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
4653 const array_len = array_ty.arrayLenIncludingSentinel();5132 const array_len = array_ty.arrayLenIncludingSentinel();
4654 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {5133 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
4655 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));5134 const stack_offset = @intCast(i32, try self.allocMem(inst, 16, 16));
4656 try self.genSetStack(ptr_ty, stack_offset, ptr);5135 try self.genSetStack(ptr_ty, stack_offset, ptr, .{});
4657 try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .{ .immediate = array_len });5136 try self.genSetStack(Type.initTag(.u64), stack_offset - 8, .{ .immediate = array_len }, .{});
4658 break :blk .{ .stack_offset = stack_offset };5137 break :blk .{ .stack_offset = stack_offset };
4659 };5138 };
4660 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });5139 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
...@@ -4808,7 +5287,8 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {...@@ -4808,7 +5287,8 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
4808 while (true) {5287 while (true) {
4809 i -= 1;5288 i -= 1;
4810 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {5289 if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| {
4811 assert(mcv != .dead);5290 // TODO see comment in `airCondBr` and `airSwitch`
5291 // assert(mcv != .dead);
4812 return mcv;5292 return mcv;
4813 }5293 }
4814 }5294 }
...@@ -4979,22 +5459,18 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -4979,22 +5459,18 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
4979 const error_type = typed_value.ty.errorUnionSet();5459 const error_type = typed_value.ty.errorUnionSet();
4980 const payload_type = typed_value.ty.errorUnionPayload();5460 const payload_type = typed_value.ty.errorUnionPayload();
49815461
4982 if (typed_value.val.castTag(.eu_payload)) |pl| {5462 if (typed_value.val.castTag(.eu_payload)) |_| {
4983 if (!payload_type.hasRuntimeBits()) {5463 if (!payload_type.hasRuntimeBits()) {
4984 // We use the error type directly as the type.5464 // We use the error type directly as the type.
4985 return MCValue{ .immediate = 0 };5465 return MCValue{ .immediate = 0 };
4986 }5466 }
4987
4988 _ = pl;
4989 return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty});
4990 } else {5467 } else {
4991 if (!payload_type.hasRuntimeBits()) {5468 if (!payload_type.hasRuntimeBits()) {
4992 // We use the error type directly as the type.5469 // We use the error type directly as the type.
4993 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });5470 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
4994 }5471 }
4995 }5472 }
49965473 return self.lowerUnnamedConst(typed_value);
4997 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});
4998 },5474 },
4999 .Struct => {5475 .Struct => {
5000 return self.lowerUnnamedConst(typed_value);5476 return self.lowerUnnamedConst(typed_value);
...@@ -5041,6 +5517,25 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5041,6 +5517,25 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5041 return result;5517 return result;
5042 },5518 },
5043 .Unspecified, .C => {5519 .Unspecified, .C => {
5520 // Return values
5521 if (ret_ty.zigTypeTag() == .NoReturn) {
5522 result.return_value = .{ .unreach = {} };
5523 } else if (!ret_ty.hasRuntimeBits()) {
5524 result.return_value = .{ .none = {} };
5525 } else {
5526 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5527 if (ret_ty_size <= 8) {
5528 const aliased_reg = registerAlias(c_abi_int_return_regs[0], ret_ty_size);
5529 result.return_value = .{ .register = aliased_reg };
5530 } else {
5531 // We simply make the return MCValue a stack offset. However, the actual value
5532 // for the offset will be populated later. We will also push the stack offset
5533 // value into .rdi register when we resolve the offset.
5534 result.return_value = .{ .stack_offset = 0 };
5535 }
5536 }
5537
5538 // Input params
5044 // First, split into args that can be passed via registers.5539 // First, split into args that can be passed via registers.
5045 // This will make it easier to then push the rest of args in reverse5540 // This will make it easier to then push the rest of args in reverse
5046 // order on the stack.5541 // order on the stack.
...@@ -5084,7 +5579,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5084,7 +5579,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5084 }5579 }
5085 }5580 }
50865581
5087 var next_stack_offset: u32 = 0;5582 var next_stack_offset: u32 = switch (result.return_value) {
5583 .stack_offset => |off| @intCast(u32, off),
5584 else => 0,
5585 };
5088 var count: usize = param_types.len;5586 var count: usize = param_types.len;
5089 while (count > 0) : (count -= 1) {5587 while (count > 0) : (count -= 1) {
5090 const i = count - 1;5588 const i = count - 1;
...@@ -5108,28 +5606,15 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5108,28 +5606,15 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5108 }5606 }
51095607
5110 result.stack_align = 16;5608 result.stack_align = 16;
5609 // TODO fix this so that the 16byte alignment padding is at the current value of $rsp, and push
5610 // the args onto the stack so that there is no padding between the first argument and
5611 // the standard preamble.
5612 // alignment padding | args ... | ret addr | $rbp |
5111 result.stack_byte_count = mem.alignForwardGeneric(u32, next_stack_offset, result.stack_align);5613 result.stack_byte_count = mem.alignForwardGeneric(u32, next_stack_offset, result.stack_align);
5112 },5614 },
5113 else => return self.fail("TODO implement function parameters for {} on x86_64", .{cc}),5615 else => return self.fail("TODO implement function parameters and return values for {} on x86_64", .{cc}),
5114 }5616 }
51155617
5116 if (ret_ty.zigTypeTag() == .NoReturn) {
5117 result.return_value = .{ .unreach = {} };
5118 } else if (!ret_ty.hasRuntimeBits()) {
5119 result.return_value = .{ .none = {} };
5120 } else switch (cc) {
5121 .Naked => unreachable,
5122 .Unspecified, .C => {
5123 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5124 if (ret_ty_size <= 8) {
5125 const aliased_reg = registerAlias(c_abi_int_return_regs[0], ret_ty_size);
5126 result.return_value = .{ .register = aliased_reg };
5127 } else {
5128 return self.fail("TODO support more return types for x86_64 backend", .{});
5129 }
5130 },
5131 else => return self.fail("TODO implement function return values for {}", .{cc}),
5132 }
5133 return result;5618 return result;
5134}5619}
51355620
src/arch/x86_64/Emit.zig+8
...@@ -162,6 +162,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void {...@@ -162,6 +162,8 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
162 => try emit.mirCondSetByte(tag, inst),162 => try emit.mirCondSetByte(tag, inst),
163163
164 .cond_mov_eq => try emit.mirCondMov(.cmove, inst),164 .cond_mov_eq => try emit.mirCondMov(.cmove, inst),
165 .cond_mov_lt => try emit.mirCondMov(.cmovl, inst),
166 .cond_mov_below => try emit.mirCondMov(.cmovb, inst),
165167
166 .ret => try emit.mirRet(inst),168 .ret => try emit.mirRet(inst),
167169
...@@ -1180,6 +1182,10 @@ const Tag = enum {...@@ -1180,6 +1182,10 @@ const Tag = enum {
1180 cqo,1182 cqo,
1181 cmove,1183 cmove,
1182 cmovz,1184 cmovz,
1185 cmovl,
1186 cmovng,
1187 cmovb,
1188 cmovnae,
11831189
1184 fn isSetCC(tag: Tag) bool {1190 fn isSetCC(tag: Tag) bool {
1185 return switch (tag) {1191 return switch (tag) {
...@@ -1406,6 +1412,8 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode {...@@ -1406,6 +1412,8 @@ inline fn getOpCode(tag: Tag, enc: Encoding, is_one_byte: bool) ?OpCode {
1406 .lea => OpCode.oneByte(if (is_one_byte) 0x8c else 0x8d),1412 .lea => OpCode.oneByte(if (is_one_byte) 0x8c else 0x8d),
1407 .imul => OpCode.twoByte(0x0f, 0xaf),1413 .imul => OpCode.twoByte(0x0f, 0xaf),
1408 .cmove, .cmovz => OpCode.twoByte(0x0f, 0x44),1414 .cmove, .cmovz => OpCode.twoByte(0x0f, 0x44),
1415 .cmovb, .cmovnae => OpCode.twoByte(0x0f, 0x42),
1416 .cmovl, .cmovng => OpCode.twoByte(0x0f, 0x4c),
1409 else => null,1417 else => null,
1410 },1418 },
1411 .oi => return switch (tag) {1419 .oi => return switch (tag) {
src/arch/x86_64/Mir.zig+4-1
...@@ -292,6 +292,8 @@ pub const Inst = struct {...@@ -292,6 +292,8 @@ pub const Inst = struct {
292 /// 0b10 reg1, dword ptr [reg2 + imm]292 /// 0b10 reg1, dword ptr [reg2 + imm]
293 /// 0b11 reg1, qword ptr [reg2 + imm]293 /// 0b11 reg1, qword ptr [reg2 + imm]
294 cond_mov_eq,294 cond_mov_eq,
295 cond_mov_lt,
296 cond_mov_below,
295297
296 /// ops flags: form:298 /// ops flags: form:
297 /// 0b00 reg1299 /// 0b00 reg1
...@@ -314,7 +316,8 @@ pub const Inst = struct {...@@ -314,7 +316,8 @@ pub const Inst = struct {
314 syscall,316 syscall,
315317
316 /// ops flags: form:318 /// ops flags: form:
317 /// 0b00 reg1, imm32319 /// 0b00 reg1, imm32 if reg2 == .none
320 /// 0b00 reg1, reg2
318 /// TODO handle more cases321 /// TODO handle more cases
319 @"test",322 @"test",
320323
src/codegen.zig+119-1
...@@ -205,13 +205,62 @@ pub fn generateSymbol(...@@ -205,13 +205,62 @@ pub fn generateSymbol(
205 .appended => {},205 .appended => {},
206 .externally_managed => |slice| {206 .externally_managed => |slice| {
207 code.appendSliceAssumeCapacity(slice);207 code.appendSliceAssumeCapacity(slice);
208 return Result{ .appended = {} };
209 },208 },
210 .fail => |em| return Result{ .fail = em },209 .fail => |em| return Result{ .fail = em },
211 }210 }
212 }211 }
213 return Result{ .appended = {} };212 return Result{ .appended = {} };
214 },213 },
214 .repeated => {
215 const array = typed_value.val.castTag(.repeated).?.data;
216 const elem_ty = typed_value.ty.childType();
217 const sentinel = typed_value.ty.sentinel();
218 const len = typed_value.ty.arrayLen();
219
220 var index: u64 = 0;
221 while (index < len) : (index += 1) {
222 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
223 .ty = elem_ty,
224 .val = array,
225 }, code, debug_output)) {
226 .appended => {},
227 .externally_managed => |slice| {
228 code.appendSliceAssumeCapacity(slice);
229 },
230 .fail => |em| return Result{ .fail = em },
231 }
232 }
233
234 if (sentinel) |sentinel_val| {
235 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
236 .ty = elem_ty,
237 .val = sentinel_val,
238 }, code, debug_output)) {
239 .appended => {},
240 .externally_managed => |slice| {
241 code.appendSliceAssumeCapacity(slice);
242 },
243 .fail => |em| return Result{ .fail = em },
244 }
245 }
246
247 return Result{ .appended = {} };
248 },
249 .empty_array_sentinel => {
250 const elem_ty = typed_value.ty.childType();
251 const sentinel_val = typed_value.ty.sentinel().?;
252 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
253 .ty = elem_ty,
254 .val = sentinel_val,
255 }, code, debug_output)) {
256 .appended => {},
257 .externally_managed => |slice| {
258 code.appendSliceAssumeCapacity(slice);
259 },
260 .fail => |em| return Result{ .fail = em },
261 }
262 return Result{ .appended = {} };
263 },
215 else => return Result{264 else => return Result{
216 .fail = try ErrorMsg.create(265 .fail = try ErrorMsg.create(
217 bin_file.allocator,266 bin_file.allocator,
...@@ -432,6 +481,75 @@ pub fn generateSymbol(...@@ -432,6 +481,75 @@ pub fn generateSymbol(
432481
433 return Result{ .appended = {} };482 return Result{ .appended = {} };
434 },483 },
484 .ErrorUnion => {
485 const error_ty = typed_value.ty.errorUnionSet();
486 const payload_ty = typed_value.ty.errorUnionPayload();
487 const is_payload = typed_value.val.errorUnionIsPayload();
488
489 const target = bin_file.options.target;
490 const abi_align = typed_value.ty.abiAlignment(target);
491
492 {
493 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
494 const begin = code.items.len;
495 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
496 .ty = error_ty,
497 .val = error_val,
498 }, code, debug_output)) {
499 .appended => {},
500 .externally_managed => |external_slice| {
501 code.appendSliceAssumeCapacity(external_slice);
502 },
503 .fail => |em| return Result{ .fail = em },
504 }
505 const unpadded_end = code.items.len - begin;
506 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
507 const padding = try math.cast(usize, padded_end - unpadded_end);
508
509 if (padding > 0) {
510 try code.writer().writeByteNTimes(0, padding);
511 }
512 }
513
514 if (payload_ty.hasRuntimeBits()) {
515 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
516 const begin = code.items.len;
517 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
518 .ty = payload_ty,
519 .val = payload_val,
520 }, code, debug_output)) {
521 .appended => {},
522 .externally_managed => |external_slice| {
523 code.appendSliceAssumeCapacity(external_slice);
524 },
525 .fail => |em| return Result{ .fail = em },
526 }
527 const unpadded_end = code.items.len - begin;
528 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
529 const padding = try math.cast(usize, padded_end - unpadded_end);
530
531 if (padding > 0) {
532 try code.writer().writeByteNTimes(0, padding);
533 }
534 }
535
536 return Result{ .appended = {} };
537 },
538 .ErrorSet => {
539 const target = bin_file.options.target;
540 switch (typed_value.val.tag()) {
541 .@"error" => {
542 const name = typed_value.val.getError().?;
543 const kv = try bin_file.options.module.?.getErrorValue(name);
544 const endian = target.cpu.arch.endian();
545 try code.writer().writeInt(u32, kv.value, endian);
546 },
547 else => {
548 try code.writer().writeByteNTimes(0, @intCast(usize, typed_value.ty.abiSize(target)));
549 },
550 }
551 return Result{ .appended = {} };
552 },
435 else => |t| {553 else => |t| {
436 return Result{554 return Result{
437 .fail = try ErrorMsg.create(555 .fail = try ErrorMsg.create(
src/link/Elf.zig+1
...@@ -3127,6 +3127,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl...@@ -3127,6 +3127,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
3127 .fail => |em| {3127 .fail => |em| {
3128 decl.analysis = .codegen_failure;3128 decl.analysis = .codegen_failure;
3129 try module.failed_decls.put(module.gpa, decl, em);3129 try module.failed_decls.put(module.gpa, decl, em);
3130 log.err("{s}", .{em.msg});
3130 return error.AnalysisFail;3131 return error.AnalysisFail;
3131 },3132 },
3132 };3133 };
test/behavior.zig+111-111
...@@ -6,14 +6,19 @@ test {...@@ -6,14 +6,19 @@ test {
6 _ = @import("behavior/array.zig");6 _ = @import("behavior/array.zig");
7 _ = @import("behavior/basic.zig");7 _ = @import("behavior/basic.zig");
8 _ = @import("behavior/bit_shifting.zig");8 _ = @import("behavior/bit_shifting.zig");
9 _ = @import("behavior/bitcast.zig");
9 _ = @import("behavior/bitreverse.zig");10 _ = @import("behavior/bitreverse.zig");
10 _ = @import("behavior/byteswap.zig");11 _ = @import("behavior/byteswap.zig");
12 _ = @import("behavior/byval_arg_var.zig");
11 _ = @import("behavior/bool.zig");13 _ = @import("behavior/bool.zig");
12 _ = @import("behavior/bugs/394.zig");14 _ = @import("behavior/bugs/394.zig");
15 _ = @import("behavior/bugs/624.zig");
13 _ = @import("behavior/bugs/655.zig");16 _ = @import("behavior/bugs/655.zig");
14 _ = @import("behavior/bugs/656.zig");17 _ = @import("behavior/bugs/656.zig");
15 _ = @import("behavior/bugs/679.zig");18 _ = @import("behavior/bugs/679.zig");
19 _ = @import("behavior/bugs/704.zig");
16 _ = @import("behavior/bugs/1025.zig");20 _ = @import("behavior/bugs/1025.zig");
21 _ = @import("behavior/bugs/1076.zig");
17 _ = @import("behavior/bugs/1111.zig");22 _ = @import("behavior/bugs/1111.zig");
18 _ = @import("behavior/bugs/1277.zig");23 _ = @import("behavior/bugs/1277.zig");
19 _ = @import("behavior/bugs/1310.zig");24 _ = @import("behavior/bugs/1310.zig");
...@@ -26,150 +31,145 @@ test {...@@ -26,150 +31,145 @@ test {
26 _ = @import("behavior/bugs/2006.zig");31 _ = @import("behavior/bugs/2006.zig");
27 _ = @import("behavior/bugs/2346.zig");32 _ = @import("behavior/bugs/2346.zig");
28 _ = @import("behavior/bugs/2578.zig");33 _ = @import("behavior/bugs/2578.zig");
34 _ = @import("behavior/bugs/2692.zig");
35 _ = @import("behavior/bugs/2889.zig");
29 _ = @import("behavior/bugs/3007.zig");36 _ = @import("behavior/bugs/3007.zig");
37 _ = @import("behavior/bugs/3046.zig");
30 _ = @import("behavior/bugs/3112.zig");38 _ = @import("behavior/bugs/3112.zig");
31 _ = @import("behavior/bugs/3367.zig");39 _ = @import("behavior/bugs/3367.zig");
40 _ = @import("behavior/bugs/3586.zig");
41 _ = @import("behavior/bugs/4560.zig");
42 _ = @import("behavior/bugs/4769_a.zig");
43 _ = @import("behavior/bugs/4769_b.zig");
44 _ = @import("behavior/bugs/4954.zig");
32 _ = @import("behavior/bugs/6850.zig");45 _ = @import("behavior/bugs/6850.zig");
33 _ = @import("behavior/bugs/7250.zig");46 _ = @import("behavior/bugs/7250.zig");
47 _ = @import("behavior/call.zig");
34 _ = @import("behavior/cast.zig");48 _ = @import("behavior/cast.zig");
35 _ = @import("behavior/comptime_memory.zig");49 _ = @import("behavior/comptime_memory.zig");
50 _ = @import("behavior/defer.zig");
51 _ = @import("behavior/enum.zig");
52 _ = @import("behavior/error.zig");
53 _ = @import("behavior/fn.zig");
36 _ = @import("behavior/fn_delegation.zig");54 _ = @import("behavior/fn_delegation.zig");
37 _ = @import("behavior/fn_in_struct_in_comptime.zig");55 _ = @import("behavior/fn_in_struct_in_comptime.zig");
56 _ = @import("behavior/for.zig");
57 _ = @import("behavior/generics.zig");
38 _ = @import("behavior/hasdecl.zig");58 _ = @import("behavior/hasdecl.zig");
39 _ = @import("behavior/hasfield.zig");59 _ = @import("behavior/hasfield.zig");
60 _ = @import("behavior/if.zig");
61 _ = @import("behavior/import.zig");
62 _ = @import("behavior/incomplete_struct_param_tld.zig");
63 _ = @import("behavior/int_div.zig");
64 _ = @import("behavior/inttoptr.zig");
40 _ = @import("behavior/ir_block_deps.zig");65 _ = @import("behavior/ir_block_deps.zig");
66 _ = @import("behavior/member_func.zig");
41 _ = @import("behavior/namespace_depends_on_compile_var.zig");67 _ = @import("behavior/namespace_depends_on_compile_var.zig");
68 _ = @import("behavior/null.zig");
42 _ = @import("behavior/optional.zig");69 _ = @import("behavior/optional.zig");
43 _ = @import("behavior/prefetch.zig");70 _ = @import("behavior/prefetch.zig");
71 _ = @import("behavior/pointers.zig");
44 _ = @import("behavior/pub_enum.zig");72 _ = @import("behavior/pub_enum.zig");
73 _ = @import("behavior/ptrcast.zig");
45 _ = @import("behavior/reflection.zig");74 _ = @import("behavior/reflection.zig");
75 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
46 _ = @import("behavior/slice.zig");76 _ = @import("behavior/slice.zig");
47 _ = @import("behavior/slice_sentinel_comptime.zig");77 _ = @import("behavior/slice_sentinel_comptime.zig");
48 _ = @import("behavior/struct.zig");78 _ = @import("behavior/struct.zig");
79 _ = @import("behavior/src.zig");
80 _ = @import("behavior/this.zig");
49 _ = @import("behavior/truncate.zig");81 _ = @import("behavior/truncate.zig");
82 _ = @import("behavior/try.zig");
50 _ = @import("behavior/tuple.zig");83 _ = @import("behavior/tuple.zig");
51 _ = @import("behavior/type.zig");84 _ = @import("behavior/type.zig");
85 _ = @import("behavior/type_info.zig");
86 _ = @import("behavior/undefined.zig");
87 _ = @import("behavior/underscore.zig");
88 _ = @import("behavior/union.zig");
89 _ = @import("behavior/usingnamespace.zig");
52 _ = @import("behavior/var_args.zig");90 _ = @import("behavior/var_args.zig");
53 _ = @import("behavior/int_div.zig");91 _ = @import("behavior/void.zig");
92 _ = @import("behavior/while.zig");
5493
55 // tests that don't pass for stage194 // tests that don't pass for stage1
56 if (builtin.zig_backend != .stage1) {95 if (builtin.zig_backend != .stage1) {
57 _ = @import("behavior/decltest.zig");96 _ = @import("behavior/decltest.zig");
58 }97 }
5998
60 if (builtin.zig_backend != .stage2_arm and builtin.zig_backend != .stage2_x86_64 and builtin.zig_backend != .stage2_aarch64) {99 if (builtin.zig_backend != .stage2_arm and
61 // Tests that pass (partly) for stage1, llvm backend, C backend, wasm backend.100 builtin.zig_backend != .stage2_x86_64 and
62 _ = @import("behavior/bitcast.zig");101 builtin.zig_backend != .stage2_aarch64 and
63 _ = @import("behavior/bugs/624.zig");102 builtin.zig_backend != .stage2_wasm)
64 _ = @import("behavior/bugs/704.zig");103 {
65 _ = @import("behavior/bugs/1076.zig");104 // Tests that pass for stage1, llvm backend, C backend
66 _ = @import("behavior/bugs/2692.zig");105 _ = @import("behavior/bugs/9584.zig");
67 _ = @import("behavior/bugs/2889.zig");106 _ = @import("behavior/cast_int.zig");
68 _ = @import("behavior/bugs/3046.zig");107 _ = @import("behavior/eval.zig");
69 _ = @import("behavior/bugs/3586.zig");108 _ = @import("behavior/int128.zig");
70 _ = @import("behavior/bugs/4560.zig");109 _ = @import("behavior/merge_error_sets.zig");
71 _ = @import("behavior/bugs/4769_a.zig");110 _ = @import("behavior/translate_c_macros.zig");
72 _ = @import("behavior/bugs/4769_b.zig");
73 _ = @import("behavior/bugs/4954.zig");
74 _ = @import("behavior/byval_arg_var.zig");
75 _ = @import("behavior/call.zig");
76 _ = @import("behavior/defer.zig");
77 _ = @import("behavior/enum.zig");
78 _ = @import("behavior/error.zig");
79 _ = @import("behavior/fn.zig");
80 _ = @import("behavior/for.zig");
81 _ = @import("behavior/generics.zig");
82 _ = @import("behavior/if.zig");
83 _ = @import("behavior/import.zig");
84 _ = @import("behavior/incomplete_struct_param_tld.zig");
85 _ = @import("behavior/inttoptr.zig");
86 _ = @import("behavior/member_func.zig");
87 _ = @import("behavior/null.zig");
88 _ = @import("behavior/pointers.zig");
89 _ = @import("behavior/ptrcast.zig");
90 _ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
91 _ = @import("behavior/src.zig");
92 _ = @import("behavior/this.zig");
93 _ = @import("behavior/try.zig");
94 _ = @import("behavior/type_info.zig");
95 _ = @import("behavior/undefined.zig");
96 _ = @import("behavior/underscore.zig");
97 _ = @import("behavior/union.zig");
98 _ = @import("behavior/usingnamespace.zig");
99 _ = @import("behavior/void.zig");
100 _ = @import("behavior/while.zig");
101111
102 if (builtin.zig_backend != .stage2_wasm) {112 if (builtin.zig_backend != .stage2_c) {
103 // Tests that pass for stage1, llvm backend, C backend113 // Tests that pass for stage1 and the llvm backend.
104 _ = @import("behavior/bugs/9584.zig");114 _ = @import("behavior/atomics.zig");
105 _ = @import("behavior/cast_int.zig");115 _ = @import("behavior/floatop.zig");
106 _ = @import("behavior/eval.zig");116 _ = @import("behavior/math.zig");
107 _ = @import("behavior/int128.zig");117 _ = @import("behavior/maximum_minimum.zig");
108 _ = @import("behavior/merge_error_sets.zig");118 _ = @import("behavior/popcount.zig");
109 _ = @import("behavior/translate_c_macros.zig");119 _ = @import("behavior/saturating_arithmetic.zig");
120 _ = @import("behavior/sizeof_and_typeof.zig");
121 _ = @import("behavior/switch.zig");
122 _ = @import("behavior/widening.zig");
110123
111 if (builtin.zig_backend != .stage2_c) {124 if (builtin.zig_backend == .stage1) {
112 // Tests that pass for stage1 and the llvm backend.125 // Tests that only pass for the stage1 backend.
113 _ = @import("behavior/atomics.zig");126 if (builtin.os.tag != .wasi) {
114 _ = @import("behavior/floatop.zig");127 _ = @import("behavior/asm.zig");
115 _ = @import("behavior/math.zig");128 _ = @import("behavior/async_fn.zig");
116 _ = @import("behavior/maximum_minimum.zig");129 }
117 _ = @import("behavior/popcount.zig");130 _ = @import("behavior/await_struct.zig");
118 _ = @import("behavior/saturating_arithmetic.zig");131 _ = @import("behavior/bugs/421.zig");
119 _ = @import("behavior/sizeof_and_typeof.zig");132 _ = @import("behavior/bugs/529.zig");
120 _ = @import("behavior/switch.zig");133 _ = @import("behavior/bugs/718.zig");
121 _ = @import("behavior/widening.zig");134 _ = @import("behavior/bugs/726.zig");
135 _ = @import("behavior/bugs/828.zig");
136 _ = @import("behavior/bugs/920.zig");
137 _ = @import("behavior/bugs/1120.zig");
138 _ = @import("behavior/bugs/1421.zig");
122 _ = @import("behavior/bugs/1442.zig");139 _ = @import("behavior/bugs/1442.zig");
123140 _ = @import("behavior/bugs/1607.zig");
124 if (builtin.zig_backend == .stage1) {141 _ = @import("behavior/bugs/1851.zig");
125 // Tests that only pass for the stage1 backend.142 _ = @import("behavior/bugs/2114.zig");
126 if (builtin.os.tag != .wasi) {143 _ = @import("behavior/bugs/3384.zig");
127 _ = @import("behavior/asm.zig");144 _ = @import("behavior/bugs/3742.zig");
128 _ = @import("behavior/async_fn.zig");145 _ = @import("behavior/bugs/3779.zig");
129 }146 _ = @import("behavior/bugs/4328.zig");
130 _ = @import("behavior/await_struct.zig");147 _ = @import("behavior/bugs/5398.zig");
131 _ = @import("behavior/bugs/421.zig");148 _ = @import("behavior/bugs/5413.zig");
132 _ = @import("behavior/bugs/529.zig");149 _ = @import("behavior/bugs/5474.zig");
133 _ = @import("behavior/bugs/718.zig");150 _ = @import("behavior/bugs/5487.zig");
134 _ = @import("behavior/bugs/726.zig");151 _ = @import("behavior/bugs/6456.zig");
135 _ = @import("behavior/bugs/828.zig");152 _ = @import("behavior/bugs/6781.zig");
136 _ = @import("behavior/bugs/920.zig");153 _ = @import("behavior/bugs/7003.zig");
137 _ = @import("behavior/bugs/1120.zig");154 _ = @import("behavior/bugs/7027.zig");
138 _ = @import("behavior/bugs/1421.zig");155 _ = @import("behavior/bugs/7047.zig");
139 _ = @import("behavior/bugs/1607.zig");156 _ = @import("behavior/bugs/10147.zig");
140 _ = @import("behavior/bugs/1851.zig");157 _ = @import("behavior/const_slice_child.zig");
141 _ = @import("behavior/bugs/2114.zig");158 _ = @import("behavior/export_self_referential_type_info.zig");
142 _ = @import("behavior/bugs/3384.zig");159 _ = @import("behavior/field_parent_ptr.zig");
143 _ = @import("behavior/bugs/3742.zig");160 _ = @import("behavior/misc.zig");
144 _ = @import("behavior/bugs/3779.zig");161 _ = @import("behavior/muladd.zig");
145 _ = @import("behavior/bugs/4328.zig");162 _ = @import("behavior/select.zig");
146 _ = @import("behavior/bugs/5398.zig");163 _ = @import("behavior/shuffle.zig");
147 _ = @import("behavior/bugs/5413.zig");164 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
148 _ = @import("behavior/bugs/5474.zig");165 _ = @import("behavior/struct_contains_slice_of_itself.zig");
149 _ = @import("behavior/bugs/5487.zig");166 _ = @import("behavior/switch_prong_err_enum.zig");
150 _ = @import("behavior/bugs/6456.zig");167 _ = @import("behavior/switch_prong_implicit_cast.zig");
151 _ = @import("behavior/bugs/6781.zig");168 _ = @import("behavior/typename.zig");
152 _ = @import("behavior/bugs/7003.zig");169 _ = @import("behavior/union_with_members.zig");
153 _ = @import("behavior/bugs/7027.zig");170 _ = @import("behavior/vector.zig");
154 _ = @import("behavior/bugs/7047.zig");171 if (builtin.target.cpu.arch == .wasm32) {
155 _ = @import("behavior/bugs/10147.zig");172 _ = @import("behavior/wasm.zig");
156 _ = @import("behavior/const_slice_child.zig");
157 _ = @import("behavior/export_self_referential_type_info.zig");
158 _ = @import("behavior/field_parent_ptr.zig");
159 _ = @import("behavior/misc.zig");
160 _ = @import("behavior/muladd.zig");
161 _ = @import("behavior/select.zig");
162 _ = @import("behavior/shuffle.zig");
163 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
164 _ = @import("behavior/struct_contains_slice_of_itself.zig");
165 _ = @import("behavior/switch_prong_err_enum.zig");
166 _ = @import("behavior/switch_prong_implicit_cast.zig");
167 _ = @import("behavior/typename.zig");
168 _ = @import("behavior/union_with_members.zig");
169 _ = @import("behavior/vector.zig");
170 if (builtin.target.cpu.arch == .wasm32) {
171 _ = @import("behavior/wasm.zig");
172 }
173 }173 }
174 }174 }
175 }175 }
test/behavior/align.zig-6
...@@ -180,8 +180,6 @@ fn noop4() align(4) void {}...@@ -180,8 +180,6 @@ fn noop4() align(4) void {}
180test "function alignment" {180test "function alignment" {
181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
184 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
186184
187 // function alignment is a compile error on wasm32/wasm64185 // function alignment is a compile error on wasm32/wasm64
...@@ -199,7 +197,6 @@ test "implicitly decreasing fn alignment" {...@@ -199,7 +197,6 @@ test "implicitly decreasing fn alignment" {
199 if (builtin.zig_backend == .stage1) return error.SkipZigTest;197 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
200 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;198 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
201 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;199 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
203 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;200 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
205202
...@@ -226,8 +223,6 @@ test "@alignCast functions" {...@@ -226,8 +223,6 @@ test "@alignCast functions" {
226 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage1) return error.SkipZigTest;224 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
228 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
229 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
231 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
232227
233 // function alignment is a compile error on wasm32/wasm64228 // function alignment is a compile error on wasm32/wasm64
...@@ -250,7 +245,6 @@ test "generic function with align param" {...@@ -250,7 +245,6 @@ test "generic function with align param" {
250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;246 if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;
252 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;247 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
253 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
254 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;248 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
255 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
256250
test/behavior/array.zig+6-4
...@@ -49,7 +49,7 @@ fn getArrayLen(a: []const u32) usize {...@@ -49,7 +49,7 @@ fn getArrayLen(a: []const u32) usize {
4949
50test "array init with mult" {50test "array init with mult" {
51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;51 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
5353
54 const a = 'a';54 const a = 'a';
55 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;55 var i: [8]u8 = [2]u8{ a, 'b' } ** 4;
...@@ -112,7 +112,7 @@ test "array len field" {...@@ -112,7 +112,7 @@ test "array len field" {
112112
113test "array with sentinels" {113test "array with sentinels" {
114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;114 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
115 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
116116
117 const S = struct {117 const S = struct {
118 fn doTheTest(is_ct: bool) !void {118 fn doTheTest(is_ct: bool) !void {
...@@ -179,7 +179,8 @@ fn plusOne(x: u32) u32 {...@@ -179,7 +179,8 @@ fn plusOne(x: u32) u32 {
179179
180test "single-item pointer to array indexing and slicing" {180test "single-item pointer to array indexing and slicing" {
181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
183184
184 try testSingleItemPtrArrayIndexSlice();185 try testSingleItemPtrArrayIndexSlice();
185 comptime try testSingleItemPtrArrayIndexSlice();186 comptime try testSingleItemPtrArrayIndexSlice();
...@@ -205,7 +206,8 @@ fn doSomeMangling(array: *[4]u8) void {...@@ -205,7 +206,8 @@ fn doSomeMangling(array: *[4]u8) void {
205206
206test "implicit cast zero sized array ptr to slice" {207test "implicit cast zero sized array ptr to slice" {
207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;208 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
208 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;209 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
209211
210 {212 {
211 var b = "".*;213 var b = "".*;
test/behavior/basic.zig-6
...@@ -117,7 +117,6 @@ fn first4KeysOfHomeRow() []const u8 {...@@ -117,7 +117,6 @@ fn first4KeysOfHomeRow() []const u8 {
117test "return string from function" {117test "return string from function" {
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
120 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
121120
122 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));121 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
123}122}
...@@ -231,7 +230,6 @@ test "compile time global reinterpret" {...@@ -231,7 +230,6 @@ test "compile time global reinterpret" {
231230
232test "cast undefined" {231test "cast undefined" {
233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
235233
236 const array: [100]u8 = undefined;234 const array: [100]u8 = undefined;
237 const slice = @as([]const u8, &array);235 const slice = @as([]const u8, &array);
...@@ -303,7 +301,6 @@ test "call function pointer in struct" {...@@ -303,7 +301,6 @@ test "call function pointer in struct" {
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;301 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;303 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
306
307 if (builtin.zig_backend == .stage1) return error.SkipZigTest;304 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
308305
309 try expect(mem.eql(u8, f3(true), "a"));306 try expect(mem.eql(u8, f3(true), "a"));
...@@ -382,7 +379,6 @@ fn testMemcpyMemset() !void {...@@ -382,7 +379,6 @@ fn testMemcpyMemset() !void {
382test "variable is allowed to be a pointer to an opaque type" {379test "variable is allowed to be a pointer to an opaque type" {
383 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
384 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
385 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO382 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
387383
388 var x: i32 = 1234;384 var x: i32 = 1234;
...@@ -425,7 +421,6 @@ test "array 2D const double ptr" {...@@ -425,7 +421,6 @@ test "array 2D const double ptr" {
425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;421 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
426 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;422 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
427 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;423 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
428
429 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO424 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
430425
431 const rect_2d_vertexes = [_][1]f32{426 const rect_2d_vertexes = [_][1]f32{
...@@ -476,7 +471,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {...@@ -476,7 +471,6 @@ fn testArray2DConstDoublePtr(ptr: *const f32) !void {
476test "double implicit cast in same expression" {471test "double implicit cast in same expression" {
477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;472 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;473 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
479 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
480474
481 var x = @as(i32, @as(u16, nine()));475 var x = @as(i32, @as(u16, nine()));
482 try expect(x == 9);476 try expect(x == 9);
test/behavior/bitcast.zig+38
...@@ -7,6 +7,9 @@ const minInt = std.math.minInt;...@@ -7,6 +7,9 @@ const minInt = std.math.minInt;
7const native_endian = builtin.target.cpu.arch.endian();7const native_endian = builtin.target.cpu.arch.endian();
88
9test "@bitCast iX -> uX (32, 64)" {9test "@bitCast iX -> uX (32, 64)" {
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
12
10 const bit_values = [_]usize{ 32, 64 };13 const bit_values = [_]usize{ 32, 64 };
1114
12 inline for (bit_values) |bits| {15 inline for (bit_values) |bits| {
...@@ -17,6 +20,10 @@ test "@bitCast iX -> uX (32, 64)" {...@@ -17,6 +20,10 @@ test "@bitCast iX -> uX (32, 64)" {
1720
18test "@bitCast iX -> uX (8, 16, 128)" {21test "@bitCast iX -> uX (8, 16, 128)" {
19 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26
20 const bit_values = [_]usize{ 8, 16, 128 };27 const bit_values = [_]usize{ 8, 16, 128 };
2128
22 inline for (bit_values) |bits| {29 inline for (bit_values) |bits| {
...@@ -29,6 +36,8 @@ test "@bitCast iX -> uX exotic integers" {...@@ -29,6 +36,8 @@ test "@bitCast iX -> uX exotic integers" {
29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;36 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;37 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;38 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3241
33 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };42 const bit_values = [_]usize{ 1, 48, 27, 512, 493, 293, 125, 204, 112 };
3443
...@@ -66,6 +75,9 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe...@@ -66,6 +75,9 @@ fn conv_uN(comptime N: usize, x: std.meta.Int(.unsigned, N)) std.meta.Int(.signe
66}75}
6776
68test "nested bitcast" {77test "nested bitcast" {
78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
80
69 const S = struct {81 const S = struct {
70 fn moo(x: isize) !void {82 fn moo(x: isize) !void {
71 try expect(@intCast(isize, 42) == x);83 try expect(@intCast(isize, 42) == x);
...@@ -83,6 +95,9 @@ test "nested bitcast" {...@@ -83,6 +95,9 @@ test "nested bitcast" {
83}95}
8496
85test "@bitCast enum to its integer type" {97test "@bitCast enum to its integer type" {
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
100
86 const SOCK = enum(c_int) {101 const SOCK = enum(c_int) {
87 A,102 A,
88 B,103 B,
...@@ -100,11 +115,17 @@ test "@bitCast enum to its integer type" {...@@ -100,11 +115,17 @@ test "@bitCast enum to its integer type" {
100115
101// issue #3010: compiler segfault116// issue #3010: compiler segfault
102test "bitcast literal [4]u8 param to u32" {117test "bitcast literal [4]u8 param to u32" {
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
120
103 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });121 const ip = @bitCast(u32, [_]u8{ 255, 255, 255, 255 });
104 try expect(ip == maxInt(u32));122 try expect(ip == maxInt(u32));
105}123}
106124
107test "bitcast generates a temporary value" {125test "bitcast generates a temporary value" {
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
128
108 var y = @as(u16, 0x55AA);129 var y = @as(u16, 0x55AA);
109 const x = @bitCast(u16, @bitCast([2]u8, y));130 const x = @bitCast(u16, @bitCast([2]u8, y));
110 try expect(y == x);131 try expect(y == x);
...@@ -115,6 +136,8 @@ test "@bitCast packed structs at runtime and comptime" {...@@ -115,6 +136,8 @@ test "@bitCast packed structs at runtime and comptime" {
115 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;136 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
116 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
117 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;138 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
140 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
118141
119 const Full = packed struct {142 const Full = packed struct {
120 number: u16,143 number: u16,
...@@ -151,6 +174,8 @@ test "@bitCast extern structs at runtime and comptime" {...@@ -151,6 +174,8 @@ test "@bitCast extern structs at runtime and comptime" {
151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;174 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
152 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;175 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;176 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
178 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
154179
155 const Full = extern struct {180 const Full = extern struct {
156 number: u16,181 number: u16,
...@@ -184,6 +209,8 @@ test "bitcast packed struct to integer and back" {...@@ -184,6 +209,8 @@ test "bitcast packed struct to integer and back" {
184 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;209 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
185 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;210 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
186 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
187214
188 const LevelUpMove = packed struct {215 const LevelUpMove = packed struct {
189 move_id: u9,216 move_id: u9,
...@@ -203,6 +230,9 @@ test "bitcast packed struct to integer and back" {...@@ -203,6 +230,9 @@ test "bitcast packed struct to integer and back" {
203}230}
204231
205test "implicit cast to error union by returning" {232test "implicit cast to error union by returning" {
233 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
235
206 const S = struct {236 const S = struct {
207 fn entry() !void {237 fn entry() !void {
208 try expect((func(-1) catch unreachable) == maxInt(u64));238 try expect((func(-1) catch unreachable) == maxInt(u64));
...@@ -220,6 +250,8 @@ test "bitcast packed struct literal to byte" {...@@ -220,6 +250,8 @@ test "bitcast packed struct literal to byte" {
220 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;250 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
221 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;251 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
222 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
254 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
223255
224 const Foo = packed struct {256 const Foo = packed struct {
225 value: u8,257 value: u8,
...@@ -233,6 +265,8 @@ test "comptime bitcast used in expression has the correct type" {...@@ -233,6 +265,8 @@ test "comptime bitcast used in expression has the correct type" {
233 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;265 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
234 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;266 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
235 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;267 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
268 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
236270
237 const Foo = packed struct {271 const Foo = packed struct {
238 value: u8,272 value: u8,
...@@ -245,6 +279,8 @@ test "bitcast passed as tuple element" {...@@ -245,6 +279,8 @@ test "bitcast passed as tuple element" {
245 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;279 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
246 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;280 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
247 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;281 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
282 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
283 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
248284
249 const S = struct {285 const S = struct {
250 fn foo(args: anytype) !void {286 fn foo(args: anytype) !void {
...@@ -257,6 +293,8 @@ test "bitcast passed as tuple element" {...@@ -257,6 +293,8 @@ test "bitcast passed as tuple element" {
257293
258test "triple level result location with bitcast sandwich passed as tuple element" {294test "triple level result location with bitcast sandwich passed as tuple element" {
259 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;295 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
297 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
260298
261 const S = struct {299 const S = struct {
262 fn foo(args: anytype) !void {300 fn foo(args: anytype) !void {
test/behavior/bugs/1076.zig+5
...@@ -1,8 +1,13 @@...@@ -1,8 +1,13 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const mem = std.mem;3const mem = std.mem;
3const expect = std.testing.expect;4const expect = std.testing.expect;
45
5test "comptime code should not modify constant data" {6test "comptime code should not modify constant data" {
7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
6 try testCastPtrOfArrayToSliceAndPtr();11 try testCastPtrOfArrayToSliceAndPtr();
7 comptime try testCastPtrOfArrayToSliceAndPtr();12 comptime try testCastPtrOfArrayToSliceAndPtr();
8}13}
test/behavior/bugs/1442.zig+3
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
23
3const Union = union(enum) {4const Union = union(enum) {
4 Text: []const u8,5 Text: []const u8,
...@@ -6,6 +7,8 @@ const Union = union(enum) {...@@ -6,6 +7,8 @@ const Union = union(enum) {
6};7};
78
8test "const error union field alignment" {9test "const error union field alignment" {
10 if (builtin.zig_backend != .stage1) return error.SkipZigTest;
11
9 var union_or_err: anyerror!Union = Union{ .Color = 1234 };12 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
10 try std.testing.expect((union_or_err catch unreachable).Color == 1234);13 try std.testing.expect((union_or_err catch unreachable).Color == 1234);
11}14}
test/behavior/bugs/2692.zig+5
...@@ -1,8 +1,13 @@...@@ -1,8 +1,13 @@
1const builtin = @import("builtin");
2
1fn foo(a: []u8) void {3fn foo(a: []u8) void {
2 _ = a;4 _ = a;
3}5}
46
5test "address of 0 length array" {7test "address of 0 length array" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
6 var pt: [0]u8 = undefined;11 var pt: [0]u8 = undefined;
7 foo(&pt);12 foo(&pt);
8}13}
test/behavior/bugs/2889.zig+5
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
23
3const source = "A-";4const source = "A-";
45
...@@ -26,6 +27,10 @@ fn parseNote() ?i32 {...@@ -26,6 +27,10 @@ fn parseNote() ?i32 {
26}27}
2728
28test "fixed" {29test "fixed" {
30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
33
29 const result = parseNote();34 const result = parseNote();
30 try std.testing.expect(result.? == 9);35 try std.testing.expect(result.? == 9);
31}36}
test/behavior/bugs/3046.zig+5-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4const SomeStruct = struct {5const SomeStruct = struct {
...@@ -12,7 +13,10 @@ fn couldFail() anyerror!i32 {...@@ -12,7 +13,10 @@ fn couldFail() anyerror!i32 {
12var some_struct: SomeStruct = undefined;13var some_struct: SomeStruct = undefined;
1314
14test "fixed" {15test "fixed" {
15 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1620
17 some_struct = SomeStruct{21 some_struct = SomeStruct{
18 .field = couldFail() catch @as(i32, 0),22 .field = couldFail() catch @as(i32, 0),
test/behavior/bugs/3586.zig+5
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1const builtin = @import("builtin");
2
1const NoteParams = struct {};3const NoteParams = struct {};
24
3const Container = struct {5const Container = struct {
...@@ -5,6 +7,9 @@ const Container = struct {...@@ -5,6 +7,9 @@ const Container = struct {
5};7};
68
7test "fixed" {9test "fixed" {
10 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12
8 var ctr = Container{13 var ctr = Container{
9 .params = NoteParams{},14 .params = NoteParams{},
10 };15 };
test/behavior/bugs/4560.zig+4
...@@ -1,6 +1,10 @@...@@ -1,6 +1,10 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
23
3test "fixed" {4test "fixed" {
5 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
6 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7
4 var s: S = .{8 var s: S = .{
5 .a = 1,9 .a = 1,
6 .b = .{10 .b = .{
test/behavior/bugs/4954.zig+6
...@@ -1,8 +1,14 @@...@@ -1,8 +1,14 @@
1const builtin = @import("builtin");
2
1fn f(buf: []u8) void {3fn f(buf: []u8) void {
2 _ = &buf[@sizeOf(u32)];4 _ = &buf[@sizeOf(u32)];
3}5}
46
5test "crash" {7test "crash" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11
6 var buf: [4096]u8 = undefined;12 var buf: [4096]u8 = undefined;
7 f(&buf);13 f(&buf);
8}14}
test/behavior/bugs/624.zig+4
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4const TestContext = struct {5const TestContext = struct {
...@@ -19,6 +20,9 @@ fn MemoryPool(comptime T: type) type {...@@ -19,6 +20,9 @@ fn MemoryPool(comptime T: type) type {
19}20}
2021
21test "foo" {22test "foo" {
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25
22 var allocator = ContextAllocator{ .n = 10 };26 var allocator = ContextAllocator{ .n = 10 };
23 try expect(allocator.n == 10);27 try expect(allocator.n == 10);
24}28}
test/behavior/bugs/704.zig+5
...@@ -1,9 +1,14 @@...@@ -1,9 +1,14 @@
1const builtin = @import("builtin");
2
1const xxx = struct {3const xxx = struct {
2 pub fn bar(self: *xxx) void {4 pub fn bar(self: *xxx) void {
3 _ = self;5 _ = self;
4 }6 }
5};7};
6test "bug 704" {8test "bug 704" {
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11
7 var x: xxx = undefined;12 var x: xxx = undefined;
8 x.bar();13 x.bar();
9}14}
test/behavior/byval_arg_var.zig+5
...@@ -1,8 +1,13 @@...@@ -1,8 +1,13 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
23
3var result: []const u8 = "wrong";4var result: []const u8 = "wrong";
45
5test "pass string literal byvalue to a generic var param" {6test "pass string literal byvalue to a generic var param" {
7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
6 start();11 start();
7 blowUpStack(10);12 blowUpStack(10);
813
test/behavior/defer.zig+13
...@@ -5,6 +5,9 @@ const expectEqual = std.testing.expectEqual;...@@ -5,6 +5,9 @@ const expectEqual = std.testing.expectEqual;
5const expectError = std.testing.expectError;5const expectError = std.testing.expectError;
66
7test "break and continue inside loop inside defer expression" {7test "break and continue inside loop inside defer expression" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
8 testBreakContInDefer(10);11 testBreakContInDefer(10);
9 comptime testBreakContInDefer(10);12 comptime testBreakContInDefer(10);
10}13}
...@@ -21,6 +24,9 @@ fn testBreakContInDefer(x: usize) void {...@@ -21,6 +24,9 @@ fn testBreakContInDefer(x: usize) void {
21}24}
2225
23test "defer and labeled break" {26test "defer and labeled break" {
27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
29
24 var i = @as(usize, 0);30 var i = @as(usize, 0);
2531
26 blk: {32 blk: {
...@@ -32,6 +38,9 @@ test "defer and labeled break" {...@@ -32,6 +38,9 @@ test "defer and labeled break" {
32}38}
3339
34test "errdefer does not apply to fn inside fn" {40test "errdefer does not apply to fn inside fn" {
41 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
43
35 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);44 if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| try expect(e == error.Bad);
36}45}
3746
...@@ -47,6 +56,10 @@ fn testNestedFnErrDefer() anyerror!void {...@@ -47,6 +56,10 @@ fn testNestedFnErrDefer() anyerror!void {
47}56}
4857
49test "return variable while defer expression in scope to modify it" {58test "return variable while defer expression in scope to modify it" {
59 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
62
50 const S = struct {63 const S = struct {
51 fn doTheTest() !void {64 fn doTheTest() !void {
52 try expect(notNull().? == 1);65 try expect(notNull().? == 1);
test/behavior/enum.zig+114
...@@ -11,6 +11,9 @@ fn shouldEqual(n: Number, expected: u3) !void {...@@ -11,6 +11,9 @@ fn shouldEqual(n: Number, expected: u3) !void {
11}11}
1212
13test "enum to int" {13test "enum to int" {
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16
14 try shouldEqual(Number.Zero, 0);17 try shouldEqual(Number.Zero, 0);
15 try shouldEqual(Number.One, 1);18 try shouldEqual(Number.One, 1);
16 try shouldEqual(Number.Two, 2);19 try shouldEqual(Number.Two, 2);
...@@ -24,6 +27,9 @@ fn testIntToEnumEval(x: i32) !void {...@@ -24,6 +27,9 @@ fn testIntToEnumEval(x: i32) !void {
24const IntToEnumNumber = enum { Zero, One, Two, Three, Four };27const IntToEnumNumber = enum { Zero, One, Two, Three, Four };
2528
26test "int to enum" {29test "int to enum" {
30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32
27 try testIntToEnumEval(3);33 try testIntToEnumEval(3);
28}34}
2935
...@@ -553,6 +559,9 @@ const ValueCount257 = enum {...@@ -553,6 +559,9 @@ const ValueCount257 = enum {
553};559};
554560
555test "enum sizes" {561test "enum sizes" {
562 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
563 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
564
556 comptime {565 comptime {
557 try expect(@sizeOf(ValueCount1) == 0);566 try expect(@sizeOf(ValueCount1) == 0);
558 try expect(@sizeOf(ValueCount2) == 1);567 try expect(@sizeOf(ValueCount2) == 1);
...@@ -562,6 +571,9 @@ test "enum sizes" {...@@ -562,6 +571,9 @@ test "enum sizes" {
562}571}
563572
564test "enum literal equality" {573test "enum literal equality" {
574 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
575 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
576
565 const x = .hi;577 const x = .hi;
566 const y = .ok;578 const y = .ok;
567 const z = .hi;579 const z = .hi;
...@@ -571,6 +583,9 @@ test "enum literal equality" {...@@ -571,6 +583,9 @@ test "enum literal equality" {
571}583}
572584
573test "enum literal cast to enum" {585test "enum literal cast to enum" {
586 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
587 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
588
574 const Color = enum { Auto, Off, On };589 const Color = enum { Auto, Off, On };
575590
576 var color1: Color = .Auto;591 var color1: Color = .Auto;
...@@ -579,6 +594,9 @@ test "enum literal cast to enum" {...@@ -579,6 +594,9 @@ test "enum literal cast to enum" {
579}594}
580595
581test "peer type resolution with enum literal" {596test "peer type resolution with enum literal" {
597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
599
582 const Items = enum { one, two };600 const Items = enum { one, two };
583601
584 try expect(Items.two == .two);602 try expect(Items.two == .two);
...@@ -603,11 +621,19 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {...@@ -603,11 +621,19 @@ fn testEnumWithSpecifiedTagValues(x: MultipleChoice) !void {
603}621}
604622
605test "enum with specified tag values" {623test "enum with specified tag values" {
624 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
626 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
627
606 try testEnumWithSpecifiedTagValues(MultipleChoice.C);628 try testEnumWithSpecifiedTagValues(MultipleChoice.C);
607 comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);629 comptime try testEnumWithSpecifiedTagValues(MultipleChoice.C);
608}630}
609631
610test "non-exhaustive enum" {632test "non-exhaustive enum" {
633 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
634 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
635 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
636
611 const S = struct {637 const S = struct {
612 const E = enum(u8) { a, b, _ };638 const E = enum(u8) { a, b, _ };
613639
...@@ -649,6 +675,9 @@ test "non-exhaustive enum" {...@@ -649,6 +675,9 @@ test "non-exhaustive enum" {
649}675}
650676
651test "empty non-exhaustive enum" {677test "empty non-exhaustive enum" {
678 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
679 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
680
652 const S = struct {681 const S = struct {
653 const E = enum(u8) { _ };682 const E = enum(u8) { _ };
654683
...@@ -668,6 +697,10 @@ test "empty non-exhaustive enum" {...@@ -668,6 +697,10 @@ test "empty non-exhaustive enum" {
668}697}
669698
670test "single field non-exhaustive enum" {699test "single field non-exhaustive enum" {
700 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
701 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
702 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
703
671 const S = struct {704 const S = struct {
672 const E = enum(u8) { a, _ };705 const E = enum(u8) { a, _ };
673 fn doTheTest(y: u8) !void {706 fn doTheTest(y: u8) !void {
...@@ -708,6 +741,9 @@ const EnumWithTagValues = enum(u4) {...@@ -708,6 +741,9 @@ const EnumWithTagValues = enum(u4) {
708 D = 1 << 3,741 D = 1 << 3,
709};742};
710test "enum with tag values don't require parens" {743test "enum with tag values don't require parens" {
744 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
745 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
746
711 try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);747 try expect(@enumToInt(EnumWithTagValues.C) == 0b0100);
712}748}
713749
...@@ -724,11 +760,18 @@ const MultipleChoice2 = enum(u32) {...@@ -724,11 +760,18 @@ const MultipleChoice2 = enum(u32) {
724};760};
725761
726test "cast integer literal to enum" {762test "cast integer literal to enum" {
763 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
764 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
765
727 try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);766 try expect(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
728 try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);767 try expect(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
729}768}
730769
731test "enum with specified and unspecified tag values" {770test "enum with specified and unspecified tag values" {
771 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
772 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
773 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
774
732 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);775 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
733 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);776 comptime try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2.D);
734}777}
...@@ -752,6 +795,9 @@ const Small2 = enum(u2) { One, Two };...@@ -752,6 +795,9 @@ const Small2 = enum(u2) { One, Two };
752const Small = enum(u2) { One, Two, Three, Four };795const Small = enum(u2) { One, Two, Three, Four };
753796
754test "set enum tag type" {797test "set enum tag type" {
798 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
799 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
800
755 {801 {
756 var x = Small.One;802 var x = Small.One;
757 x = Small.Two;803 x = Small.Two;
...@@ -765,6 +811,9 @@ test "set enum tag type" {...@@ -765,6 +811,9 @@ test "set enum tag type" {
765}811}
766812
767test "casting enum to its tag type" {813test "casting enum to its tag type" {
814 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816
768 try testCastEnumTag(Small2.Two);817 try testCastEnumTag(Small2.Two);
769 comptime try testCastEnumTag(Small2.Two);818 comptime try testCastEnumTag(Small2.Two);
770}819}
...@@ -774,6 +823,9 @@ fn testCastEnumTag(value: Small2) !void {...@@ -774,6 +823,9 @@ fn testCastEnumTag(value: Small2) !void {
774}823}
775824
776test "enum with 1 field but explicit tag type should still have the tag type" {825test "enum with 1 field but explicit tag type should still have the tag type" {
826 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
828
777 const Enum = enum(u8) {829 const Enum = enum(u8) {
778 B = 2,830 B = 2,
779 };831 };
...@@ -781,6 +833,9 @@ test "enum with 1 field but explicit tag type should still have the tag type" {...@@ -781,6 +833,9 @@ test "enum with 1 field but explicit tag type should still have the tag type" {
781}833}
782834
783test "signed integer as enum tag" {835test "signed integer as enum tag" {
836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
837 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
838
784 const SignedEnum = enum(i2) {839 const SignedEnum = enum(i2) {
785 A0 = -1,840 A0 = -1,
786 A1 = 0,841 A1 = 0,
...@@ -793,6 +848,9 @@ test "signed integer as enum tag" {...@@ -793,6 +848,9 @@ test "signed integer as enum tag" {
793}848}
794849
795test "enum with one member and custom tag type" {850test "enum with one member and custom tag type" {
851 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
853
796 const E = enum(u2) {854 const E = enum(u2) {
797 One,855 One,
798 };856 };
...@@ -804,6 +862,9 @@ test "enum with one member and custom tag type" {...@@ -804,6 +862,9 @@ test "enum with one member and custom tag type" {
804}862}
805863
806test "enum with one member and u1 tag type @enumToInt" {864test "enum with one member and u1 tag type @enumToInt" {
865 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
866 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
867
807 const Enum = enum(u1) {868 const Enum = enum(u1) {
808 Test,869 Test,
809 };870 };
...@@ -811,6 +872,9 @@ test "enum with one member and u1 tag type @enumToInt" {...@@ -811,6 +872,9 @@ test "enum with one member and u1 tag type @enumToInt" {
811}872}
812873
813test "enum with comptime_int tag type" {874test "enum with comptime_int tag type" {
875 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
876 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
877
814 const Enum = enum(comptime_int) {878 const Enum = enum(comptime_int) {
815 One = 3,879 One = 3,
816 Two = 2,880 Two = 2,
...@@ -820,6 +884,9 @@ test "enum with comptime_int tag type" {...@@ -820,6 +884,9 @@ test "enum with comptime_int tag type" {
820}884}
821885
822test "enum with one member default to u0 tag type" {886test "enum with one member default to u0 tag type" {
887 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
888 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
889
823 const E0 = enum { X };890 const E0 = enum { X };
824 comptime try expect(Tag(E0) == u0);891 comptime try expect(Tag(E0) == u0);
825}892}
...@@ -836,11 +903,17 @@ fn doALoopThing(id: EnumWithOneMember) void {...@@ -836,11 +903,17 @@ fn doALoopThing(id: EnumWithOneMember) void {
836}903}
837904
838test "comparison operator on enum with one member is comptime known" {905test "comparison operator on enum with one member is comptime known" {
906 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
907 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
908
839 doALoopThing(EnumWithOneMember.Eof);909 doALoopThing(EnumWithOneMember.Eof);
840}910}
841911
842const State = enum { Start };912const State = enum { Start };
843test "switch on enum with one member is comptime known" {913test "switch on enum with one member is comptime known" {
914 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
915 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
916
844 var state = State.Start;917 var state = State.Start;
845 switch (state) {918 switch (state) {
846 State.Start => return,919 State.Start => return,
...@@ -849,6 +922,9 @@ test "switch on enum with one member is comptime known" {...@@ -849,6 +922,9 @@ test "switch on enum with one member is comptime known" {
849}922}
850923
851test "method call on an enum" {924test "method call on an enum" {
925 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
926 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
927
852 const S = struct {928 const S = struct {
853 const E = enum {929 const E = enum {
854 one,930 one,
...@@ -885,6 +961,10 @@ test "enum value allocation" {...@@ -885,6 +961,10 @@ test "enum value allocation" {
885}961}
886962
887test "enum literal casting to tagged union" {963test "enum literal casting to tagged union" {
964 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
965 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
966 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
967
888 const Arch = union(enum) {968 const Arch = union(enum) {
889 x86_64,969 x86_64,
890 arm: Arm32,970 arm: Arm32,
...@@ -907,6 +987,10 @@ test "enum literal casting to tagged union" {...@@ -907,6 +987,10 @@ test "enum literal casting to tagged union" {
907const Bar = enum { A, B, C, D };987const Bar = enum { A, B, C, D };
908988
909test "enum literal casting to error union with payload enum" {989test "enum literal casting to error union with payload enum" {
990 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
991 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
992 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
993
910 var bar: error{B}!Bar = undefined;994 var bar: error{B}!Bar = undefined;
911 bar = .B; // should never cast to the error set995 bar = .B; // should never cast to the error set
912996
...@@ -930,6 +1014,11 @@ test "exporting enum type and value" {...@@ -930,6 +1014,11 @@ test "exporting enum type and value" {
930}1014}
9311015
932test "constant enum initialization with differing sizes" {1016test "constant enum initialization with differing sizes" {
1017 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1018 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1019 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1020 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1021
933 try test3_1(test3_foo);1022 try test3_1(test3_foo);
934 try test3_2(test3_bar);1023 try test3_2(test3_bar);
935}1024}
...@@ -970,6 +1059,9 @@ fn test3_2(f: Test3Foo) !void {...@@ -970,6 +1059,9 @@ fn test3_2(f: Test3Foo) !void {
970test "@tagName" {1059test "@tagName" {
971 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1060 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
972 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1061 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1062 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1063 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1064 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9731065
974 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));1066 try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
975 comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));1067 comptime try expect(mem.eql(u8, testEnumTagNameBare(BareNumber.Three), "Three"));
...@@ -984,6 +1076,9 @@ const BareNumber = enum { One, Two, Three };...@@ -984,6 +1076,9 @@ const BareNumber = enum { One, Two, Three };
984test "@tagName non-exhaustive enum" {1076test "@tagName non-exhaustive enum" {
985 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1077 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
986 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1078 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1079 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1080 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1081 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9871082
988 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));1083 try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
989 comptime try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));1084 comptime try expect(mem.eql(u8, testEnumTagNameBare(NonExhaustive.B), "B"));
...@@ -993,6 +1088,9 @@ const NonExhaustive = enum(u8) { A, B, _ };...@@ -993,6 +1088,9 @@ const NonExhaustive = enum(u8) { A, B, _ };
993test "@tagName is null-terminated" {1088test "@tagName is null-terminated" {
994 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1089 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
995 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1090 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1091 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1092 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1093 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9961094
997 const S = struct {1095 const S = struct {
998 fn doTheTest(n: BareNumber) !void {1096 fn doTheTest(n: BareNumber) !void {
...@@ -1006,6 +1104,9 @@ test "@tagName is null-terminated" {...@@ -1006,6 +1104,9 @@ test "@tagName is null-terminated" {
1006test "tag name with assigned enum values" {1104test "tag name with assigned enum values" {
1007 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1105 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1008 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1106 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1107 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1108 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10091110
1010 const LocalFoo = enum(u8) {1111 const LocalFoo = enum(u8) {
1011 A = 1,1112 A = 1,
...@@ -1016,11 +1117,18 @@ test "tag name with assigned enum values" {...@@ -1016,11 +1117,18 @@ test "tag name with assigned enum values" {
1016}1117}
10171118
1018test "@tagName on enum literals" {1119test "@tagName on enum literals" {
1120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1122
1019 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));1123 try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1020 comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));1124 comptime try expect(mem.eql(u8, @tagName(.FooBar), "FooBar"));
1021}1125}
10221126
1023test "enum literal casting to optional" {1127test "enum literal casting to optional" {
1128 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1131
1024 var bar: ?Bar = undefined;1132 var bar: ?Bar = undefined;
1025 bar = .B;1133 bar = .B;
10261134
...@@ -1045,6 +1153,9 @@ const bit_field_1 = BitFieldOfEnums{...@@ -1045,6 +1153,9 @@ const bit_field_1 = BitFieldOfEnums{
10451153
1046test "bit field access with enum fields" {1154test "bit field access with enum fields" {
1047 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1155 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1156 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10481159
1049 var data = bit_field_1;1160 var data = bit_field_1;
1050 try expect(getA(&data) == A.Two);1161 try expect(getA(&data) == A.Two);
...@@ -1073,6 +1184,9 @@ fn getC(data: *const BitFieldOfEnums) C {...@@ -1073,6 +1184,9 @@ fn getC(data: *const BitFieldOfEnums) C {
1073}1184}
10741185
1075test "enum literal in array literal" {1186test "enum literal in array literal" {
1187 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1188 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1189
1076 const Items = enum { one, two };1190 const Items = enum { one, two };
1077 const array = [_]Items{ .one, .two };1191 const array = [_]Items{ .one, .two };
10781192
test/behavior/error.zig+48
...@@ -6,12 +6,18 @@ const expectEqual = std.testing.expectEqual;...@@ -6,12 +6,18 @@ const expectEqual = std.testing.expectEqual;
6const mem = std.mem;6const mem = std.mem;
77
8test "error values" {8test "error values" {
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11
9 const a = @errorToInt(error.err1);12 const a = @errorToInt(error.err1);
10 const b = @errorToInt(error.err2);13 const b = @errorToInt(error.err2);
11 try expect(a != b);14 try expect(a != b);
12}15}
1316
14test "redefinition of error values allowed" {17test "redefinition of error values allowed" {
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
20
15 shouldBeNotEqual(error.AnError, error.SecondError);21 shouldBeNotEqual(error.AnError, error.SecondError);
16}22}
17fn shouldBeNotEqual(a: anyerror, b: anyerror) void {23fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
...@@ -19,6 +25,10 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {...@@ -19,6 +25,10 @@ fn shouldBeNotEqual(a: anyerror, b: anyerror) void {
19}25}
2026
21test "error binary operator" {27test "error binary operator" {
28 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31
22 const a = errBinaryOperatorG(true) catch 3;32 const a = errBinaryOperatorG(true) catch 3;
23 const b = errBinaryOperatorG(false) catch 3;33 const b = errBinaryOperatorG(false) catch 3;
24 try expect(a == 3);34 try expect(a == 3);
...@@ -29,6 +39,9 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {...@@ -29,6 +39,9 @@ fn errBinaryOperatorG(x: bool) anyerror!isize {
29}39}
3040
31test "empty error union" {41test "empty error union" {
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
43 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
44
32 const x = error{} || error{};45 const x = error{} || error{};
33 _ = x;46 _ = x;
34}47}
...@@ -48,10 +61,18 @@ pub fn baz() anyerror!i32 {...@@ -48,10 +61,18 @@ pub fn baz() anyerror!i32 {
48}61}
4962
50test "error wrapping" {63test "error wrapping" {
64 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
67
51 try expect((baz() catch unreachable) == 15);68 try expect((baz() catch unreachable) == 15);
52}69}
5370
54test "unwrap simple value from error" {71test "unwrap simple value from error" {
72 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
75
55 const i = unwrapSimpleValueFromErrorDo() catch unreachable;76 const i = unwrapSimpleValueFromErrorDo() catch unreachable;
56 try expect(i == 13);77 try expect(i == 13);
57}78}
...@@ -60,6 +81,10 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {...@@ -60,6 +81,10 @@ fn unwrapSimpleValueFromErrorDo() anyerror!isize {
60}81}
6182
62test "error return in assignment" {83test "error return in assignment" {
84 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
86 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
87
63 doErrReturnInAssignment() catch unreachable;88 doErrReturnInAssignment() catch unreachable;
64}89}
6590
...@@ -73,12 +98,19 @@ fn makeANonErr() anyerror!i32 {...@@ -73,12 +98,19 @@ fn makeANonErr() anyerror!i32 {
73}98}
7499
75test "syntax: optional operator in front of error union operator" {100test "syntax: optional operator in front of error union operator" {
101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103
76 comptime {104 comptime {
77 try expect(?(anyerror!i32) == ?(anyerror!i32));105 try expect(?(anyerror!i32) == ?(anyerror!i32));
78 }106 }
79}107}
80108
81test "widen cast integer payload of error union function call" {109test "widen cast integer payload of error union function call" {
110 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
111 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
112 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
113
82 const S = struct {114 const S = struct {
83 fn errorable() !u64 {115 fn errorable() !u64 {
84 var x = @as(u64, try number());116 var x = @as(u64, try number());
...@@ -93,12 +125,19 @@ test "widen cast integer payload of error union function call" {...@@ -93,12 +125,19 @@ test "widen cast integer payload of error union function call" {
93}125}
94126
95test "debug info for optional error set" {127test "debug info for optional error set" {
128 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
129 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
130 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
131
96 const SomeError = error{Hello};132 const SomeError = error{Hello};
97 var a_local_variable: ?SomeError = null;133 var a_local_variable: ?SomeError = null;
98 _ = a_local_variable;134 _ = a_local_variable;
99}135}
100136
101test "implicit cast to optional to error union to return result loc" {137test "implicit cast to optional to error union to return result loc" {
138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
140
102 const S = struct {141 const S = struct {
103 fn entry() !void {142 fn entry() !void {
104 var x: Foo = undefined;143 var x: Foo = undefined;
...@@ -118,6 +157,9 @@ test "implicit cast to optional to error union to return result loc" {...@@ -118,6 +157,9 @@ test "implicit cast to optional to error union to return result loc" {
118}157}
119158
120test "error: fn returning empty error set can be passed as fn returning any error" {159test "error: fn returning empty error set can be passed as fn returning any error" {
160 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162
121 entry();163 entry();
122 comptime entry();164 comptime entry();
123}165}
...@@ -482,6 +524,9 @@ test "error union comptime caching" {...@@ -482,6 +524,9 @@ test "error union comptime caching" {
482test "@errorName" {524test "@errorName" {
483 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO525 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
484 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO526 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
527 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
528 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
529 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
485530
486 try expect(mem.eql(u8, @errorName(error.AnError), "AnError"));531 try expect(mem.eql(u8, @errorName(error.AnError), "AnError"));
487 try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));532 try expect(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName"));
...@@ -494,6 +539,9 @@ fn gimmeItBroke() anyerror {...@@ -494,6 +539,9 @@ fn gimmeItBroke() anyerror {
494test "@errorName sentinel length matches slice length" {539test "@errorName sentinel length matches slice length" {
495 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO540 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO541 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
542 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
543 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
544 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
497545
498 const name = testBuiltinErrorName(error.FooBar);546 const name = testBuiltinErrorName(error.FooBar);
499 const length: usize = 6;547 const length: usize = 6;
test/behavior/fn.zig+71
...@@ -5,6 +5,9 @@ const expect = testing.expect;...@@ -5,6 +5,9 @@ const expect = testing.expect;
5const expectEqual = testing.expectEqual;5const expectEqual = testing.expectEqual;
66
7test "params" {7test "params" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
8 try expect(testParamsAdd(22, 11) == 33);11 try expect(testParamsAdd(22, 11) == 33);
9}12}
10fn testParamsAdd(a: i32, b: i32) i32 {13fn testParamsAdd(a: i32, b: i32) i32 {
...@@ -12,6 +15,9 @@ fn testParamsAdd(a: i32, b: i32) i32 {...@@ -12,6 +15,9 @@ fn testParamsAdd(a: i32, b: i32) i32 {
12}15}
1316
14test "local variables" {17test "local variables" {
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
20
15 testLocVars(2);21 testLocVars(2);
16}22}
17fn testLocVars(b: i32) void {23fn testLocVars(b: i32) void {
...@@ -20,6 +26,9 @@ fn testLocVars(b: i32) void {...@@ -20,6 +26,9 @@ fn testLocVars(b: i32) void {
20}26}
2127
22test "mutable local variables" {28test "mutable local variables" {
29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
31
23 var zero: i32 = 0;32 var zero: i32 = 0;
24 try expect(zero == 0);33 try expect(zero == 0);
2534
...@@ -31,6 +40,9 @@ test "mutable local variables" {...@@ -31,6 +40,9 @@ test "mutable local variables" {
31}40}
3241
33test "separate block scopes" {42test "separate block scopes" {
43 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
45
34 {46 {
35 const no_conflict: i32 = 5;47 const no_conflict: i32 = 5;
36 try expect(no_conflict == 5);48 try expect(no_conflict == 5);
...@@ -47,10 +59,16 @@ fn @"weird function name"() i32 {...@@ -47,10 +59,16 @@ fn @"weird function name"() i32 {
47 return 1234;59 return 1234;
48}60}
49test "weird function name" {61test "weird function name" {
62 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
63 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
64
50 try expect(@"weird function name"() == 1234);65 try expect(@"weird function name"() == 1234);
51}66}
5267
53test "assign inline fn to const variable" {68test "assign inline fn to const variable" {
69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
71
54 const a = inlineFn;72 const a = inlineFn;
55 a();73 a();
56}74}
...@@ -68,6 +86,9 @@ fn outer(y: u32) *const fn (u32) u32 {...@@ -68,6 +86,9 @@ fn outer(y: u32) *const fn (u32) u32 {
68}86}
6987
70test "return inner function which references comptime variable of outer function" {88test "return inner function which references comptime variable of outer function" {
89 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
90 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
91
71 if (builtin.zig_backend == .stage1) return error.SkipZigTest;92 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
7293
73 var func = outer(10);94 var func = outer(10);
...@@ -76,6 +97,9 @@ test "return inner function which references comptime variable of outer function...@@ -76,6 +97,9 @@ test "return inner function which references comptime variable of outer function
7697
77test "discard the result of a function that returns a struct" {98test "discard the result of a function that returns a struct" {
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO99 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
102
79 const S = struct {103 const S = struct {
80 fn entry() void {104 fn entry() void {
81 _ = func();105 _ = func();
...@@ -97,6 +121,9 @@ test "discard the result of a function that returns a struct" {...@@ -97,6 +121,9 @@ test "discard the result of a function that returns a struct" {
97test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {121test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {
98 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage1) return error.SkipZigTest;123 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
124 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
125 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
100127
101 const S = struct {128 const S = struct {
102 field: u32,129 field: u32,
...@@ -129,6 +156,9 @@ test "inline function call that calls optional function pointer, return pointer...@@ -129,6 +156,9 @@ test "inline function call that calls optional function pointer, return pointer
129}156}
130157
131test "implicit cast function unreachable return" {158test "implicit cast function unreachable return" {
159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161
132 wantsFnWithVoid(fnWithUnreachable);162 wantsFnWithVoid(fnWithUnreachable);
133}163}
134164
...@@ -143,6 +173,8 @@ fn fnWithUnreachable() noreturn {...@@ -143,6 +173,8 @@ fn fnWithUnreachable() noreturn {
143test "extern struct with stdcallcc fn pointer" {173test "extern struct with stdcallcc fn pointer" {
144 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO174 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage1) return error.SkipZigTest;175 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
176 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146178
147 const S = extern struct {179 const S = extern struct {
148 ptr: *const fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32,180 ptr: *const fn () callconv(if (builtin.target.cpu.arch == .i386) .Stdcall else .C) i32,
...@@ -170,10 +202,16 @@ fn fComplexCallconvRet(x: u32) callconv(blk: {...@@ -170,10 +202,16 @@ fn fComplexCallconvRet(x: u32) callconv(blk: {
170}202}
171203
172test "function with complex callconv and return type expressions" {204test "function with complex callconv and return type expressions" {
205 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
206 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
207
173 try expect(fComplexCallconvRet(3).x == 9);208 try expect(fComplexCallconvRet(3).x == 9);
174}209}
175210
176test "pass by non-copying value" {211test "pass by non-copying value" {
212 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
214
177 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);215 try expect(addPointCoords(Point{ .x = 1, .y = 2 }) == 3);
178}216}
179217
...@@ -187,6 +225,10 @@ fn addPointCoords(pt: Point) i32 {...@@ -187,6 +225,10 @@ fn addPointCoords(pt: Point) i32 {
187}225}
188226
189test "pass by non-copying value through var arg" {227test "pass by non-copying value through var arg" {
228 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
229 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
230 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
231
190 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);232 try expect((try addPointCoordsVar(Point{ .x = 1, .y = 2 })) == 3);
191}233}
192234
...@@ -196,6 +238,9 @@ fn addPointCoordsVar(pt: anytype) !i32 {...@@ -196,6 +238,9 @@ fn addPointCoordsVar(pt: anytype) !i32 {
196}238}
197239
198test "pass by non-copying value as method" {240test "pass by non-copying value as method" {
241 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
243
199 var pt = Point2{ .x = 1, .y = 2 };244 var pt = Point2{ .x = 1, .y = 2 };
200 try expect(pt.addPointCoords() == 3);245 try expect(pt.addPointCoords() == 3);
201}246}
...@@ -210,6 +255,9 @@ const Point2 = struct {...@@ -210,6 +255,9 @@ const Point2 = struct {
210};255};
211256
212test "pass by non-copying value as method, which is generic" {257test "pass by non-copying value as method, which is generic" {
258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
259 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
260
213 var pt = Point3{ .x = 1, .y = 2 };261 var pt = Point3{ .x = 1, .y = 2 };
214 try expect(pt.addPointCoords(i32) == 3);262 try expect(pt.addPointCoords(i32) == 3);
215}263}
...@@ -225,6 +273,9 @@ const Point3 = struct {...@@ -225,6 +273,9 @@ const Point3 = struct {
225};273};
226274
227test "pass by non-copying value as method, at comptime" {275test "pass by non-copying value as method, at comptime" {
276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
278
228 comptime {279 comptime {
229 var pt = Point2{ .x = 1, .y = 2 };280 var pt = Point2{ .x = 1, .y = 2 };
230 try expect(pt.addPointCoords() == 3);281 try expect(pt.addPointCoords() == 3);
...@@ -232,6 +283,9 @@ test "pass by non-copying value as method, at comptime" {...@@ -232,6 +283,9 @@ test "pass by non-copying value as method, at comptime" {
232}283}
233284
234test "implicit cast fn call result to optional in field result" {285test "implicit cast fn call result to optional in field result" {
286 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
287 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
288
235 const S = struct {289 const S = struct {
236 fn entry() !void {290 fn entry() !void {
237 var x = Foo{291 var x = Foo{
...@@ -255,6 +309,10 @@ test "implicit cast fn call result to optional in field result" {...@@ -255,6 +309,10 @@ test "implicit cast fn call result to optional in field result" {
255}309}
256310
257test "void parameters" {311test "void parameters" {
312 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
314 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
315
258 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO316 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
259 try voidFun(1, void{}, 2, {});317 try voidFun(1, void{}, 2, {});
260}318}
...@@ -267,6 +325,9 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {...@@ -267,6 +325,9 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {
267}325}
268326
269test "call function with empty string" {327test "call function with empty string" {
328 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
329 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
330
270 acceptsString("");331 acceptsString("");
271}332}
272333
...@@ -301,6 +362,9 @@ fn fn4() u32 {...@@ -301,6 +362,9 @@ fn fn4() u32 {
301}362}
302363
303test "number literal as an argument" {364test "number literal as an argument" {
365 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
367
304 try numberLiteralArg(3);368 try numberLiteralArg(3);
305 comptime try numberLiteralArg(3);369 comptime try numberLiteralArg(3);
306}370}
...@@ -311,6 +375,10 @@ fn numberLiteralArg(a: anytype) !void {...@@ -311,6 +375,10 @@ fn numberLiteralArg(a: anytype) !void {
311375
312test "function call with anon list literal" {376test "function call with anon list literal" {
313 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO377 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
378 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
379 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
380 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
381
314 const S = struct {382 const S = struct {
315 fn doTheTest() !void {383 fn doTheTest() !void {
316 try consumeVec(.{ 9, 8, 7 });384 try consumeVec(.{ 9, 8, 7 });
...@@ -327,6 +395,9 @@ test "function call with anon list literal" {...@@ -327,6 +395,9 @@ test "function call with anon list literal" {
327}395}
328396
329test "ability to give comptime types and non comptime types to same parameter" {397test "ability to give comptime types and non comptime types to same parameter" {
398 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
399 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
400
330 const S = struct {401 const S = struct {
331 fn doTheTest() !void {402 fn doTheTest() !void {
332 var x: i32 = 1;403 var x: i32 = 1;
test/behavior/for.zig+23-1
...@@ -5,6 +5,9 @@ const expectEqual = std.testing.expectEqual;...@@ -5,6 +5,9 @@ const expectEqual = std.testing.expectEqual;
5const mem = std.mem;5const mem = std.mem;
66
7test "continue in for loop" {7test "continue in for loop" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
8 const array = [_]i32{ 1, 2, 3, 4, 5 };11 const array = [_]i32{ 1, 2, 3, 4, 5 };
9 var sum: i32 = 0;12 var sum: i32 = 0;
10 for (array) |x| {13 for (array) |x| {
...@@ -18,6 +21,9 @@ test "continue in for loop" {...@@ -18,6 +21,9 @@ test "continue in for loop" {
18}21}
1922
20test "break from outer for loop" {23test "break from outer for loop" {
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
26
21 try testBreakOuter();27 try testBreakOuter();
22 comptime try testBreakOuter();28 comptime try testBreakOuter();
23}29}
...@@ -35,6 +41,9 @@ fn testBreakOuter() !void {...@@ -35,6 +41,9 @@ fn testBreakOuter() !void {
35}41}
3642
37test "continue outer for loop" {43test "continue outer for loop" {
44 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
45 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46
38 try testContinueOuter();47 try testContinueOuter();
39 comptime try testContinueOuter();48 comptime try testContinueOuter();
40}49}
...@@ -52,6 +61,9 @@ fn testContinueOuter() !void {...@@ -52,6 +61,9 @@ fn testContinueOuter() !void {
52}61}
5362
54test "ignore lval with underscore (for loop)" {63test "ignore lval with underscore (for loop)" {
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
66
55 for ([_]void{}) |_, i| {67 for ([_]void{}) |_, i| {
56 _ = i;68 _ = i;
57 for ([_]void{}) |_, j| {69 for ([_]void{}) |_, j| {
...@@ -63,7 +75,10 @@ test "ignore lval with underscore (for loop)" {...@@ -63,7 +75,10 @@ test "ignore lval with underscore (for loop)" {
63}75}
6476
65test "basic for loop" {77test "basic for loop" {
66 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6782
68 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;83 const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3;
6984
...@@ -104,6 +119,10 @@ test "basic for loop" {...@@ -104,6 +119,10 @@ test "basic for loop" {
104}119}
105120
106test "for with null and T peer types and inferred result location type" {121test "for with null and T peer types and inferred result location type" {
122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
125
107 const S = struct {126 const S = struct {
108 fn doTheTest(slice: []const u8) !void {127 fn doTheTest(slice: []const u8) !void {
109 if (for (slice) |item| {128 if (for (slice) |item| {
...@@ -121,6 +140,9 @@ test "for with null and T peer types and inferred result location type" {...@@ -121,6 +140,9 @@ test "for with null and T peer types and inferred result location type" {
121}140}
122141
123test "2 break statements and an else" {142test "2 break statements and an else" {
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
144 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
145
124 const S = struct {146 const S = struct {
125 fn entry(t: bool, f: bool) !void {147 fn entry(t: bool, f: bool) !void {
126 var buf: [10]u8 = undefined;148 var buf: [10]u8 = undefined;
test/behavior/generics.zig+41-2
...@@ -5,6 +5,9 @@ const expect = testing.expect;...@@ -5,6 +5,9 @@ const expect = testing.expect;
5const expectEqual = testing.expectEqual;5const expectEqual = testing.expectEqual;
66
7test "one param, explicit comptime" {7test "one param, explicit comptime" {
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10
8 var x: usize = 0;11 var x: usize = 0;
9 x += checkSize(i32);12 x += checkSize(i32);
10 x += checkSize(bool);13 x += checkSize(bool);
...@@ -17,6 +20,9 @@ fn checkSize(comptime T: type) usize {...@@ -17,6 +20,9 @@ fn checkSize(comptime T: type) usize {
17}20}
1821
19test "simple generic fn" {22test "simple generic fn" {
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
25
20 try expect(max(i32, 3, -1) == 3);26 try expect(max(i32, 3, -1) == 3);
21 try expect(max(u8, 1, 100) == 100);27 try expect(max(u8, 1, 100) == 100);
22 if (builtin.zig_backend == .stage1) {28 if (builtin.zig_backend == .stage1) {
...@@ -37,6 +43,9 @@ fn add(comptime a: i32, b: i32) i32 {...@@ -37,6 +43,9 @@ fn add(comptime a: i32, b: i32) i32 {
3743
38const the_max = max(u32, 1234, 5678);44const the_max = max(u32, 1234, 5678);
39test "compile time generic eval" {45test "compile time generic eval" {
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
48
40 try expect(the_max == 5678);49 try expect(the_max == 5678);
41}50}
4251
...@@ -53,12 +62,20 @@ fn sameButWithFloats(a: f64, b: f64) f64 {...@@ -53,12 +62,20 @@ fn sameButWithFloats(a: f64, b: f64) f64 {
53}62}
5463
55test "fn with comptime args" {64test "fn with comptime args" {
65 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
67 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68
56 try expect(gimmeTheBigOne(1234, 5678) == 5678);69 try expect(gimmeTheBigOne(1234, 5678) == 5678);
57 try expect(shouldCallSameInstance(34, 12) == 34);70 try expect(shouldCallSameInstance(34, 12) == 34);
58 try expect(sameButWithFloats(0.43, 0.49) == 0.49);71 try expect(sameButWithFloats(0.43, 0.49) == 0.49);
59}72}
6073
61test "anytype params" {74test "anytype params" {
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
78
62 try expect(max_i32(12, 34) == 34);79 try expect(max_i32(12, 34) == 34);
63 try expect(max_f64(1.2, 3.4) == 3.4);80 try expect(max_f64(1.2, 3.4) == 3.4);
64 comptime {81 comptime {
...@@ -80,6 +97,10 @@ fn max_f64(a: f64, b: f64) f64 {...@@ -80,6 +97,10 @@ fn max_f64(a: f64, b: f64) f64 {
80}97}
8198
82test "type constructed by comptime function call" {99test "type constructed by comptime function call" {
100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
102 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
103
83 var l: SimpleList(10) = undefined;104 var l: SimpleList(10) = undefined;
84 l.array[0] = 10;105 l.array[0] = 10;
85 l.array[1] = 11;106 l.array[1] = 11;
...@@ -99,6 +120,9 @@ fn SimpleList(comptime L: usize) type {...@@ -99,6 +120,9 @@ fn SimpleList(comptime L: usize) type {
99}120}
100121
101test "function with return type type" {122test "function with return type type" {
123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
124 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
125
102 var list: List(i32) = undefined;126 var list: List(i32) = undefined;
103 var list2: List(i32) = undefined;127 var list2: List(i32) = undefined;
104 list.length = 10;128 list.length = 10;
...@@ -120,6 +144,9 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {...@@ -120,6 +144,9 @@ pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) type {
120}144}
121145
122test "const decls in struct" {146test "const decls in struct" {
147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
149
123 try expect(GenericDataThing(3).count_plus_one == 4);150 try expect(GenericDataThing(3).count_plus_one == 4);
124}151}
125fn GenericDataThing(comptime count: isize) type {152fn GenericDataThing(comptime count: isize) type {
...@@ -129,6 +156,9 @@ fn GenericDataThing(comptime count: isize) type {...@@ -129,6 +156,9 @@ fn GenericDataThing(comptime count: isize) type {
129}156}
130157
131test "use generic param in generic param" {158test "use generic param in generic param" {
159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
161
132 try expect(aGenericFn(i32, 3, 4) == 7);162 try expect(aGenericFn(i32, 3, 4) == 7);
133}163}
134fn aGenericFn(comptime T: type, comptime a: T, b: T) T {164fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
...@@ -136,6 +166,9 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {...@@ -136,6 +166,9 @@ fn aGenericFn(comptime T: type, comptime a: T, b: T) T {
136}166}
137167
138test "generic fn with implicit cast" {168test "generic fn with implicit cast" {
169 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
171
139 try expect(getFirstByte(u8, &[_]u8{13}) == 13);172 try expect(getFirstByte(u8, &[_]u8{13}) == 13);
140 try expect(getFirstByte(u16, &[_]u16{173 try expect(getFirstByte(u16, &[_]u16{
141 0,174 0,
...@@ -150,6 +183,9 @@ fn getFirstByte(comptime T: type, mem: []const T) u8 {...@@ -150,6 +183,9 @@ fn getFirstByte(comptime T: type, mem: []const T) u8 {
150}183}
151184
152test "generic fn keeps non-generic parameter types" {185test "generic fn keeps non-generic parameter types" {
186 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
187 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
188
153 const A = 128;189 const A = 128;
154190
155 const S = struct {191 const S = struct {
...@@ -165,8 +201,10 @@ test "generic fn keeps non-generic parameter types" {...@@ -165,8 +201,10 @@ test "generic fn keeps non-generic parameter types" {
165}201}
166202
167test "array of generic fns" {203test "array of generic fns" {
204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
205 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
168 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;206 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
169 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;207
170 try expect(foos[0](true));208 try expect(foos[0](true));
171 try expect(!foos[1](true));209 try expect(!foos[1](true));
172}210}
...@@ -185,7 +223,8 @@ fn foo2(arg: anytype) bool {...@@ -185,7 +223,8 @@ fn foo2(arg: anytype) bool {
185223
186test "generic struct" {224test "generic struct" {
187 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;225 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
188 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;226 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
227 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
189 var a1 = GenNode(i32){228 var a1 = GenNode(i32){
190 .value = 13,229 .value = 13,
191 .next = null,230 .next = null,
test/behavior/if.zig+20
...@@ -4,6 +4,9 @@ const expect = std.testing.expect;...@@ -4,6 +4,9 @@ const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
55
6test "if statements" {6test "if statements" {
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9
7 shouldBeEqual(1, 1);10 shouldBeEqual(1, 1);
8 firstEqlThird(2, 1, 2);11 firstEqlThird(2, 1, 2);
9}12}
...@@ -27,6 +30,9 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {...@@ -27,6 +30,9 @@ fn firstEqlThird(a: i32, b: i32, c: i32) void {
27}30}
2831
29test "else if expression" {32test "else if expression" {
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
35
30 try expect(elseIfExpressionF(1) == 1);36 try expect(elseIfExpressionF(1) == 1);
31}37}
32fn elseIfExpressionF(c: u8) u8 {38fn elseIfExpressionF(c: u8) u8 {
...@@ -44,6 +50,10 @@ var global_with_val: anyerror!u32 = 0;...@@ -44,6 +50,10 @@ var global_with_val: anyerror!u32 = 0;
44var global_with_err: anyerror!u32 = error.SomeError;50var global_with_err: anyerror!u32 = error.SomeError;
4551
46test "unwrap mutable global var" {52test "unwrap mutable global var" {
53 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
56
47 if (global_with_val) |v| {57 if (global_with_val) |v| {
48 try expect(v == 0);58 try expect(v == 0);
49 } else |_| {59 } else |_| {
...@@ -57,6 +67,9 @@ test "unwrap mutable global var" {...@@ -57,6 +67,9 @@ test "unwrap mutable global var" {
57}67}
5868
59test "labeled break inside comptime if inside runtime if" {69test "labeled break inside comptime if inside runtime if" {
70 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
71 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
72
60 var answer: i32 = 0;73 var answer: i32 = 0;
61 var c = true;74 var c = true;
62 if (c) {75 if (c) {
...@@ -68,6 +81,9 @@ test "labeled break inside comptime if inside runtime if" {...@@ -68,6 +81,9 @@ test "labeled break inside comptime if inside runtime if" {
68}81}
6982
70test "const result loc, runtime if cond, else unreachable" {83test "const result loc, runtime if cond, else unreachable" {
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
86
71 const Num = enum { One, Two };87 const Num = enum { One, Two };
7288
73 var t = true;89 var t = true;
...@@ -76,6 +92,10 @@ test "const result loc, runtime if cond, else unreachable" {...@@ -76,6 +92,10 @@ test "const result loc, runtime if cond, else unreachable" {
76}92}
7793
78test "if copies its payload" {94test "if copies its payload" {
95 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
96 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
97 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
98
79 const S = struct {99 const S = struct {
80 fn doTheTest() !void {100 fn doTheTest() !void {
81 var tmp: ?i32 = 10;101 var tmp: ?i32 = 10;
test/behavior/incomplete_struct_param_tld.zig+3
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1const builtin = @import("builtin");
1const expect = @import("std").testing.expect;2const expect = @import("std").testing.expect;
23
3const A = struct {4const A = struct {
...@@ -21,6 +22,8 @@ fn foo(a: A) i32 {...@@ -21,6 +22,8 @@ fn foo(a: A) i32 {
21}22}
2223
23test "incomplete struct param top level declaration" {24test "incomplete struct param top level declaration" {
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24 const a = A{27 const a = A{
25 .b = B{28 .b = B{
26 .c = C{ .x = 13 },29 .c = C{ .x = 13 },
test/behavior/inttoptr.zig+6
...@@ -3,6 +3,8 @@ const builtin = @import("builtin");...@@ -3,6 +3,8 @@ const builtin = @import("builtin");
3test "casting integer address to function pointer" {3test "casting integer address to function pointer" {
4 if (builtin.zig_backend == .stage1) return error.SkipZigTest;4 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
5 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO5 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) return error.SkipZigTest; // TODO
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
68
7 addressToFunction();9 addressToFunction();
8 comptime addressToFunction();10 comptime addressToFunction();
...@@ -14,6 +16,10 @@ fn addressToFunction() void {...@@ -14,6 +16,10 @@ fn addressToFunction() void {
14}16}
1517
16test "mutate through ptr initialized with constant intToPtr value" {18test "mutate through ptr initialized with constant intToPtr value" {
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22
17 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);23 forceCompilerAnalyzeBranchHardCodedPtrDereference(false);
18}24}
1925
test/behavior/member_func.zig+6
...@@ -28,6 +28,9 @@ const HasFuncs = struct {...@@ -28,6 +28,9 @@ const HasFuncs = struct {
2828
29test "standard field calls" {29test "standard field calls" {
30 if (builtin.zig_backend == .stage1) return error.SkipZigTest;30 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3134
32 try expect(HasFuncs.one(0) == 1);35 try expect(HasFuncs.one(0) == 1);
33 try expect(HasFuncs.two(0) == 2);36 try expect(HasFuncs.two(0) == 2);
...@@ -69,6 +72,9 @@ test "standard field calls" {...@@ -69,6 +72,9 @@ test "standard field calls" {
6972
70test "@field field calls" {73test "@field field calls" {
71 if (builtin.zig_backend == .stage1) return error.SkipZigTest;74 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7278
73 try expect(@field(HasFuncs, "one")(0) == 1);79 try expect(@field(HasFuncs, "one")(0) == 1);
74 try expect(@field(HasFuncs, "two")(0) == 2);80 try expect(@field(HasFuncs, "two")(0) == 2);
test/behavior/null.zig+29
...@@ -29,6 +29,10 @@ test "optional type" {...@@ -29,6 +29,10 @@ test "optional type" {
29}29}
3030
31test "test maybe object and get a pointer to the inner value" {31test "test maybe object and get a pointer to the inner value" {
32 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
33 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
35
32 var maybe_bool: ?bool = true;36 var maybe_bool: ?bool = true;
3337
34 if (maybe_bool) |*b| {38 if (maybe_bool) |*b| {
...@@ -45,6 +49,10 @@ test "rhs maybe unwrap return" {...@@ -45,6 +49,10 @@ test "rhs maybe unwrap return" {
45}49}
4650
47test "maybe return" {51test "maybe return" {
52 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
55
48 try maybeReturnImpl();56 try maybeReturnImpl();
49 comptime try maybeReturnImpl();57 comptime try maybeReturnImpl();
50}58}
...@@ -61,6 +69,10 @@ fn foo(x: ?i32) ?bool {...@@ -61,6 +69,10 @@ fn foo(x: ?i32) ?bool {
61}69}
6270
63test "test null runtime" {71test "test null runtime" {
72 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
73 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
74 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
75
64 try testTestNullRuntime(null);76 try testTestNullRuntime(null);
65}77}
66fn testTestNullRuntime(x: ?i32) !void {78fn testTestNullRuntime(x: ?i32) !void {
...@@ -69,6 +81,9 @@ fn testTestNullRuntime(x: ?i32) !void {...@@ -69,6 +81,9 @@ fn testTestNullRuntime(x: ?i32) !void {
69}81}
7082
71test "optional void" {83test "optional void" {
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
85 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
86
72 try optionalVoidImpl();87 try optionalVoidImpl();
73 comptime try optionalVoidImpl();88 comptime try optionalVoidImpl();
74}89}
...@@ -89,6 +104,9 @@ fn bar(x: ?void) ?void {...@@ -89,6 +104,9 @@ fn bar(x: ?void) ?void {
89const Empty = struct {};104const Empty = struct {};
90105
91test "optional struct{}" {106test "optional struct{}" {
107 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109
92 _ = try optionalEmptyStructImpl();110 _ = try optionalEmptyStructImpl();
93 _ = comptime try optionalEmptyStructImpl();111 _ = comptime try optionalEmptyStructImpl();
94}112}
...@@ -107,17 +125,25 @@ fn baz(x: ?Empty) ?Empty {...@@ -107,17 +125,25 @@ fn baz(x: ?Empty) ?Empty {
107}125}
108126
109test "null with default unwrap" {127test "null with default unwrap" {
128 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
129
110 const x: i32 = null orelse 1;130 const x: i32 = null orelse 1;
111 try expect(x == 1);131 try expect(x == 1);
112}132}
113133
114test "optional pointer to 0 bit type null value at runtime" {134test "optional pointer to 0 bit type null value at runtime" {
135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
136
115 const EmptyStruct = struct {};137 const EmptyStruct = struct {};
116 var x: ?*EmptyStruct = null;138 var x: ?*EmptyStruct = null;
117 try expect(x == null);139 try expect(x == null);
118}140}
119141
120test "if var maybe pointer" {142test "if var maybe pointer" {
143 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
144 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
146
121 try expect(shouldBeAPlus1(Particle{147 try expect(shouldBeAPlus1(Particle{
122 .a = 14,148 .a = 14,
123 .b = 1,149 .b = 1,
...@@ -159,6 +185,9 @@ const here_is_a_null_literal = SillyStruct{ .context = null };...@@ -159,6 +185,9 @@ const here_is_a_null_literal = SillyStruct{ .context = null };
159test "unwrap optional which is field of global var" {185test "unwrap optional which is field of global var" {
160 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO186 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO187 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
188 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
190 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
162191
163 struct_with_optional.field = null;192 struct_with_optional.field = null;
164 if (struct_with_optional.field) |payload| {193 if (struct_with_optional.field) |payload| {
test/behavior/pointers.zig+19
...@@ -17,6 +17,10 @@ fn testDerefPtr() !void {...@@ -17,6 +17,10 @@ fn testDerefPtr() !void {
17}17}
1818
19test "pointer arithmetic" {19test "pointer arithmetic" {
20 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
23
20 var ptr: [*]const u8 = "abcd";24 var ptr: [*]const u8 = "abcd";
2125
22 try expect(ptr[0] == 'a');26 try expect(ptr[0] == 'a');
...@@ -61,6 +65,10 @@ test "initialize const optional C pointer to null" {...@@ -61,6 +65,10 @@ test "initialize const optional C pointer to null" {
61}65}
6266
63test "assigning integer to C pointer" {67test "assigning integer to C pointer" {
68 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
70 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
71
64 var x: i32 = 0;72 var x: i32 = 0;
65 var y: i32 = 1;73 var y: i32 = 1;
66 var ptr: [*c]u8 = 0;74 var ptr: [*c]u8 = 0;
...@@ -75,6 +83,10 @@ test "assigning integer to C pointer" {...@@ -75,6 +83,10 @@ test "assigning integer to C pointer" {
75}83}
7684
77test "C pointer comparison and arithmetic" {85test "C pointer comparison and arithmetic" {
86 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
89
78 const S = struct {90 const S = struct {
79 fn doTheTest() !void {91 fn doTheTest() !void {
80 var ptr1: [*c]u32 = 0;92 var ptr1: [*c]u32 = 0;
...@@ -133,6 +145,10 @@ test "peer type resolution with C pointers" {...@@ -133,6 +145,10 @@ test "peer type resolution with C pointers" {
133}145}
134146
135test "implicit casting between C pointer and optional non-C pointer" {147test "implicit casting between C pointer and optional non-C pointer" {
148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
151
136 var slice: []const u8 = "aoeu";152 var slice: []const u8 = "aoeu";
137 const opt_many_ptr: ?[*]const u8 = slice.ptr;153 const opt_many_ptr: ?[*]const u8 = slice.ptr;
138 var ptr_opt_many_ptr = &opt_many_ptr;154 var ptr_opt_many_ptr = &opt_many_ptr;
...@@ -172,6 +188,9 @@ test "compare equality of optional and non-optional pointer" {...@@ -172,6 +188,9 @@ test "compare equality of optional and non-optional pointer" {
172test "allowzero pointer and slice" {188test "allowzero pointer and slice" {
173 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO189 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
174 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO190 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
191 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
193 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
175194
176 var ptr = @intToPtr([*]allowzero i32, 0);195 var ptr = @intToPtr([*]allowzero i32, 0);
177 var opt_ptr: ?[*]allowzero i32 = ptr;196 var opt_ptr: ?[*]allowzero i32 = ptr;
test/behavior/ref_var_in_if_after_if_2nd_switch_prong.zig+5
...@@ -1,9 +1,14 @@...@@ -1,9 +1,14 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
3const mem = std.mem;4const mem = std.mem;
45
5var ok: bool = false;6var ok: bool = false;
6test "reference a variable in an if after an if in the 2nd switch prong" {7test "reference a variable in an if after an if in the 2nd switch prong" {
8 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11
7 try foo(true, Num.Two, false, "aoeu");12 try foo(true, Num.Two, false, "aoeu");
8 try expect(!ok);13 try expect(!ok);
9 try foo(false, Num.One, false, "aoeu");14 try foo(false, Num.One, false, "aoeu");
test/behavior/slice.zig-1
...@@ -248,7 +248,6 @@ test "result location zero sized array inside struct field implicit cast to slic...@@ -248,7 +248,6 @@ test "result location zero sized array inside struct field implicit cast to slic
248test "runtime safety lets us slice from len..len" {248test "runtime safety lets us slice from len..len" {
249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
252251
253 var an_array = [_]u8{ 1, 2, 3 };252 var an_array = [_]u8{ 1, 2, 3 };
254 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));253 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
test/behavior/src.zig+5-1
...@@ -1,8 +1,12 @@...@@ -1,8 +1,12 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4test "@src" {5test "@src" {
5 try doTheTest();6 // TODO why is this failing on stage1?
7 return error.SkipZigTest;
8
9 // try doTheTest();
6}10}
711
8fn doTheTest() !void {12fn doTheTest() !void {
test/behavior/struct.zig+4-8
...@@ -86,7 +86,8 @@ const StructFoo = struct {...@@ -86,7 +86,8 @@ const StructFoo = struct {
8686
87test "structs" {87test "structs" {
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
89 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;89 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
90 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9091
91 var foo: StructFoo = undefined;92 var foo: StructFoo = undefined;
92 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));93 @memset(@ptrCast([*]u8, &foo), 0, @sizeOf(StructFoo));
...@@ -248,7 +249,8 @@ test "usingnamespace within struct scope" {...@@ -248,7 +249,8 @@ test "usingnamespace within struct scope" {
248249
249test "struct field init with catch" {250test "struct field init with catch" {
250 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;252 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
253 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
252254
253 const S = struct {255 const S = struct {
254 fn doTheTest() !void {256 fn doTheTest() !void {
...@@ -310,7 +312,6 @@ test "struct point to self" {...@@ -310,7 +312,6 @@ test "struct point to self" {
310 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO312 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
311 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO313 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
312 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
313 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
314315
315 var root: Node = undefined;316 var root: Node = undefined;
316 root.val.x = 1;317 root.val.x = 1;
...@@ -350,7 +351,6 @@ test "return empty struct from fn" {...@@ -350,7 +351,6 @@ test "return empty struct from fn" {
350 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO351 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
351 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO352 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
353 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
354354
355 _ = testReturnEmptyStructFromFn();355 _ = testReturnEmptyStructFromFn();
356}356}
...@@ -364,7 +364,6 @@ test "pass slice of empty struct to fn" {...@@ -364,7 +364,6 @@ test "pass slice of empty struct to fn" {
364 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO364 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO366 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
367 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
368367
369 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);368 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
370}369}
...@@ -409,7 +408,6 @@ test "align 1 field before self referential align 8 field as slice return type"...@@ -409,7 +408,6 @@ test "align 1 field before self referential align 8 field as slice return type"
409 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO408 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
410 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO409 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
411 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO410 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
412 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
413411
414 const result = alloc(Expr);412 const result = alloc(Expr);
415 try expect(result.len == 0);413 try expect(result.len == 0);
...@@ -670,7 +668,6 @@ test "default struct initialization fields" {...@@ -670,7 +668,6 @@ test "default struct initialization fields" {
670 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO668 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
671 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO669 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
672 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO670 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
673 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
674671
675 const S = struct {672 const S = struct {
676 a: i32 = 1234,673 a: i32 = 1234,
...@@ -936,7 +933,6 @@ test "anonymous struct literal syntax" {...@@ -936,7 +933,6 @@ test "anonymous struct literal syntax" {
936 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO933 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
937 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO934 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
938 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO935 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
939 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
940936
941 const S = struct {937 const S = struct {
942 const Point = struct {938 const Point = struct {
test/behavior/this.zig+7
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const expect = @import("std").testing.expect;1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
23
3const module = @This();4const module = @This();
45
...@@ -20,10 +21,16 @@ fn add(x: i32, y: i32) i32 {...@@ -20,10 +21,16 @@ fn add(x: i32, y: i32) i32 {
20}21}
2122
22test "this refer to module call private fn" {23test "this refer to module call private fn" {
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
26
23 try expect(module.add(1, 2) == 3);27 try expect(module.add(1, 2) == 3);
24}28}
2529
26test "this refer to container" {30test "this refer to container" {
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
33
27 var pt: Point(i32) = undefined;34 var pt: Point(i32) = undefined;
28 pt.x = 12;35 pt.x = 12;
29 pt.y = 34;36 pt.y = 34;
test/behavior/try.zig+13-1
...@@ -1,6 +1,12 @@...@@ -1,6 +1,12 @@
1const expect = @import("std").testing.expect;1const std = @import("std");
2const builtin = @import("builtin");
3const expect = std.testing.expect;
24
3test "try on error union" {5test "try on error union" {
6 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9
4 try tryOnErrorUnionImpl();10 try tryOnErrorUnionImpl();
5 comptime try tryOnErrorUnionImpl();11 comptime try tryOnErrorUnionImpl();
6}12}
...@@ -19,6 +25,9 @@ fn returnsTen() anyerror!i32 {...@@ -19,6 +25,9 @@ fn returnsTen() anyerror!i32 {
19}25}
2026
21test "try without vars" {27test "try without vars" {
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
30
22 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);31 const result1 = if (failIfTrue(true)) 1 else |_| @as(i32, 2);
23 try expect(result1 == 2);32 try expect(result1 == 2);
2433
...@@ -35,6 +44,9 @@ fn failIfTrue(ok: bool) anyerror!void {...@@ -35,6 +44,9 @@ fn failIfTrue(ok: bool) anyerror!void {
35}44}
3645
37test "try then not executed with assignment" {46test "try then not executed with assignment" {
47 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
48 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
49
38 if (failIfTrue(true)) {50 if (failIfTrue(true)) {
39 unreachable;51 unreachable;
40 } else |err| {52 } else |err| {
test/behavior/type_info.zig+11
...@@ -186,6 +186,10 @@ fn testErrorSet() !void {...@@ -186,6 +186,10 @@ fn testErrorSet() !void {
186}186}
187187
188test "type info: enum info" {188test "type info: enum info" {
189 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
190 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
192
189 try testEnum();193 try testEnum();
190 comptime try testEnum();194 comptime try testEnum();
191}195}
...@@ -249,6 +253,9 @@ fn testUnion() !void {...@@ -249,6 +253,9 @@ fn testUnion() !void {
249}253}
250254
251test "type info: struct info" {255test "type info: struct info" {
256 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
258
252 try testStruct();259 try testStruct();
253 comptime try testStruct();260 comptime try testStruct();
254}261}
...@@ -439,6 +446,10 @@ test "type info for async frames" {...@@ -439,6 +446,10 @@ test "type info for async frames" {
439}446}
440447
441test "Declarations are returned in declaration order" {448test "Declarations are returned in declaration order" {
449 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
450 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
451 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
452
442 const S = struct {453 const S = struct {
443 const a = 1;454 const a = 1;
444 const b = 2;455 const b = 2;
test/behavior/undefined.zig+11
...@@ -16,6 +16,8 @@ test "init static array to undefined" {...@@ -16,6 +16,8 @@ test "init static array to undefined" {
16 // This test causes `initStaticArray()` to be codegen'd, and the16 // This test causes `initStaticArray()` to be codegen'd, and the
17 // C backend does not yet support returning arrays, so it fails17 // C backend does not yet support returning arrays, so it fails
18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1921
20 try expect(static_array[0] == 1);22 try expect(static_array[0] == 1);
21 try expect(static_array[4] == 2);23 try expect(static_array[4] == 2);
...@@ -43,6 +45,9 @@ fn setFooX(foo: *Foo) void {...@@ -43,6 +45,9 @@ fn setFooX(foo: *Foo) void {
43}45}
4446
45test "assign undefined to struct" {47test "assign undefined to struct" {
48 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
50
46 comptime {51 comptime {
47 var foo: Foo = undefined;52 var foo: Foo = undefined;
48 setFooX(&foo);53 setFooX(&foo);
...@@ -56,6 +61,9 @@ test "assign undefined to struct" {...@@ -56,6 +61,9 @@ test "assign undefined to struct" {
56}61}
5762
58test "assign undefined to struct with method" {63test "assign undefined to struct with method" {
64 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
66
59 comptime {67 comptime {
60 var foo: Foo = undefined;68 var foo: Foo = undefined;
61 foo.setFooXMethod();69 foo.setFooXMethod();
...@@ -69,6 +77,9 @@ test "assign undefined to struct with method" {...@@ -69,6 +77,9 @@ test "assign undefined to struct with method" {
69}77}
7078
71test "type name of undefined" {79test "type name of undefined" {
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
81 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
82
72 const x = undefined;83 const x = undefined;
73 try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@Type(.Undefined)"));84 try expect(mem.eql(u8, @typeName(@TypeOf(x)), "@Type(.Undefined)"));
74}85}
test/behavior/underscore.zig+5
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4test "ignore lval with underscore" {5test "ignore lval with underscore" {
...@@ -6,6 +7,10 @@ test "ignore lval with underscore" {...@@ -6,6 +7,10 @@ test "ignore lval with underscore" {
6}7}
78
8test "ignore lval with underscore (while loop)" {9test "ignore lval with underscore (while loop)" {
10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
12 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
13
9 while (optionalReturnError()) |_| {14 while (optionalReturnError()) |_| {
10 while (optionalReturnError()) |_| {15 while (optionalReturnError()) |_| {
11 break;16 break;
test/behavior/union.zig+140
...@@ -10,6 +10,10 @@ const Foo = union {...@@ -10,6 +10,10 @@ const Foo = union {
10};10};
1111
12test "basic unions" {12test "basic unions" {
13 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16
13 var foo = Foo{ .int = 1 };17 var foo = Foo{ .int = 1 };
14 try expect(foo.int == 1);18 try expect(foo.int == 1);
15 foo = Foo{ .float = 12.34 };19 foo = Foo{ .float = 12.34 };
...@@ -17,6 +21,10 @@ test "basic unions" {...@@ -17,6 +21,10 @@ test "basic unions" {
17}21}
1822
19test "init union with runtime value" {23test "init union with runtime value" {
24 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
26 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
27
20 var foo: Foo = undefined;28 var foo: Foo = undefined;
2129
22 setFloat(&foo, 12.34);30 setFloat(&foo, 12.34);
...@@ -35,6 +43,9 @@ fn setInt(foo: *Foo, x: i32) void {...@@ -35,6 +43,9 @@ fn setInt(foo: *Foo, x: i32) void {
35}43}
3644
37test "comptime union field access" {45test "comptime union field access" {
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
48
38 comptime {49 comptime {
39 var foo = Foo{ .int = 0 };50 var foo = Foo{ .int = 0 };
40 try expect(foo.int == 0);51 try expect(foo.int == 0);
...@@ -50,6 +61,10 @@ const FooExtern = extern union {...@@ -50,6 +61,10 @@ const FooExtern = extern union {
50};61};
5162
52test "basic extern unions" {63test "basic extern unions" {
64 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
65 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
67
53 var foo = FooExtern{ .int = 1 };68 var foo = FooExtern{ .int = 1 };
54 try expect(foo.int == 1);69 try expect(foo.int == 1);
55 foo.float = 12.34;70 foo.float = 12.34;
...@@ -61,10 +76,16 @@ const ExternPtrOrInt = extern union {...@@ -61,10 +76,16 @@ const ExternPtrOrInt = extern union {
61 int: u64,76 int: u64,
62};77};
63test "extern union size" {78test "extern union size" {
79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
80 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
81
64 comptime try expect(@sizeOf(ExternPtrOrInt) == 8);82 comptime try expect(@sizeOf(ExternPtrOrInt) == 8);
65}83}
6684
67test "0-sized extern union definition" {85test "0-sized extern union definition" {
86 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
87 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
88
68 const U = extern union {89 const U = extern union {
69 a: void,90 a: void,
70 const f = 1;91 const f = 1;
...@@ -94,6 +115,10 @@ const err = @as(anyerror!Agg, Agg{...@@ -94,6 +115,10 @@ const err = @as(anyerror!Agg, Agg{
94const array = [_]Value{ v1, v2, v1, v2 };115const array = [_]Value{ v1, v2, v1, v2 };
95116
96test "unions embedded in aggregate types" {117test "unions embedded in aggregate types" {
118 if (builtin.zig_backend == .stage2_x86_64 and builtin.os.tag == .macos) return error.SkipZigTest;
119 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
120 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
121
97 switch (array[1]) {122 switch (array[1]) {
98 Value.Array => |arr| try expect(arr[4] == 3),123 Value.Array => |arr| try expect(arr[4] == 3),
99 else => unreachable,124 else => unreachable,
...@@ -105,6 +130,9 @@ test "unions embedded in aggregate types" {...@@ -105,6 +130,9 @@ test "unions embedded in aggregate types" {
105}130}
106131
107test "access a member of tagged union with conflicting enum tag name" {132test "access a member of tagged union with conflicting enum tag name" {
133 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
134 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
135
108 const Bar = union(enum) {136 const Bar = union(enum) {
109 A: A,137 A: A,
110 B: B,138 B: B,
...@@ -117,6 +145,10 @@ test "access a member of tagged union with conflicting enum tag name" {...@@ -117,6 +145,10 @@ test "access a member of tagged union with conflicting enum tag name" {
117}145}
118146
119test "constant tagged union with payload" {147test "constant tagged union with payload" {
148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
151
120 var empty = TaggedUnionWithPayload{ .Empty = {} };152 var empty = TaggedUnionWithPayload{ .Empty = {} };
121 var full = TaggedUnionWithPayload{ .Full = 13 };153 var full = TaggedUnionWithPayload{ .Full = 13 };
122 shouldBeEmpty(empty);154 shouldBeEmpty(empty);
...@@ -143,6 +175,9 @@ const TaggedUnionWithPayload = union(enum) {...@@ -143,6 +175,9 @@ const TaggedUnionWithPayload = union(enum) {
143};175};
144176
145test "union alignment" {177test "union alignment" {
178 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
180
146 comptime {181 comptime {
147 try expect(@alignOf(AlignTestTaggedUnion) >= @alignOf([9]u8));182 try expect(@alignOf(AlignTestTaggedUnion) >= @alignOf([9]u8));
148 try expect(@alignOf(AlignTestTaggedUnion) >= @alignOf(u64));183 try expect(@alignOf(AlignTestTaggedUnion) >= @alignOf(u64));
...@@ -162,11 +197,18 @@ const Payload = union(Letter) {...@@ -162,11 +197,18 @@ const Payload = union(Letter) {
162};197};
163198
164test "union with specified enum tag" {199test "union with specified enum tag" {
200 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
202 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
203
165 try doTest();204 try doTest();
166 comptime try doTest();205 comptime try doTest();
167}206}
168207
169test "packed union generates correctly aligned LLVM type" {208test "packed union generates correctly aligned LLVM type" {
209 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
170 if (builtin.zig_backend == .stage1) return error.SkipZigTest;212 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
171213
172 const U = packed union {214 const U = packed union {
...@@ -204,6 +246,10 @@ fn testComparison() !void {...@@ -204,6 +246,10 @@ fn testComparison() !void {
204}246}
205247
206test "comparison between union and enum literal" {248test "comparison between union and enum literal" {
249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
252
207 try testComparison();253 try testComparison();
208 comptime try testComparison();254 comptime try testComparison();
209}255}
...@@ -215,6 +261,10 @@ const TheUnion = union(TheTag) {...@@ -215,6 +261,10 @@ const TheUnion = union(TheTag) {
215 C: i32,261 C: i32,
216};262};
217test "cast union to tag type of union" {263test "cast union to tag type of union" {
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267
218 try testCastUnionToTag();268 try testCastUnionToTag();
219 comptime try testCastUnionToTag();269 comptime try testCastUnionToTag();
220}270}
...@@ -225,12 +275,19 @@ fn testCastUnionToTag() !void {...@@ -225,12 +275,19 @@ fn testCastUnionToTag() !void {
225}275}
226276
227test "union field access gives the enum values" {277test "union field access gives the enum values" {
278 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
279 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
280
228 try expect(TheUnion.A == TheTag.A);281 try expect(TheUnion.A == TheTag.A);
229 try expect(TheUnion.B == TheTag.B);282 try expect(TheUnion.B == TheTag.B);
230 try expect(TheUnion.C == TheTag.C);283 try expect(TheUnion.C == TheTag.C);
231}284}
232285
233test "cast tag type of union to union" {286test "cast tag type of union to union" {
287 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
288 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
289 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
290
234 var x: Value2 = Letter2.B;291 var x: Value2 = Letter2.B;
235 try expect(@as(Letter2, x) == Letter2.B);292 try expect(@as(Letter2, x) == Letter2.B);
236}293}
...@@ -242,6 +299,10 @@ const Value2 = union(Letter2) {...@@ -242,6 +299,10 @@ const Value2 = union(Letter2) {
242};299};
243300
244test "implicit cast union to its tag type" {301test "implicit cast union to its tag type" {
302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
305
245 var x: Value2 = Letter2.B;306 var x: Value2 = Letter2.B;
246 try expect(x == Letter2.B);307 try expect(x == Letter2.B);
247 try giveMeLetterB(x);308 try giveMeLetterB(x);
...@@ -258,6 +319,10 @@ pub const PackThis = union(enum) {...@@ -258,6 +319,10 @@ pub const PackThis = union(enum) {
258};319};
259320
260test "constant packed union" {321test "constant packed union" {
322 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
324 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
325
261 try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }});326 try testConstPackedUnion(&[_]PackThis{PackThis{ .StringLiteral = 1 }});
262}327}
263328
...@@ -272,6 +337,10 @@ const MultipleChoice = union(enum(u32)) {...@@ -272,6 +337,10 @@ const MultipleChoice = union(enum(u32)) {
272 D = 1000,337 D = 1000,
273};338};
274test "simple union(enum(u32))" {339test "simple union(enum(u32))" {
340 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
341 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
342 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
343
275 var x = MultipleChoice.C;344 var x = MultipleChoice.C;
276 try expect(x == MultipleChoice.C);345 try expect(x == MultipleChoice.C);
277 try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60);346 try expect(@enumToInt(@as(Tag(MultipleChoice), x)) == 60);
...@@ -282,6 +351,9 @@ const PackedPtrOrInt = packed union {...@@ -282,6 +351,9 @@ const PackedPtrOrInt = packed union {
282 int: u64,351 int: u64,
283};352};
284test "packed union size" {353test "packed union size" {
354 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
355 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
356
285 comptime try expect(@sizeOf(PackedPtrOrInt) == 8);357 comptime try expect(@sizeOf(PackedPtrOrInt) == 8);
286}358}
287359
...@@ -289,10 +361,17 @@ const ZeroBits = union {...@@ -289,10 +361,17 @@ const ZeroBits = union {
289 OnlyField: void,361 OnlyField: void,
290};362};
291test "union with only 1 field which is void should be zero bits" {363test "union with only 1 field which is void should be zero bits" {
364 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
365 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
366
292 comptime try expect(@sizeOf(ZeroBits) == 0);367 comptime try expect(@sizeOf(ZeroBits) == 0);
293}368}
294369
295test "tagged union initialization with runtime void" {370test "tagged union initialization with runtime void" {
371 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
374
296 try expect(testTaggedUnionInit({}));375 try expect(testTaggedUnionInit({}));
297}376}
298377
...@@ -309,6 +388,10 @@ fn testTaggedUnionInit(x: anytype) bool {...@@ -309,6 +388,10 @@ fn testTaggedUnionInit(x: anytype) bool {
309pub const UnionEnumNoPayloads = union(enum) { A, B };388pub const UnionEnumNoPayloads = union(enum) { A, B };
310389
311test "tagged union with no payloads" {390test "tagged union with no payloads" {
391 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
394
312 const a = UnionEnumNoPayloads{ .B = {} };395 const a = UnionEnumNoPayloads{ .B = {} };
313 switch (a) {396 switch (a) {
314 Tag(UnionEnumNoPayloads).A => @panic("wrong"),397 Tag(UnionEnumNoPayloads).A => @panic("wrong"),
...@@ -317,6 +400,10 @@ test "tagged union with no payloads" {...@@ -317,6 +400,10 @@ test "tagged union with no payloads" {
317}400}
318401
319test "union with only 1 field casted to its enum type" {402test "union with only 1 field casted to its enum type" {
403 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
404 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
405 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
406
320 const Literal = union(enum) {407 const Literal = union(enum) {
321 Number: f64,408 Number: f64,
322 Bool: bool,409 Bool: bool,
...@@ -334,6 +421,9 @@ test "union with only 1 field casted to its enum type" {...@@ -334,6 +421,9 @@ test "union with only 1 field casted to its enum type" {
334}421}
335422
336test "union with one member defaults to u0 tag type" {423test "union with one member defaults to u0 tag type" {
424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
426
337 const U0 = union(enum) {427 const U0 = union(enum) {
338 X: u32,428 X: u32,
339 };429 };
...@@ -348,6 +438,10 @@ const Foo1 = union(enum) {...@@ -348,6 +438,10 @@ const Foo1 = union(enum) {
348var glbl: Foo1 = undefined;438var glbl: Foo1 = undefined;
349439
350test "global union with single field is correctly initialized" {440test "global union with single field is correctly initialized" {
441 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
444
351 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO445 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
352 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO446 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
353447
...@@ -365,6 +459,10 @@ pub const FooUnion = union(enum) {...@@ -365,6 +459,10 @@ pub const FooUnion = union(enum) {
365var glbl_array: [2]FooUnion = undefined;459var glbl_array: [2]FooUnion = undefined;
366460
367test "initialize global array of union" {461test "initialize global array of union" {
462 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
465
368 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;466 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
369 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;467 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
370468
...@@ -375,6 +473,10 @@ test "initialize global array of union" {...@@ -375,6 +473,10 @@ test "initialize global array of union" {
375}473}
376474
377test "update the tag value for zero-sized unions" {475test "update the tag value for zero-sized unions" {
476 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
477 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
479
378 const S = union(enum) {480 const S = union(enum) {
379 U0: void,481 U0: void,
380 U1: void,482 U1: void,
...@@ -386,6 +488,10 @@ test "update the tag value for zero-sized unions" {...@@ -386,6 +488,10 @@ test "update the tag value for zero-sized unions" {
386}488}
387489
388test "union initializer generates padding only if needed" {490test "union initializer generates padding only if needed" {
491 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
492 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
493 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
494
389 const U = union(enum) {495 const U = union(enum) {
390 A: u24,496 A: u24,
391 };497 };
...@@ -395,6 +501,10 @@ test "union initializer generates padding only if needed" {...@@ -395,6 +501,10 @@ test "union initializer generates padding only if needed" {
395}501}
396502
397test "runtime tag name with single field" {503test "runtime tag name with single field" {
504 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
505 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
507
398 const U = union(enum) {508 const U = union(enum) {
399 A: i32,509 A: i32,
400 };510 };
...@@ -404,6 +514,10 @@ test "runtime tag name with single field" {...@@ -404,6 +514,10 @@ test "runtime tag name with single field" {
404}514}
405515
406test "method call on an empty union" {516test "method call on an empty union" {
517 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
518 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
519 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
520
407 const S = struct {521 const S = struct {
408 const MyUnion = union(MyUnionTag) {522 const MyUnion = union(MyUnionTag) {
409 pub const MyUnionTag = enum { X1, X2 };523 pub const MyUnionTag = enum { X1, X2 };
...@@ -441,6 +555,10 @@ const FooNoVoid = union(enum) {...@@ -441,6 +555,10 @@ const FooNoVoid = union(enum) {
441const Baz = enum { A, B, C, D };555const Baz = enum { A, B, C, D };
442556
443test "tagged union type" {557test "tagged union type" {
558 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
559 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
560 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
561
444 const foo1 = TaggedFoo{ .One = 13 };562 const foo1 = TaggedFoo{ .One = 13 };
445 const foo2 = TaggedFoo{563 const foo2 = TaggedFoo{
446 .Two = Point{564 .Two = Point{
...@@ -460,6 +578,10 @@ test "tagged union type" {...@@ -460,6 +578,10 @@ test "tagged union type" {
460}578}
461579
462test "tagged union as return value" {580test "tagged union as return value" {
581 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
582 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
583 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
584
463 switch (returnAnInt(13)) {585 switch (returnAnInt(13)) {
464 TaggedFoo.One => |value| try expect(value == 13),586 TaggedFoo.One => |value| try expect(value == 13),
465 else => unreachable,587 else => unreachable,
...@@ -471,6 +593,10 @@ fn returnAnInt(x: i32) TaggedFoo {...@@ -471,6 +593,10 @@ fn returnAnInt(x: i32) TaggedFoo {
471}593}
472594
473test "tagged union with all void fields but a meaningful tag" {595test "tagged union with all void fields but a meaningful tag" {
596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
597 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
599
474 const S = struct {600 const S = struct {
475 const B = union(enum) {601 const B = union(enum) {
476 c: C,602 c: C,
...@@ -496,6 +622,9 @@ test "tagged union with all void fields but a meaningful tag" {...@@ -496,6 +622,9 @@ test "tagged union with all void fields but a meaningful tag" {
496622
497test "union(enum(u32)) with specified and unspecified tag values" {623test "union(enum(u32)) with specified and unspecified tag values" {
498 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO624 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
625 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
626 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
627 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
499628
500 comptime try expect(Tag(Tag(MultipleChoice2)) == u32);629 comptime try expect(Tag(Tag(MultipleChoice2)) == u32);
501 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });630 try testEnumWithSpecifiedAndUnspecifiedTagValues(MultipleChoice2{ .C = 123 });
...@@ -558,6 +687,10 @@ const PartialInstWithPayload = union(enum) {...@@ -558,6 +687,10 @@ const PartialInstWithPayload = union(enum) {
558};687};
559688
560test "union with only 1 field casted to its enum type which has enum value specified" {689test "union with only 1 field casted to its enum type which has enum value specified" {
690 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
691 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
692 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
693
561 const Literal = union(enum) {694 const Literal = union(enum) {
562 Number: f64,695 Number: f64,
563 Bool: bool,696 Bool: bool,
...@@ -638,6 +771,10 @@ fn Setter(attr: Attribute) type {...@@ -638,6 +771,10 @@ fn Setter(attr: Attribute) type {
638}771}
639772
640test "return union init with void payload" {773test "return union init with void payload" {
774 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
775 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
776 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
777
641 const S = struct {778 const S = struct {
642 fn entry() !void {779 fn entry() !void {
643 try expect(func().state == State.one);780 try expect(func().state == State.one);
...@@ -948,6 +1085,9 @@ test "union enum type gets a separate scope" {...@@ -948,6 +1085,9 @@ test "union enum type gets a separate scope" {
948test "global variable struct contains union initialized to non-most-aligned field" {1085test "global variable struct contains union initialized to non-most-aligned field" {
949 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1086 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
950 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1087 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1088 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1090 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9511091
952 const T = struct {1092 const T = struct {
953 const U = union(enum) {1093 const U = union(enum) {
test/behavior/usingnamespace.zig+19
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4const A = struct {5const A = struct {
...@@ -10,6 +11,9 @@ const C = struct {...@@ -10,6 +11,9 @@ const C = struct {
10};11};
1112
12test "basic usingnamespace" {13test "basic usingnamespace" {
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
16
13 try std.testing.expect(C.B == bool);17 try std.testing.expect(C.B == bool);
14}18}
1519
...@@ -20,6 +24,9 @@ fn Foo(comptime T: type) type {...@@ -20,6 +24,9 @@ fn Foo(comptime T: type) type {
20}24}
2125
22test "usingnamespace inside a generic struct" {26test "usingnamespace inside a generic struct" {
27 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
28 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
29
23 const std2 = Foo(std);30 const std2 = Foo(std);
24 const testing2 = Foo(std.testing);31 const testing2 = Foo(std.testing);
25 try std2.testing.expect(true);32 try std2.testing.expect(true);
...@@ -31,11 +38,17 @@ usingnamespace struct {...@@ -31,11 +38,17 @@ usingnamespace struct {
31};38};
3239
33test "usingnamespace does not redeclare an imported variable" {40test "usingnamespace does not redeclare an imported variable" {
41 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
42 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
43
34 comptime try std.testing.expect(@This().foo == 42);44 comptime try std.testing.expect(@This().foo == 42);
35}45}
3646
37usingnamespace @import("usingnamespace/foo.zig");47usingnamespace @import("usingnamespace/foo.zig");
38test "usingnamespace omits mixing in private functions" {48test "usingnamespace omits mixing in private functions" {
49 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51
39 try expect(@This().privateFunction());52 try expect(@This().privateFunction());
40 try expect(!@This().printText());53 try expect(!@This().printText());
41}54}
...@@ -44,10 +57,16 @@ fn privateFunction() bool {...@@ -44,10 +57,16 @@ fn privateFunction() bool {
44}57}
4558
46test {59test {
60 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
61 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
62
47 _ = @import("usingnamespace/import_segregation.zig");63 _ = @import("usingnamespace/import_segregation.zig");
48}64}
4965
50usingnamespace @import("usingnamespace/a.zig");66usingnamespace @import("usingnamespace/a.zig");
51test "two files usingnamespace import each other" {67test "two files usingnamespace import each other" {
68 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
69 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
70
52 try expect(@This().ok());71 try expect(@This().ok());
53}72}
test/behavior/void.zig+11
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const expect = @import("std").testing.expect;1const expect = @import("std").testing.expect;
2const builtin = @import("builtin");
23
3const Foo = struct {4const Foo = struct {
4 a: void,5 a: void,
...@@ -18,6 +19,9 @@ test "compare void with void compile time known" {...@@ -18,6 +19,9 @@ test "compare void with void compile time known" {
18}19}
1920
20test "iterate over a void slice" {21test "iterate over a void slice" {
22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
23 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
24
21 var j: usize = 0;25 var j: usize = 0;
22 for (times(10)) |_, i| {26 for (times(10)) |_, i| {
23 try expect(i == j);27 try expect(i == j);
...@@ -30,11 +34,18 @@ fn times(n: usize) []const void {...@@ -30,11 +34,18 @@ fn times(n: usize) []const void {
30}34}
3135
32test "void optional" {36test "void optional" {
37 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
40
33 var x: ?void = {};41 var x: ?void = {};
34 try expect(x != null);42 try expect(x != null);
35}43}
3644
37test "void array as a local variable initializer" {45test "void array as a local variable initializer" {
46 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
47 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
48
38 var x = [_]void{{}} ** 1004;49 var x = [_]void{{}} ** 1004;
39 _ = x[0];50 _ = x[0];
40}51}
test/behavior/while.zig+49
...@@ -1,7 +1,11 @@...@@ -1,7 +1,11 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4test "while loop" {5test "while loop" {
6 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8
5 var i: i32 = 0;9 var i: i32 = 0;
6 while (i < 4) {10 while (i < 4) {
7 i += 1;11 i += 1;
...@@ -19,6 +23,9 @@ fn whileLoop2() i32 {...@@ -19,6 +23,9 @@ fn whileLoop2() i32 {
19}23}
2024
21test "static eval while" {25test "static eval while" {
26 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28
22 try expect(static_eval_while_number == 1);29 try expect(static_eval_while_number == 1);
23}30}
24const static_eval_while_number = staticWhileLoop1();31const static_eval_while_number = staticWhileLoop1();
...@@ -98,6 +105,10 @@ fn testBreakOuter() void {...@@ -98,6 +105,10 @@ fn testBreakOuter() void {
98}105}
99106
100test "while copies its payload" {107test "while copies its payload" {
108 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
111
101 const S = struct {112 const S = struct {
102 fn doTheTest() !void {113 fn doTheTest() !void {
103 var tmp: ?i32 = 10;114 var tmp: ?i32 = 10;
...@@ -113,6 +124,8 @@ test "while copies its payload" {...@@ -113,6 +124,8 @@ test "while copies its payload" {
113}124}
114125
115test "continue and break" {126test "continue and break" {
127 if (builtin.zig_backend == .stage2_aarch64 and builtin.os.tag == .macos) return error.SkipZigTest;
128
116 try runContinueAndBreakTest();129 try runContinueAndBreakTest();
117 try expect(continue_and_break_counter == 8);130 try expect(continue_and_break_counter == 8);
118}131}
...@@ -131,6 +144,10 @@ fn runContinueAndBreakTest() !void {...@@ -131,6 +144,10 @@ fn runContinueAndBreakTest() !void {
131}144}
132145
133test "while with optional as condition" {146test "while with optional as condition" {
147 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
150
134 numbers_left = 10;151 numbers_left = 10;
135 var sum: i32 = 0;152 var sum: i32 = 0;
136 while (getNumberOrNull()) |value| {153 while (getNumberOrNull()) |value| {
...@@ -140,6 +157,10 @@ test "while with optional as condition" {...@@ -140,6 +157,10 @@ test "while with optional as condition" {
140}157}
141158
142test "while with optional as condition with else" {159test "while with optional as condition with else" {
160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
163
143 numbers_left = 10;164 numbers_left = 10;
144 var sum: i32 = 0;165 var sum: i32 = 0;
145 var got_else: i32 = 0;166 var got_else: i32 = 0;
...@@ -154,6 +175,10 @@ test "while with optional as condition with else" {...@@ -154,6 +175,10 @@ test "while with optional as condition with else" {
154}175}
155176
156test "while with error union condition" {177test "while with error union condition" {
178 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
180 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
181
157 numbers_left = 10;182 numbers_left = 10;
158 var sum: i32 = 0;183 var sum: i32 = 0;
159 var got_else: i32 = 0;184 var got_else: i32 = 0;
...@@ -182,6 +207,10 @@ test "while on bool with else result follow break prong" {...@@ -182,6 +207,10 @@ test "while on bool with else result follow break prong" {
182}207}
183208
184test "while on optional with else result follow else prong" {209test "while on optional with else result follow else prong" {
210 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
211 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
212 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
213
185 const result = while (returnNull()) |value| {214 const result = while (returnNull()) |value| {
186 break value;215 break value;
187 } else @as(i32, 2);216 } else @as(i32, 2);
...@@ -189,6 +218,10 @@ test "while on optional with else result follow else prong" {...@@ -189,6 +218,10 @@ test "while on optional with else result follow else prong" {
189}218}
190219
191test "while on optional with else result follow break prong" {220test "while on optional with else result follow break prong" {
221 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
224
192 const result = while (returnOptional(10)) |value| {225 const result = while (returnOptional(10)) |value| {
193 break value;226 break value;
194 } else @as(i32, 2);227 } else @as(i32, 2);
...@@ -215,6 +248,10 @@ fn returnTrue() bool {...@@ -215,6 +248,10 @@ fn returnTrue() bool {
215}248}
216249
217test "return with implicit cast from while loop" {250test "return with implicit cast from while loop" {
251 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
252 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
253 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
254
218 returnWithImplicitCastFromWhileLoopTest() catch unreachable;255 returnWithImplicitCastFromWhileLoopTest() catch unreachable;
219}256}
220fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {257fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
...@@ -224,6 +261,10 @@ fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {...@@ -224,6 +261,10 @@ fn returnWithImplicitCastFromWhileLoopTest() anyerror!void {
224}261}
225262
226test "while on error union with else result follow else prong" {263test "while on error union with else result follow else prong" {
264 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
267
227 const result = while (returnError()) |value| {268 const result = while (returnError()) |value| {
228 break value;269 break value;
229 } else |_| @as(i32, 2);270 } else |_| @as(i32, 2);
...@@ -231,6 +272,10 @@ test "while on error union with else result follow else prong" {...@@ -231,6 +272,10 @@ test "while on error union with else result follow else prong" {
231}272}
232273
233test "while on error union with else result follow break prong" {274test "while on error union with else result follow break prong" {
275 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
276 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
278
234 const result = while (returnSuccess(10)) |value| {279 const result = while (returnSuccess(10)) |value| {
235 break value;280 break value;
236 } else |_| @as(i32, 2);281 } else |_| @as(i32, 2);
...@@ -253,6 +298,10 @@ test "while bool 2 break statements and an else" {...@@ -253,6 +298,10 @@ test "while bool 2 break statements and an else" {
253}298}
254299
255test "while optional 2 break statements and an else" {300test "while optional 2 break statements and an else" {
301 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
302 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304
256 const S = struct {305 const S = struct {
257 fn entry(opt_t: ?bool, f: bool) !void {306 fn entry(opt_t: ?bool, f: bool) !void {
258 var ok = false;307 var ok = false;