| ... | ... | @@ -341,7 +341,7 @@ const InnerError = error{ |
| 341 | 341 | AlreadyReported, |
| 342 | 342 | /// Compiler implementation could not handle a large integer. |
| 343 | 343 | Overflow, |
| 344 | | } || link.File.UpdateDebugInfoError; |
| 344 | }; |
| 345 | 345 | |
| 346 | 346 | pub fn deinit(cg: *CodeGen) void { |
| 347 | 347 | const gpa = cg.gpa; |
| ... | ... | @@ -1577,7 +1577,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1577 | 1577 | .int_from_ptr => cg.airIntFromPtr(inst), |
| 1578 | 1578 | |
| 1579 | 1579 | .bit_cast => cg.airBitcast(inst), |
| 1580 | | .union_from_enum => cg.airBitcast(inst), |
| 1580 | .union_from_enum => cg.airUnionFromEnum(inst), |
| 1581 | 1581 | |
| 1582 | 1582 | .int_cast => { |
| 1583 | 1583 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| ... | ... | @@ -5570,6 +5570,21 @@ fn airIntFromPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5570 | 5570 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5571 | 5571 | } |
| 5572 | 5572 | |
| 5573 | fn airUnionFromEnum(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5574 | const zcu = cg.pt.zcu; |
| 5575 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5576 | |
| 5577 | const union_ty = cg.typeOfIndex(inst); |
| 5578 | const enum_ty = cg.typeOf(ty_op.operand); |
| 5579 | const layout = union_ty.unionGetLayout(zcu); |
| 5580 | |
| 5581 | const enum_value = try cg.resolveInst(ty_op.operand); |
| 5582 | const result = try cg.allocStack(union_ty); |
| 5583 | try cg.store(result, enum_value, enum_ty, @intCast(layout.tagOffset())); |
| 5584 | |
| 5585 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5586 | } |
| 5587 | |
| 5573 | 5588 | fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5574 | 5589 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5575 | 5590 | const operand = try cg.resolveInst(ty_op.operand); |
| ... | ... | @@ -5581,25 +5596,62 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5581 | 5596 | return cg.finishAir(inst, result, &.{ty_op.operand}); |
| 5582 | 5597 | } |
| 5583 | 5598 | |
| 5599 | const BitcastClass = union(enum) { |
| 5600 | int: IntType, |
| 5601 | float: FloatType, |
| 5602 | aggregate, // arrays and vectors. |
| 5603 | }; |
| 5604 | |
| 5605 | fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass { |
| 5606 | const zcu = cg.pt.zcu; |
| 5607 | return switch (ty.zigTypeTag(zcu)) { |
| 5608 | .bool, |
| 5609 | .int, |
| 5610 | .@"enum", |
| 5611 | .error_set, |
| 5612 | .@"struct", |
| 5613 | .@"union", |
| 5614 | => .{ .int = .fromType(cg, ty) }, |
| 5615 | .float => .{ .float = .fromType(cg, ty) }, |
| 5616 | .array, .vector => .aggregate, |
| 5617 | else => unreachable, |
| 5618 | }; |
| 5619 | } |
| 5620 | |
| 5584 | 5621 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { |
| 5585 | 5622 | const zcu = cg.pt.zcu; |
| 5586 | | const bit_size = src_ty.bitSize(zcu); |
| 5587 | | const dest_signed = if (dest_ty.isAbiInt(zcu)) IntType.fromType(cg, dest_ty).is_signed else false; |
| 5588 | | const src_signed = if (src_ty.isAbiInt(zcu)) IntType.fromType(cg, src_ty).is_signed else false; |
| 5589 | | const needs_wrapping = (src_signed != dest_signed) and |
| 5590 | | bit_size != 32 and bit_size != 64 and bit_size != 128; |
| 5591 | | |
| 5592 | | if (src_ty.isAnyFloat()) { |
| 5593 | | const float_ty: FloatType = .fromType(cg, src_ty); |
| 5594 | | switch (float_ty) { |
| 5595 | | .f16, .f80, .f128 => { |
| 5596 | | if (dest_signed) { |
| 5597 | | const int_ty: IntType = .fromType(cg, dest_ty); |
| 5598 | | return try cg.intWrap(int_ty, operand); |
| 5599 | | } else { |
| 5600 | | return null; |
| 5601 | | } |
| 5623 | const src_class = cg.bitcastClass(src_ty); |
| 5624 | const dest_class = cg.bitcastClass(dest_ty); |
| 5625 | const src_by_ref = isByRef(src_ty, zcu, cg.target); |
| 5626 | const dest_by_ref = isByRef(dest_ty, zcu, cg.target); |
| 5627 | |
| 5628 | const needs_wrapping = switch (dest_class) { |
| 5629 | .int => |dest_int| dest_int.bits != cg.intBackingBits(dest_int.bits) and |
| 5630 | switch (src_class) { |
| 5631 | .int => |src_int| src_int.is_signed != dest_int.is_signed, |
| 5632 | .float, .aggregate => true, |
| 5602 | 5633 | }, |
| 5634 | .float, .aggregate => false, |
| 5635 | }; |
| 5636 | |
| 5637 | if (src_by_ref and dest_by_ref) { |
| 5638 | if (needs_wrapping) return try cg.intWrap(dest_class.int, operand); |
| 5639 | return null; |
| 5640 | } |
| 5641 | |
| 5642 | if (dest_by_ref) { |
| 5643 | const result = try cg.allocStack(src_ty); |
| 5644 | try cg.store(result, operand, src_ty, 0); |
| 5645 | return result; |
| 5646 | } |
| 5647 | |
| 5648 | if (src_by_ref) { |
| 5649 | return try cg.load(operand, dest_ty, 0); |
| 5650 | } |
| 5651 | |
| 5652 | switch (src_class) { |
| 5653 | .float => |float_ty| switch (float_ty) { |
| 5654 | .f16 => return try cg.intWrap(dest_class.int, operand), |
| 5603 | 5655 | .f32 => { |
| 5604 | 5656 | try cg.emitWValue(operand); |
| 5605 | 5657 | try cg.addTag(.i32_reinterpret_f32); |
| ... | ... | @@ -5610,19 +5662,15 @@ fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerErro |
| 5610 | 5662 | try cg.addTag(.i64_reinterpret_f64); |
| 5611 | 5663 | return .stack; |
| 5612 | 5664 | }, |
| 5613 | | } |
| 5665 | .f80, .f128 => unreachable, |
| 5666 | }, |
| 5667 | .int => {}, |
| 5668 | .aggregate => unreachable, |
| 5614 | 5669 | } |
| 5615 | 5670 | |
| 5616 | | if (dest_ty.isAnyFloat()) { |
| 5617 | | const float_ty: FloatType = .fromType(cg, dest_ty); |
| 5618 | | switch (float_ty) { |
| 5619 | | .f16, .f80, .f128 => { |
| 5620 | | if (src_signed) { |
| 5621 | | return try cg.intWrap(.{ .bits = @intCast(bit_size), .is_signed = false }, operand); |
| 5622 | | } else { |
| 5623 | | return null; |
| 5624 | | } |
| 5625 | | }, |
| 5671 | switch (dest_class) { |
| 5672 | .float => |float_ty| switch (float_ty) { |
| 5673 | .f16 => return null, |
| 5626 | 5674 | .f32 => { |
| 5627 | 5675 | try cg.emitWValue(operand); |
| 5628 | 5676 | try cg.addTag(.f32_reinterpret_i32); |
| ... | ... | @@ -5633,40 +5681,17 @@ fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerErro |
| 5633 | 5681 | try cg.addTag(.f64_reinterpret_i64); |
| 5634 | 5682 | return .stack; |
| 5635 | 5683 | }, |
| 5636 | | } |
| 5637 | | } |
| 5638 | | |
| 5639 | | if (isByRef(src_ty, zcu, cg.target) and !isByRef(dest_ty, zcu, cg.target)) { |
| 5640 | | const loaded_memory = try cg.load(operand, dest_ty, 0); |
| 5641 | | if (needs_wrapping) { |
| 5642 | | const int_ty: IntType = .fromType(cg, dest_ty); |
| 5643 | | return try cg.intWrap(int_ty, loaded_memory); |
| 5644 | | } else { |
| 5645 | | return loaded_memory; |
| 5646 | | } |
| 5647 | | } |
| 5648 | | |
| 5649 | | if (!isByRef(src_ty, zcu, cg.target) and isByRef(dest_ty, zcu, cg.target)) { |
| 5650 | | const stack_memory = try cg.allocStack(dest_ty); |
| 5651 | | try cg.store(stack_memory, operand, src_ty, 0); |
| 5652 | | if (needs_wrapping) { |
| 5653 | | const int_ty: IntType = .fromType(cg, dest_ty); |
| 5654 | | return try cg.intWrap(int_ty, stack_memory); |
| 5655 | | } else { |
| 5656 | | return stack_memory; |
| 5657 | | } |
| 5684 | .f80, .f128 => unreachable, |
| 5685 | }, |
| 5686 | .int => {}, |
| 5687 | .aggregate => unreachable, |
| 5658 | 5688 | } |
| 5659 | 5689 | |
| 5660 | 5690 | if (needs_wrapping) { |
| 5661 | | const int_ty: IntType = .fromType(cg, dest_ty); |
| 5662 | | return try cg.intWrap(int_ty, operand); |
| 5691 | return try cg.intWrap(dest_class.int, operand); |
| 5663 | 5692 | } |
| 5664 | 5693 | |
| 5665 | | return switch (operand) { |
| 5666 | | // for stack offset, return a pointer to this offset. |
| 5667 | | .stack_offset => try cg.buildPointerOffset(operand, 0, .new), |
| 5668 | | else => null, // caller should use cg.reuseOperand, if returnes for AIR |
| 5669 | | }; |
| 5694 | return null; |
| 5670 | 5695 | } |
| 5671 | 5696 | |
| 5672 | 5697 | fn airStructFieldPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| ... | ... | @@ -6992,8 +7017,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6992 | 7017 | } |
| 6993 | 7018 | break :result result_ptr; |
| 6994 | 7019 | } else { |
| 6995 | | const operand = try cg.resolveInst(extra.init); |
| 6996 | | break :result (try cg.bitcast(union_ty, field_ty, operand)) orelse cg.reuseOperand(extra.init, operand); |
| 7020 | unreachable; |
| 6997 | 7021 | } |
| 6998 | 7022 | }; |
| 6999 | 7023 | |