| author | |
| committer | |
| log | aa867c7dbe6576f61f957667fef769030aff7c69 |
| tree | 1afb2b62fbefe367a329ead59c266428ead66738 |
| parent | 7cfc3f0cfa626abe25c8318a7852977cbc1c723b |
| parent | 77072d1a1785f389c3c9918c6d7c6179ac2e43f4 |
| signature |
x64: handle more optional types8 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 | 472 | .regs = 0, |
| 473 | 473 | .disp = mem.alignForwardGeneric(u32, self.next_stack_offset, 8), |
| 474 | 474 | }; |
| 475 | var disp = data.disp + 8; | |
| 475 | 476 | inline for (callee_preserved_regs) |reg, i| { |
| 476 | 477 | if (self.register_manager.isRegAllocated(reg)) { |
| 477 | 478 | if (reg.to64() == .rdi) { |
| 478 | 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 | 483 | const ops = Mir.Ops.decode(self.mir_instructions.items(.ops)[inst]); |
| 480 | 484 | self.mir_instructions.set(inst, Mir.Inst{ |
| 481 | 485 | .tag = .mov, |
| ... | ... | @@ -484,12 +488,13 @@ fn gen(self: *Self) InnerError!void { |
| 484 | 488 | .reg2 = .rbp, |
| 485 | 489 | .flags = 0b01, |
| 486 | 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 | 495 | data.regs |= 1 << @intCast(u5, i); |
| 492 | 496 | self.max_end_stack += 8; |
| 497 | disp += 8; | |
| 493 | 498 | } |
| 494 | 499 | } |
| 495 | 500 | break :blk try self.addExtra(data); |
| ... | ... | @@ -981,7 +986,10 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 981 | 986 | operand.freezeIfRegister(&self.register_manager); |
| 982 | 987 | defer operand.unfreezeIfRegister(&self.register_manager); |
| 983 | 988 | |
| 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 | }; |
| 986 | 994 | |
| 987 | 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 | 1712 | |
| 1705 | 1713 | fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { |
| 1706 | 1714 | 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}), | |
| 1711 | 1744 | } |
| 1712 | break :result try self.copyToRegisterWithInstTracking(inst, self.air.typeOfIndex(inst), operand); | |
| 1713 | 1745 | }; |
| 1714 | 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 | 1859 | |
| 1828 | 1860 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { |
| 1829 | 1861 | 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 | } | |
| 1832 | 1865 | |
| 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()) { | |
| 1835 | 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; | |
| 1836 | 1889 | |
| 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 | 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 | 3817 | try self.spillCompareFlagsIfOccupied(); |
| 3762 | 3818 | self.compare_flags_inst = inst; |
| 3763 | 3819 | |
| 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 | 3828 | return MCValue{ .compare_flags_unsigned = .eq }; |
| 3766 | 3829 | } |
| 3767 | 3830 | |
| ... | ... | @@ -5625,7 +5688,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 5625 | 5688 | .val = typed_value.val, |
| 5626 | 5689 | }); |
| 5627 | 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 | 5694 | .Enum => { |
src/codegen.zig+87-13| ... | ... | @@ -140,6 +140,16 @@ pub fn generateFunction( |
| 140 | 140 | } |
| 141 | 141 | } |
| 142 | 142 | |
| 143 | fn 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 | ||
| 143 | 153 | pub fn generateSymbol( |
| 144 | 154 | bin_file: *link.File, |
| 145 | 155 | src_loc: Module.SrcLoc, |
| ... | ... | @@ -151,10 +161,12 @@ pub fn generateSymbol( |
| 151 | 161 | const tracy = trace(@src()); |
| 152 | 162 | defer tracy.end(); |
| 153 | 163 | |
| 164 | const target = bin_file.options.target; | |
| 165 | const endian = target.cpu.arch.endian(); | |
| 166 | ||
| 154 | 167 | log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val }); |
| 155 | 168 | |
| 156 | 169 | if (typed_value.val.isUndefDeep()) { |
| 157 | const target = bin_file.options.target; | |
| 158 | 170 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); |
| 159 | 171 | try code.appendNTimes(0xaa, abi_size); |
| 160 | 172 | return Result{ .appended = {} }; |
| ... | ... | @@ -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 | 205 | .Array => switch (typed_value.val.tag()) { |
| 175 | 206 | .bytes => { |
| 176 | 207 | // TODO populate .debug_info for the array |
| ... | ... | @@ -311,7 +342,6 @@ pub fn generateSymbol( |
| 311 | 342 | return Result{ .appended = {} }; |
| 312 | 343 | }, |
| 313 | 344 | .field_ptr => { |
| 314 | const target = bin_file.options.target; | |
| 315 | 345 | const field_ptr = typed_value.val.castTag(.field_ptr).?.data; |
| 316 | 346 | const container_ptr = field_ptr.container_ptr; |
| 317 | 347 | |
| ... | ... | @@ -373,7 +403,6 @@ pub fn generateSymbol( |
| 373 | 403 | }, |
| 374 | 404 | .Int => { |
| 375 | 405 | // TODO populate .debug_info for the integer |
| 376 | const endian = bin_file.options.target.cpu.arch.endian(); | |
| 377 | 406 | const info = typed_value.ty.intInfo(bin_file.options.target); |
| 378 | 407 | if (info.bits <= 8) { |
| 379 | 408 | const x = @intCast(u8, typed_value.val.toUnsignedInt()); |
| ... | ... | @@ -423,7 +452,6 @@ pub fn generateSymbol( |
| 423 | 452 | var int_buffer: Value.Payload.U64 = undefined; |
| 424 | 453 | const int_val = typed_value.enumToInt(&int_buffer); |
| 425 | 454 | |
| 426 | const target = bin_file.options.target; | |
| 427 | 455 | const info = typed_value.ty.intInfo(target); |
| 428 | 456 | if (info.bits <= 8) { |
| 429 | 457 | const x = @intCast(u8, int_val.toUnsignedInt()); |
| ... | ... | @@ -440,7 +468,6 @@ pub fn generateSymbol( |
| 440 | 468 | ), |
| 441 | 469 | }; |
| 442 | 470 | } |
| 443 | const endian = target.cpu.arch.endian(); | |
| 444 | 471 | switch (info.signedness) { |
| 445 | 472 | .unsigned => { |
| 446 | 473 | if (info.bits <= 16) { |
| ... | ... | @@ -506,7 +533,6 @@ pub fn generateSymbol( |
| 506 | 533 | const unpadded_field_end = code.items.len - struct_begin; |
| 507 | 534 | |
| 508 | 535 | // Pad struct members if required |
| 509 | const target = bin_file.options.target; | |
| 510 | 536 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target); |
| 511 | 537 | const padding = try math.cast(usize, padded_field_end - unpadded_field_end); |
| 512 | 538 | |
| ... | ... | @@ -519,7 +545,6 @@ pub fn generateSymbol( |
| 519 | 545 | }, |
| 520 | 546 | .Union => { |
| 521 | 547 | // TODO generate debug info for unions |
| 522 | const target = bin_file.options.target; | |
| 523 | 548 | const union_obj = typed_value.val.castTag(.@"union").?.data; |
| 524 | 549 | const layout = typed_value.ty.unionGetLayout(target); |
| 525 | 550 | |
| ... | ... | @@ -590,19 +615,69 @@ pub fn generateSymbol( |
| 590 | 615 | return Result{ .appended = {} }; |
| 591 | 616 | }, |
| 592 | 617 | .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(); | |
| 595 | 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 | } | |
| 597 | 672 | |
| 598 | 673 | return Result{ .appended = {} }; |
| 599 | 674 | }, |
| 600 | 675 | .ErrorUnion => { |
| 676 | // TODO generate debug info for error unions | |
| 601 | 677 | const error_ty = typed_value.ty.errorUnionSet(); |
| 602 | 678 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| 603 | 679 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 604 | 680 | |
| 605 | const target = bin_file.options.target; | |
| 606 | 681 | const abi_align = typed_value.ty.abiAlignment(target); |
| 607 | 682 | |
| 608 | 683 | const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero); |
| ... | ... | @@ -643,12 +718,11 @@ pub fn generateSymbol( |
| 643 | 718 | return Result{ .appended = {} }; |
| 644 | 719 | }, |
| 645 | 720 | .ErrorSet => { |
| 646 | const target = bin_file.options.target; | |
| 721 | // TODO generate debug info for error sets | |
| 647 | 722 | switch (typed_value.val.tag()) { |
| 648 | 723 | .@"error" => { |
| 649 | 724 | const name = typed_value.val.getError().?; |
| 650 | 725 | const kv = try bin_file.options.module.?.getErrorValue(name); |
| 651 | const endian = target.cpu.arch.endian(); | |
| 652 | 726 | try code.writer().writeInt(u32, kv.value, endian); |
| 653 | 727 | }, |
| 654 | 728 | else => { |
test/behavior/basic.zig-1| ... | ... | @@ -728,7 +728,6 @@ test "thread local variable" { |
| 728 | 728 | test "result location is optional inside error union" { |
| 729 | 729 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 730 | 730 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 731 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 732 | 731 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 733 | 732 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 734 | 733 |
test/behavior/bugs/2889.zig-1| ... | ... | @@ -27,7 +27,6 @@ fn parseNote() ?i32 { |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | test "fixed" { |
| 30 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 31 | 30 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 32 | 31 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 33 | 32 |
test/behavior/bugs/3112.zig-1| ... | ... | @@ -16,7 +16,6 @@ test "zig test crash" { |
| 16 | 16 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 17 | 17 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 18 | 18 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 19 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 20 | 19 | var global: State = undefined; |
| 21 | 20 | global.enter = prev; |
| 22 | 21 | global.enter(null); |
test/behavior/cast.zig+4-12| ... | ... | @@ -19,7 +19,7 @@ test "integer literal to pointer cast" { |
| 19 | 19 | |
| 20 | 20 | test "peer type resolution: ?T and T" { |
| 21 | 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; | |
| 23 | 23 | |
| 24 | 24 | try expect(peerTypeTAndOptionalT(true, false).? == 0); |
| 25 | 25 | try expect(peerTypeTAndOptionalT(false, false).? == 3); |
| ... | ... | @@ -179,7 +179,7 @@ test "@floatCast comptime_int and comptime_float" { |
| 179 | 179 | |
| 180 | 180 | test "coerce undefined to optional" { |
| 181 | 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; | |
| 183 | 183 | |
| 184 | 184 | try expect(MakeType(void).getNull() == null); |
| 185 | 185 | try expect(MakeType(void).getNonNull() != null); |
| ... | ... | @@ -237,7 +237,7 @@ test "@intCast to u0 and use the result" { |
| 237 | 237 | |
| 238 | 238 | test "peer result null and comptime_int" { |
| 239 | 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; | |
| 241 | 241 | |
| 242 | 242 | const S = struct { |
| 243 | 243 | fn blah(n: i32) ?i32 { |
| ... | ... | @@ -302,7 +302,7 @@ fn implicitIntLitToOptional() void { |
| 302 | 302 | |
| 303 | 303 | test "return u8 coercing into ?u32 return type" { |
| 304 | 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; | |
| 306 | 306 | |
| 307 | 307 | const S = struct { |
| 308 | 308 | fn doTheTest() !void { |
| ... | ... | @@ -373,7 +373,6 @@ fn testPeerResolveArrayConstSlice(b: bool) !void { |
| 373 | 373 | test "implicitly cast from T to anyerror!?T" { |
| 374 | 374 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 375 | 375 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 376 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 377 | 376 | |
| 378 | 377 | try castToOptionalTypeError(1); |
| 379 | 378 | comptime try castToOptionalTypeError(1); |
| ... | ... | @@ -1036,7 +1035,6 @@ test "implicit cast from [*]T to ?*anyopaque" { |
| 1036 | 1035 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1037 | 1036 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1038 | 1037 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1039 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1040 | 1038 | |
| 1041 | 1039 | var a = [_]u8{ 3, 2, 1 }; |
| 1042 | 1040 | var runtime_zero: usize = 0; |
| ... | ... | @@ -1073,7 +1071,6 @@ test "implicit ptr to *anyopaque" { |
| 1073 | 1071 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1074 | 1072 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1075 | 1073 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1076 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1077 | 1074 | |
| 1078 | 1075 | var a: u32 = 1; |
| 1079 | 1076 | var ptr: *align(@alignOf(u32)) anyopaque = &a; |
| ... | ... | @@ -1087,7 +1084,6 @@ test "implicit ptr to *anyopaque" { |
| 1087 | 1084 | test "return null from fn() anyerror!?&T" { |
| 1088 | 1085 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1089 | 1086 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1090 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1091 | 1087 | |
| 1092 | 1088 | const a = returnNullFromOptionalTypeErrorRef(); |
| 1093 | 1089 | const b = returnNullLitFromOptionalTypeErrorRef(); |
| ... | ... | @@ -1125,7 +1121,6 @@ test "implicitly cast from [N]T to ?[]const T" { |
| 1125 | 1121 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1126 | 1122 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1127 | 1123 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1128 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1129 | 1124 | |
| 1130 | 1125 | try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); |
| 1131 | 1126 | comptime try expect(mem.eql(u8, castToOptionalSlice().?, "hi")); |
| ... | ... | @@ -1177,7 +1172,6 @@ test "implicit cast from *T to ?*anyopaque" { |
| 1177 | 1172 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1178 | 1173 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1179 | 1174 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1180 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1181 | 1175 | |
| 1182 | 1176 | var a: u8 = 1; |
| 1183 | 1177 | incrementVoidPtrValue(&a); |
| ... | ... | @@ -1213,7 +1207,6 @@ test "*const [N]null u8 to ?[]const u8" { |
| 1213 | 1207 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1214 | 1208 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1215 | 1209 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1216 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1217 | 1210 | |
| 1218 | 1211 | const S = struct { |
| 1219 | 1212 | fn doTheTest() !void { |
| ... | ... | @@ -1249,7 +1242,6 @@ test "assignment to optional pointer result loc" { |
| 1249 | 1242 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1250 | 1243 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1251 | 1244 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1252 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 1253 | 1245 | |
| 1254 | 1246 | var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct }; |
| 1255 | 1247 | try expect(foo.ptr.? == @ptrCast(*anyopaque, &global_struct)); |
test/behavior/enum.zig-1| ... | ... | @@ -1083,7 +1083,6 @@ test "@tagName on enum literals" { |
| 1083 | 1083 | } |
| 1084 | 1084 | |
| 1085 | 1085 | test "enum literal casting to optional" { |
| 1086 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 1087 | 1086 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1088 | 1087 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1089 | 1088 |
test/behavior/optional.zig-4| ... | ... | @@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual; |
| 7 | 7 | test "passing an optional integer as a parameter" { |
| 8 | 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 9 | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 10 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 11 | 10 | |
| 12 | 11 | const S = struct { |
| 13 | 12 | fn entry() bool { |
| ... | ... | @@ -60,7 +59,6 @@ fn testNullPtrsEql() !void { |
| 60 | 59 | test "optional with void type" { |
| 61 | 60 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 62 | 61 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 63 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 64 | 62 | |
| 65 | 63 | const Foo = struct { |
| 66 | 64 | x: ?void, |
| ... | ... | @@ -171,7 +169,6 @@ test "unwrap function call with optional pointer return value" { |
| 171 | 169 | test "nested orelse" { |
| 172 | 170 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 173 | 171 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 174 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 175 | 172 | |
| 176 | 173 | const S = struct { |
| 177 | 174 | fn entry() !void { |
| ... | ... | @@ -199,7 +196,6 @@ test "self-referential struct through a slice of optional" { |
| 199 | 196 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 200 | 197 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 201 | 198 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 202 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 203 | 199 | |
| 204 | 200 | const S = struct { |
| 205 | 201 | const Node = struct { |