| author | |
| committer | |
| log | 9f4649b197b720dbc168ced25eee0805d3b678b1 |
| tree | edc09234b4d8385fce36a306bb36c55cfadd823c |
| parent | 4e9f5f25c8226144eff8d9c1df79cfcffbae5492 |
4 files changed, 51 insertions(+), 35 deletions(-)
src/Sema.zig+1-1| ... | ... | @@ -32879,7 +32879,7 @@ fn unionToTag( |
| 32879 | 32879 | return Air.internedToRef(opv.toIntern()); |
| 32880 | 32880 | } |
| 32881 | 32881 | if (try sema.resolveMaybeUndefVal(un)) |un_val| { |
| 32882 | return Air.internedToRef(un_val.unionTag(mod).toIntern()); | |
| 32882 | return Air.internedToRef(un_val.unionTag(mod).?.toIntern()); | |
| 32883 | 32883 | } |
| 32884 | 32884 | try sema.requireRuntimeBlock(block, un_src, null); |
| 32885 | 32885 | return block.addTyOp(.get_union_tag, enum_ty, un); |
src/TypedValue.zig+16-14| ... | ... | @@ -87,18 +87,19 @@ pub fn print( |
| 87 | 87 | const union_val = val.castTag(.@"union").?.data; |
| 88 | 88 | try writer.writeAll(".{ "); |
| 89 | 89 | |
| 90 | try print(.{ | |
| 91 | .ty = ip.indexToKey(ty.toIntern()).union_type.enum_tag_ty.toType(), | |
| 92 | .val = union_val.tag, | |
| 93 | }, writer, level - 1, mod); | |
| 94 | try writer.writeAll(" = "); | |
| 95 | if (ty.unionFieldType(union_val.tag, mod)) |field_ty| { | |
| 90 | if (union_val.tag.toIntern() != .none) { | |
| 91 | try print(.{ | |
| 92 | .ty = ip.indexToKey(ty.toIntern()).union_type.enum_tag_ty.toType(), | |
| 93 | .val = union_val.tag, | |
| 94 | }, writer, level - 1, mod); | |
| 95 | try writer.writeAll(" = "); | |
| 96 | const field_ty = ty.unionFieldType(union_val.tag, mod).?; | |
| 96 | 97 | try print(.{ |
| 97 | 98 | .ty = field_ty, |
| 98 | 99 | .val = union_val.val, |
| 99 | 100 | }, writer, level - 1, mod); |
| 100 | 101 | } else { |
| 101 | return writer.writeAll("(no tag)"); | |
| 102 | return writer.writeAll("(unknown tag)"); | |
| 102 | 103 | } |
| 103 | 104 | |
| 104 | 105 | return writer.writeAll(" }"); |
| ... | ... | @@ -408,18 +409,19 @@ pub fn print( |
| 408 | 409 | .un => |un| { |
| 409 | 410 | try writer.writeAll(".{ "); |
| 410 | 411 | if (level > 0) { |
| 411 | try print(.{ | |
| 412 | .ty = ty.unionTagTypeHypothetical(mod), | |
| 413 | .val = un.tag.toValue(), | |
| 414 | }, writer, level - 1, mod); | |
| 415 | try writer.writeAll(" = "); | |
| 416 | if (ty.unionFieldType(un.tag.toValue(), mod)) |field_ty| { | |
| 412 | if (un.tag != .none) { | |
| 413 | try print(.{ | |
| 414 | .ty = ty.unionTagTypeHypothetical(mod), | |
| 415 | .val = un.tag.toValue(), | |
| 416 | }, writer, level - 1, mod); | |
| 417 | try writer.writeAll(" = "); | |
| 418 | const field_ty = ty.unionFieldType(un.tag.toValue(), mod).?; | |
| 417 | 419 | try print(.{ |
| 418 | 420 | .ty = field_ty, |
| 419 | 421 | .val = un.val.toValue(), |
| 420 | 422 | }, writer, level - 1, mod); |
| 421 | 423 | } else { |
| 422 | try writer.writeAll("(no tag)"); | |
| 424 | try writer.writeAll("(unknown tag)"); | |
| 423 | 425 | } |
| 424 | 426 | } else try writer.writeAll("..."); |
| 425 | 427 | return writer.writeAll(" }"); |
src/codegen.zig+19-10| ... | ... | @@ -583,24 +583,33 @@ pub fn generateSymbol( |
| 583 | 583 | } |
| 584 | 584 | |
| 585 | 585 | const union_obj = mod.typeToUnion(typed_value.ty).?; |
| 586 | const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?; | |
| 586 | if (un.tag != .none) { | |
| 587 | const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?; | |
| 588 | const field_ty = union_obj.field_types.get(ip)[field_index].toType(); | |
| 589 | if (!field_ty.hasRuntimeBits(mod)) { | |
| 590 | try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); | |
| 591 | } else { | |
| 592 | switch (try generateSymbol(bin_file, src_loc, .{ | |
| 593 | .ty = field_ty, | |
| 594 | .val = un.val.toValue(), | |
| 595 | }, code, debug_output, reloc_info)) { | |
| 596 | .ok => {}, | |
| 597 | .fail => |em| return Result{ .fail = em }, | |
| 598 | } | |
| 587 | 599 | |
| 588 | const field_ty = union_obj.field_types.get(ip)[field_index].toType(); | |
| 589 | if (!field_ty.hasRuntimeBits(mod)) { | |
| 590 | try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); | |
| 600 | const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow; | |
| 601 | if (padding > 0) { | |
| 602 | try code.appendNTimes(0, padding); | |
| 603 | } | |
| 604 | } | |
| 591 | 605 | } else { |
| 592 | 606 | switch (try generateSymbol(bin_file, src_loc, .{ |
| 593 | .ty = field_ty, | |
| 607 | .ty = ip.typeOf(un.val).toType(), | |
| 594 | 608 | .val = un.val.toValue(), |
| 595 | 609 | }, code, debug_output, reloc_info)) { |
| 596 | 610 | .ok => {}, |
| 597 | 611 | .fail => |em| return Result{ .fail = em }, |
| 598 | 612 | } |
| 599 | ||
| 600 | const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow; | |
| 601 | if (padding > 0) { | |
| 602 | try code.appendNTimes(0, padding); | |
| 603 | } | |
| 604 | 613 | } |
| 605 | 614 | |
| 606 | 615 | if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) { |
src/value.zig+15-10| ... | ... | @@ -706,8 +706,8 @@ pub const Value = struct { |
| 706 | 706 | .Auto => return error.IllDefinedMemoryLayout, // Sema is supposed to have emitted a compile error already |
| 707 | 707 | .Extern => { |
| 708 | 708 | const union_obj = mod.typeToUnion(ty).?; |
| 709 | const union_tag = val.unionTag(mod); | |
| 710 | if (mod.unionTagFieldIndex(union_obj, union_tag)) |field_index| { | |
| 709 | if (val.unionTag(mod)) |union_tag| { | |
| 710 | const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?; | |
| 711 | 711 | const field_type = union_obj.field_types.get(&mod.intern_pool)[field_index].toType(); |
| 712 | 712 | const field_val = try val.fieldValue(mod, field_index); |
| 713 | 713 | const byte_count = @as(usize, @intCast(field_type.abiSize(mod))); |
| ... | ... | @@ -715,7 +715,7 @@ pub const Value = struct { |
| 715 | 715 | } else { |
| 716 | 716 | const union_size = ty.abiSize(mod); |
| 717 | 717 | const array_type = try mod.arrayType(.{ .len = union_size, .child = .u8_type }); |
| 718 | return writeToMemory(val.unionValue(mod), array_type, mod, buffer[0..union_size]); | |
| 718 | return writeToMemory(val.unionValue(mod), array_type, mod, buffer[0..@as(usize, @intCast(union_size))]); | |
| 719 | 719 | } |
| 720 | 720 | }, |
| 721 | 721 | .Packed => { |
| ... | ... | @@ -832,10 +832,16 @@ pub const Value = struct { |
| 832 | 832 | switch (union_obj.getLayout(ip)) { |
| 833 | 833 | .Auto, .Extern => unreachable, // Handled in non-packed writeToMemory |
| 834 | 834 | .Packed => { |
| 835 | const field_index = mod.unionTagFieldIndex(union_obj, val.unionTag(mod)).?; | |
| 836 | const field_type = union_obj.field_types.get(ip)[field_index].toType(); | |
| 837 | const field_val = try val.fieldValue(mod, field_index); | |
| 838 | return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset); | |
| 835 | if (val.unionTag(mod)) |union_tag| { | |
| 836 | const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?; | |
| 837 | const field_type = union_obj.field_types.get(ip)[field_index].toType(); | |
| 838 | const field_val = try val.fieldValue(mod, field_index); | |
| 839 | return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset); | |
| 840 | } else { | |
| 841 | const union_bits: u16 = @intCast(ty.bitSize(mod)); | |
| 842 | const int_ty = try mod.intType(.unsigned, union_bits); | |
| 843 | return val.unionValue(mod).writeToPackedMemory(int_ty, mod, buffer, bit_offset); | |
| 844 | } | |
| 839 | 845 | }, |
| 840 | 846 | } |
| 841 | 847 | }, |
| ... | ... | @@ -1137,7 +1143,6 @@ pub const Value = struct { |
| 1137 | 1143 | .Auto, .Extern => unreachable, // Handled by non-packed readFromMemory |
| 1138 | 1144 | .Packed => { |
| 1139 | 1145 | const union_bits: u16 = @intCast(ty.bitSize(mod)); |
| 1140 | // TODO: Remove after tests pass | |
| 1141 | 1146 | assert(union_bits != 0); |
| 1142 | 1147 | const int_ty = try mod.intType(.unsigned, union_bits); |
| 1143 | 1148 | const val = (try readFromPackedMemory(int_ty, mod, buffer, bit_offset, arena)).toIntern(); |
| ... | ... | @@ -1754,11 +1759,11 @@ pub const Value = struct { |
| 1754 | 1759 | }; |
| 1755 | 1760 | } |
| 1756 | 1761 | |
| 1757 | pub fn unionTag(val: Value, mod: *Module) Value { | |
| 1762 | pub fn unionTag(val: Value, mod: *Module) ?Value { | |
| 1758 | 1763 | if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag; |
| 1759 | 1764 | return switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| 1760 | 1765 | .undef, .enum_tag => val, |
| 1761 | .un => |un| un.tag.toValue(), | |
| 1766 | .un => |un| if (un.tag != .none) un.tag.toValue() else return null, | |
| 1762 | 1767 | else => unreachable, |
| 1763 | 1768 | }; |
| 1764 | 1769 | } |