| ... | @@ -341,7 +341,7 @@ const InnerError = error{ | ... | @@ -341,7 +341,7 @@ const InnerError = error{ |
| 341 | AlreadyReported, | 341 | AlreadyReported, |
| 342 | /// Compiler implementation could not handle a large integer. | 342 | /// Compiler implementation could not handle a large integer. |
| 343 | Overflow, | 343 | Overflow, |
| 344 | } || link.File.UpdateDebugInfoError; | 344 | }; |
| 345 | | 345 | |
| 346 | pub fn deinit(cg: *CodeGen) void { | 346 | pub fn deinit(cg: *CodeGen) void { |
| 347 | const gpa = cg.gpa; | 347 | const gpa = cg.gpa; |
| ... | @@ -1577,7 +1577,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -1577,7 +1577,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1577 | .int_from_ptr => cg.airIntFromPtr(inst), | 1577 | .int_from_ptr => cg.airIntFromPtr(inst), |
| 1578 | | 1578 | |
| 1579 | .bit_cast => cg.airBitcast(inst), | 1579 | .bit_cast => cg.airBitcast(inst), |
| 1580 | .union_from_enum => cg.airBitcast(inst), | 1580 | .union_from_enum => cg.airUnionFromEnum(inst), |
| 1581 | | 1581 | |
| 1582 | .int_cast => { | 1582 | .int_cast => { |
| 1583 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 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,6 +5570,21 @@ fn airIntFromPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5570 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 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 | fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 5588 | fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5574 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 5589 | const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 5575 | const operand = try cg.resolveInst(ty_op.operand); | 5590 | const operand = try cg.resolveInst(ty_op.operand); |
| ... | @@ -5581,25 +5596,62 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5581,25 +5596,62 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5581 | return cg.finishAir(inst, result, &.{ty_op.operand}); | 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 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { | 5621 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { |
| 5585 | const zcu = cg.pt.zcu; | 5622 | const zcu = cg.pt.zcu; |
| 5586 | const bit_size = src_ty.bitSize(zcu); | 5623 | const src_class = cg.bitcastClass(src_ty); |
| 5587 | const dest_signed = if (dest_ty.isAbiInt(zcu)) IntType.fromType(cg, dest_ty).is_signed else false; | 5624 | const dest_class = cg.bitcastClass(dest_ty); |
| 5588 | const src_signed = if (src_ty.isAbiInt(zcu)) IntType.fromType(cg, src_ty).is_signed else false; | 5625 | const src_by_ref = isByRef(src_ty, zcu, cg.target); |
| 5589 | const needs_wrapping = (src_signed != dest_signed) and | 5626 | const dest_by_ref = isByRef(dest_ty, zcu, cg.target); |
| 5590 | bit_size != 32 and bit_size != 64 and bit_size != 128; | 5627 | |
| 5591 | | 5628 | const needs_wrapping = switch (dest_class) { |
| 5592 | if (src_ty.isAnyFloat()) { | 5629 | .int => |dest_int| dest_int.bits != cg.intBackingBits(dest_int.bits) and |
| 5593 | const float_ty: FloatType = .fromType(cg, src_ty); | 5630 | switch (src_class) { |
| 5594 | switch (float_ty) { | 5631 | .int => |src_int| src_int.is_signed != dest_int.is_signed, |
| 5595 | .f16, .f80, .f128 => { | 5632 | .float, .aggregate => true, |
| 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 | } | | |
| 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 | .f32 => { | 5655 | .f32 => { |
| 5604 | try cg.emitWValue(operand); | 5656 | try cg.emitWValue(operand); |
| 5605 | try cg.addTag(.i32_reinterpret_f32); | 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,19 +5662,15 @@ fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerErro |
| 5610 | try cg.addTag(.i64_reinterpret_f64); | 5662 | try cg.addTag(.i64_reinterpret_f64); |
| 5611 | return .stack; | 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()) { | 5671 | switch (dest_class) { |
| 5617 | const float_ty: FloatType = .fromType(cg, dest_ty); | 5672 | .float => |float_ty| switch (float_ty) { |
| 5618 | switch (float_ty) { | 5673 | .f16 => return null, |
| 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 | }, | | |
| 5626 | .f32 => { | 5674 | .f32 => { |
| 5627 | try cg.emitWValue(operand); | 5675 | try cg.emitWValue(operand); |
| 5628 | try cg.addTag(.f32_reinterpret_i32); | 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,40 +5681,17 @@ fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerErro |
| 5633 | try cg.addTag(.f64_reinterpret_i64); | 5681 | try cg.addTag(.f64_reinterpret_i64); |
| 5634 | return .stack; | 5682 | return .stack; |
| 5635 | }, | 5683 | }, |
| 5636 | } | 5684 | .f80, .f128 => unreachable, |
| 5637 | } | 5685 | }, |
| 5638 | | 5686 | .int => {}, |
| 5639 | if (isByRef(src_ty, zcu, cg.target) and !isByRef(dest_ty, zcu, cg.target)) { | 5687 | .aggregate => unreachable, |
| 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 | } | | |
| 5658 | } | 5688 | } |
| 5659 | | 5689 | |
| 5660 | if (needs_wrapping) { | 5690 | if (needs_wrapping) { |
| 5661 | const int_ty: IntType = .fromType(cg, dest_ty); | 5691 | return try cg.intWrap(dest_class.int, operand); |
| 5662 | return try cg.intWrap(int_ty, operand); | | |
| 5663 | } | 5692 | } |
| 5664 | | 5693 | |
| 5665 | return switch (operand) { | 5694 | return null; |
| 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 | }; | | |
| 5670 | } | 5695 | } |
| 5671 | | 5696 | |
| 5672 | fn airStructFieldPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | 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,8 +7017,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 6992 | } | 7017 | } |
| 6993 | break :result result_ptr; | 7018 | break :result result_ptr; |
| 6994 | } else { | 7019 | } else { |
| 6995 | const operand = try cg.resolveInst(extra.init); | 7020 | unreachable; |
| 6996 | break :result (try cg.bitcast(union_ty, field_ty, operand)) orelse cg.reuseOperand(extra.init, operand); | | |
| 6997 | } | 7021 | } |
| 6998 | }; | 7022 | }; |
| 6999 | | 7023 | |