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 {
472472 .regs = 0,
473473 .disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8),
474474 };
475 var disp = data.disp + 8;
475476 inline for (callee_preserved_regs) |reg, i| {
476477 if (self.register_manager.isRegAllocated(reg)) {
477478 if (reg.to64() == .rdi) {
478479 for (self.ret_backpatches.items) |inst| {
480 log.debug(".rdi was spilled, backpatching with mov from stack at offset {}", .{
481 -@intCast(i32, disp),
482 });
479483 const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]);
480484 self.mir_instructions.set(inst, Mir.Inst{
481485 .tag = .mov,
......@@ -484,12 +488,13 @@ fn gen(self: *Self) InnerError!void {
484488 .reg2 = .rbp,
485489 .flags = 0b01,
486490 }).encode(),
487 .data = .{ .imm = @bitCast(u32, -@intCast(i32, self.max_end_stack + 8)) },
491 .data = .{ .imm = @bitCast(u32, -@intCast(i32, disp)) },
488492 });
489493 }
490494 }
491495 data.regs |= 1 << @intCast(u5, i);
492496 self.max_end_stack += 8;
497 disp += 8;
493498 }
494499 }
495500 break :blk try self.addExtra(data);
......@@ -981,7 +986,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
981986 operand.freezeIfRegister(&self.register_manager);
982987 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 };
985993 };
986994
987995 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
......@@ -1704,12 +1712,36 @@ fn airShr(self: *Self, inst: Air.Inst.Index) !void {
17041712
17051713fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
17061714 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1707 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1708 const operand = try self.resolveInst(ty_op.operand);
1709 if (self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1710 break :result operand;
1715 if (self.liveness.isUnused(inst)) {
1716 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1717 }
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}),
17111744 }
1712 break :result try self.copyToRegisterWithInstTracking(inst, self.air.typeOfIndex(inst), operand);
17131745 };
17141746 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
17151747}
......@@ -1827,14 +1859,38 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
18271859
18281860fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
18291861 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1830 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1831 const optional_ty = self.air.typeOfIndex(inst);
1862 if (self.liveness.isUnused(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 true
1834 if (optional_ty.abiSize(self.target.*) == 1)
1866 const payload_ty = self.air.typeOf(ty_op.operand);
1867 const result: MCValue = result: {
1868 if (!payload_ty.hasRuntimeBits()) {
18351869 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 };
18381894 };
18391895 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
18401896}
......@@ -3761,7 +3817,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu
37613817 try self.spillCompareFlagsIfOccupied();
37623818 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
37653828 return MCValue{ .compare_flags_unsigned = .eq };
37663829}
37673830
......@@ -5625,7 +5688,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
56255688 .val = typed_value.val,
56265689 });
56275690 } 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()) };
56295692 }
56305693 },
56315694 .Enum => {
src/codegen.zig+87-13
......@@ -140,6 +140,16 @@ pub fn generateFunction(
140140 }
141141}
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
143153pub fn generateSymbol(
144154 bin_file: *link.File,
145155 src_loc: Module.SrcLoc,
......@@ -151,10 +161,12 @@ pub fn generateSymbol(
151161 const tracy = trace(@src());
152162 defer tracy.end();
153163
164 const target = bin_file.options.target;
165 const endian = target.cpu.arch.endian();
166
154167 log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val });
155168
156169 if (typed_value.val.isUndefDeep()) {
157 const target = bin_file.options.target;
158170 const abi_size = try math.cast(usize, typed_value.ty.abiSize(target));
159171 try code.appendNTimes(0xaa, abi_size);
160172 return Result{ .appended = {} };
......@@ -171,6 +183,25 @@ pub fn generateSymbol(
171183 ),
172184 };
173185 },
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 },
174205 .Array => switch (typed_value.val.tag()) {
175206 .bytes => {
176207 // TODO populate .debug_info for the array
......@@ -311,7 +342,6 @@ pub fn generateSymbol(
311342 return Result{ .appended = {} };
312343 },
313344 .field_ptr => {
314 const target = bin_file.options.target;
315345 const field_ptr = typed_value.val.castTag(.field_ptr).?.data;
316346 const container_ptr = field_ptr.container_ptr;
317347
......@@ -373,7 +403,6 @@ pub fn generateSymbol(
373403 },
374404 .Int => {
375405 // TODO populate .debug_info for the integer
376 const endian = bin_file.options.target.cpu.arch.endian();
377406 const info = typed_value.ty.intInfo(bin_file.options.target);
378407 if (info.bits <= 8) {
379408 const x = @intCast(u8, typed_value.val.toUnsignedInt());
......@@ -423,7 +452,6 @@ pub fn generateSymbol(
423452 var int_buffer: Value.Payload.U64 = undefined;
424453 const int_val = typed_value.enumToInt(&int_buffer);
425454
426 const target = bin_file.options.target;
427455 const info = typed_value.ty.intInfo(target);
428456 if (info.bits <= 8) {
429457 const x = @intCast(u8, int_val.toUnsignedInt());
......@@ -440,7 +468,6 @@ pub fn generateSymbol(
440468 ),
441469 };
442470 }
443 const endian = target.cpu.arch.endian();
444471 switch (info.signedness) {
445472 .unsigned => {
446473 if (info.bits <= 16) {
......@@ -506,7 +533,6 @@ pub fn generateSymbol(
506533 const unpadded_field_end = code.items.len - struct_begin;
507534
508535 // Pad struct members if required
509 const target = bin_file.options.target;
510536 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
511537 const padding = try math.cast(usize, padded_field_end - unpadded_field_end);
512538
......@@ -519,7 +545,6 @@ pub fn generateSymbol(
519545 },
520546 .Union => {
521547 // TODO generate debug info for unions
522 const target = bin_file.options.target;
523548 const union_obj = typed_value.val.castTag(.@"union").?.data;
524549 const layout = typed_value.ty.unionGetLayout(target);
525550
......@@ -590,19 +615,69 @@ pub fn generateSymbol(
590615 return Result{ .appended = {} };
591616 },
592617 .Optional => {
593 // TODO generateSymbol for optionals
594 const target = bin_file.options.target;
618 // TODO generate debug info for optionals
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();
595622 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
598673 return Result{ .appended = {} };
599674 },
600675 .ErrorUnion => {
676 // TODO generate debug info for error unions
601677 const error_ty = typed_value.ty.errorUnionSet();
602678 const payload_ty = typed_value.ty.errorUnionPayload();
603679 const is_payload = typed_value.val.errorUnionIsPayload();
604680
605 const target = bin_file.options.target;
606681 const abi_align = typed_value.ty.abiAlignment(target);
607682
608683 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
......@@ -643,12 +718,11 @@ pub fn generateSymbol(
643718 return Result{ .appended = {} };
644719 },
645720 .ErrorSet => {
646 const target = bin_file.options.target;
721 // TODO generate debug info for error sets
647722 switch (typed_value.val.tag()) {
648723 .@"error" => {
649724 const name = typed_value.val.getError().?;
650725 const kv = try bin_file.options.module.?.getErrorValue(name);
651 const endian = target.cpu.arch.endian();
652726 try code.writer().writeInt(u32, kv.value, endian);
653727 },
654728 else => {
test/behavior/basic.zig-1
......@@ -728,7 +728,6 @@ test "thread local variable" {
728728test "result location is optional inside error union" {
729729 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
730730 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
731 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
732731 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
733732 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
734733
test/behavior/bugs/2889.zig-1
......@@ -27,7 +27,6 @@ fn parseNote() ?i32 {
2727}
2828
2929test "fixed" {
30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3332
test/behavior/bugs/3112.zig-1
......@@ -16,7 +16,6 @@ test "zig test crash" {
1616 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1717 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1818 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
2019 var global: State = undefined;
2120 global.enter = prev;
2221 global.enter(null);
test/behavior/cast.zig+4-12
......@@ -19,7 +19,7 @@ test "integer literal to pointer cast" {
1919
2020test "peer type resolution: ?T and T" {
2121 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
2424 try expect(peerTypeTAndOptionalT(true, false).? == 0);
2525 try expect(peerTypeTAndOptionalT(false, false).? == 3);
......@@ -179,7 +179,7 @@ test "@floatCast comptime_int and comptime_float" {
179179
180180test "coerce undefined to optional" {
181181 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
184184 try expect(MakeType(void).getNull() == null);
185185 try expect(MakeType(void).getNonNull() != null);
......@@ -237,7 +237,7 @@ test "@intCast to u0 and use the result" {
237237
238238test "peer result null and comptime_int" {
239239 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
242242 const S = struct {
243243 fn blah(n: i32) ?i32 {
......@@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void {
302302
303303test "return u8 coercing into ?u32 return type" {
304304 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
307307 const S = struct {
308308 fn doTheTest() !void {
......@@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void {
373373test "implicitly cast from T to anyerror!?T" {
374374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
375375 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
376 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
377376
378377 try castToOptionalTypeError(1);
379378 comptime try castToOptionalTypeError(1);
......@@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" {
10361035 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10371036 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10381037 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1039 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10401038
10411039 var a = [_]u8{ 3, 2, 1 };
10421040 var runtime_zero: usize = 0;
......@@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" {
10731071 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10741072 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10751073 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1076 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10771074
10781075 var a: u32 = 1;
10791076 var ptr: *align(@alignOf(u32)) anyopaque = &a;
......@@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" {
10871084test "return null from fn() anyerror!?&T" {
10881085 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10891086 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1090 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10911087
10921088 const a = returnNullFromOptionalTypeErrorRef();
10931089 const b = returnNullLitFromOptionalTypeErrorRef();
......@@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" {
11251121 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11261122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11271123 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1128 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11291124
11301125 try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
11311126 comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi"));
......@@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" {
11771172 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11781173 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11791174 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1180 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11811175
11821176 var a: u8 = 1;
11831177 incrementVoidPtrValue(&a);
......@@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" {
12131207 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12141208 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12151209 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1216 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12171210
12181211 const S = struct {
12191212 fn doTheTest() !void {
......@@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" {
12491242 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
12501243 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12511244 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1252 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12531245
12541246 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
12551247 try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct));
test/behavior/enum.zig-1
......@@ -1083,7 +1083,6 @@ test "@tagName on enum literals" {
10831083}
10841084
10851085test "enum literal casting to optional" {
1086 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10871086 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10881087 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10891088
test/behavior/optional.zig-4
......@@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual;
77test "passing an optional integer as a parameter" {
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1110
1211 const S = struct {
1312 fn entry() bool {
......@@ -60,7 +59,6 @@ fn testNullPtrsEql() !void {
6059test "optional with void type" {
6160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
6261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
63 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6462
6563 const Foo = struct {
6664 x: ?void,
......@@ -171,7 +169,6 @@ test "unwrap function call with optional pointer return value" {
171169test "nested orelse" {
172170 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
173171 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
174 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
175172
176173 const S = struct {
177174 fn entry() !void {
......@@ -199,7 +196,6 @@ test "self-referential struct through a slice of optional" {
199196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
200197 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
201198 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
203199
204200 const S = struct {
205201 const Node = struct {