authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-02 20:04:53+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-02 20:04:53+01:00
logaa867c7dbe6576f61f957667fef769030aff7c69
tree1afb2b62fbefe367a329ead59c266428ead66738
parent7cfc3f0cfa626abe25c8318a7852977cbc1c723b
parent77072d1a1785f389c3c9918c6d7c6179ac2e43f4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11036 from ziglang/x64-optionals

x64: handle more optional types

8 files changed, 168 insertions(+), 47 deletions(-)

src/arch/x86_64/CodeGen.zig+77-14
...@@ -472,10 +472,14 @@ fn gen(self: *Self) InnerError!void {...@@ -472,10 +472,14 @@ fn gen(self: *Self) InnerError!void {
472 .regs = 0,472 .regs = 0,
473 .disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8),473 .disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8),
474 };474 };
475 var disp = data.disp + 8;
475 inline for (callee_preserved_regs) |reg, i| {476 inline for (callee_preserved_regs) |reg, i| {
476 if (self.register_manager.isRegAllocated(reg)) {477 if (self.register_manager.isRegAllocated(reg)) {
477 if (reg.to64() == .rdi) {478 if (reg.to64() == .rdi) {
478 for (self.ret_backpatches.items) |inst| {479 for (self.ret_backpatches.items) |inst| {
480 log.debug(".rdi was spilled, backpatching with mov from stack at offset {}", .{
481 -@intCast(i32, disp),
482 });
479 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);483 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
480 self.mir_instructions.set(inst, Mir.Inst{484 self.mir_instructions.set(inst, Mir.Inst{
481 .tag = .mov,485 .tag = .mov,
...@@ -484,12 +488,13 @@ fn gen(self: *Self) InnerError!void {...@@ -484,12 +488,13 @@ fn gen(self: *Self) InnerError!void {
484 .reg2 = .rbp,488 .reg2 = .rbp,
485 .flags = 0b01,489 .flags = 0b01,
486 }).encode(),490 }).encode(),
487 .data = .{ .imm = @bitCast(u32, -@intCast(i32, self.max_end_stack + 8)) },491 .data = .{ .imm = @bitCast(u32, -@intCast(i32, disp)) },
488 });492 });
489 }493 }
490 }494 }
491 data.regs |= 1 << @intCast(u5, i);495 data.regs |= 1 << @intCast(u5, i);
492 self.max_end_stack += 8;496 self.max_end_stack += 8;
497 disp += 8;
493 }498 }
494 }499 }
495 break :blk try self.addExtra(data);500 break :blk try self.addExtra(data);
...@@ -981,7 +986,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -981,7 +986,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
981 operand.freezeIfRegister(&self.register_manager);986 operand.freezeIfRegister(&self.register_manager);
982 defer operand.unfreezeIfRegister(&self.register_manager);987 defer operand.unfreezeIfRegister(&self.register_manager);
983988
984 break :blk try self.copyToRegisterWithInstTracking(inst, dest_ty, operand);989 const reg = try self.register_manager.allocReg(inst);
990 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
991 try self.genSetReg(operand_ty, reg, operand);
992 break :blk MCValue{ .register = reg };
985 };993 };
986994
987 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });995 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
...@@ -1704,12 +1712,36 @@ fn airShr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1704,12 +1712,36 @@ fn airShr(self: *Self, inst: Air.Inst.Index) !void {
17041712
1705fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {1713fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
1706 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1714 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1707 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1715 if (self.liveness.isUnused(inst)) {
1708 const operand = try self.resolveInst(ty_op.operand);1716 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1709 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {1717 }
1710 break :result operand;1718
1719 const payload_ty = self.air.typeOfIndex(inst);
1720 const optional_ty = self.air.typeOf(ty_op.operand);
1721 const operand = try self.resolveInst(ty_op.operand);
1722 const result: MCValue = result: {
1723 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
1724 if (optional_ty.isPtrLikeOptional()) {
1725 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1726 break :result operand;
1727 }
1728 break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand);
1729 }
1730
1731 const offset = optional_ty.abiSize(self.target.*) - payload_ty.abiSize(self.target.*);
1732 switch (operand) {
1733 .stack_offset => |off| {
1734 break :result MCValue{ .stack_offset = off - @intCast(i32, offset) };
1735 },
1736 .register => {
1737 // TODO reuse the operand
1738 const result = try self.copyToRegisterWithInstTracking(inst, optional_ty, operand);
1739 const shift = @intCast(u8, offset * 8);
1740 try self.shiftRegister(result.register, @intCast(u8, shift));
1741 break :result result;
1742 },
1743 else => return self.fail("TODO implement optional_payload when operand is {}", .{operand}),
1711 }1744 }
1712 break :result try self.copyToRegisterWithInstTracking(inst, self.air.typeOfIndex(inst), operand);
1713 };1745 };
1714 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1746 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1715}1747}
...@@ -1827,14 +1859,38 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -1827,14 +1859,38 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
18271859
1828fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {1860fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1829 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1861 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1830 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1862 if (self.liveness.isUnused(inst)) {
1831 const optional_ty = self.air.typeOfIndex(inst);1863 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1864 }
18321865
1833 // Optional with a zero-bit payload type is just a boolean true1866 const payload_ty = self.air.typeOf(ty_op.operand);
1834 if (optional_ty.abiSize(self.target.*) == 1)1867 const result: MCValue = result: {
1868 if (!payload_ty.hasRuntimeBits()) {
1835 break :result MCValue{ .immediate = 1 };1869 break :result MCValue{ .immediate = 1 };
1870 }
1871
1872 const optional_ty = self.air.typeOfIndex(inst);
1873 const operand = try self.resolveInst(ty_op.operand);
1874 operand.freezeIfRegister(&self.register_manager);
1875 defer operand.unfreezeIfRegister(&self.register_manager);
1876
1877 if (optional_ty.isPtrLikeOptional()) {
1878 // TODO should we check if we can reuse the operand?
1879 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1880 break :result operand;
1881 }
1882 break :result try self.copyToRegisterWithInstTracking(inst, payload_ty, operand);
1883 }
1884
1885 const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));
1886 const optional_abi_align = optional_ty.abiAlignment(self.target.*);
1887 const payload_abi_size = @intCast(u32, payload_ty.abiSize(self.target.*));
1888 const offset = optional_abi_size - payload_abi_size;
18361889
1837 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});1890 const stack_offset = @intCast(i32, try self.allocMem(inst, optional_abi_size, optional_abi_align));
1891 try self.genSetStack(Type.bool, stack_offset, .{ .immediate = 1 }, .{});
1892 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, offset), operand, .{});
1893 break :result MCValue{ .stack_offset = stack_offset };
1838 };1894 };
1839 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1895 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1840}1896}
...@@ -3761,7 +3817,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu...@@ -3761,7 +3817,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu
3761 try self.spillCompareFlagsIfOccupied();3817 try self.spillCompareFlagsIfOccupied();
3762 self.compare_flags_inst = inst;3818 self.compare_flags_inst = inst;
37633819
3764 try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 });3820 const cmp_ty: Type = if (!ty.isPtrLikeOptional()) blk: {
3821 var buf: Type.Payload.ElemType = undefined;
3822 const payload_ty = ty.optionalChild(&buf);
3823 break :blk if (payload_ty.hasRuntimeBits()) Type.bool else ty;
3824 } else ty;
3825
3826 try self.genBinMathOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });
3827
3765 return MCValue{ .compare_flags_unsigned = .eq };3828 return MCValue{ .compare_flags_unsigned = .eq };
3766}3829}
37673830
...@@ -5625,7 +5688,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -5625,7 +5688,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
5625 .val = typed_value.val,5688 .val = typed_value.val,
5626 });5689 });
5627 } else if (typed_value.ty.abiSize(self.target.*) == 1) {5690 } else if (typed_value.ty.abiSize(self.target.*) == 1) {
5628 return MCValue{ .immediate = @boolToInt(typed_value.val.isNull()) };5691 return MCValue{ .immediate = @boolToInt(!typed_value.val.isNull()) };
5629 }5692 }
5630 },5693 },
5631 .Enum => {5694 .Enum => {
src/codegen.zig+87-13
...@@ -140,6 +140,16 @@ pub fn generateFunction(...@@ -140,6 +140,16 @@ pub fn generateFunction(
140 }140 }
141}141}
142142
143fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void {
144 _ = target;
145 const Int = @Type(.{ .Int = .{
146 .signedness = .unsigned,
147 .bits = @typeInfo(F).Float.bits,
148 } });
149 const int = @bitCast(Int, f);
150 mem.writeInt(Int, code[0..@sizeOf(Int)], int, endian);
151}
152
143pub fn generateSymbol(153pub fn generateSymbol(
144 bin_file: *link.File,154 bin_file: *link.File,
145 src_loc: Module.SrcLoc,155 src_loc: Module.SrcLoc,
...@@ -151,10 +161,12 @@ pub fn generateSymbol(...@@ -151,10 +161,12 @@ pub fn generateSymbol(
151 const tracy = trace(@src());161 const tracy = trace(@src());
152 defer tracy.end();162 defer tracy.end();
153163
164 const target = bin_file.options.target;
165 const endian = target.cpu.arch.endian();
166
154 log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });167 log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });
155168
156 if (typed_value.val.isUndefDeep()) {169 if (typed_value.val.isUndefDeep()) {
157 const target = bin_file.options.target;
158 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));170 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
159 try code.appendNTimes(0xaa, abi_size);171 try code.appendNTimes(0xaa, abi_size);
160 return Result{ .appended = {} };172 return Result{ .appended = {} };
...@@ -171,6 +183,25 @@ pub fn generateSymbol(...@@ -171,6 +183,25 @@ pub fn generateSymbol(
171 ),183 ),
172 };184 };
173 },185 },
186 .Float => {
187 const float_bits = typed_value.ty.floatBits(target);
188 switch (float_bits) {
189 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)),
190 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)),
191 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)),
192 80 => return Result{
193 .fail = try ErrorMsg.create(
194 bin_file.allocator,
195 src_loc,
196 "TODO handle f80 in generateSymbol",
197 .{},
198 ),
199 },
200 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)),
201 else => unreachable,
202 }
203 return Result{ .appended = {} };
204 },
174 .Array => switch (typed_value.val.tag()) {205 .Array => switch (typed_value.val.tag()) {
175 .bytes => {206 .bytes => {
176 // TODO populate .debug_info for the array207 // TODO populate .debug_info for the array
...@@ -311,7 +342,6 @@ pub fn generateSymbol(...@@ -311,7 +342,6 @@ pub fn generateSymbol(
311 return Result{ .appended = {} };342 return Result{ .appended = {} };
312 },343 },
313 .field_ptr => {344 .field_ptr => {
314 const target = bin_file.options.target;
315 const field_ptr = typed_value.val.castTag(.field_ptr).?.data;345 const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
316 const container_ptr = field_ptr.container_ptr;346 const container_ptr = field_ptr.container_ptr;
317347
...@@ -373,7 +403,6 @@ pub fn generateSymbol(...@@ -373,7 +403,6 @@ pub fn generateSymbol(
373 },403 },
374 .Int => {404 .Int => {
375 // TODO populate .debug_info for the integer405 // TODO populate .debug_info for the integer
376 const endian = bin_file.options.target.cpu.arch.endian();
377 const info = typed_value.ty.intInfo(bin_file.options.target);406 const info = typed_value.ty.intInfo(bin_file.options.target);
378 if (info.bits <= 8) {407 if (info.bits <= 8) {
379 const x = @intCast(u8, typed_value.val.toUnsignedInt());408 const x = @intCast(u8, typed_value.val.toUnsignedInt());
...@@ -423,7 +452,6 @@ pub fn generateSymbol(...@@ -423,7 +452,6 @@ pub fn generateSymbol(
423 var int_buffer: Value.Payload.U64 = undefined;452 var int_buffer: Value.Payload.U64 = undefined;
424 const int_val = typed_value.enumToInt(&int_buffer);453 const int_val = typed_value.enumToInt(&int_buffer);
425454
426 const target = bin_file.options.target;
427 const info = typed_value.ty.intInfo(target);455 const info = typed_value.ty.intInfo(target);
428 if (info.bits <= 8) {456 if (info.bits <= 8) {
429 const x = @intCast(u8, int_val.toUnsignedInt());457 const x = @intCast(u8, int_val.toUnsignedInt());
...@@ -440,7 +468,6 @@ pub fn generateSymbol(...@@ -440,7 +468,6 @@ pub fn generateSymbol(
440 ),468 ),
441 };469 };
442 }470 }
443 const endian = target.cpu.arch.endian();
444 switch (info.signedness) {471 switch (info.signedness) {
445 .unsigned => {472 .unsigned => {
446 if (info.bits <= 16) {473 if (info.bits <= 16) {
...@@ -506,7 +533,6 @@ pub fn generateSymbol(...@@ -506,7 +533,6 @@ pub fn generateSymbol(
506 const unpadded_field_end = code.items.len - struct_begin;533 const unpadded_field_end = code.items.len - struct_begin;
507534
508 // Pad struct members if required535 // Pad struct members if required
509 const target = bin_file.options.target;
510 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);536 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
511 const padding = try math.cast(usize, padded_field_end - unpadded_field_end);537 const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
512538
...@@ -519,7 +545,6 @@ pub fn generateSymbol(...@@ -519,7 +545,6 @@ pub fn generateSymbol(
519 },545 },
520 .Union => {546 .Union => {
521 // TODO generate debug info for unions547 // TODO generate debug info for unions
522 const target = bin_file.options.target;
523 const union_obj = typed_value.val.castTag(.@"union").?.data;548 const union_obj = typed_value.val.castTag(.@"union").?.data;
524 const layout = typed_value.ty.unionGetLayout(target);549 const layout = typed_value.ty.unionGetLayout(target);
525550
...@@ -590,19 +615,69 @@ pub fn generateSymbol(...@@ -590,19 +615,69 @@ pub fn generateSymbol(
590 return Result{ .appended = {} };615 return Result{ .appended = {} };
591 },616 },
592 .Optional => {617 .Optional => {
593 // TODO generateSymbol for optionals618 // TODO generate debug info for optionals
594 const target = bin_file.options.target;619 var opt_buf: Type.Payload.ElemType = undefined;
620 const payload_type = typed_value.ty.optionalChild(&opt_buf);
621 const is_pl = !typed_value.val.isNull();
595 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));622 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
596 try code.writer().writeByteNTimes(0xaa, abi_size);623 const offset = abi_size - try math.cast(usize, payload_type.abiSize(target));
624
625 if (!payload_type.hasRuntimeBits()) {
626 try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size);
627 return Result{ .appended = {} };
628 }
629
630 if (typed_value.ty.isPtrLikeOptional()) {
631 if (typed_value.val.castTag(.opt_payload)) |payload| {
632 switch (try generateSymbol(bin_file, src_loc, .{
633 .ty = payload_type,
634 .val = payload.data,
635 }, code, debug_output, reloc_info)) {
636 .appended => {},
637 .externally_managed => |external_slice| {
638 code.appendSliceAssumeCapacity(external_slice);
639 },
640 .fail => |em| return Result{ .fail = em },
641 }
642 } else if (!typed_value.val.isNull()) {
643 switch (try generateSymbol(bin_file, src_loc, .{
644 .ty = payload_type,
645 .val = typed_value.val,
646 }, code, debug_output, reloc_info)) {
647 .appended => {},
648 .externally_managed => |external_slice| {
649 code.appendSliceAssumeCapacity(external_slice);
650 },
651 .fail => |em| return Result{ .fail = em },
652 }
653 } else {
654 try code.writer().writeByteNTimes(0, abi_size);
655 }
656
657 return Result{ .appended = {} };
658 }
659
660 const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef);
661 try code.writer().writeByteNTimes(@boolToInt(is_pl), offset);
662 switch (try generateSymbol(bin_file, src_loc, .{
663 .ty = payload_type,
664 .val = value,
665 }, code, debug_output, reloc_info)) {
666 .appended => {},
667 .externally_managed => |external_slice| {
668 code.appendSliceAssumeCapacity(external_slice);
669 },
670 .fail => |em| return Result{ .fail = em },
671 }
597672
598 return Result{ .appended = {} };673 return Result{ .appended = {} };
599 },674 },
600 .ErrorUnion => {675 .ErrorUnion => {
676 // TODO generate debug info for error unions
601 const error_ty = typed_value.ty.errorUnionSet();677 const error_ty = typed_value.ty.errorUnionSet();
602 const payload_ty = typed_value.ty.errorUnionPayload();678 const payload_ty = typed_value.ty.errorUnionPayload();
603 const is_payload = typed_value.val.errorUnionIsPayload();679 const is_payload = typed_value.val.errorUnionIsPayload();
604680
605 const target = bin_file.options.target;
606 const abi_align = typed_value.ty.abiAlignment(target);681 const abi_align = typed_value.ty.abiAlignment(target);
607682
608 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);683 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
...@@ -643,12 +718,11 @@ pub fn generateSymbol(...@@ -643,12 +718,11 @@ pub fn generateSymbol(
643 return Result{ .appended = {} };718 return Result{ .appended = {} };
644 },719 },
645 .ErrorSet => {720 .ErrorSet => {
646 const target = bin_file.options.target;721 // TODO generate debug info for error sets
647 switch (typed_value.val.tag()) {722 switch (typed_value.val.tag()) {
648 .@"error" => {723 .@"error" => {
649 const name = typed_value.val.getError().?;724 const name = typed_value.val.getError().?;
650 const kv = try bin_file.options.module.?.getErrorValue(name);725 const kv = try bin_file.options.module.?.getErrorValue(name);
651 const endian = target.cpu.arch.endian();
652 try code.writer().writeInt(u32, kv.value, endian);726 try code.writer().writeInt(u32, kv.value, endian);
653 },727 },
654 else => {728 else => {
test/behavior/basic.zig-1
...@@ -728,7 +728,6 @@ test "thread local variable" {...@@ -728,7 +728,6 @@ test "thread local variable" {
728test "result location is optional inside error union" {728test "result location is optional inside error union" {
729 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO729 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
731 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
732 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
733 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
734733
test/behavior/bugs/2889.zig-1
...@@ -27,7 +27,6 @@ fn parseNote() ?i32 {...@@ -27,7 +27,6 @@ fn parseNote() ?i32 {
27}27}
2828
29test "fixed" {29test "fixed" {
30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;30 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
32 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3332
test/behavior/bugs/3112.zig-1
...@@ -16,7 +16,6 @@ test "zig test crash" {...@@ -16,7 +16,6 @@ test "zig test crash" {
16 if (builtin.zig_backend == .stage1) return error.SkipZigTest;16 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;18 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
20 var global: State = undefined;19 var global: State = undefined;
21 global.enter = prev;20 global.enter = prev;
22 global.enter(null);21 global.enter(null);
test/behavior/cast.zig+4-12
...@@ -19,7 +19,7 @@ test "integer literal to pointer cast" {...@@ -19,7 +19,7 @@ test "integer literal to pointer cast" {
1919
20test "peer type resolution: ?T and T" {20test "peer type resolution: ?T and T" {
21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;22 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2323
24 try expect(peerTypeTAndOptionalT(true, false).? == 0);24 try expect(peerTypeTAndOptionalT(true, false).? == 0);
25 try expect(peerTypeTAndOptionalT(false, false).? == 3);25 try expect(peerTypeTAndOptionalT(false, false).? == 3);
...@@ -179,7 +179,7 @@ test "@floatCast comptime_int and comptime_float" {...@@ -179,7 +179,7 @@ test "@floatCast comptime_int and comptime_float" {
179179
180test "coerce undefined to optional" {180test "coerce undefined to optional" {
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_arm) return error.SkipZigTest;
183183
184 try expect(MakeType(void).getNull() == null);184 try expect(MakeType(void).getNull() == null);
185 try expect(MakeType(void).getNonNull() != null);185 try expect(MakeType(void).getNonNull() != null);
...@@ -237,7 +237,7 @@ test "@intCast to u0 and use the result" {...@@ -237,7 +237,7 @@ test "@intCast to u0 and use the result" {
237237
238test "peer result null and comptime_int" {238test "peer result null and comptime_int" {
239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;239 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
240 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;240 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
241241
242 const S = struct {242 const S = struct {
243 fn blah(n: i32) ?i32 {243 fn blah(n: i32) ?i32 {
...@@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void {...@@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void {
302302
303test "return u8 coercing into ?u32 return type" {303test "return u8 coercing into ?u32 return type" {
304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
305 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;305 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
306306
307 const S = struct {307 const S = struct {
308 fn doTheTest() !void {308 fn doTheTest() !void {
...@@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {...@@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
373test "implicitly cast from T to anyerror!?T" {373test "implicitly cast from T to anyerror!?T" {
374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
377376
378 try castToOptionalTypeError(1);377 try castToOptionalTypeError(1);
379 comptime try castToOptionalTypeError(1);378 comptime try castToOptionalTypeError(1);
...@@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" {...@@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" {
1036 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1035 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1037 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1036 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1038 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1037 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10401038
1041 var a = [_]u8{ 3, 2, 1 };1039 var a = [_]u8{ 3, 2, 1 };
1042 var runtime_zero: usize = 0;1040 var runtime_zero: usize = 0;
...@@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" {...@@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" {
1073 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1071 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1074 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1072 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1075 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1073 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1076 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10771074
1078 var a: u32 = 1;1075 var a: u32 = 1;
1079 var ptr: *align(@alignOf(u32)) anyopaque = &a;1076 var ptr: *align(@alignOf(u32)) anyopaque = &a;
...@@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" {...@@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" {
1087test "return null from fn() anyerror!?&T" {1084test "return null from fn() anyerror!?&T" {
1088 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1085 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1089 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1086 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1090 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10911087
1092 const a = returnNullFromOptionalTypeErrorRef();1088 const a = returnNullFromOptionalTypeErrorRef();
1093 const b = returnNullLitFromOptionalTypeErrorRef();1089 const b = returnNullLitFromOptionalTypeErrorRef();
...@@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" {...@@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" {
1125 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1126 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1127 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1128 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11291124
1130 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));1125 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
1131 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));1126 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
...@@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" {...@@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" {
1177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1178 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1173 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1174 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1180 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11811175
1182 var a: u8 = 1;1176 var a: u8 = 1;
1183 incrementVoidPtrValue(&a);1177 incrementVoidPtrValue(&a);
...@@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" {...@@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" {
1213 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1214 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1208 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1215 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1216 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12171210
1218 const S = struct {1211 const S = struct {
1219 fn doTheTest() !void {1212 fn doTheTest() !void {
...@@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" {...@@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" {
1249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO1243 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1251 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1252 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12531245
1254 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };1246 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
1255 try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));1247 try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));
test/behavior/enum.zig-1
...@@ -1083,7 +1083,6 @@ test "@tagName on enum literals" {...@@ -1083,7 +1083,6 @@ test "@tagName on enum literals" {
1083}1083}
10841084
1085test "enum literal casting to optional" {1085test "enum literal casting to optional" {
1086 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1087 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;1086 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1088 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1087 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10891088
test/behavior/optional.zig-4
...@@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual;...@@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual;
7test "passing an optional integer as a parameter" {7test "passing an optional integer as a parameter" {
8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1110
12 const S = struct {11 const S = struct {
13 fn entry() bool {12 fn entry() bool {
...@@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {...@@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {
60test "optional with void type" {59test "optional with void type" {
61 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;60 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
62 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO61 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
63 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6462
65 const Foo = struct {63 const Foo = struct {
66 x: ?void,64 x: ?void,
...@@ -171,7 +169,6 @@ test "unwrap function call with optional pointer return value" {...@@ -171,7 +169,6 @@ test "unwrap function call with optional pointer return value" {
171test "nested orelse" {169test "nested orelse" {
172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
173 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
174 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
175172
176 const S = struct {173 const S = struct {
177 fn entry() !void {174 fn entry() !void {
...@@ -199,7 +196,6 @@ test "self-referential struct through a slice of optional" {...@@ -199,7 +196,6 @@ test "self-referential struct through a slice of optional" {
199 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
200 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO197 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO198 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
203199
204 const S = struct {200 const S = struct {
205 const Node = struct {201 const Node = struct {