| 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,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); |
| 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 | 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 { |
| 1704 | 1712 | ||
| 1705 | fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void { | 1713 | fn 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 { |
| 1827 | 1859 | ||
| 1828 | fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { | 1860 | fn 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 | } | ||
| 1832 | 1865 | ||
| 1833 | // Optional with a zero-bit payload type is just a boolean true | 1866 | 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; | ||
| 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 | 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; |
| 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 | return MCValue{ .compare_flags_unsigned = .eq }; | 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,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 | } |
| 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 | pub fn generateSymbol( | 153 | pub 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(); |
| 153 | 163 | ||
| 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 }); |
| 155 | 168 | ||
| 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 array | 207 | // 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; |
| 317 | 347 | ||
| ... | @@ -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 integer | 405 | // 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); |
| 425 | 454 | ||
| 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; |
| 507 | 534 | ||
| 508 | // Pad struct members if required | 535 | // 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); |
| 512 | 538 | ||
| ... | @@ -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 unions | 547 | // 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); |
| 525 | 550 | ||
| ... | @@ -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 optionals | 618 | // 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 | } | ||
| 597 | 672 | ||
| 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(); |
| 604 | 680 | ||
| 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); |
| 607 | 682 | ||
| 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" { |
| 728 | test "result location is optional inside error union" { | 728 | test "result location is optional inside error union" { |
| 729 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 729 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 730 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 730 | 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; // TODO | 731 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 733 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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,7 +27,6 @@ fn parseNote() ?i32 { |
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | test "fixed" { | 29 | test "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; |
| 33 | 32 |
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" { |
| 19 | 19 | ||
| 20 | test "peer type resolution: ?T and T" { | 20 | test "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; |
| 23 | 23 | ||
| 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" { |
| 179 | 179 | ||
| 180 | test "coerce undefined to optional" { | 180 | test "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; |
| 183 | 183 | ||
| 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" { |
| 237 | 237 | ||
| 238 | test "peer result null and comptime_int" { | 238 | test "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; |
| 241 | 241 | ||
| 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 { |
| 302 | 302 | ||
| 303 | test "return u8 coercing into ?u32 return type" { | 303 | test "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; |
| 306 | 306 | ||
| 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 { |
| 373 | test "implicitly cast from T to anyerror!?T" { | 373 | test "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; | ||
| 377 | 376 | ||
| 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; // TODO | 1036 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1038 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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; // TODO | 1072 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1075 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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" { |
| 1087 | test "return null from fn() anyerror!?&T" { | 1084 | test "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; // TODO | 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 | 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; // TODO | 1122 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1127 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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; // TODO | 1173 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1179 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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; // TODO | 1208 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1215 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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; // TODO | 1243 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1251 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | 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 | } |
| 1084 | 1084 | ||
| 1085 | test "enum literal casting to optional" { | 1085 | test "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; |
| 1089 | 1088 |
test/behavior/optional.zig-4| ... | @@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual; | ... | @@ -7,7 +7,6 @@ const expectEqual = testing.expectEqual; |
| 7 | test "passing an optional integer as a parameter" { | 7 | test "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; // TODO | 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 | 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 { |
| 60 | test "optional with void type" { | 59 | test "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; // TODO | 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 | 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" { |
| 171 | test "nested orelse" { | 169 | test "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; // TODO | 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 | 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; // TODO | 197 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 201 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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 | const S = struct { | 200 | const S = struct { |
| 205 | const Node = struct { | 201 | const Node = struct { |