| ... | @@ -12607,18 +12607,16 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12607,18 +12607,16 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12607 | enum_obj.tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); | 12607 | enum_obj.tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator); |
| 12608 | | 12608 | |
| 12609 | // Fields | 12609 | // Fields |
| 12610 | const slice_val = fields_val.castTag(.slice).?.data; | 12610 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen()); |
| 12611 | const decl = slice_val.ptr.pointerDecl().?; | | |
| 12612 | try sema.ensureDeclAnalyzed(decl); | | |
| 12613 | const fields_len = try sema.usizeCast(block, src, decl.ty.arrayLen()); | | |
| 12614 | if (fields_len > 0) { | 12611 | if (fields_len > 0) { |
| 12615 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); | 12612 | try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| 12616 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ | 12613 | try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{ |
| 12617 | .ty = enum_obj.tag_ty, | 12614 | .ty = enum_obj.tag_ty, |
| 12618 | }); | 12615 | }); |
| 12619 | | 12616 | |
| 12620 | const array_vals = decl.val.castTag(.aggregate).?.data; | 12617 | var i: usize = 0; |
| 12621 | for (array_vals) |elem_val| { | 12618 | while (i < fields_len) : (i += 1) { |
| | 12619 | const elem_val = try fields_val.elemValue(sema.arena, i); |
| 12622 | const field_struct_val = elem_val.castTag(.aggregate).?.data; | 12620 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| 12623 | // TODO use reflection instead of magic numbers here | 12621 | // TODO use reflection instead of magic numbers here |
| 12624 | // name: []const u8 | 12622 | // name: []const u8 |
| ... | @@ -12691,7 +12689,103 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I | ... | @@ -12691,7 +12689,103 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 12691 | try new_decl.finalizeNewArena(&new_decl_arena); | 12689 | try new_decl.finalizeNewArena(&new_decl_arena); |
| 12692 | return sema.analyzeDeclVal(block, src, new_decl); | 12690 | return sema.analyzeDeclVal(block, src, new_decl); |
| 12693 | }, | 12691 | }, |
| 12694 | .Union => return sema.fail(block, src, "TODO: Sema.zirReify for Union", .{}), | 12692 | .Union => { |
| | 12693 | // TODO use reflection instead of magic numbers here |
| | 12694 | const struct_val = union_val.val.castTag(.aggregate).?.data; |
| | 12695 | // layout: containerlayout, |
| | 12696 | const layout_val = struct_val[0]; |
| | 12697 | // tag_type: ?type, |
| | 12698 | const tag_type_val = struct_val[1]; |
| | 12699 | // fields: []const enumfield, |
| | 12700 | const fields_val = struct_val[2]; |
| | 12701 | // decls: []const declaration, |
| | 12702 | const decls_val = struct_val[3]; |
| | 12703 | |
| | 12704 | // Decls |
| | 12705 | if (decls_val.sliceLen() > 0) { |
| | 12706 | return sema.fail(block, src, "reified unions must have no decls", .{}); |
| | 12707 | } |
| | 12708 | |
| | 12709 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |
| | 12710 | errdefer new_decl_arena.deinit(); |
| | 12711 | const new_decl_arena_allocator = new_decl_arena.allocator(); |
| | 12712 | |
| | 12713 | const union_obj = try new_decl_arena_allocator.create(Module.Union); |
| | 12714 | const type_tag: Type.Tag = if (!tag_type_val.isNull()) .union_tagged else .@"union"; |
| | 12715 | const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union); |
| | 12716 | union_payload.* = .{ |
| | 12717 | .base = .{ .tag = type_tag }, |
| | 12718 | .data = union_obj, |
| | 12719 | }; |
| | 12720 | const union_ty = Type.initPayload(&union_payload.base); |
| | 12721 | const new_union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty); |
| | 12722 | const type_name = try sema.createTypeName(block, .anon); |
| | 12723 | const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ |
| | 12724 | .ty = Type.type, |
| | 12725 | .val = new_union_val, |
| | 12726 | }, type_name); |
| | 12727 | new_decl.owns_tv = true; |
| | 12728 | errdefer sema.mod.abortAnonDecl(new_decl); |
| | 12729 | union_obj.* = .{ |
| | 12730 | .owner_decl = new_decl, |
| | 12731 | .tag_ty = Type.initTag(.@"null"), |
| | 12732 | .fields = .{}, |
| | 12733 | .node_offset = src.node_offset, |
| | 12734 | .zir_index = inst, |
| | 12735 | .layout = layout_val.toEnum(std.builtin.Type.ContainerLayout), |
| | 12736 | .status = .have_field_types, |
| | 12737 | .namespace = .{ |
| | 12738 | .parent = block.namespace, |
| | 12739 | .ty = union_ty, |
| | 12740 | .file_scope = block.getFileScope(), |
| | 12741 | }, |
| | 12742 | }; |
| | 12743 | |
| | 12744 | // Tag type |
| | 12745 | const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen()); |
| | 12746 | union_obj.tag_ty = if (tag_type_val.optionalValue()) |payload_val| blk: { |
| | 12747 | var buffer: Value.ToTypeBuffer = undefined; |
| | 12748 | break :blk try payload_val.toType(&buffer).copy(new_decl_arena_allocator); |
| | 12749 | } else try sema.generateUnionTagTypeSimple(block, fields_len); |
| | 12750 | |
| | 12751 | // Fields |
| | 12752 | if (fields_len > 0) { |
| | 12753 | try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len); |
| | 12754 | |
| | 12755 | var i: usize = 0; |
| | 12756 | while (i < fields_len) : (i += 1) { |
| | 12757 | const elem_val = try fields_val.elemValue(sema.arena, i); |
| | 12758 | const field_struct_val = elem_val.castTag(.aggregate).?.data; |
| | 12759 | // TODO use reflection instead of magic numbers here |
| | 12760 | // name: []const u8 |
| | 12761 | const name_val = field_struct_val[0]; |
| | 12762 | // field_type: type, |
| | 12763 | const field_type_val = field_struct_val[1]; |
| | 12764 | // alignment: comptime_int, |
| | 12765 | const alignment_val = field_struct_val[2]; |
| | 12766 | |
| | 12767 | const field_name = try name_val.toAllocatedBytes( |
| | 12768 | Type.initTag(.const_slice_u8), |
| | 12769 | new_decl_arena_allocator, |
| | 12770 | ); |
| | 12771 | |
| | 12772 | const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); |
| | 12773 | if (gop.found_existing) { |
| | 12774 | // TODO: better source location |
| | 12775 | return sema.fail(block, src, "duplicate union field {s}", .{field_name}); |
| | 12776 | } |
| | 12777 | |
| | 12778 | var buffer: Value.ToTypeBuffer = undefined; |
| | 12779 | gop.value_ptr.* = .{ |
| | 12780 | .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator), |
| | 12781 | .abi_align = try alignment_val.copy(new_decl_arena_allocator), |
| | 12782 | }; |
| | 12783 | } |
| | 12784 | } |
| | 12785 | |
| | 12786 | try new_decl.finalizeNewArena(&new_decl_arena); |
| | 12787 | return sema.analyzeDeclVal(block, src, new_decl); |
| | 12788 | }, |
| 12695 | .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), | 12789 | .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), |
| 12696 | .BoundFn => @panic("TODO delete BoundFn from the language"), | 12790 | .BoundFn => @panic("TODO delete BoundFn from the language"), |
| 12697 | .Frame => @panic("TODO implement https://github.com/ziglang/zig/issues/10710"), | 12791 | .Frame => @panic("TODO implement https://github.com/ziglang/zig/issues/10710"), |
| ... | @@ -20417,7 +20511,7 @@ fn generateUnionTagTypeNumbered( | ... | @@ -20417,7 +20511,7 @@ fn generateUnionTagTypeNumbered( |
| 20417 | return enum_ty; | 20511 | return enum_ty; |
| 20418 | } | 20512 | } |
| 20419 | | 20513 | |
| 20420 | fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: u32) !Type { | 20514 | fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize) !Type { |
| 20421 | const mod = sema.mod; | 20515 | const mod = sema.mod; |
| 20422 | | 20516 | |
| 20423 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); | 20517 | var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); |