authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-11-22 21:59:46+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-11-22 22:42:37+00:00
logc5383173a0de17210f3036acd942738e906997e5
tree081ef03298de2fbfe679e7eb843f24036c7a9c1c
parent3f2cf1c002a8eb46fa9beb9854c43174b5816e67
signaturelock-open Commit is signed but in an unrecognized format.

compiler: replace `@Type` with individual type-creating builtins

The new builtins are: * `@EnumLiteral` * `@Int` * `@Fn` * `@Pointer` * `@Tuple` * `@Enum` * `@Union` * `@Struct` Their usage is documented in the language reference. There is no `@Array` because arrays can be created like this: if (sentinel) |s| [n:s]T else [n]T There is also no `@Float`. Instead, `std.meta.Float` can serve this use case if necessary. There is no `@ErrorSet` and intentionally no way to achieve this. Likewise, there is intentionally no way to reify tuples with comptime fields, or function types with comptime parameters. These decisions simplify the Zig language specification, and moreover make Zig code more readable by discouraging overly complex metaprogramming. Co-authored-by: Ali Cheraghi <alichraghi@proton.me> Resolves: #10710

16 files changed, 2034 insertions(+), 1429 deletions(-)

doc/langref.html.in+74-40
......@@ -638,7 +638,7 @@
638638 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
639639 integer type is {#syntax#}65535{#endsyntax#}.
640640 </p>
641 {#see_also|Integers|Floats|void|Errors|@Type#}
641 {#see_also|Integers|Floats|void|Errors|@Int#}
642642 {#header_close#}
643643 {#header_open|Primitive Values#}
644644 <div class="table-wrapper">
......@@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {
37233723 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>
37243724 </tr>
37253725 <tr>
3726 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>
3726 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
37273727 <td>-</td>
3728 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Type{#endsyntax#}</td>
3728 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Signedness{#endsyntax#}, {#syntax#}y{#endsyntax#} is a {#syntax#}u16{#endsyntax#}</td>
37293729 </tr>
37303730 <tr>
37313731 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
......@@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {
38393839 <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>
38403840 </tr>
38413841 <tr>
3842 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>
3843 <td>{#syntax#}ptr{#endsyntax#}</td>
3844 <td>{#syntax#}x{#endsyntax#} has no result location</td>
3842 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
3843 <td>-</td>
3844 <td>{#syntax#}x{#endsyntax#} and {#syntax#}y{#endsyntax#} do not have result locations</td>
38453845 </tr>
38463846 <tr>
38473847 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
......@@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
57555755 </p>
57565756 {#header_close#}
57575757
5758 {#header_open|@Type#}
5759 <pre>{#syntax#}@Type(comptime info: std.builtin.Type) type{#endsyntax#}</pre>
5760 <p>
5761 This function is the inverse of {#link|@typeInfo#}. It reifies type information
5762 into a {#syntax#}type{#endsyntax#}.
5763 </p>
5764 <p>
5765 It is available for the following types:
5766 </p>
5767 <ul>
5768 <li>{#syntax#}type{#endsyntax#}</li>
5769 <li>{#syntax#}noreturn{#endsyntax#}</li>
5770 <li>{#syntax#}void{#endsyntax#}</li>
5771 <li>{#syntax#}bool{#endsyntax#}</li>
5772 <li>{#link|Integers#} - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.</li>
5773 <li>{#link|Floats#}</li>
5774 <li>{#link|Pointers#}</li>
5775 <li>{#syntax#}comptime_int{#endsyntax#}</li>
5776 <li>{#syntax#}comptime_float{#endsyntax#}</li>
5777 <li>{#syntax#}@TypeOf(undefined){#endsyntax#}</li>
5778 <li>{#syntax#}@TypeOf(null){#endsyntax#}</li>
5779 <li>{#link|Arrays#}</li>
5780 <li>{#link|Optionals#}</li>
5781 <li>{#link|Error Set Type#}</li>
5782 <li>{#link|Error Union Type#}</li>
5783 <li>{#link|Vectors#}</li>
5784 <li>{#link|opaque#}</li>
5785 <li>{#syntax#}anyframe{#endsyntax#}</li>
5786 <li>{#link|struct#}</li>
5787 <li>{#link|enum#}</li>
5788 <li>{#link|Enum Literals#}</li>
5789 <li>{#link|union#}</li>
5790 <li>{#link|Functions#}</li>
5791 </ul>
5758 {#header_open|@EnumLiteral#}
5759 <pre>{#syntax#}@EnumLiteral() type{#endsyntax#}</pre>
5760 <p>Returns the comptime-only "enum literal" type. This is the type of uncoerced {#link|Enum Literals#}. Values of this type can coerce to any {#link|enum#} with a matching field.</p>
5761 {#header_close#}
5762
5763 {#header_open|@Int#}
5764 <pre>{#syntax#}@Int(comptime signedness: std.builtin.Signedness, comptime bits: u16) type{#endsyntax#}</pre>
5765 <p>Returns an integer type with the given signedness and bit width.</p>
5766 <p>For instance, {#syntax#}@Int(.unsigned, 18){#endsyntax#} returns the type {#syntax#}u18{#endsyntax#}.</p>
57925767 {#header_close#}
5768
5769 {#header_open|@Tuple#}
5770 <pre>{#syntax#}@Tuple(comptime field_types: []const type) type{#endsyntax#}</pre>
5771 <p>Returns a {#link|tuple|Tuples#} type with the given field types.</p>
5772 {#header_close#}
5773
5774 {#header_open|@Pointer#}
5775 <pre>{#syntax#}@Pointer(
5776 comptime size: std.builtin.Type.Pointer.Size,
5777 comptime attrs: std.builtin.Type.Pointer.Attributes,
5778 comptime Element: type,
5779 comptime sentinel: ?Element,
5780) type{#endsyntax#}</pre>
5781 <p>Returns a {#link|pointer|Pointers#} type with the properties specified by the arguments.</p>
5782 {#header_close#}
5783
5784 {#header_open|@Fn#}
5785 <pre>{#syntax#}@Fn(
5786 comptime param_types: []const type,
5787 comptime param_attrs: *const [param_types.len]std.builtin.Type.Fn.Param.Attributes,
5788 comptime ReturnType: type,
5789 comptime attrs: std.builtin.Type.Fn.Attributes,
5790) type{#endsyntax#}</pre>
5791 <p>Returns a {#link|function|Functions#} type with the properties specified by the arguments.</p>
5792 {#header_close#}
5793
5794 {#header_open|@Struct#}
5795 <pre>{#syntax#}@Struct(
5796 comptime layout: std.builtin.Type.ContainerLayout,
5797 comptime BackingInt: ?type,
5798 comptime field_names: []const []const u8,
5799 comptime field_types: *const [field_names.len]type,
5800 comptime field_attrs: *const [field_names.len]std.builtin.Type.StructField.Attributes,
5801) type{#endsyntax#}</pre>
5802 <p>Returns a {#link|struct#} type with the properties specified by the arguments.</p>
5803 {#header_close#}
5804
5805 {#header_open|@Union#}
5806 <pre>{#syntax#}@Union(
5807 comptime layout: std.builtin.Type.ContainerLayout,
5808 /// Either the integer tag type, or the integer backing type, depending on `layout`.
5809 comptime ArgType: ?type,
5810 comptime field_names: []const []const u8,
5811 comptime field_types: *const [field_names.len]type,
5812 comptime field_attrs: *const [field_names.len]std.builtin.Type.UnionField.Attributes,
5813) type{#endsyntax#}</pre>
5814 <p>Returns a {#link|union#} type with the properties specified by the arguments.</p>
5815 {#header_close#}
5816
5817 {#header_open|@Enum#}
5818 <pre>{#syntax#}@Enum(
5819 comptime TagInt: type,
5820 comptime mode: std.builtin.Type.Enum.Mode,
5821 comptime field_names: []const []const u8,
5822 comptime field_values: *const [field_names.len]TagInt,
5823) type{#endsyntax#}</pre>
5824 <p>Returns an {#link|enum#} type with the properties specified by the arguments.</p>
5825 {#header_close#}
5826
57935827 {#header_open|@typeInfo#}
57945828 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>
57955829 <p>
lib/std/builtin.zig+50-9
......@@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);
548548/// This data structure is used by the Zig language code generation and
549549/// therefore must be kept in sync with the compiler implementation.
550550pub const Type = union(enum) {
551 type: void,
552 void: void,
553 bool: void,
554 noreturn: void,
551 type,
552 void,
553 bool,
554 noreturn,
555555 int: Int,
556556 float: Float,
557557 pointer: Pointer,
558558 array: Array,
559559 @"struct": Struct,
560 comptime_float: void,
561 comptime_int: void,
562 undefined: void,
563 null: void,
560 comptime_float,
561 comptime_int,
562 undefined,
563 null,
564564 optional: Optional,
565565 error_union: ErrorUnion,
566566 error_set: ErrorSet,
......@@ -571,7 +571,7 @@ pub const Type = union(enum) {
571571 frame: Frame,
572572 @"anyframe": AnyFrame,
573573 vector: Vector,
574 enum_literal: void,
574 enum_literal,
575575
576576 /// This data structure is used by the Zig language code generation and
577577 /// therefore must be kept in sync with the compiler implementation.
......@@ -619,6 +619,16 @@ pub const Type = union(enum) {
619619 slice,
620620 c,
621621 };
622
623 /// This data structure is used by the Zig language code generation and
624 /// therefore must be kept in sync with the compiler implementation.
625 pub const Attributes = struct {
626 @"const": bool = false,
627 @"volatile": bool = false,
628 @"allowzero": bool = false,
629 @"addrspace": ?AddressSpace = null,
630 @"align": ?usize = null,
631 };
622632 };
623633
624634 /// This data structure is used by the Zig language code generation and
......@@ -668,6 +678,14 @@ pub const Type = union(enum) {
668678 const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));
669679 return dp.*;
670680 }
681
682 /// This data structure is used by the Zig language code generation and
683 /// therefore must be kept in sync with the compiler implementation.
684 pub const Attributes = struct {
685 @"comptime": bool = false,
686 @"align": ?usize = null,
687 default_value_ptr: ?*const anyopaque = null,
688 };
671689 };
672690
673691 /// This data structure is used by the Zig language code generation and
......@@ -718,6 +736,10 @@ pub const Type = union(enum) {
718736 fields: []const EnumField,
719737 decls: []const Declaration,
720738 is_exhaustive: bool,
739
740 /// This data structure is used by the Zig language code generation and
741 /// therefore must be kept in sync with the compiler implementation.
742 pub const Mode = enum { exhaustive, nonexhaustive };
721743 };
722744
723745 /// This data structure is used by the Zig language code generation and
......@@ -726,6 +748,12 @@ pub const Type = union(enum) {
726748 name: [:0]const u8,
727749 type: type,
728750 alignment: comptime_int,
751
752 /// This data structure is used by the Zig language code generation and
753 /// therefore must be kept in sync with the compiler implementation.
754 pub const Attributes = struct {
755 @"align": ?usize = null,
756 };
729757 };
730758
731759 /// This data structure is used by the Zig language code generation and
......@@ -753,6 +781,19 @@ pub const Type = union(enum) {
753781 is_generic: bool,
754782 is_noalias: bool,
755783 type: ?type,
784
785 /// This data structure is used by the Zig language code generation and
786 /// therefore must be kept in sync with the compiler implementation.
787 pub const Attributes = struct {
788 @"noalias": bool = false,
789 };
790 };
791
792 /// This data structure is used by the Zig language code generation and
793 /// therefore must be kept in sync with the compiler implementation.
794 pub const Attributes = struct {
795 @"callconv": CallingConvention = .auto,
796 varargs: bool = false,
756797 };
757798 };
758799
lib/std/zig.zig+40-24
......@@ -773,7 +773,6 @@ pub const EnvVar = enum {
773773pub const SimpleComptimeReason = enum(u32) {
774774 // Evaluating at comptime because a builtin operand must be comptime-known.
775775 // These messages all mention a specific builtin.
776 operand_Type,
777776 operand_setEvalBranchQuota,
778777 operand_setFloatMode,
779778 operand_branchHint,
......@@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {
809808 // Evaluating at comptime because types must be comptime-known.
810809 // Reasons other than `.type` are just more specific messages.
811810 type,
811 int_signedness,
812 int_bit_width,
812813 array_sentinel,
814 array_length,
815 pointer_size,
816 pointer_attrs,
813817 pointer_sentinel,
814818 slice_sentinel,
815 array_length,
816819 vector_length,
817 error_set_contents,
818 struct_fields,
819 enum_fields,
820 union_fields,
821 function_ret_ty,
822 function_parameters,
820 fn_ret_ty,
821 fn_param_types,
822 fn_param_attrs,
823 fn_attrs,
824 struct_layout,
825 struct_field_names,
826 struct_field_types,
827 struct_field_attrs,
828 union_layout,
829 union_field_names,
830 union_field_types,
831 union_field_attrs,
832 tuple_field_types,
833 enum_field_names,
834 enum_field_values,
823835
824836 // Evaluating at comptime because decl/field name must be comptime-known.
825837 decl_name,
826838 field_name,
827 struct_field_name,
828 enum_field_name,
829 union_field_name,
830 tuple_field_name,
831839 tuple_field_index,
832840
833841 // Evaluating at comptime because it is an attribute of a global declaration.
......@@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {
856864 pub fn message(r: SimpleComptimeReason) []const u8 {
857865 return switch (r) {
858866 // zig fmt: off
859 .operand_Type => "operand to '@Type' must be comptime-known",
860867 .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
861868 .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
862869 .operand_branchHint => "operand to '@branchHint' must be comptime-known",
......@@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {
888895 .clobber => "clobber must be comptime-known",
889896
890897 .type => "types must be comptime-known",
898 .int_signedness => "integer signedness must be comptime-known",
899 .int_bit_width => "integer bit width must be comptime-known",
891900 .array_sentinel => "array sentinel value must be comptime-known",
901 .array_length => "array length must be comptime-known",
902 .pointer_size => "pointer size must be comptime-known",
903 .pointer_attrs => "pointer attributes must be comptime-known",
892904 .pointer_sentinel => "pointer sentinel value must be comptime-known",
893905 .slice_sentinel => "slice sentinel value must be comptime-known",
894 .array_length => "array length must be comptime-known",
895906 .vector_length => "vector length must be comptime-known",
896 .error_set_contents => "error set contents must be comptime-known",
897 .struct_fields => "struct fields must be comptime-known",
898 .enum_fields => "enum fields must be comptime-known",
899 .union_fields => "union fields must be comptime-known",
900 .function_ret_ty => "function return type must be comptime-known",
901 .function_parameters => "function parameters must be comptime-known",
907 .fn_ret_ty => "function return type must be comptime-known",
908 .fn_param_types => "function parameter types must be comptime-known",
909 .fn_param_attrs => "function parameter attributes must be comptime-known",
910 .fn_attrs => "function attributes must be comptime-known",
911 .struct_layout => "struct layout must be comptime-known",
912 .struct_field_names => "struct field names must be comptime-known",
913 .struct_field_types => "struct field types must be comptime-known",
914 .struct_field_attrs => "struct field attributes must be comptime-known",
915 .union_layout => "union layout must be comptime-known",
916 .union_field_names => "union field names must be comptime-known",
917 .union_field_types => "union field types must be comptime-known",
918 .union_field_attrs => "union field attributes must be comptime-known",
919 .tuple_field_types => "tuple field types must be comptime-known",
920 .enum_field_names => "enum field names must be comptime-known",
921 .enum_field_values => "enum field values must be comptime-known",
902922
903923 .decl_name => "declaration name must be comptime-known",
904924 .field_name => "field name must be comptime-known",
905 .struct_field_name => "struct field name must be comptime-known",
906 .enum_field_name => "enum field name must be comptime-known",
907 .union_field_name => "union field name must be comptime-known",
908 .tuple_field_name => "tuple field name must be comptime-known",
909925 .tuple_field_index => "tuple field index must be comptime-known",
910926
911927 .container_var_init => "initializer of container-level variable must be comptime-known",
lib/std/zig/AstGen.zig+150-46
......@@ -833,7 +833,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
833833 => {
834834 var buf: [2]Ast.Node.Index = undefined;
835835 const params = tree.builtinCallParams(&buf, node).?;
836 return builtinCall(gz, scope, ri, node, params, false);
836 return builtinCall(gz, scope, ri, node, params, false, .anon);
837837 },
838838
839839 .call_one,
......@@ -1194,14 +1194,20 @@ fn nameStratExpr(
11941194 },
11951195 .builtin_call_two,
11961196 .builtin_call_two_comma,
1197 .builtin_call,
1198 .builtin_call_comma,
11971199 => {
11981200 const builtin_token = tree.nodeMainToken(node);
11991201 const builtin_name = tree.tokenSlice(builtin_token);
1200 if (!std.mem.eql(u8, builtin_name, "@Type")) return null;
1201 var buf: [2]Ast.Node.Index = undefined;
1202 const params = tree.builtinCallParams(&buf, node).?;
1203 if (params.len != 1) return null; // let `builtinCall` error
1204 return try builtinReify(gz, scope, ri, node, params[0], name_strat);
1202 const info = BuiltinFn.list.get(builtin_name) orelse return null;
1203 switch (info.tag) {
1204 .Enum, .Struct, .Union => {
1205 var buf: [2]Ast.Node.Index = undefined;
1206 const params = tree.builtinCallParams(&buf, node).?;
1207 return try builtinCall(gz, scope, ri, node, params, false, name_strat);
1208 },
1209 else => return null,
1210 }
12051211 },
12061212 else => return null,
12071213 }
......@@ -1406,7 +1412,7 @@ fn fnProtoExprInner(
14061412 .none;
14071413
14081414 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
1409 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty);
1415 const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .fn_ret_ty);
14101416
14111417 const result = try block_scope.addFunc(.{
14121418 .src_node = fn_proto.ast.proto_node,
......@@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
26292635 const params = tree.builtinCallParams(&buf, inner_node).?;
26302636
26312637 try emitDbgNode(gz, inner_node);
2632 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint);
2638 const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint, .anon);
26332639 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
26342640 },
26352641
......@@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
27072713 .elem_type,
27082714 .indexable_ptr_elem_type,
27092715 .splat_op_result_ty,
2716 .reify_int,
27102717 .vector_type,
27112718 .indexable_ptr_len,
27122719 .anyframe_type,
......@@ -8942,7 +8949,7 @@ fn unionInit(
89428949 params: []const Ast.Node.Index,
89438950) InnerError!Zir.Inst.Ref {
89448951 const union_type = try typeExpr(gz, scope, params[0]);
8945 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_name);
8952 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_names);
89468953 const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
89478954 .container_type = union_type,
89488955 .field_name = field_name,
......@@ -9210,6 +9217,7 @@ fn builtinCall(
92109217 node: Ast.Node.Index,
92119218 params: []const Ast.Node.Index,
92129219 allow_branch_hint: bool,
9220 reify_name_strat: Zir.Inst.NameStrategy,
92139221) InnerError!Zir.Inst.Ref {
92149222 const astgen = gz.astgen;
92159223 const tree = astgen.tree;
......@@ -9443,9 +9451,140 @@ fn builtinCall(
94439451 return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);
94449452 },
94459453
9446 .Type => {
9447 return builtinReify(gz, scope, ri, node, params[0], .anon);
9454 .EnumLiteral => return rvalue(gz, ri, .enum_literal_type, node),
9455 .Int => {
9456 const signedness_ty = try gz.addBuiltinValue(node, .signedness);
9457 const result = try gz.addPlNode(.reify_int, node, Zir.Inst.Bin{
9458 .lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = signedness_ty } }, params[0], .int_signedness),
9459 .rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[1], .int_bit_width),
9460 });
9461 return rvalue(gz, ri, result, node);
9462 },
9463 .Tuple => {
9464 const result = try gz.addExtendedPayload(.reify_tuple, Zir.Inst.UnNode{
9465 .node = gz.nodeIndexToRelative(node),
9466 .operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .tuple_field_types),
9467 });
9468 return rvalue(gz, ri, result, node);
9469 },
9470 .Pointer => {
9471 const ptr_size_ty = try gz.addBuiltinValue(node, .pointer_size);
9472 const ptr_attrs_ty = try gz.addBuiltinValue(node, .pointer_attributes);
9473 const size = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_size_ty } }, params[0], .pointer_size);
9474 const attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_attrs_ty } }, params[1], .pointer_attrs);
9475 const elem_ty = try typeExpr(gz, scope, params[2]);
9476 const sentinel_ty = try gz.addExtendedPayload(.reify_pointer_sentinel_ty, Zir.Inst.UnNode{
9477 .node = gz.nodeIndexToRelative(params[2]),
9478 .operand = elem_ty,
9479 });
9480 const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, params[3], .pointer_sentinel);
9481 const result = try gz.addExtendedPayload(.reify_pointer, Zir.Inst.ReifyPointer{
9482 .node = gz.nodeIndexToRelative(node),
9483 .size = size,
9484 .attrs = attrs,
9485 .elem_ty = elem_ty,
9486 .sentinel = sentinel,
9487 });
9488 return rvalue(gz, ri, result, node);
94489489 },
9490 .Fn => {
9491 const fn_attrs_ty = try gz.addBuiltinValue(node, .fn_attributes);
9492 const param_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .fn_param_types);
9493 const param_attrs_ty = try gz.addExtendedPayloadSmall(
9494 .reify_slice_arg_ty,
9495 @intFromEnum(Zir.Inst.ReifySliceArgInfo.type_to_fn_param_attrs),
9496 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[0]), .operand = param_types },
9497 );
9498 const param_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = param_attrs_ty } }, params[1], .fn_param_attrs);
9499 const ret_ty = try comptimeExpr(gz, scope, coerced_type_ri, params[2], .fn_ret_ty);
9500 const fn_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = fn_attrs_ty } }, params[3], .fn_attrs);
9501 const result = try gz.addExtendedPayload(.reify_fn, Zir.Inst.ReifyFn{
9502 .node = gz.nodeIndexToRelative(node),
9503 .param_types = param_types,
9504 .param_attrs = param_attrs,
9505 .ret_ty = ret_ty,
9506 .fn_attrs = fn_attrs,
9507 });
9508 return rvalue(gz, ri, result, node);
9509 },
9510 .Struct => {
9511 const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
9512 const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .struct_layout);
9513 const backing_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
9514 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .struct_field_names);
9515 const field_types_ty = try gz.addExtendedPayloadSmall(
9516 .reify_slice_arg_ty,
9517 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_type),
9518 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9519 );
9520 const field_attrs_ty = try gz.addExtendedPayloadSmall(
9521 .reify_slice_arg_ty,
9522 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_attrs),
9523 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9524 );
9525 const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .struct_field_types);
9526 const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .struct_field_attrs);
9527 const result = try gz.addExtendedPayloadSmall(.reify_struct, @intFromEnum(reify_name_strat), Zir.Inst.ReifyStruct{
9528 .src_line = gz.astgen.source_line,
9529 .node = node,
9530 .layout = layout,
9531 .backing_ty = backing_ty,
9532 .field_names = field_names,
9533 .field_types = field_types,
9534 .field_attrs = field_attrs,
9535 });
9536 return rvalue(gz, ri, result, node);
9537 },
9538 .Union => {
9539 const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
9540 const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .union_layout);
9541 const arg_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
9542 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .union_field_names);
9543 const field_types_ty = try gz.addExtendedPayloadSmall(
9544 .reify_slice_arg_ty,
9545 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_type),
9546 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9547 );
9548 const field_attrs_ty = try gz.addExtendedPayloadSmall(
9549 .reify_slice_arg_ty,
9550 @intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_attrs),
9551 Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
9552 );
9553 const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .union_field_types);
9554 const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .union_field_attrs);
9555 const result = try gz.addExtendedPayloadSmall(.reify_union, @intFromEnum(reify_name_strat), Zir.Inst.ReifyUnion{
9556 .src_line = gz.astgen.source_line,
9557 .node = node,
9558 .layout = layout,
9559 .arg_ty = arg_ty,
9560 .field_names = field_names,
9561 .field_types = field_types,
9562 .field_attrs = field_attrs,
9563 });
9564 return rvalue(gz, ri, result, node);
9565 },
9566 .Enum => {
9567 const enum_mode_ty = try gz.addBuiltinValue(node, .enum_mode);
9568 const tag_ty = try typeExpr(gz, scope, params[0]);
9569 const mode = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = enum_mode_ty } }, params[1], .type);
9570 const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .enum_field_names);
9571 const field_values_ty = try gz.addExtendedPayload(.reify_enum_value_slice_ty, Zir.Inst.BinNode{
9572 .node = gz.nodeIndexToRelative(node),
9573 .lhs = tag_ty,
9574 .rhs = field_names,
9575 });
9576 const field_values = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_values_ty } }, params[3], .enum_field_values);
9577 const result = try gz.addExtendedPayloadSmall(.reify_enum, @intFromEnum(reify_name_strat), Zir.Inst.ReifyEnum{
9578 .src_line = gz.astgen.source_line,
9579 .node = node,
9580 .tag_ty = tag_ty,
9581 .mode = mode,
9582 .field_names = field_names,
9583 .field_values = field_values,
9584 });
9585 return rvalue(gz, ri, result, node);
9586 },
9587
94499588 .panic => {
94509589 try emitDbgNode(gz, node);
94519590 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);
......@@ -9764,41 +9903,6 @@ fn builtinCall(
97649903 },
97659904 }
97669905}
9767fn builtinReify(
9768 gz: *GenZir,
9769 scope: *Scope,
9770 ri: ResultInfo,
9771 node: Ast.Node.Index,
9772 arg_node: Ast.Node.Index,
9773 name_strat: Zir.Inst.NameStrategy,
9774) InnerError!Zir.Inst.Ref {
9775 const astgen = gz.astgen;
9776 const gpa = astgen.gpa;
9777
9778 const type_info_ty = try gz.addBuiltinValue(node, .type_info);
9779 const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = type_info_ty } }, arg_node);
9780
9781 try gz.instructions.ensureUnusedCapacity(gpa, 1);
9782 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
9783
9784 const payload_index = try astgen.addExtra(Zir.Inst.Reify{
9785 .node = node, // Absolute node index -- see the definition of `Reify`.
9786 .operand = operand,
9787 .src_line = astgen.source_line,
9788 });
9789 const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
9790 astgen.instructions.appendAssumeCapacity(.{
9791 .tag = .extended,
9792 .data = .{ .extended = .{
9793 .opcode = .reify,
9794 .small = @intFromEnum(name_strat),
9795 .operand = payload_index,
9796 } },
9797 });
9798 gz.instructions.appendAssumeCapacity(new_index);
9799 const result = new_index.toRef();
9800 return rvalue(gz, ri, result, node);
9801}
98029906
98039907fn hasDeclOrField(
98049908 gz: *GenZir,
lib/std/zig/AstRlAnnotate.zig+44-1
......@@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
866866 // These builtins take no args and do not consume the result pointer.
867867 .src,
868868 .This,
869 .EnumLiteral,
869870 .return_address,
870871 .error_return_trace,
871872 .frame,
......@@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
906907 .embed_file,
907908 .error_name,
908909 .set_runtime_safety,
909 .Type,
910 .Tuple,
910911 .c_undef,
911912 .c_include,
912913 .wasm_memory_size,
......@@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
10581059 _ = try astrl.expr(args[3], block, ResultInfo.none);
10591060 return false;
10601061 },
1062 .Int => {
1063 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1064 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1065 return false;
1066 },
1067 .Pointer => {
1068 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1069 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1070 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1071 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1072 return false;
1073 },
1074 .Fn => {
1075 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1076 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1077 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1078 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1079 return false;
1080 },
1081 .Struct => {
1082 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1083 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1084 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1085 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1086 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1087 return false;
1088 },
1089 .Union => {
1090 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1091 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1092 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1093 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1094 _ = try astrl.expr(args[4], block, ResultInfo.type_only);
1095 return false;
1096 },
1097 .Enum => {
1098 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1099 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
1100 _ = try astrl.expr(args[2], block, ResultInfo.type_only);
1101 _ = try astrl.expr(args[3], block, ResultInfo.type_only);
1102 return false;
1103 },
10611104 .Vector => {
10621105 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
10631106 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
lib/std/zig/BuiltinFn.zig+59-3
......@@ -110,7 +110,14 @@ pub const Tag = enum {
110110 This,
111111 trap,
112112 truncate,
113 Type,
113 EnumLiteral,
114 Int,
115 Tuple,
116 Pointer,
117 Fn,
118 Struct,
119 Union,
120 Enum,
114121 type_info,
115122 type_name,
116123 TypeOf,
......@@ -937,12 +944,61 @@ pub const list = list: {
937944 },
938945 },
939946 .{
940 "@Type",
947 "@EnumLiteral",
941948 .{
942 .tag = .Type,
949 .tag = .EnumLiteral,
950 .param_count = 0,
951 },
952 },
953 .{
954 "@Int",
955 .{
956 .tag = .Int,
957 .param_count = 2,
958 },
959 },
960 .{
961 "@Tuple",
962 .{
963 .tag = .Tuple,
943964 .param_count = 1,
944965 },
945966 },
967 .{
968 "@Pointer",
969 .{
970 .tag = .Pointer,
971 .param_count = 4,
972 },
973 },
974 .{
975 "@Fn",
976 .{
977 .tag = .Fn,
978 .param_count = 4,
979 },
980 },
981 .{
982 "@Struct",
983 .{
984 .tag = .Struct,
985 .param_count = 5,
986 },
987 },
988 .{
989 "@Union",
990 .{
991 .tag = .Union,
992 .param_count = 5,
993 },
994 },
995 .{
996 "@Enum",
997 .{
998 .tag = .Enum,
999 .param_count = 4,
1000 },
1001 },
9461002 .{
9471003 "@typeInfo",
9481004 .{
lib/std/zig/Zir.zig+131-8
......@@ -260,6 +260,10 @@ pub const Inst = struct {
260260 /// `[N:S]T` syntax. Source location is the array type expression node.
261261 /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.
262262 array_type_sentinel,
263 /// `@Int` builtin.
264 /// Uses the `pl_node` union field with `Bin` payload.
265 /// lhs is signedness, rhs is bit count.
266 reify_int,
263267 /// `@Vector` builtin.
264268 /// Uses the `pl_node` union field with `Bin` payload.
265269 /// lhs is length, rhs is element type.
......@@ -1112,6 +1116,7 @@ pub const Inst = struct {
11121116 .array_mul,
11131117 .array_type,
11141118 .array_type_sentinel,
1119 .reify_int,
11151120 .vector_type,
11161121 .elem_type,
11171122 .indexable_ptr_elem_type,
......@@ -1409,6 +1414,7 @@ pub const Inst = struct {
14091414 .array_mul,
14101415 .array_type,
14111416 .array_type_sentinel,
1417 .reify_int,
14121418 .vector_type,
14131419 .elem_type,
14141420 .indexable_ptr_elem_type,
......@@ -1644,6 +1650,7 @@ pub const Inst = struct {
16441650 .array_mul = .pl_node,
16451651 .array_type = .pl_node,
16461652 .array_type_sentinel = .pl_node,
1653 .reify_int = .pl_node,
16471654 .vector_type = .pl_node,
16481655 .elem_type = .un_node,
16491656 .indexable_ptr_elem_type = .un_node,
......@@ -2035,10 +2042,43 @@ pub const Inst = struct {
20352042 /// Implement builtin `@errorFromInt`.
20362043 /// `operand` is payload index to `UnNode`.
20372044 error_from_int,
2038 /// Implement builtin `@Type`.
2039 /// `operand` is payload index to `Reify`.
2045 /// Given a comptime-known operand of type `[]const A`, returns the type `*const [operand.len]B`.
2046 /// The types `A` and `B` are determined from `ReifySliceArgInfo`.
2047 /// This instruction is used to provide result types to arguments of `@Fn`, `@Struct`, etc.
2048 /// `operand` is payload index to `UnNode`.
2049 /// `small` is a bitcast `ReifySliceArgInfo`.
2050 reify_slice_arg_ty,
2051 /// Like `reify_slice_arg_ty` for the specific case of `[]const []const u8` to `[]const TagInt`,
2052 /// as needed for `@Enum`.
2053 /// `operand` is payload index to `BinNode`. lhs is the type `TagInt`. rhs is the `[]const []const u8` value.
2054 /// `small` is unused.
2055 reify_enum_value_slice_ty,
2056 /// Given a comptime-known operand of type `type`, returns the type `?operand` if possible, otherwise `?noreturn`.
2057 /// Used for the final arg of `@Pointer` to allow reifying pointers to opaque types.
2058 /// `operand` is payload index to `UnNode`.
2059 /// `small` is unused.
2060 reify_pointer_sentinel_ty,
2061 /// Implements builtin `@Tuple`.
2062 /// `operand` is payload index to `UnNode`.
2063 reify_tuple,
2064 /// Implements builtin `@Pointer`.
2065 /// `operand` is payload index to `ReifyPointer`.
2066 reify_pointer,
2067 /// Implements builtin `@Fn`.
2068 /// `operand` is payload index to `ReifyFn`.
2069 reify_fn,
2070 /// Implements builtin `@Struct`.
2071 /// `operand` is payload index to `ReifyStruct`.
2072 /// `small` contains `NameStrategy`.
2073 reify_struct,
2074 /// Implements builtin `@Union`.
2075 /// `operand` is payload index to `ReifyUnion`.
2076 /// `small` contains `NameStrategy`.
2077 reify_union,
2078 /// Implements builtin `@Enum`.
2079 /// `operand` is payload index to `ReifyEnum`.
20402080 /// `small` contains `NameStrategy`.
2041 reify,
2081 reify_enum,
20422082 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
20432083 /// `small` 0=>weak 1=>strong
20442084 /// `operand` is payload index to `Cmpxchg`.
......@@ -2226,6 +2266,11 @@ pub const Inst = struct {
22262266 manyptr_const_u8_sentinel_0_type,
22272267 slice_const_u8_type,
22282268 slice_const_u8_sentinel_0_type,
2269 manyptr_const_slice_const_u8_type,
2270 slice_const_slice_const_u8_type,
2271 optional_type_type,
2272 manyptr_const_type_type,
2273 slice_const_type_type,
22292274 vector_8_i8_type,
22302275 vector_16_i8_type,
22312276 vector_32_i8_type,
......@@ -3169,6 +3214,23 @@ pub const Inst = struct {
31693214 rhs: Ref,
31703215 };
31713216
3217 pub const ReifySliceArgInfo = enum(u16) {
3218 /// Input element type is `type`.
3219 /// Output element type is `std.builtin.Type.Fn.Param.Attributes`.
3220 type_to_fn_param_attrs,
3221 /// Input element type is `[]const u8`.
3222 /// Output element type is `type`.
3223 string_to_struct_field_type,
3224 /// Identical to `string_to_struct_field_type` aside from emitting slightly different error messages.
3225 string_to_union_field_type,
3226 /// Input element type is `[]const u8`.
3227 /// Output element type is `std.builtin.Type.StructField.Attributes`.
3228 string_to_struct_field_attrs,
3229 /// Input element type is `[]const u8`.
3230 /// Output element type is `std.builtin.Type.UnionField.Attributes`.
3231 string_to_union_field_attrs,
3232 };
3233
31723234 pub const UnNode = struct {
31733235 node: Ast.Node.Offset,
31743236 operand: Ref,
......@@ -3179,12 +3241,55 @@ pub const Inst = struct {
31793241 index: u32,
31803242 };
31813243
3182 pub const Reify = struct {
3244 pub const ReifyPointer = struct {
3245 node: Ast.Node.Offset,
3246 size: Ref,
3247 attrs: Ref,
3248 elem_ty: Ref,
3249 sentinel: Ref,
3250 };
3251
3252 pub const ReifyFn = struct {
3253 node: Ast.Node.Offset,
3254 param_types: Ref,
3255 param_attrs: Ref,
3256 ret_ty: Ref,
3257 fn_attrs: Ref,
3258 };
3259
3260 pub const ReifyStruct = struct {
3261 src_line: u32,
31833262 /// This node is absolute, because `reify` instructions are tracked across updates, and
31843263 /// this simplifies the logic for getting source locations for types.
31853264 node: Ast.Node.Index,
3186 operand: Ref,
3265 layout: Ref,
3266 backing_ty: Ref,
3267 field_names: Ref,
3268 field_types: Ref,
3269 field_attrs: Ref,
3270 };
3271
3272 pub const ReifyUnion = struct {
31873273 src_line: u32,
3274 /// This node is absolute, because `reify` instructions are tracked across updates, and
3275 /// this simplifies the logic for getting source locations for types.
3276 node: Ast.Node.Index,
3277 layout: Ref,
3278 arg_ty: Ref,
3279 field_names: Ref,
3280 field_types: Ref,
3281 field_attrs: Ref,
3282 };
3283
3284 pub const ReifyEnum = struct {
3285 src_line: u32,
3286 /// This node is absolute, because `reify` instructions are tracked across updates, and
3287 /// this simplifies the logic for getting source locations for types.
3288 node: Ast.Node.Index,
3289 tag_ty: Ref,
3290 mode: Ref,
3291 field_names: Ref,
3292 field_values: Ref,
31883293 };
31893294
31903295 /// Trailing:
......@@ -3496,14 +3601,19 @@ pub const Inst = struct {
34963601 calling_convention,
34973602 address_space,
34983603 float_mode,
3604 signedness,
34993605 reduce_op,
35003606 call_modifier,
35013607 prefetch_options,
35023608 export_options,
35033609 extern_options,
3504 type_info,
35053610 branch_hint,
35063611 clobbers,
3612 pointer_size,
3613 pointer_attributes,
3614 fn_attributes,
3615 container_layout,
3616 enum_mode,
35073617 // Values
35083618 calling_convention_c,
35093619 calling_convention_inline,
......@@ -4190,6 +4300,7 @@ fn findTrackableInner(
41904300 .array_mul,
41914301 .array_type,
41924302 .array_type_sentinel,
4303 .reify_int,
41934304 .vector_type,
41944305 .elem_type,
41954306 .indexable_ptr_elem_type,
......@@ -4432,6 +4543,12 @@ fn findTrackableInner(
44324543 .select,
44334544 .int_from_error,
44344545 .error_from_int,
4546 .reify_slice_arg_ty,
4547 .reify_enum_value_slice_ty,
4548 .reify_pointer_sentinel_ty,
4549 .reify_tuple,
4550 .reify_pointer,
4551 .reify_fn,
44354552 .cmpxchg,
44364553 .c_va_arg,
44374554 .c_va_copy,
......@@ -4463,7 +4580,11 @@ fn findTrackableInner(
44634580 },
44644581
44654582 // Reifications and opaque declarations need tracking, but have no body.
4466 .reify, .opaque_decl => return contents.other.append(gpa, inst),
4583 .reify_enum,
4584 .reify_struct,
4585 .reify_union,
4586 .opaque_decl,
4587 => return contents.other.append(gpa, inst),
44674588
44684589 // Struct declarations need tracking and have bodies.
44694590 .struct_decl => {
......@@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
52465367 .union_decl,
52475368 .enum_decl,
52485369 .opaque_decl,
5249 .reify,
5370 .reify_enum,
5371 .reify_struct,
5372 .reify_union,
52505373 => {}, // tracked in order, as the owner instructions of explicit container types
52515374 else => unreachable, // assertion failure; not trackable
52525375 },
src/Air.zig+5
......@@ -1062,6 +1062,11 @@ pub const Inst = struct {
10621062 manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
10631063 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
10641064 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
1065 manyptr_const_slice_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_slice_const_u8_type),
1066 slice_const_slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_slice_const_u8_type),
1067 optional_type_type = @intFromEnum(InternPool.Index.optional_type_type),
1068 manyptr_const_type_type = @intFromEnum(InternPool.Index.manyptr_const_type_type),
1069 slice_const_type_type = @intFromEnum(InternPool.Index.slice_const_type_type),
10651070 vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),
10661071 vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),
10671072 vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type),
src/InternPool.zig+70-38
......@@ -2017,8 +2017,7 @@ pub const Key = union(enum) {
20172017 error_union_type: ErrorUnionType,
20182018 simple_type: SimpleType,
20192019 /// This represents a struct that has been explicitly declared in source code,
2020 /// or was created with `@Type`. It is unique and based on a declaration.
2021 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
2020 /// or was created with `@Struct`. It is unique and based on a declaration.
20222021 struct_type: NamespaceType,
20232022 /// This is a tuple type. Tuples are logically similar to structs, but have some
20242023 /// important differences in semantics; they do not undergo staged type resolution,
......@@ -2175,7 +2174,7 @@ pub const Key = union(enum) {
21752174 /// The union for which this is a tag type.
21762175 union_type: Index,
21772176 },
2178 /// This type originates from a reification via `@Type`, or from an anonymous initialization.
2177 /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization.
21792178 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
21802179 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.
21812180 reified: struct {
......@@ -4641,6 +4640,13 @@ pub const Index = enum(u32) {
46414640 slice_const_u8_type,
46424641 slice_const_u8_sentinel_0_type,
46434642
4643 manyptr_const_slice_const_u8_type,
4644 slice_const_slice_const_u8_type,
4645
4646 optional_type_type,
4647 manyptr_const_type_type,
4648 slice_const_type_type,
4649
46444650 vector_8_i8_type,
46454651 vector_16_i8_type,
46464652 vector_32_i8_type,
......@@ -5201,6 +5207,45 @@ pub const static_keys: [static_len]Key = .{
52015207 },
52025208 } },
52035209
5210 // [*]const []const u8
5211 .{ .ptr_type = .{
5212 .child = .slice_const_u8_type,
5213 .flags = .{
5214 .size = .many,
5215 .is_const = true,
5216 },
5217 } },
5218
5219 // []const []const u8
5220 .{ .ptr_type = .{
5221 .child = .slice_const_u8_type,
5222 .flags = .{
5223 .size = .slice,
5224 .is_const = true,
5225 },
5226 } },
5227
5228 // ?type
5229 .{ .opt_type = .type_type },
5230
5231 // [*]const type
5232 .{ .ptr_type = .{
5233 .child = .type_type,
5234 .flags = .{
5235 .size = .many,
5236 .is_const = true,
5237 },
5238 } },
5239
5240 // []const type
5241 .{ .ptr_type = .{
5242 .child = .type_type,
5243 .flags = .{
5244 .size = .slice,
5245 .is_const = true,
5246 },
5247 } },
5248
52045249 // @Vector(8, i8)
52055250 .{ .vector_type = .{ .len = 8, .child = .i8_type } },
52065251 // @Vector(16, i8)
......@@ -10225,16 +10270,8 @@ pub fn getGeneratedTagEnumType(
1022510270}
1022610271
1022710272pub const OpaqueTypeInit = struct {
10228 key: union(enum) {
10229 declared: struct {
10230 zir_index: TrackedInst.Index,
10231 captures: []const CaptureValue,
10232 },
10233 reified: struct {
10234 zir_index: TrackedInst.Index,
10235 // No type hash since reifid opaques have no data other than the `@Type` location
10236 },
10237 },
10273 zir_index: TrackedInst.Index,
10274 captures: []const CaptureValue,
1023810275};
1023910276
1024010277pub fn getOpaqueType(
......@@ -10243,16 +10280,10 @@ pub fn getOpaqueType(
1024310280 tid: Zcu.PerThread.Id,
1024410281 ini: OpaqueTypeInit,
1024510282) Allocator.Error!WipNamespaceType.Result {
10246 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = switch (ini.key) {
10247 .declared => |d| .{ .declared = .{
10248 .zir_index = d.zir_index,
10249 .captures = .{ .external = d.captures },
10250 } },
10251 .reified => |r| .{ .reified = .{
10252 .zir_index = r.zir_index,
10253 .type_hash = 0,
10254 } },
10255 } });
10283 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{
10284 .zir_index = ini.zir_index,
10285 .captures = .{ .external = ini.captures },
10286 } } });
1025610287 defer gop.deinit();
1025710288 if (gop == .existing) return .{ .existing = gop.existing };
1025810289
......@@ -10261,30 +10292,19 @@ pub fn getOpaqueType(
1026110292 const extra = local.getMutableExtra(gpa);
1026210293 try items.ensureUnusedCapacity(1);
1026310294
10264 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + switch (ini.key) {
10265 .declared => |d| d.captures.len,
10266 .reified => 0,
10267 });
10295 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
1026810296 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
1026910297 .name = undefined, // set by `finish`
1027010298 .name_nav = undefined, // set by `finish`
1027110299 .namespace = undefined, // set by `finish`
10272 .zir_index = switch (ini.key) {
10273 inline else => |x| x.zir_index,
10274 },
10275 .captures_len = switch (ini.key) {
10276 .declared => |d| @intCast(d.captures.len),
10277 .reified => std.math.maxInt(u32),
10278 },
10300 .zir_index = ini.zir_index,
10301 .captures_len = @intCast(ini.captures.len),
1027910302 });
1028010303 items.appendAssumeCapacity(.{
1028110304 .tag = .type_opaque,
1028210305 .data = extra_index,
1028310306 });
10284 switch (ini.key) {
10285 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
10286 .reified => {},
10287 }
10307 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
1028810308 return .{
1028910309 .wip = .{
1029010310 .tid = tid,
......@@ -10555,6 +10575,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {
1055510575 switch (index) {
1055610576 .slice_const_u8_type => return .manyptr_const_u8_type,
1055710577 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
10578 .slice_const_slice_const_u8_type => return .manyptr_const_slice_const_u8_type,
10579 .slice_const_type_type => return .manyptr_const_type_type,
1055810580 else => {},
1055910581 }
1056010582 const item = index.unwrap(ip).getItem(ip);
......@@ -12013,8 +12035,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
1201312035 .manyptr_u8_type,
1201412036 .manyptr_const_u8_type,
1201512037 .manyptr_const_u8_sentinel_0_type,
12038 .manyptr_const_slice_const_u8_type,
1201612039 .slice_const_u8_type,
1201712040 .slice_const_u8_sentinel_0_type,
12041 .slice_const_slice_const_u8_type,
12042 .optional_type_type,
12043 .manyptr_const_type_type,
12044 .slice_const_type_type,
1201812045 .vector_8_i8_type,
1201912046 .vector_16_i8_type,
1202012047 .vector_32_i8_type,
......@@ -12355,8 +12382,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
1235512382 .manyptr_u8_type,
1235612383 .manyptr_const_u8_type,
1235712384 .manyptr_const_u8_sentinel_0_type,
12385 .manyptr_const_slice_const_u8_type,
1235812386 .slice_const_u8_type,
1235912387 .slice_const_u8_sentinel_0_type,
12388 .slice_const_slice_const_u8_type,
12389 .manyptr_const_type_type,
12390 .slice_const_type_type,
1236012391 => .pointer,
1236112392
1236212393 .vector_8_i8_type,
......@@ -12408,6 +12439,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
1240812439 .vector_8_f64_type,
1240912440 => .vector,
1241012441
12442 .optional_type_type => .optional,
1241112443 .optional_noreturn_type => .optional,
1241212444 .anyerror_void_error_union_type => .error_union,
1241312445 .empty_tuple_type => .@"struct",
src/Sema.zig+1192-1241
......@@ -1167,6 +1167,7 @@ fn analyzeBodyInner(
11671167 .array_mul => try sema.zirArrayMul(block, inst),
11681168 .array_type => try sema.zirArrayType(block, inst),
11691169 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
1170 .reify_int => try sema.zirReifyInt(block, inst),
11701171 .vector_type => try sema.zirVectorType(block, inst),
11711172 .as_node => try sema.zirAsNode(block, inst),
11721173 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),
......@@ -1411,7 +1412,6 @@ fn analyzeBodyInner(
14111412 .select => try sema.zirSelect( block, extended),
14121413 .int_from_error => try sema.zirIntFromError( block, extended),
14131414 .error_from_int => try sema.zirErrorFromInt( block, extended),
1414 .reify => try sema.zirReify( block, extended, inst),
14151415 .cmpxchg => try sema.zirCmpxchg( block, extended),
14161416 .c_va_arg => try sema.zirCVaArg( block, extended),
14171417 .c_va_copy => try sema.zirCVaCopy( block, extended),
......@@ -1424,6 +1424,16 @@ fn analyzeBodyInner(
14241424 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),
14251425 .in_comptime => try sema.zirInComptime( block),
14261426 .closure_get => try sema.zirClosureGet( block, extended),
1427
1428 .reify_slice_arg_ty => try sema.zirReifySliceArgTy( block, extended),
1429 .reify_enum_value_slice_ty => try sema.zirReifyEnumValueSliceTy(block, extended),
1430 .reify_pointer_sentinel_ty => try sema.zirReifyPointerSentinelTy(block, extended),
1431 .reify_tuple => try sema.zirReifyTuple( block, extended),
1432 .reify_pointer => try sema.zirReifyPointer( block, extended),
1433 .reify_fn => try sema.zirReifyFn( block, extended),
1434 .reify_struct => try sema.zirReifyStruct( block, extended, inst),
1435 .reify_union => try sema.zirReifyUnion( block, extended, inst),
1436 .reify_enum => try sema.zirReifyEnum( block, extended, inst),
14271437 // zig fmt: on
14281438
14291439 .set_float_mode => {
......@@ -3517,10 +3527,8 @@ fn zirOpaqueDecl(
35173527 extra_index += captures_len * 2;
35183528
35193529 const opaque_init: InternPool.OpaqueTypeInit = .{
3520 .key = .{ .declared = .{
3521 .zir_index = tracked_inst,
3522 .captures = captures,
3523 } },
3530 .zir_index = tracked_inst,
3531 .captures = captures,
35243532 };
35253533 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {
35263534 .existing => |ty| {
......@@ -7386,7 +7394,7 @@ fn analyzeCall(
73867394 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);
73877395
73887396 generic_block.comptime_reason = .{ .reason = .{
7389 .r = .{ .simple = .function_parameters },
7397 .r = .{ .simple = .fn_param_types },
73907398 .src = param_src,
73917399 } };
73927400
......@@ -7470,7 +7478,7 @@ fn analyzeCall(
74707478 sema.inst_map = generic_inst_map;
74717479
74727480 generic_block.comptime_reason = .{ .reason = .{
7473 .r = .{ .simple = .function_ret_ty },
7481 .r = .{ .simple = .fn_ret_ty },
74747482 .src = func_ret_ty_src,
74757483 } };
74767484
......@@ -8927,7 +8935,7 @@ fn zirFunc(
89278935 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
89288936 extra_index += ret_ty_body.len;
89298937
8930 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .function_ret_ty });
8938 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .fn_ret_ty });
89318939 break :blk ret_ty_val.toType();
89328940 },
89338941 };
......@@ -9171,6 +9179,181 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
91719179 }
91729180}
91739181
9182fn checkParamTypeCommon(
9183 sema: *Sema,
9184 block: *Block,
9185 param_idx: u32,
9186 param_ty: Type,
9187 param_is_noalias: bool,
9188 param_src: LazySrcLoc,
9189 cc: std.builtin.CallingConvention,
9190) CompileError!void {
9191 const pt = sema.pt;
9192 const zcu = pt.zcu;
9193 const target = zcu.getTarget();
9194
9195 if (!param_ty.isValidParamType(zcu)) {
9196 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9197 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
9198 opaque_str, param_ty.fmt(pt),
9199 });
9200 }
9201 if (!param_ty.isGenericPoison() and
9202 !target_util.fnCallConvAllowsZigTypes(cc) and
9203 !try sema.validateExternType(param_ty, .param_ty))
9204 {
9205 return sema.failWithOwnedErrorMsg(block, msg: {
9206 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
9207 param_ty.fmt(pt), @tagName(cc),
9208 });
9209 errdefer msg.destroy(sema.gpa);
9210
9211 try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty);
9212
9213 try sema.addDeclaredHereNote(msg, param_ty);
9214 break :msg msg;
9215 });
9216 }
9217 switch (cc) {
9218 .x86_64_interrupt, .x86_interrupt => {
9219 const err_code_size = target.ptrBitWidth();
9220 switch (param_idx) {
9221 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}),
9222 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }),
9223 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), param_idx + 1 }),
9224 }
9225 },
9226 .arc_interrupt,
9227 .arm_interrupt,
9228 .microblaze_interrupt,
9229 .mips64_interrupt,
9230 .mips_interrupt,
9231 .riscv64_interrupt,
9232 .riscv32_interrupt,
9233 .sh_interrupt,
9234 .avr_interrupt,
9235 .csky_interrupt,
9236 .m68k_interrupt,
9237 .msp430_interrupt,
9238 .avr_signal,
9239 => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}),
9240 else => {},
9241 }
9242 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) {
9243 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9244 }
9245}
9246
9247fn checkReturnTypeAndCallConvCommon(
9248 sema: *Sema,
9249 block: *Block,
9250 bare_ret_ty: Type,
9251 ret_ty_src: LazySrcLoc,
9252 @"callconv": std.builtin.CallingConvention,
9253 callconv_src: LazySrcLoc,
9254 /// non-`null` only if the function is varargs.
9255 opt_varargs_src: ?LazySrcLoc,
9256 inferred_error_set: bool,
9257 is_noinline: bool,
9258) CompileError!void {
9259 const pt = sema.pt;
9260 const zcu = pt.zcu;
9261 const gpa = zcu.gpa;
9262 if (opt_varargs_src) |varargs_src| {
9263 try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv");
9264 }
9265 if (inferred_error_set and !bare_ret_ty.isGenericPoison()) {
9266 try sema.validateErrorUnionPayloadType(block, bare_ret_ty, ret_ty_src);
9267 }
9268 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
9269 if (!bare_ret_ty.isValidReturnType(zcu)) {
9270 const opaque_str = if (bare_ret_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9271 return sema.fail(block, ret_ty_src, "{s}return type '{s}{f}' not allowed", .{
9272 opaque_str, ies_ret_ty_prefix, bare_ret_ty.fmt(pt),
9273 });
9274 }
9275 if (!bare_ret_ty.isGenericPoison() and
9276 !target_util.fnCallConvAllowsZigTypes(@"callconv") and
9277 (inferred_error_set or !try sema.validateExternType(bare_ret_ty, .ret_ty)))
9278 {
9279 return sema.failWithOwnedErrorMsg(block, msg: {
9280 const msg = try sema.errMsg(ret_ty_src, "return type '{s}{f}' not allowed in function with calling convention '{s}'", .{
9281 ies_ret_ty_prefix, bare_ret_ty.fmt(pt), @tagName(@"callconv"),
9282 });
9283 errdefer msg.destroy(gpa);
9284 if (!inferred_error_set) {
9285 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, bare_ret_ty, .ret_ty);
9286 try sema.addDeclaredHereNote(msg, bare_ret_ty);
9287 }
9288 break :msg msg;
9289 });
9290 }
9291 validate_incoming_stack_align: {
9292 const a: u64 = switch (@"callconv") {
9293 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment"))
9294 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align
9295 else
9296 break :validate_incoming_stack_align,
9297 };
9298 if (!std.math.isPowerOfTwo(a)) {
9299 return sema.fail(block, callconv_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a});
9300 }
9301 }
9302 switch (@"callconv") {
9303 .x86_64_interrupt,
9304 .x86_interrupt,
9305 .arm_interrupt,
9306 .mips64_interrupt,
9307 .mips_interrupt,
9308 .riscv64_interrupt,
9309 .riscv32_interrupt,
9310 .sh_interrupt,
9311 .arc_interrupt,
9312 .avr_interrupt,
9313 .csky_interrupt,
9314 .m68k_interrupt,
9315 .microblaze_interrupt,
9316 .msp430_interrupt,
9317 .avr_signal,
9318 => {
9319 const ret_ok = !inferred_error_set and switch (bare_ret_ty.toIntern()) {
9320 .void_type, .noreturn_type => true,
9321 else => false,
9322 };
9323 if (!ret_ok) {
9324 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(@"callconv")});
9325 }
9326 },
9327 .@"inline" => if (is_noinline) {
9328 return sema.fail(block, callconv_src, "'noinline' function cannot have calling convention 'inline'", .{});
9329 },
9330 else => {},
9331 }
9332 switch (zcu.callconvSupported(@"callconv")) {
9333 .ok => {},
9334 .bad_arch => |allowed_archs| {
9335 const ArchListFormatter = struct {
9336 archs: []const std.Target.Cpu.Arch,
9337 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
9338 for (formatter.archs, 0..) |arch, i| {
9339 if (i != 0)
9340 try w.writeAll(", ");
9341 try w.print("'{s}'", .{@tagName(arch)});
9342 }
9343 }
9344 };
9345 return sema.fail(block, callconv_src, "calling convention '{s}' only available on architectures {f}", .{
9346 @tagName(@"callconv"),
9347 ArchListFormatter{ .archs = allowed_archs },
9348 });
9349 },
9350 .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{
9351 @tagName(@"callconv"),
9352 @tagName(bad_backend),
9353 }),
9354 }
9355}
9356
91749357fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {
91759358 return switch (cc) {
91769359 .naked,
......@@ -9259,7 +9442,6 @@ fn funcCommon(
92599442 const pt = sema.pt;
92609443 const zcu = pt.zcu;
92619444 const gpa = sema.gpa;
9262 const target = zcu.getTarget();
92639445 const ip = &zcu.intern_pool;
92649446 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });
92659447 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
......@@ -9293,26 +9475,14 @@ fn funcCommon(
92939475 if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) {
92949476 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
92959477 }
9296 if (!param_ty.isValidParamType(zcu)) {
9297 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9298 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{
9299 opaque_str, param_ty.fmt(pt),
9300 });
9301 }
9302 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {
9303 const msg = msg: {
9304 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{s}'", .{
9305 param_ty.fmt(pt), @tagName(cc),
9306 });
9307 errdefer msg.destroy(sema.gpa);
9308
9309 try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty);
9310
9311 try sema.addDeclaredHereNote(msg, param_ty);
9312 break :msg msg;
9313 };
9314 return sema.failWithOwnedErrorMsg(block, msg);
9315 }
9478 try sema.checkParamTypeCommon(
9479 block,
9480 @intCast(i),
9481 param_ty,
9482 is_noalias,
9483 param_src,
9484 cc,
9485 );
93169486 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
93179487 const msg = msg: {
93189488 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
......@@ -9327,209 +9497,40 @@ fn funcCommon(
93279497 };
93289498 return sema.failWithOwnedErrorMsg(block, msg);
93299499 }
9330 if (!param_ty_generic and is_noalias and
9331 !(param_ty.zigTypeTag(zcu) == .pointer or param_ty.isPtrLikeOptional(zcu)))
9332 {
9333 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
9334 }
9335 switch (cc) {
9336 .x86_64_interrupt, .x86_interrupt => {
9337 const err_code_size = target.ptrBitWidth();
9338 switch (i) {
9339 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{s}' calling convention must be a pointer type", .{@tagName(cc)}),
9340 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{s}' calling convention must be a {d}-bit integer", .{ @tagName(cc), err_code_size }),
9341 else => return sema.fail(block, param_src, "'{s}' calling convention supports up to 2 parameters, found {d}", .{ @tagName(cc), i + 1 }),
9342 }
9343 },
9344 .arc_interrupt,
9345 .arm_interrupt,
9346 .microblaze_interrupt,
9347 .mips64_interrupt,
9348 .mips_interrupt,
9349 .riscv64_interrupt,
9350 .riscv32_interrupt,
9351 .sh_interrupt,
9352 .avr_interrupt,
9353 .csky_interrupt,
9354 .m68k_interrupt,
9355 .msp430_interrupt,
9356 .avr_signal,
9357 => return sema.fail(block, param_src, "parameters are not allowed with '{s}' calling convention", .{@tagName(cc)}),
9358 else => {},
9359 }
9360 }
9361
9362 if (var_args) {
9363 if (is_generic) {
9364 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
9365 }
9366 const va_args_src = block.src(.{
9367 .fn_proto_param = .{
9368 .fn_proto_node_offset = src_node_offset,
9369 .param_index = @intCast(block.params.len), // va_arg must be the last parameter
9370 },
9371 });
9372 try sema.checkCallConvSupportsVarArgs(block, va_args_src, cc);
9373 }
9374
9375 const ret_poison = bare_return_type.isGenericPoison();
9376
9377 const param_types = block.params.items(.ty);
9378
9379 if (inferred_error_set) {
9380 assert(has_body);
9381 if (!ret_poison)
9382 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
9383 const func_index = try ip.getFuncDeclIes(gpa, pt.tid, .{
9384 .owner_nav = sema.owner.unwrap().nav_val,
9385
9386 .param_types = param_types,
9387 .noalias_bits = noalias_bits,
9388 .comptime_bits = comptime_bits,
9389 .bare_return_type = bare_return_type.toIntern(),
9390 .cc = cc,
9391 .is_var_args = var_args,
9392 .is_generic = is_generic,
9393 .is_noinline = is_noinline,
9394
9395 .zir_body_inst = try block.trackZir(func_inst),
9396 .lbrace_line = src_locs.lbrace_line,
9397 .rbrace_line = src_locs.rbrace_line,
9398 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9399 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9400 });
9401 return finishFunc(
9402 sema,
9403 block,
9404 func_index,
9405 .none,
9406 ret_poison,
9407 bare_return_type,
9408 ret_ty_src,
9409 cc,
9410 ret_ty_requires_comptime,
9411 func_inst,
9412 cc_src,
9413 is_noinline,
9414 );
94159500 }
94169501
9417 const func_ty = try ip.getFuncType(gpa, pt.tid, .{
9418 .param_types = param_types,
9419 .noalias_bits = noalias_bits,
9420 .comptime_bits = comptime_bits,
9421 .return_type = bare_return_type.toIntern(),
9422 .cc = cc,
9423 .is_var_args = var_args,
9424 .is_generic = is_generic,
9425 .is_noinline = is_noinline,
9426 });
9427
9428 if (has_body) {
9429 const func_index = try ip.getFuncDecl(gpa, pt.tid, .{
9430 .owner_nav = sema.owner.unwrap().nav_val,
9431 .ty = func_ty,
9432 .cc = cc,
9433 .is_noinline = is_noinline,
9434 .zir_body_inst = try block.trackZir(func_inst),
9435 .lbrace_line = src_locs.lbrace_line,
9436 .rbrace_line = src_locs.rbrace_line,
9437 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9438 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9439 });
9440 return finishFunc(
9441 sema,
9442 block,
9443 func_index,
9444 func_ty,
9445 ret_poison,
9446 bare_return_type,
9447 ret_ty_src,
9448 cc,
9449 ret_ty_requires_comptime,
9450 func_inst,
9451 cc_src,
9452 is_noinline,
9453 );
9502 if (var_args and is_generic) {
9503 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
94549504 }
94559505
9456 return finishFunc(
9457 sema,
9506 try sema.checkReturnTypeAndCallConvCommon(
94589507 block,
9459 .none,
9460 func_ty,
9461 ret_poison,
94629508 bare_return_type,
94639509 ret_ty_src,
94649510 cc,
9465 ret_ty_requires_comptime,
9466 func_inst,
94679511 cc_src,
9512 if (var_args) block.src(.{ .fn_proto_param = .{
9513 .fn_proto_node_offset = src_node_offset,
9514 .param_index = @intCast(block.params.len),
9515 } }) else null,
9516 inferred_error_set,
94689517 is_noinline,
94699518 );
9470}
9471
9472fn finishFunc(
9473 sema: *Sema,
9474 block: *Block,
9475 opt_func_index: InternPool.Index,
9476 func_ty: InternPool.Index,
9477 ret_poison: bool,
9478 bare_return_type: Type,
9479 ret_ty_src: LazySrcLoc,
9480 cc_resolved: std.builtin.CallingConvention,
9481 ret_ty_requires_comptime: bool,
9482 func_inst: Zir.Inst.Index,
9483 cc_src: LazySrcLoc,
9484 is_noinline: bool,
9485) CompileError!Air.Inst.Ref {
9486 const pt = sema.pt;
9487 const zcu = pt.zcu;
9488 const ip = &zcu.intern_pool;
9489 const gpa = sema.gpa;
9490
9491 const return_type: Type = if (opt_func_index == .none or ret_poison)
9492 bare_return_type
9493 else
9494 .fromInterned(ip.funcTypeReturnType(ip.typeOf(opt_func_index)));
9495
9496 if (!return_type.isValidReturnType(zcu)) {
9497 const opaque_str = if (return_type.zigTypeTag(zcu) == .@"opaque") "opaque " else "";
9498 return sema.fail(block, ret_ty_src, "{s}return type '{f}' not allowed", .{
9499 opaque_str, return_type.fmt(pt),
9500 });
9501 }
9502 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(cc_resolved) and
9503 !try sema.validateExternType(return_type, .ret_ty))
9504 {
9505 const msg = msg: {
9506 const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{s}'", .{
9507 return_type.fmt(pt), @tagName(cc_resolved),
9508 });
9509 errdefer msg.destroy(gpa);
9510
9511 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, return_type, .ret_ty);
9512
9513 try sema.addDeclaredHereNote(msg, return_type);
9514 break :msg msg;
9515 };
9516 return sema.failWithOwnedErrorMsg(block, msg);
9517 }
95189519
95199520 // If the return type is comptime-only but not dependent on parameters then
95209521 // all parameter types also need to be comptime.
9521 if (opt_func_index != .none and ret_ty_requires_comptime and !block.isComptime()) comptime_check: {
9522 if (has_body and ret_ty_requires_comptime and !block.isComptime()) comptime_check: {
95229523 for (block.params.items(.is_comptime)) |is_comptime| {
95239524 if (!is_comptime) break;
95249525 } else break :comptime_check;
9525
9526 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
95269527 const msg = try sema.errMsg(
95279528 ret_ty_src,
9528 "function with comptime-only return type '{f}' requires all parameters to be comptime",
9529 .{return_type.fmt(pt)},
9529 "function with comptime-only return type '{s}{f}' requires all parameters to be comptime",
9530 .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) },
95309531 );
95319532 errdefer msg.destroy(sema.gpa);
9532 try sema.explainWhyTypeIsComptime(msg, ret_ty_src, return_type);
9533 try sema.explainWhyTypeIsComptime(msg, ret_ty_src, bare_return_type);
95339534
95349535 const tags = sema.code.instructions.items(.tag);
95359536 const data = sema.code.instructions.items(.data);
......@@ -9556,68 +9557,56 @@ fn finishFunc(
95569557 return sema.failWithOwnedErrorMsg(block, msg);
95579558 }
95589559
9559 validate_incoming_stack_align: {
9560 const a: u64 = switch (cc_resolved) {
9561 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment"))
9562 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align
9563 else
9564 break :validate_incoming_stack_align,
9565 };
9566 if (!std.math.isPowerOfTwo(a)) {
9567 return sema.fail(block, cc_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a});
9568 }
9569 }
9560 const param_types = block.params.items(.ty);
95709561
9571 switch (cc_resolved) {
9572 .x86_64_interrupt,
9573 .x86_interrupt,
9574 .arm_interrupt,
9575 .mips64_interrupt,
9576 .mips_interrupt,
9577 .riscv64_interrupt,
9578 .riscv32_interrupt,
9579 .sh_interrupt,
9580 .arc_interrupt,
9581 .avr_interrupt,
9582 .csky_interrupt,
9583 .m68k_interrupt,
9584 .microblaze_interrupt,
9585 .msp430_interrupt,
9586 .avr_signal,
9587 => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) {
9588 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});
9589 },
9590 .@"inline" => if (is_noinline) {
9591 return sema.fail(block, cc_src, "'noinline' function cannot have calling convention 'inline'", .{});
9592 },
9593 else => {},
9562 if (inferred_error_set) {
9563 assert(has_body);
9564 return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{
9565 .owner_nav = sema.owner.unwrap().nav_val,
9566
9567 .param_types = param_types,
9568 .noalias_bits = noalias_bits,
9569 .comptime_bits = comptime_bits,
9570 .bare_return_type = bare_return_type.toIntern(),
9571 .cc = cc,
9572 .is_var_args = var_args,
9573 .is_generic = is_generic,
9574 .is_noinline = is_noinline,
9575
9576 .zir_body_inst = try block.trackZir(func_inst),
9577 .lbrace_line = src_locs.lbrace_line,
9578 .rbrace_line = src_locs.rbrace_line,
9579 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9580 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9581 }));
95949582 }
95959583
9596 switch (zcu.callconvSupported(cc_resolved)) {
9597 .ok => {},
9598 .bad_arch => |allowed_archs| {
9599 const ArchListFormatter = struct {
9600 archs: []const std.Target.Cpu.Arch,
9601 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {
9602 for (formatter.archs, 0..) |arch, i| {
9603 if (i != 0)
9604 try w.writeAll(", ");
9605 try w.print("'{s}'", .{@tagName(arch)});
9606 }
9607 }
9608 };
9609 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{
9610 @tagName(cc_resolved),
9611 ArchListFormatter{ .archs = allowed_archs },
9612 });
9613 },
9614 .bad_backend => |bad_backend| return sema.fail(block, cc_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{
9615 @tagName(cc_resolved),
9616 @tagName(bad_backend),
9617 }),
9584 const func_ty = try ip.getFuncType(gpa, pt.tid, .{
9585 .param_types = param_types,
9586 .noalias_bits = noalias_bits,
9587 .comptime_bits = comptime_bits,
9588 .return_type = bare_return_type.toIntern(),
9589 .cc = cc,
9590 .is_var_args = var_args,
9591 .is_generic = is_generic,
9592 .is_noinline = is_noinline,
9593 });
9594
9595 if (has_body) {
9596 return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{
9597 .owner_nav = sema.owner.unwrap().nav_val,
9598 .ty = func_ty,
9599 .cc = cc,
9600 .is_noinline = is_noinline,
9601 .zir_body_inst = try block.trackZir(func_inst),
9602 .lbrace_line = src_locs.lbrace_line,
9603 .rbrace_line = src_locs.rbrace_line,
9604 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9605 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9606 }));
96189607 }
96199608
9620 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
9609 return .fromIntern(func_ty);
96219610}
96229611
96239612fn zirParam(
......@@ -19395,7 +19384,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1939519384 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
1939619385 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
1939719386 }
19398 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_name });
19387 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .union_field_names });
1939919388 const init = try sema.resolveInst(extra.init);
1940019389 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);
1940119390}
......@@ -20553,589 +20542,529 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2055320542 return block.addUnOp(.tag_name, casted_operand);
2055420543}
2055520544
20556fn zirReify(
20545fn zirReifyInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20546 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
20547 const signedness_src = block.builtinCallArgSrc(inst_data.src_node, 0);
20548 const bits_src = block.builtinCallArgSrc(inst_data.src_node, 1);
20549 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
20550 const signedness = try sema.resolveBuiltinEnum(block, signedness_src, extra.lhs, .Signedness, .{ .simple = .int_signedness });
20551 const bits: u16 = @intCast(try sema.resolveInt(block, bits_src, extra.rhs, .u16, .{ .simple = .int_bit_width }));
20552 return .fromType(try sema.pt.intType(signedness, bits));
20553}
20554
20555fn zirReifySliceArgTy(
2055720556 sema: *Sema,
2055820557 block: *Block,
2055920558 extended: Zir.Inst.Extended.InstData,
20560 inst: Zir.Inst.Index,
2056120559) CompileError!Air.Inst.Ref {
2056220560 const pt = sema.pt;
2056320561 const zcu = pt.zcu;
20564 const gpa = sema.gpa;
20565 const ip = &zcu.intern_pool;
20566 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
20567 const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data;
20568 const tracked_inst = try block.trackZir(inst);
20569 const src: LazySrcLoc = .{
20570 .base_node_inst = tracked_inst,
20571 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
20572 };
20573 const operand_src: LazySrcLoc = .{
20574 .base_node_inst = tracked_inst,
20575 .offset = .{
20576 .node_offset_builtin_call_arg = .{
20577 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 0
20578 .arg_index = 0,
20579 },
20580 },
20562
20563 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20564 const info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.small);
20565
20566 const src = block.nodeOffset(extra.node);
20567
20568 const comptime_reason: std.zig.SimpleComptimeReason, const in_scalar_ty: Type, const out_scalar_ty: Type = switch (info) {
20569 // zig fmt: off
20570 .type_to_fn_param_attrs => .{ .fn_param_attrs, .type, try sema.getBuiltinType(src, .@"Type.Fn.Param.Attributes") },
20571 .string_to_struct_field_type => .{ .struct_field_types, .slice_const_u8, .type },
20572 .string_to_union_field_type => .{ .union_field_types, .slice_const_u8, .type },
20573 .string_to_struct_field_attrs => .{ .struct_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.StructField.Attributes") },
20574 .string_to_union_field_attrs => .{ .union_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.UnionField.Attributes") },
20575 // zig fmt: on
2058120576 };
20582 const type_info_ty = try sema.getBuiltinType(src, .Type);
20583 const uncasted_operand = try sema.resolveInst(extra.operand);
20584 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
20585 const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{ .simple = .operand_Type });
20586 const union_val = ip.indexToKey(val.toIntern()).un;
20587 if (try sema.anyUndef(block, operand_src, Value.fromInterned(union_val.val))) {
20588 return sema.failWithUseOfUndef(block, operand_src, null);
20589 }
20590 const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), zcu).?;
20591 switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) {
20592 .type => return .type_type,
20593 .void => return .void_type,
20594 .bool => return .bool_type,
20595 .noreturn => return .noreturn_type,
20596 .comptime_float => return .comptime_float_type,
20597 .comptime_int => return .comptime_int_type,
20598 .undefined => return .undefined_type,
20599 .null => return .null_type,
20600 .@"anyframe" => return sema.failWithUseOfAsync(block, src),
20601 .enum_literal => return .enum_literal_type,
20602 .int => {
20603 const int = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Int);
20604 const ty = try pt.intType(int.signedness, int.bits);
20605 return Air.internedToRef(ty.toIntern());
20606 },
20607 .vector => {
20608 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20609 const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20610 ip,
20611 try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
20612 ).?);
20613 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20614 ip,
20615 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20616 ).?);
20617
20618 const len: u32 = @intCast(try len_val.toUnsignedIntSema(pt));
20619 const child_ty = child_val.toType();
20620
20621 try sema.checkVectorElemType(block, src, child_ty);
20622
20623 const ty = try pt.vectorType(.{
20624 .len = len,
20625 .child = child_ty.toIntern(),
20626 });
20627 return Air.internedToRef(ty.toIntern());
20628 },
20629 .float => {
20630 const float = try sema.interpretBuiltinType(block, operand_src, .fromInterned(union_val.val), std.builtin.Type.Float);
20631
20632 const ty: Type = switch (float.bits) {
20633 16 => .f16,
20634 32 => .f32,
20635 64 => .f64,
20636 80 => .f80,
20637 128 => .f128,
20638 else => return sema.fail(block, src, "{d}-bit float unsupported", .{float.bits}),
20639 };
20640 return Air.internedToRef(ty.toIntern());
20641 },
20642 .pointer => {
20643 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20644 const size_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20645 ip,
20646 try ip.getOrPutString(gpa, pt.tid, "size", .no_embedded_nulls),
20647 ).?);
20648 const is_const_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20649 ip,
20650 try ip.getOrPutString(gpa, pt.tid, "is_const", .no_embedded_nulls),
20651 ).?);
20652 const is_volatile_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20653 ip,
20654 try ip.getOrPutString(gpa, pt.tid, "is_volatile", .no_embedded_nulls),
20655 ).?);
20656 const alignment_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20657 ip,
20658 try ip.getOrPutString(gpa, pt.tid, "alignment", .no_embedded_nulls),
20659 ).?);
20660 const address_space_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20661 ip,
20662 try ip.getOrPutString(gpa, pt.tid, "address_space", .no_embedded_nulls),
20663 ).?);
20664 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20665 ip,
20666 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20667 ).?);
20668 const is_allowzero_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20669 ip,
20670 try ip.getOrPutString(gpa, pt.tid, "is_allowzero", .no_embedded_nulls),
20671 ).?);
20672 const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20673 ip,
20674 try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
20675 ).?);
20676
20677 if (!try sema.intFitsInType(alignment_val, align_ty, null)) {
20678 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
20679 }
20680 const alignment_val_int = try alignment_val.toUnsignedIntSema(pt);
20681 const abi_align = try sema.validateAlign(block, src, alignment_val_int);
20682
20683 const elem_ty = child_val.toType();
20684 if (abi_align != .none) {
20685 try elem_ty.resolveLayout(pt);
20686 }
20687
20688 const ptr_size = try sema.interpretBuiltinType(block, operand_src, size_val, std.builtin.Type.Pointer.Size);
20689
20690 const actual_sentinel: InternPool.Index = s: {
20691 if (!sentinel_val.isNull(zcu)) {
20692 if (ptr_size == .one or ptr_size == .c) {
20693 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
20694 }
20695 const sentinel_ptr_val = sentinel_val.optionalValue(zcu).?;
20696 const ptr_ty = try pt.singleMutPtrType(elem_ty);
20697 const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
20698 try sema.checkSentinelType(block, src, elem_ty);
20699 if (sent_val.canMutateComptimeVarState(zcu)) {
20700 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20701 return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sent_val);
20702 }
20703 break :s sent_val.toIntern();
20704 }
20705 break :s .none;
20706 };
2070720577
20708 if (elem_ty.zigTypeTag(zcu) == .noreturn) {
20709 return sema.fail(block, src, "pointer to noreturn not allowed", .{});
20710 } else if (elem_ty.zigTypeTag(zcu) == .@"fn") {
20711 if (ptr_size != .one) {
20712 return sema.fail(block, src, "function pointers must be single pointers", .{});
20713 }
20714 } else if (ptr_size != .one and elem_ty.zigTypeTag(zcu) == .@"opaque") {
20715 return sema.fail(block, src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)});
20716 } else if (ptr_size == .c) {
20717 if (!try sema.validateExternType(elem_ty, .other)) {
20718 const msg = msg: {
20719 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20720 errdefer msg.destroy(gpa);
20578 const operand_ty = try pt.ptrTypeSema(.{
20579 .child = in_scalar_ty.toIntern(),
20580 .flags = .{ .size = .slice, .is_const = true },
20581 });
2072120582
20722 try sema.explainWhyTypeIsNotExtern(msg, src, elem_ty, .other);
20583 const operand_uncoerced = try sema.resolveInst(extra.operand);
20584 const operand_coerced = try sema.coerce(block, operand_ty, operand_uncoerced, src);
20585 const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason });
20586 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
20587 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null);
20588 const len = try len_val.toUnsignedIntSema(pt);
2072320589
20724 try sema.addDeclaredHereNote(msg, elem_ty);
20725 break :msg msg;
20726 };
20727 return sema.failWithOwnedErrorMsg(block, msg);
20728 }
20729 }
20590 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20591 .len = len,
20592 .child = out_scalar_ty.toIntern(),
20593 })));
20594}
2073020595
20731 const ty = try pt.ptrTypeSema(.{
20732 .child = elem_ty.toIntern(),
20733 .sentinel = actual_sentinel,
20734 .flags = .{
20735 .size = ptr_size,
20736 .is_const = is_const_val.toBool(),
20737 .is_volatile = is_volatile_val.toBool(),
20738 .alignment = abi_align,
20739 .address_space = try sema.interpretBuiltinType(block, operand_src, address_space_val, std.builtin.AddressSpace),
20740 .is_allowzero = is_allowzero_val.toBool(),
20741 },
20742 });
20743 return Air.internedToRef(ty.toIntern());
20744 },
20745 .array => {
20746 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20747 const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20748 ip,
20749 try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
20750 ).?);
20751 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20752 ip,
20753 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20754 ).?);
20755 const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20756 ip,
20757 try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls),
20758 ).?);
20759
20760 const len = try len_val.toUnsignedIntSema(pt);
20761 const child_ty = child_val.toType();
20762 const sentinel = if (sentinel_val.optionalValue(zcu)) |p| blk: {
20763 const ptr_ty = try pt.singleMutPtrType(child_ty);
20764 try sema.checkSentinelType(block, src, child_ty);
20765 const sentinel = (try sema.pointerDeref(block, src, p, ptr_ty)).?;
20766 if (sentinel.canMutateComptimeVarState(zcu)) {
20767 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel_ptr", .no_embedded_nulls);
20768 return sema.failWithContainsReferenceToComptimeVar(block, src, sentinel_name, "sentinel", sentinel);
20769 }
20770 break :blk sentinel;
20771 } else null;
20772
20773 const ty = try pt.arrayType(.{
20774 .len = len,
20775 .sentinel = if (sentinel) |s| s.toIntern() else .none,
20776 .child = child_ty.toIntern(),
20777 });
20778 return Air.internedToRef(ty.toIntern());
20779 },
20780 .optional => {
20781 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20782 const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20783 ip,
20784 try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
20785 ).?);
20596fn zirReifyEnumValueSliceTy(
20597 sema: *Sema,
20598 block: *Block,
20599 extended: Zir.Inst.Extended.InstData,
20600) CompileError!Air.Inst.Ref {
20601 const pt = sema.pt;
20602 const zcu = pt.zcu;
2078620603
20787 const child_ty = child_val.toType();
20604 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2078820605
20789 const ty = try pt.optionalType(child_ty.toIntern());
20790 return Air.internedToRef(ty.toIntern());
20791 },
20792 .error_union => {
20793 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20794 const error_set_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20795 ip,
20796 try ip.getOrPutString(gpa, pt.tid, "error_set", .no_embedded_nulls),
20797 ).?);
20798 const payload_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20799 ip,
20800 try ip.getOrPutString(gpa, pt.tid, "payload", .no_embedded_nulls),
20801 ).?);
20606 const int_tag_ty_src = block.builtinCallArgSrc(extra.node, 0);
20607 const field_names_src = block.builtinCallArgSrc(extra.node, 2);
2080220608
20803 const error_set_ty = error_set_val.toType();
20804 const payload_ty = payload_val.toType();
20609 const int_tag_ty = try sema.resolveType(block, int_tag_ty_src, extra.lhs);
2080520610
20806 if (error_set_ty.zigTypeTag(zcu) != .error_set) {
20807 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});
20808 }
20611 const operand_uncoerced = try sema.resolveInst(extra.rhs);
20612 const operand_coerced = try sema.coerce(block, .slice_const_slice_const_u8, operand_uncoerced, field_names_src);
20613 const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names });
20614 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
20615 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, field_names_src, null);
20616 const len = try len_val.toUnsignedIntSema(pt);
2080920617
20810 const ty = try pt.errorUnionType(error_set_ty, payload_ty);
20811 return Air.internedToRef(ty.toIntern());
20812 },
20813 .error_set => {
20814 const payload_val = Value.fromInterned(union_val.val).optionalValue(zcu) orelse
20815 return .anyerror_type;
20618 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20619 .len = len,
20620 .child = int_tag_ty.toIntern(),
20621 })));
20622}
20623
20624fn zirReifyPointerSentinelTy(
20625 sema: *Sema,
20626 block: *Block,
20627 extended: Zir.Inst.Extended.InstData,
20628) CompileError!Air.Inst.Ref {
20629 const pt = sema.pt;
20630 const zcu = pt.zcu;
20631 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20632 const src = block.nodeOffset(extra.node);
20633 const elem_ty = try sema.resolveType(block, src, extra.operand);
20634 return .fromType(switch (elem_ty.zigTypeTag(zcu)) {
20635 else => try pt.optionalType(elem_ty.toIntern()),
20636 // These types cannot be the child of an optional. To allow reifying pointers to them still,
20637 // we treat the "sentinel" argument to `@Pointer` as `?noreturn` instead of `?T`.
20638 .@"opaque", .null => .optional_noreturn,
20639 });
20640}
2081620641
20817 const names_val = try sema.derefSliceAsArray(block, src, payload_val, .{ .simple = .error_set_contents });
20642fn zirReifyTuple(
20643 sema: *Sema,
20644 block: *Block,
20645 extended: Zir.Inst.Extended.InstData,
20646) CompileError!Air.Inst.Ref {
20647 const pt = sema.pt;
20648 const zcu = pt.zcu;
2081820649
20819 const len = try sema.usizeCast(block, src, names_val.typeOf(zcu).arrayLen(zcu));
20820 var names: InferredErrorSet.NameMap = .{};
20821 try names.ensureUnusedCapacity(sema.arena, len);
20822 for (0..len) |i| {
20823 const elem_val = try names_val.elemValue(pt, i);
20824 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
20825 const name_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
20826 ip,
20827 try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls),
20828 ).?);
20829
20830 const name = try sema.sliceToIpString(block, src, name_val, .{ .simple = .error_set_contents });
20831 _ = try pt.getErrorValue(name);
20832 const gop = names.getOrPutAssumeCapacity(name);
20833 if (gop.found_existing) {
20834 return sema.fail(block, src, "duplicate error '{f}'", .{
20835 name.fmt(ip),
20836 });
20837 }
20838 }
20650 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20651 const operand_src = block.builtinCallArgSrc(extra.node, 0);
2083920652
20840 const ty = try pt.errorSetFromUnsortedNames(names.keys());
20841 return Air.internedToRef(ty.toIntern());
20842 },
20843 .@"struct" => {
20844 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20845 const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20846 ip,
20847 try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),
20848 ).?);
20849 const backing_integer_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20850 ip,
20851 try ip.getOrPutString(gpa, pt.tid, "backing_integer", .no_embedded_nulls),
20852 ).?);
20853 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20854 ip,
20855 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
20856 ).?);
20857 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20858 ip,
20859 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20860 ).?);
20861 const is_tuple_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20862 ip,
20863 try ip.getOrPutString(gpa, pt.tid, "is_tuple", .no_embedded_nulls),
20864 ).?);
20865
20866 const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout);
20867
20868 // Decls
20869 if (try decls_val.sliceLen(pt) > 0) {
20870 return sema.fail(block, src, "reified structs must have no decls", .{});
20871 }
20872
20873 if (layout != .@"packed" and !backing_integer_val.isNull(zcu)) {
20874 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
20875 }
20876
20877 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .struct_fields });
20878
20879 if (is_tuple_val.toBool()) {
20880 switch (layout) {
20881 .@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}),
20882 .@"packed" => return sema.fail(block, src, "packed tuples are not supported", .{}),
20883 .auto => {},
20884 }
20885 return sema.reifyTuple(block, src, fields_arr);
20886 } else {
20887 return sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_arr, name_strategy);
20888 }
20889 },
20890 .@"enum" => {
20891 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20892 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20893 ip,
20894 try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),
20895 ).?);
20896 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20897 ip,
20898 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
20899 ).?);
20900 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20901 ip,
20902 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20903 ).?);
20904 const is_exhaustive_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20905 ip,
20906 try ip.getOrPutString(gpa, pt.tid, "is_exhaustive", .no_embedded_nulls),
20907 ).?);
20908
20909 if (try decls_val.sliceLen(pt) > 0) {
20910 return sema.fail(block, src, "reified enums must have no decls", .{});
20911 }
20912
20913 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .enum_fields });
20914
20915 return sema.reifyEnum(block, inst, src, tag_type_val.toType(), is_exhaustive_val.toBool(), fields_arr, name_strategy);
20916 },
20917 .@"opaque" => {
20918 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20919 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20920 ip,
20921 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20922 ).?);
20653 const types_uncoerced = try sema.resolveInst(extra.operand);
20654 const types_coerced = try sema.coerce(block, .slice_const_type, types_uncoerced, operand_src);
20655 const types_slice_val = try sema.resolveConstDefinedValue(block, operand_src, types_coerced, .{ .simple = .tuple_field_types });
20656 const types_array_val = try sema.derefSliceAsArray(block, operand_src, types_slice_val, .{ .simple = .tuple_field_types });
20657 const fields_len: u32 = @intCast(types_array_val.typeOf(zcu).arrayLen(zcu));
2092320658
20924 // Decls
20925 if (try decls_val.sliceLen(pt) > 0) {
20926 return sema.fail(block, src, "reified opaque must have no decls", .{});
20927 }
20659 const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
20660 for (field_types, 0..) |*field_ty, field_idx| {
20661 const field_ty_val = try types_array_val.elemValue(pt, field_idx);
20662 if (field_ty_val.isUndef(zcu)) {
20663 return sema.failWithUseOfUndef(block, operand_src, null);
20664 }
20665 field_ty.* = field_ty_val.toIntern();
20666 }
2092820667
20929 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, .{
20930 .key = .{ .reified = .{
20931 .zir_index = try block.trackZir(inst),
20932 } },
20933 })) {
20934 .existing => |ty| {
20935 try sema.addTypeReferenceEntry(src, ty);
20936 return Air.internedToRef(ty);
20937 },
20938 .wip => |wip| wip,
20939 };
20940 errdefer wip_ty.cancel(ip, pt.tid);
20668 const field_values = try sema.arena.alloc(InternPool.Index, fields_len);
20669 @memset(field_values, .none);
2094120670
20942 const type_name = try sema.createTypeName(
20943 block,
20944 name_strategy,
20945 "opaque",
20946 inst,
20947 wip_ty.index,
20948 );
20949 wip_ty.setName(ip, type_name.name, type_name.nav);
20671 return .fromIntern(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
20672 .types = field_types,
20673 .values = field_values,
20674 }));
20675}
2095020676
20951 const new_namespace_index = try pt.createNamespace(.{
20952 .parent = block.namespace.toOptional(),
20953 .owner_type = wip_ty.index,
20954 .file_scope = block.getFileScopeIndex(zcu),
20955 .generation = zcu.generation,
20956 });
20677fn zirReifyPointer(
20678 sema: *Sema,
20679 block: *Block,
20680 extended: Zir.Inst.Extended.InstData,
20681) CompileError!Air.Inst.Ref {
20682 const pt = sema.pt;
20683 const zcu = pt.zcu;
20684 const gpa = zcu.gpa;
20685 const ip = &zcu.intern_pool;
2095720686
20958 try sema.addTypeReferenceEntry(src, wip_ty.index);
20959 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
20960 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
20961 },
20962 .@"union" => {
20963 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
20964 const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20965 ip,
20966 try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),
20967 ).?);
20968 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20969 ip,
20970 try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),
20971 ).?);
20972 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20973 ip,
20974 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
20975 ).?);
20976 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
20977 ip,
20978 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
20979 ).?);
20687 const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
20688 const src = block.nodeOffset(extra.node);
20689 const size_src = block.builtinCallArgSrc(extra.node, 0);
20690 const attrs_src = block.builtinCallArgSrc(extra.node, 1);
20691 const elem_ty_src = block.builtinCallArgSrc(extra.node, 2);
20692 const sentinel_src = block.builtinCallArgSrc(extra.node, 3);
20693
20694 const size_ty = try sema.getBuiltinType(size_src, .@"Type.Pointer.Size");
20695 const attrs_ty = try sema.getBuiltinType(attrs_src, .@"Type.Pointer.Attributes");
20696
20697 const size_uncoerced = try sema.resolveInst(extra.size);
20698 const size_coerced = try sema.coerce(block, size_ty, size_uncoerced, size_src);
20699 const size_val = try sema.resolveConstDefinedValue(block, size_src, size_coerced, .{ .simple = .pointer_size });
20700 const size = try sema.interpretBuiltinType(block, size_src, size_val, std.builtin.Type.Pointer.Size);
20701
20702 const attrs_uncoerced = try sema.resolveInst(extra.attrs);
20703 const attrs_coerced = try sema.coerce(block, attrs_ty, attrs_uncoerced, attrs_src);
20704 const attrs_val = try sema.resolveConstDefinedValue(block, attrs_src, attrs_coerced, .{ .simple = .pointer_attrs });
20705 const attrs = try sema.interpretBuiltinType(block, attrs_src, attrs_val, std.builtin.Type.Pointer.Attributes);
20706
20707 const @"align": Alignment = if (attrs.@"align") |bytes| a: {
20708 break :a try sema.validateAlign(block, attrs_src, bytes);
20709 } else .none;
2098020710
20981 if (try decls_val.sliceLen(pt) > 0) {
20982 return sema.fail(block, src, "reified unions must have no decls", .{});
20983 }
20984 const layout = try sema.interpretBuiltinType(block, operand_src, layout_val, std.builtin.Type.ContainerLayout);
20711 const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_ty);
2098520712
20986 const has_tag = tag_type_val.optionalValue(zcu) != null;
20713 switch (elem_ty.zigTypeTag(zcu)) {
20714 .noreturn => return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{}),
20715 // This needs to be disallowed, because the sentinel parameter would otherwise have type
20716 // `?@TypeOf(null)`, which is not a valid type because you cannot differentiate between
20717 // constructing the "inner" null value and the "outer" null value.
20718 .null => return sema.fail(block, elem_ty_src, "cannot reify pointer to '@TypeOf(null)'", .{}),
20719 .@"fn" => switch (size) {
20720 .one => {},
20721 .many, .c, .slice => return sema.fail(block, src, "function pointers must be single pointers", .{}),
20722 },
20723 .@"opaque" => switch (size) {
20724 .one => {},
20725 .many, .c, .slice => return sema.fail(block, src, "indexable pointer to opaque type '{f}' not allowed", .{elem_ty.fmt(pt)}),
20726 },
20727 else => {},
20728 }
2098720729
20988 if (has_tag) {
20989 switch (layout) {
20990 .@"extern" => return sema.fail(block, src, "extern union does not support enum tag type", .{}),
20991 .@"packed" => return sema.fail(block, src, "packed union does not support enum tag type", .{}),
20992 .auto => {},
20993 }
20994 }
20730 if (size == .c and !try sema.validateExternType(elem_ty, .other)) {
20731 return sema.failWithOwnedErrorMsg(block, msg: {
20732 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20733 errdefer msg.destroy(gpa);
20734 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
20735 try sema.addDeclaredHereNote(msg, elem_ty);
20736 break :msg msg;
20737 });
20738 }
2099520739
20996 const fields_arr = try sema.derefSliceAsArray(block, operand_src, fields_val, .{ .simple = .union_fields });
20740 const sentinel_ty = try pt.optionalType(elem_ty.toIntern());
20741 const sentinel_uncoerced = try sema.resolveInst(extra.sentinel);
20742 const sentinel_coerced = try sema.coerce(block, sentinel_ty, sentinel_uncoerced, sentinel_src);
20743 const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel_coerced, .{ .simple = .pointer_sentinel });
20744 const opt_sentinel = sentinel_val.optionalValue(zcu);
20745 if (opt_sentinel) |sentinel| {
20746 switch (size) {
20747 .many, .slice => {},
20748 .one, .c => return sema.fail(block, sentinel_src, "sentinels are only allowed on slices and unknown-length pointers", .{}),
20749 }
20750 try checkSentinelType(sema, block, sentinel_src, elem_ty);
20751 if (sentinel.canMutateComptimeVarState(zcu)) {
20752 const sentinel_name = try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls);
20753 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel);
20754 }
20755 }
2099720756
20998 return sema.reifyUnion(block, inst, src, layout, tag_type_val, fields_arr, name_strategy);
20757 return .fromType(try pt.ptrTypeSema(.{
20758 .child = elem_ty.toIntern(),
20759 .sentinel = if (opt_sentinel) |s| s.toIntern() else .none,
20760 .flags = .{
20761 .size = size,
20762 .is_const = attrs.@"const",
20763 .is_volatile = attrs.@"volatile",
20764 .is_allowzero = attrs.@"allowzero",
20765 .address_space = attrs.@"addrspace" orelse as: {
20766 if (elem_ty.zigTypeTag(zcu) == .@"fn" and zcu.getTarget().cpu.arch == .avr) break :as .flash;
20767 break :as .generic;
20768 },
20769 .alignment = @"align",
2099920770 },
21000 .@"fn" => {
21001 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
21002 const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21003 ip,
21004 try ip.getOrPutString(gpa, pt.tid, "calling_convention", .no_embedded_nulls),
21005 ).?);
21006 const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21007 ip,
21008 try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),
21009 ).?);
21010 const is_var_args_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21011 ip,
21012 try ip.getOrPutString(gpa, pt.tid, "is_var_args", .no_embedded_nulls),
21013 ).?);
21014 const return_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21015 ip,
21016 try ip.getOrPutString(gpa, pt.tid, "return_type", .no_embedded_nulls),
21017 ).?);
21018 const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
21019 ip,
21020 try ip.getOrPutString(gpa, pt.tid, "params", .no_embedded_nulls),
21021 ).?);
21022
21023 const is_generic = is_generic_val.toBool();
21024 if (is_generic) {
21025 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
21026 }
21027
21028 const is_var_args = is_var_args_val.toBool();
21029 const cc = try sema.analyzeValueAsCallconv(block, src, calling_convention_val);
21030 if (is_var_args) {
21031 try sema.checkCallConvSupportsVarArgs(block, src, cc);
21032 }
21033
21034 const return_type = return_type_val.optionalValue(zcu) orelse
21035 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
21036
21037 const params_val = try sema.derefSliceAsArray(block, operand_src, params_slice_val, .{ .simple = .function_parameters });
21038
21039 const args_len = try sema.usizeCast(block, src, params_val.typeOf(zcu).arrayLen(zcu));
21040 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
20771 }));
20772}
2104120773
21042 var noalias_bits: u32 = 0;
21043 for (param_types, 0..) |*param_type, i| {
21044 const elem_val = try params_val.elemValue(pt, i);
21045 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
21046 const param_is_generic_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
21047 ip,
21048 try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),
21049 ).?);
21050 const param_is_noalias_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
21051 ip,
21052 try ip.getOrPutString(gpa, pt.tid, "is_noalias", .no_embedded_nulls),
21053 ).?);
21054 const opt_param_type_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
21055 ip,
21056 try ip.getOrPutString(gpa, pt.tid, "type", .no_embedded_nulls),
21057 ).?);
21058
21059 if (param_is_generic_val.toBool()) {
21060 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});
21061 }
21062
21063 const param_type_val = opt_param_type_val.optionalValue(zcu) orelse
21064 return sema.fail(block, src, "Type.Fn.Param.type must be non-null for @Type", .{});
21065 param_type.* = param_type_val.toIntern();
21066
21067 if (param_is_noalias_val.toBool()) {
21068 if (!Type.fromInterned(param_type.*).isPtrAtRuntime(zcu)) {
21069 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
21070 }
21071 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
21072 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
21073 }
20774fn zirReifyFn(
20775 sema: *Sema,
20776 block: *Block,
20777 extended: Zir.Inst.Extended.InstData,
20778) CompileError!Air.Inst.Ref {
20779 const pt = sema.pt;
20780 const zcu = pt.zcu;
20781 const gpa = zcu.gpa;
20782 const ip = &zcu.intern_pool;
20783
20784 const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
20785 const param_types_src = block.builtinCallArgSrc(extra.node, 0);
20786 const param_attrs_src = block.builtinCallArgSrc(extra.node, 1);
20787 const ret_ty_src = block.builtinCallArgSrc(extra.node, 2);
20788 const fn_attrs_src = block.builtinCallArgSrc(extra.node, 3);
20789
20790 const single_param_attrs_ty = try sema.getBuiltinType(param_attrs_src, .@"Type.Fn.Param.Attributes");
20791 const fn_attrs_ty = try sema.getBuiltinType(fn_attrs_src, .@"Type.Fn.Attributes");
20792
20793 const param_types_uncoerced = try sema.resolveInst(extra.param_types);
20794 const param_types_coerced = try sema.coerce(block, .slice_const_type, param_types_uncoerced, param_types_src);
20795 const param_types_slice = try sema.resolveConstDefinedValue(block, param_types_src, param_types_coerced, .{ .simple = .fn_param_types });
20796 const param_types_arr = try sema.derefSliceAsArray(block, param_types_src, param_types_slice, .{ .simple = .fn_param_types });
20797
20798 const params_len = param_types_arr.typeOf(zcu).arrayLen(zcu);
20799
20800 const param_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
20801 .len = params_len,
20802 .child = single_param_attrs_ty.toIntern(),
20803 }));
20804 const param_attrs_uncoerced = try sema.resolveInst(extra.param_attrs);
20805 const param_attrs_coerced = try sema.coerce(block, param_attrs_ty, param_attrs_uncoerced, param_attrs_src);
20806 const param_attrs_slice = try sema.resolveConstDefinedValue(block, param_attrs_src, param_attrs_coerced, .{ .simple = .fn_param_attrs });
20807 const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs });
20808
20809 const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty);
20810
20811 const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs);
20812 const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src);
20813 const fn_attrs_val = try sema.resolveConstDefinedValue(block, fn_attrs_src, fn_attrs_coerced, .{ .simple = .fn_attrs });
20814 const fn_attrs = try sema.interpretBuiltinType(block, fn_attrs_src, fn_attrs_val, std.builtin.Type.Fn.Attributes);
20815
20816 var noalias_bits: u32 = 0;
20817 const param_types_ip = try sema.arena.alloc(InternPool.Index, @intCast(params_len));
20818 for (param_types_ip, 0..@intCast(params_len)) |*param_ty_ip, param_idx| {
20819 const param_ty: Type = (try param_types_arr.elemValue(pt, param_idx)).toType();
20820 const param_attrs = try sema.interpretBuiltinType(
20821 block,
20822 param_attrs_src,
20823 try param_attrs_arr.elemValue(pt, param_idx),
20824 std.builtin.Type.Fn.Param.Attributes,
20825 );
20826 try sema.checkParamTypeCommon(
20827 block,
20828 @intCast(param_idx),
20829 param_ty,
20830 param_attrs.@"noalias",
20831 param_types_src,
20832 fn_attrs.@"callconv",
20833 );
20834 if (try param_ty.comptimeOnlySema(pt)) {
20835 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)});
20836 }
20837 if (param_attrs.@"noalias") {
20838 if (param_idx > 31) {
20839 return sema.fail(block, param_attrs_src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{});
2107420840 }
20841 noalias_bits |= @as(u32, 1) << @intCast(param_idx);
20842 }
20843 param_ty_ip.* = param_ty.toIntern();
20844 }
2107520845
21076 const ty = try pt.funcType(.{
21077 .param_types = param_types,
21078 .noalias_bits = noalias_bits,
21079 .return_type = return_type.toIntern(),
21080 .cc = cc,
21081 .is_var_args = is_var_args,
21082 });
21083 return Air.internedToRef(ty.toIntern());
21084 },
21085 .frame => return sema.failWithUseOfAsync(block, src),
20846 if (fn_attrs.varargs) {
20847 try sema.checkCallConvSupportsVarArgs(block, fn_attrs_src, fn_attrs.@"callconv");
2108620848 }
20849
20850 try sema.checkReturnTypeAndCallConvCommon(
20851 block,
20852 ret_ty,
20853 ret_ty_src,
20854 fn_attrs.@"callconv",
20855 fn_attrs_src,
20856 if (fn_attrs.varargs) fn_attrs_src else null,
20857 false,
20858 false,
20859 );
20860 if (try ret_ty.comptimeOnlySema(pt)) {
20861 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)});
20862 }
20863
20864 return .fromIntern(try ip.getFuncType(gpa, pt.tid, .{
20865 .param_types = param_types_ip,
20866 .noalias_bits = noalias_bits,
20867 .comptime_bits = 0,
20868 .return_type = ret_ty.toIntern(),
20869 .cc = fn_attrs.@"callconv",
20870 .is_var_args = fn_attrs.varargs,
20871 .is_generic = false,
20872 .is_noinline = false,
20873 }));
2108720874}
2108820875
21089fn reifyEnum(
20876fn zirReifyStruct(
2109020877 sema: *Sema,
2109120878 block: *Block,
20879 extended: Zir.Inst.Extended.InstData,
2109220880 inst: Zir.Inst.Index,
21093 src: LazySrcLoc,
21094 tag_ty: Type,
21095 is_exhaustive: bool,
21096 fields_val: Value,
21097 name_strategy: Zir.Inst.NameStrategy,
2109820881) CompileError!Air.Inst.Ref {
2109920882 const pt = sema.pt;
2110020883 const zcu = pt.zcu;
2110120884 const gpa = sema.gpa;
2110220885 const ip = &zcu.intern_pool;
2110320886
21104 // This logic must stay in sync with the structure of `std.builtin.Type.Enum` - search for `fieldValue`.
20887 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
20888 const extra = sema.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
20889 const tracked_inst = try block.trackZir(inst);
20890 const src: LazySrcLoc = .{
20891 .base_node_inst = tracked_inst,
20892 .offset = .nodeOffset(.zero),
20893 };
20894
20895 const layout_src: LazySrcLoc = .{
20896 .base_node_inst = tracked_inst,
20897 .offset = .{ .node_offset_builtin_call_arg = .{
20898 .builtin_call_node = .zero,
20899 .arg_index = 0,
20900 } },
20901 };
20902 const backing_ty_src: LazySrcLoc = .{
20903 .base_node_inst = tracked_inst,
20904 .offset = .{ .node_offset_builtin_call_arg = .{
20905 .builtin_call_node = .zero,
20906 .arg_index = 1,
20907 } },
20908 };
20909 const field_names_src: LazySrcLoc = .{
20910 .base_node_inst = tracked_inst,
20911 .offset = .{ .node_offset_builtin_call_arg = .{
20912 .builtin_call_node = .zero,
20913 .arg_index = 2,
20914 } },
20915 };
20916 const field_types_src: LazySrcLoc = .{
20917 .base_node_inst = tracked_inst,
20918 .offset = .{ .node_offset_builtin_call_arg = .{
20919 .builtin_call_node = .zero,
20920 .arg_index = 3,
20921 } },
20922 };
20923 const field_attrs_src: LazySrcLoc = .{
20924 .base_node_inst = tracked_inst,
20925 .offset = .{ .node_offset_builtin_call_arg = .{
20926 .builtin_call_node = .zero,
20927 .arg_index = 4,
20928 } },
20929 };
20930
20931 const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout");
20932 const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.StructField.Attributes");
20933
20934 const layout_uncoerced = try sema.resolveInst(extra.layout);
20935 const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src);
20936 const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .struct_layout });
20937 const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout);
20938
20939 const backing_int_ty_uncoerced = try sema.resolveInst(extra.backing_ty);
20940 const backing_int_ty_coerced = try sema.coerce(block, .optional_type, backing_int_ty_uncoerced, backing_ty_src);
20941 const backing_int_ty_val = try sema.resolveConstDefinedValue(block, backing_ty_src, backing_int_ty_coerced, .{ .simple = .type });
20942
20943 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
20944 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
20945 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .struct_field_names });
20946 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .struct_field_names });
20947
20948 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
20949
20950 const field_types_ty = try pt.singleConstPtrType(try pt.arrayType(.{
20951 .len = fields_len,
20952 .child = .type_type,
20953 }));
20954 const field_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
20955 .len = fields_len,
20956 .child = single_field_attrs_ty.toIntern(),
20957 }));
20958
20959 const field_types_uncoerced = try sema.resolveInst(extra.field_types);
20960 const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src);
20961 const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .struct_field_types });
20962 const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .struct_field_types });
2110520963
21106 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));
20964 const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs);
20965 const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src);
20966 const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .struct_field_attrs });
20967 const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .struct_field_attrs });
20968
20969 // Before we begin, check for undefs...
20970 if (try sema.anyUndef(block, field_attrs_src, field_attrs_arr)) {
20971 return sema.failWithUseOfUndef(block, field_attrs_src, null);
20972 }
20973 if (try sema.anyUndef(block, field_types_src, field_types_arr)) {
20974 return sema.failWithUseOfUndef(block, field_types_src, null);
20975 }
20976 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
20977 if (try sema.anyUndef(block, backing_ty_src, backing_int_ty_val)) {
20978 return sema.failWithUseOfUndef(block, backing_ty_src, null);
20979 }
2110720980
2110820981 // The validation work here is non-trivial, and it's possible the type already exists.
2110920982 // So in this first pass, let's just construct a hash to optimize for this case. If the
2111020983 // inputs turn out to be invalid, we can cancel the WIP type later.
2111120984
20985 var any_comptime_fields = false;
20986 var any_default_inits = false;
20987 var any_aligned_fields = false;
20988
2111220989 // For deduplication purposes, we must create a hash including all details of this type.
2111320990 // TODO: use a longer hash!
2111420991 var hasher = std.hash.Wyhash.init(0);
21115 std.hash.autoHash(&hasher, tag_ty.toIntern());
21116 std.hash.autoHash(&hasher, is_exhaustive);
21117 std.hash.autoHash(&hasher, fields_len);
21118
20992 std.hash.autoHash(&hasher, layout);
20993 std.hash.autoHash(&hasher, backing_int_ty_val);
20994 // The field *type* array has already been deduplicated for us thanks to the InternPool!
20995 std.hash.autoHash(&hasher, field_types_arr);
20996 // However, for field names and attributes, we need to actually iterate the individual fields,
20997 // because the presence of pointers (the `[]const u8` for the name and the `*const anyopaque`
20998 // for the default value) means that distinct interned values could ultimately result in the
20999 // same struct type.
2111921000 for (0..fields_len) |field_idx| {
21120 const field_info = try fields_val.elemValue(pt, field_idx);
21001 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21002 const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx);
21003
21004 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .struct_field_names });
21005
21006 const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21007 std.builtin.Type.StructField.Attributes,
21008 "comptime",
21009 ).?);
21010 const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21011 std.builtin.Type.StructField.Attributes,
21012 "align",
21013 ).?);
21014 const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21015 std.builtin.Type.StructField.Attributes,
21016 "default_value_ptr",
21017 ).?);
2112121018
21122 const field_name_val = try field_info.fieldValue(pt, 0);
21123 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));
21124
21125 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .enum_field_name });
21019 const field_default: InternPool.Index = d: {
21020 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
21021 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21022 const ptr_ty = try pt.singleConstPtrType(field_ty);
21023 const deref_val = try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21024 block,
21025 field_attrs_src,
21026 .{ .simple = .struct_field_default_value },
21027 );
21028 // Resolve the value so that lazy values do not create distinct types.
21029 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
21030 };
2112621031
2112721032 std.hash.autoHash(&hasher, .{
2112821033 field_name,
21129 field_value_val.toIntern(),
21034 field_attr_comptime,
21035 field_attr_align,
21036 field_default,
2113021037 });
21038
21039 if (field_attr_comptime.toBool()) any_comptime_fields = true;
21040 if (field_attr_align.optionalValue(zcu)) |_| any_aligned_fields = true;
21041 if (field_default != .none) any_default_inits = true;
2113121042 }
2113221043
21133 const tracked_inst = try block.trackZir(inst);
21044 // Some basic validation to avoid a bogus `getStructType` call...
21045 const backing_int_ty: ?Type = if (backing_int_ty_val.optionalValue(zcu)) |backing| ty: {
21046 switch (layout) {
21047 .auto, .@"extern" => return sema.fail(block, backing_ty_src, "non-packed struct does not support backing integer type", .{}),
21048 .@"packed" => {},
21049 }
21050 break :ty backing.toType();
21051 } else null;
21052 if (any_aligned_fields and layout == .@"packed") {
21053 return sema.fail(block, field_attrs_src, "packed struct fields cannot be aligned", .{});
21054 }
21055 if (any_comptime_fields and layout != .auto) {
21056 return sema.fail(block, field_attrs_src, "{t} struct fields cannot be marked comptime", .{layout});
21057 }
2113421058
21135 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{
21136 .has_values = true,
21137 .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive,
21138 .fields_len = fields_len,
21059 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
21060 .layout = layout,
21061 .fields_len = @intCast(fields_len),
21062 .known_non_opv = false,
21063 .requires_comptime = .unknown,
21064 .any_comptime_fields = any_comptime_fields,
21065 .any_default_inits = any_default_inits,
21066 .any_aligned_fields = any_aligned_fields,
21067 .inits_resolved = true,
2113921068 .key = .{ .reified = .{
2114021069 .zir_index = tracked_inst,
2114121070 .type_hash = hasher.final(),
......@@ -21148,79 +21077,144 @@ fn reifyEnum(
2114821077 return Air.internedToRef(ty);
2114921078 },
2115021079 };
21151 var done = false;
21152 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
21153
21154 if (tag_ty.zigTypeTag(zcu) != .int) {
21155 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
21156 }
21080 errdefer wip_ty.cancel(ip, pt.tid);
2115721081
2115821082 const type_name = try sema.createTypeName(
2115921083 block,
2116021084 name_strategy,
21161 "enum",
21085 "struct",
2116221086 inst,
2116321087 wip_ty.index,
2116421088 );
2116521089 wip_ty.setName(ip, type_name.name, type_name.nav);
2116621090
21167 const new_namespace_index = try pt.createNamespace(.{
21168 .parent = block.namespace.toOptional(),
21169 .owner_type = wip_ty.index,
21170 .file_scope = block.getFileScopeIndex(zcu),
21171 .generation = zcu.generation,
21172 });
21173
21174 try sema.declareDependency(.{ .interned = wip_ty.index });
21175 try sema.addTypeReferenceEntry(src, wip_ty.index);
21176 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21177 wip_ty.prepare(ip, new_namespace_index);
21178 wip_ty.setTagTy(ip, tag_ty.toIntern());
21179 done = true;
21091 const wip_struct_type = ip.loadStructType(wip_ty.index);
2118021092
2118121093 for (0..fields_len) |field_idx| {
21182 const field_info = try fields_val.elemValue(pt, field_idx);
21094 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21095 const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx);
2118321096
21184 const field_name_val = try field_info.fieldValue(pt, 0);
21185 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));
21097 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
2118621098
21187 // Don't pass a reason; first loop acts as an assertion that this is valid.
21188 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21099 // Don't pass a reason; first loop acts as a check that this is valid.
21100 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
21101 if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| {
21102 _ = prev_index; // TODO: better source location
21103 return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21104 }
21105
21106 const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21107 std.builtin.Type.StructField.Attributes,
21108 "comptime",
21109 ).?);
21110 const field_attr_align = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21111 std.builtin.Type.StructField.Attributes,
21112 "align",
21113 ).?);
21114 const field_attr_default_value_ptr = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
21115 std.builtin.Type.StructField.Attributes,
21116 "default_value_ptr",
21117 ).?);
21118
21119 if (field_attr_align.optionalValue(zcu)) |field_align_val| {
21120 assert(layout != .@"packed");
21121 const bytes = try field_align_val.toUnsignedIntSema(pt);
21122 const a = try sema.validateAlign(block, field_attrs_src, bytes);
21123 wip_struct_type.field_aligns.get(ip)[field_idx] = a;
21124 } else if (any_aligned_fields) {
21125 assert(layout != .@"packed");
21126 wip_struct_type.field_aligns.get(ip)[field_idx] = .none;
21127 }
2118921128
21190 if (!try sema.intFitsInType(field_value_val, tag_ty, null)) {
21191 // TODO: better source location
21192 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{
21193 field_name.fmt(ip),
21194 field_value_val.fmtValueSema(pt, sema),
21195 tag_ty.fmt(pt),
21196 });
21129 const field_default: InternPool.Index = d: {
21130 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
21131 assert(any_default_inits);
21132 const ptr_ty = try pt.singleConstPtrType(field_ty);
21133 // The first loop checked that this is comptime-dereferencable.
21134 const deref_val = (try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty)).?;
21135 // ...but we've not checked this yet!
21136 if (deref_val.canMutateComptimeVarState(zcu)) {
21137 return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val);
21138 }
21139 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
21140 };
21141
21142 if (field_attr_comptime.toBool()) {
21143 assert(layout == .auto);
21144 if (field_default == .none) {
21145 return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{});
21146 }
21147 wip_struct_type.setFieldComptime(ip, field_idx);
2119721148 }
2119821149
21199 const coerced_field_val = try pt.getCoerced(field_value_val, tag_ty);
21200 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {
21201 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21202 .name => msg: {
21203 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21150 wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern();
21151 if (field_default != .none) {
21152 wip_struct_type.field_inits.get(ip)[field_idx] = field_default;
21153 }
21154
21155 switch (field_ty.zigTypeTag(zcu)) {
21156 .@"opaque" => return sema.failWithOwnedErrorMsg(block, msg: {
21157 const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
21158 errdefer msg.destroy(gpa);
21159 try sema.addDeclaredHereNote(msg, field_ty);
21160 break :msg msg;
21161 }),
21162 .noreturn => return sema.failWithOwnedErrorMsg(block, msg: {
21163 const msg = try sema.errMsg(field_types_src, "struct fields cannot be 'noreturn'", .{});
21164 errdefer msg.destroy(gpa);
21165 try sema.addDeclaredHereNote(msg, field_ty);
21166 break :msg msg;
21167 }),
21168 else => {},
21169 }
21170
21171 switch (layout) {
21172 .auto => {},
21173 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
21174 return sema.failWithOwnedErrorMsg(block, msg: {
21175 const msg = try sema.errMsg(field_types_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2120421176 errdefer msg.destroy(gpa);
21205 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21206 try sema.errNote(src, msg, "other field here", .{});
21177 try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .struct_field);
21178 try sema.addDeclaredHereNote(msg, field_ty);
2120721179 break :msg msg;
21208 },
21209 .value => msg: {
21210 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});
21180 });
21181 },
21182 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
21183 return sema.failWithOwnedErrorMsg(block, msg: {
21184 const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2121121185 errdefer msg.destroy(gpa);
21212 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21213 try sema.errNote(src, msg, "other enum tag value here", .{});
21186 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
21187 try sema.addDeclaredHereNote(msg, field_ty);
2121421188 break :msg msg;
21215 },
21216 });
21189 });
21190 },
2121721191 }
2121821192 }
2121921193
21220 if (!is_exhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {
21221 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});
21194 if (layout == .@"packed") {
21195 var fields_bit_sum: u64 = 0;
21196 for (0..wip_struct_type.field_types.len) |field_idx| {
21197 const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]);
21198 try field_ty.resolveLayout(pt);
21199 fields_bit_sum += field_ty.bitSize(zcu);
21200 }
21201 if (backing_int_ty) |ty| {
21202 try sema.checkBackingIntType(block, src, ty, fields_bit_sum);
21203 wip_struct_type.setBackingIntType(ip, ty.toIntern());
21204 } else {
21205 const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
21206 wip_struct_type.setBackingIntType(ip, ty.toIntern());
21207 }
2122221208 }
2122321209
21210 const new_namespace_index = try pt.createNamespace(.{
21211 .parent = block.namespace.toOptional(),
21212 .owner_type = wip_ty.index,
21213 .file_scope = block.getFileScopeIndex(zcu),
21214 .generation = zcu.generation,
21215 });
21216
21217 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
2122421218 codegen_type: {
2122521219 if (zcu.comp.config.use_llvm) break :codegen_type;
2122621220 if (block.ownerModule().strip) break :codegen_type;
......@@ -21228,75 +21222,177 @@ fn reifyEnum(
2122821222 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2122921223 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2123021224 }
21231 return Air.internedToRef(wip_ty.index);
21225 try sema.declareDependency(.{ .interned = wip_ty.index });
21226 try sema.addTypeReferenceEntry(src, wip_ty.index);
21227 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21228 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
2123221229}
2123321230
21234fn reifyUnion(
21231fn zirReifyUnion(
2123521232 sema: *Sema,
2123621233 block: *Block,
21234 extended: Zir.Inst.Extended.InstData,
2123721235 inst: Zir.Inst.Index,
21238 src: LazySrcLoc,
21239 layout: std.builtin.Type.ContainerLayout,
21240 opt_tag_type_val: Value,
21241 fields_val: Value,
21242 name_strategy: Zir.Inst.NameStrategy,
2124321236) CompileError!Air.Inst.Ref {
2124421237 const pt = sema.pt;
2124521238 const zcu = pt.zcu;
2124621239 const gpa = sema.gpa;
2124721240 const ip = &zcu.intern_pool;
2124821241
21249 // This logic must stay in sync with the structure of `std.builtin.Type.Union` - search for `fieldValue`.
21242 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
21243 const extra = sema.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
21244 const tracked_inst = try block.trackZir(inst);
21245 const src: LazySrcLoc = .{
21246 .base_node_inst = tracked_inst,
21247 .offset = .nodeOffset(.zero),
21248 };
21249
21250 const layout_src: LazySrcLoc = .{
21251 .base_node_inst = tracked_inst,
21252 .offset = .{ .node_offset_builtin_call_arg = .{
21253 .builtin_call_node = .zero,
21254 .arg_index = 0,
21255 } },
21256 };
21257 const arg_ty_src: LazySrcLoc = .{
21258 .base_node_inst = tracked_inst,
21259 .offset = .{ .node_offset_builtin_call_arg = .{
21260 .builtin_call_node = .zero,
21261 .arg_index = 1,
21262 } },
21263 };
21264 const field_names_src: LazySrcLoc = .{
21265 .base_node_inst = tracked_inst,
21266 .offset = .{ .node_offset_builtin_call_arg = .{
21267 .builtin_call_node = .zero,
21268 .arg_index = 2,
21269 } },
21270 };
21271 const field_types_src: LazySrcLoc = .{
21272 .base_node_inst = tracked_inst,
21273 .offset = .{ .node_offset_builtin_call_arg = .{
21274 .builtin_call_node = .zero,
21275 .arg_index = 3,
21276 } },
21277 };
21278 const field_attrs_src: LazySrcLoc = .{
21279 .base_node_inst = tracked_inst,
21280 .offset = .{ .node_offset_builtin_call_arg = .{
21281 .builtin_call_node = .zero,
21282 .arg_index = 4,
21283 } },
21284 };
21285
21286 const container_layout_ty = try sema.getBuiltinType(layout_src, .@"Type.ContainerLayout");
21287 const single_field_attrs_ty = try sema.getBuiltinType(field_attrs_src, .@"Type.UnionField.Attributes");
21288
21289 const layout_uncoerced = try sema.resolveInst(extra.layout);
21290 const layout_coerced = try sema.coerce(block, container_layout_ty, layout_uncoerced, layout_src);
21291 const layout_val = try sema.resolveConstDefinedValue(block, layout_src, layout_coerced, .{ .simple = .union_layout });
21292 const layout = try sema.interpretBuiltinType(block, layout_src, layout_val, std.builtin.Type.ContainerLayout);
21293
21294 const arg_ty_uncoerced = try sema.resolveInst(extra.arg_ty);
21295 const arg_ty_coerced = try sema.coerce(block, .optional_type, arg_ty_uncoerced, arg_ty_src);
21296 const arg_ty_val = try sema.resolveConstDefinedValue(block, arg_ty_src, arg_ty_coerced, .{ .simple = .type });
21297
21298 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
21299 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
21300 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .union_field_names });
21301 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .union_field_names });
21302
21303 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
21304
21305 const field_types_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21306 .len = fields_len,
21307 .child = .type_type,
21308 }));
21309 const field_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21310 .len = fields_len,
21311 .child = single_field_attrs_ty.toIntern(),
21312 }));
21313
21314 const field_types_uncoerced = try sema.resolveInst(extra.field_types);
21315 const field_types_coerced = try sema.coerce(block, field_types_ty, field_types_uncoerced, field_types_src);
21316 const field_types_slice = try sema.resolveConstDefinedValue(block, field_types_src, field_types_coerced, .{ .simple = .union_field_types });
21317 const field_types_arr = try sema.derefSliceAsArray(block, field_types_src, field_types_slice, .{ .simple = .union_field_types });
2125021318
21251 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));
21319 const field_attrs_uncoerced = try sema.resolveInst(extra.field_attrs);
21320 const field_attrs_coerced = try sema.coerce(block, field_attrs_ty, field_attrs_uncoerced, field_attrs_src);
21321 const field_attrs_slice = try sema.resolveConstDefinedValue(block, field_attrs_src, field_attrs_coerced, .{ .simple = .union_field_attrs });
21322 const field_attrs_arr = try sema.derefSliceAsArray(block, field_attrs_src, field_attrs_slice, .{ .simple = .union_field_attrs });
21323
21324 // Before we begin, check for undefs...
21325 if (try sema.anyUndef(block, field_attrs_src, field_attrs_arr)) {
21326 return sema.failWithUseOfUndef(block, field_attrs_src, null);
21327 }
21328 if (try sema.anyUndef(block, field_types_src, field_types_arr)) {
21329 return sema.failWithUseOfUndef(block, field_types_src, null);
21330 }
21331 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
21332 if (try sema.anyUndef(block, arg_ty_src, arg_ty_val)) {
21333 return sema.failWithUseOfUndef(block, arg_ty_src, null);
21334 }
2125221335
2125321336 // The validation work here is non-trivial, and it's possible the type already exists.
2125421337 // So in this first pass, let's just construct a hash to optimize for this case. If the
2125521338 // inputs turn out to be invalid, we can cancel the WIP type later.
2125621339
21340 var any_aligned_fields = false;
21341
2125721342 // For deduplication purposes, we must create a hash including all details of this type.
2125821343 // TODO: use a longer hash!
2125921344 var hasher = std.hash.Wyhash.init(0);
2126021345 std.hash.autoHash(&hasher, layout);
21261 std.hash.autoHash(&hasher, opt_tag_type_val.toIntern());
21262 std.hash.autoHash(&hasher, fields_len);
21263
21346 std.hash.autoHash(&hasher, arg_ty_val);
21347 // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool!
21348 std.hash.autoHash(&hasher, field_types_arr);
21349 std.hash.autoHash(&hasher, field_attrs_arr);
21350 // However, for field names, we need to iterate the individual fields, because the pointers (the
21351 // names are slices) mean that distinct values could ultimately result in the same union type.
2126421352 for (0..fields_len) |field_idx| {
21265 const field_info = try fields_val.elemValue(pt, field_idx);
21266
21267 const field_name_val = try field_info.fieldValue(pt, 0);
21268 const field_type_val = try field_info.fieldValue(pt, 1);
21269 const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 2));
21353 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21354 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .union_field_names });
21355 std.hash.autoHash(&hasher, field_name);
2127021356
21271 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name });
21272 std.hash.autoHash(&hasher, .{
21273 field_name,
21274 field_type_val.toIntern(),
21275 field_align_val.toIntern(),
21276 });
21357 const field_attrs = try sema.interpretBuiltinType(
21358 block,
21359 field_attrs_src,
21360 try field_attrs_arr.elemValue(pt, field_idx),
21361 std.builtin.Type.UnionField.Attributes,
21362 );
21363 if (field_attrs.@"align" != null) {
21364 any_aligned_fields = true;
21365 }
2127721366 }
2127821367
21279 const tracked_inst = try block.trackZir(inst);
21368 // Some basic validation to avoid a bogus `getUnionType` call...
21369 const explicit_tag_ty: ?Type = if (arg_ty_val.optionalValue(zcu)) |arg_ty| ty: {
21370 switch (layout) {
21371 .@"extern", .@"packed" => return sema.fail(block, arg_ty_src, "{t} union does not support enum tag type", .{layout}),
21372 .auto => {},
21373 }
21374 break :ty arg_ty.toType();
21375 } else null;
21376 if (any_aligned_fields and layout == .@"packed") {
21377 return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{});
21378 }
2128021379
2128121380 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{
2128221381 .flags = .{
2128321382 .layout = layout,
2128421383 .status = .none,
21285 .runtime_tag = if (opt_tag_type_val.optionalValue(zcu) != null)
21286 .tagged
21287 else if (layout != .auto)
21288 .none
21289 else switch (block.wantSafeTypes()) {
21290 true => .safety,
21291 false => .none,
21384 .runtime_tag = rt: {
21385 if (explicit_tag_ty != null) break :rt .tagged;
21386 if (layout == .auto and block.wantSafeTypes()) break :rt .safety;
21387 break :rt .none;
2129221388 },
21293 .any_aligned_fields = layout != .@"packed",
21389 .any_aligned_fields = any_aligned_fields,
2129421390 .requires_comptime = .unknown,
2129521391 .assumed_runtime_bits = false,
2129621392 .assumed_pointer_aligned = false,
2129721393 .alignment = .none,
2129821394 },
21299 .fields_len = fields_len,
21395 .fields_len = @intCast(fields_len),
2130021396 .enum_tag_ty = .none, // set later because not yet validated
2130121397 .field_types = &.{}, // set later
2130221398 .field_aligns = &.{}, // set later
......@@ -21325,128 +21421,117 @@ fn reifyUnion(
2132521421
2132621422 const loaded_union = ip.loadUnionType(wip_ty.index);
2132721423
21328 const enum_tag_ty, const has_explicit_tag = if (opt_tag_type_val.optionalValue(zcu)) |tag_type_val| tag_ty: {
21329 switch (ip.indexToKey(tag_type_val.toIntern())) {
21330 .enum_type => {},
21331 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
21424 const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: {
21425 if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") {
21426 return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{});
2133221427 }
21333 const enum_tag_ty = tag_type_val.toType();
2133421428
21335 // We simply track which fields of the tag type have been seen.
2133621429 const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu);
21337 var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len);
2133821430
2133921431 for (0..fields_len) |field_idx| {
21340 const field_info = try fields_val.elemValue(pt, field_idx);
21432 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21433 // Don't pass a reason; first loop acts as a check that this is valid.
21434 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
2134121435
21342 const field_name_val = try field_info.fieldValue(pt, 0);
21343 const field_type_val = try field_info.fieldValue(pt, 1);
21344 const field_alignment_val = try field_info.fieldValue(pt, 2);
21345
21346 // Don't pass a reason; first loop acts as an assertion that this is valid.
21347 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21348
21349 const enum_index = enum_tag_ty.enumFieldIndex(field_name, zcu) orelse {
21350 // TODO: better source location
21351 return sema.fail(block, src, "no field named '{f}' in enum '{f}'", .{
21436 if (field_idx >= tag_ty_fields_len) {
21437 return sema.fail(block, field_names_src, "no field named '{f}' in enum '{f}'", .{
2135221438 field_name.fmt(ip), enum_tag_ty.fmt(pt),
2135321439 });
21354 };
21355 if (seen_tags.isSet(enum_index)) {
21356 // TODO: better source location
21357 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
2135821440 }
21359 seen_tags.set(enum_index);
2136021441
21361 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21362 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21363 if (layout == .@"packed") {
21364 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});
21365 } else {
21366 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21442 const enum_field_name = enum_tag_ty.enumFieldName(field_idx, zcu);
21443 if (enum_field_name != field_name) {
21444 return sema.fail(block, field_names_src, "union field name '{f}' does not match enum field name '{f}'", .{
21445 field_name.fmt(ip), enum_field_name.fmt(ip),
21446 });
2136721447 }
2136821448 }
21369
2137021449 if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: {
21371 const msg = try sema.errMsg(src, "enum fields missing in union", .{});
21450 const msg = try sema.errMsg(field_names_src, "{d} enum fields missing in union", .{
21451 tag_ty_fields_len - fields_len,
21452 });
2137221453 errdefer msg.destroy(gpa);
21373 var it = seen_tags.iterator(.{ .kind = .unset });
21374 while (it.next()) |enum_index| {
21375 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);
21376 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
21377 field_name.fmt(ip),
21454 for (fields_len..tag_ty_fields_len) |enum_field_idx| {
21455 try sema.addFieldErrNote(enum_tag_ty, enum_field_idx, msg, "field '{f}' missing, declared here", .{
21456 enum_tag_ty.enumFieldName(enum_field_idx, zcu).fmt(ip),
2137821457 });
2137921458 }
2138021459 try sema.addDeclaredHereNote(msg, enum_tag_ty);
2138121460 break :msg msg;
2138221461 });
21383
21384 break :tag_ty .{ enum_tag_ty.toIntern(), true };
21385 } else tag_ty: {
21462 break :tag .{ enum_tag_ty.toIntern(), true };
21463 } else tag: {
2138621464 // We must track field names and set up the tag type ourselves.
2138721465 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
2138821466 try field_names.ensureTotalCapacity(sema.arena, fields_len);
2138921467
2139021468 for (0..fields_len) |field_idx| {
21391 const field_info = try fields_val.elemValue(pt, field_idx);
21392
21393 const field_name_val = try field_info.fieldValue(pt, 0);
21394 const field_type_val = try field_info.fieldValue(pt, 1);
21395 const field_alignment_val = try field_info.fieldValue(pt, 2);
21396
21397 // Don't pass a reason; first loop acts as an assertion that this is valid.
21398 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21469 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21470 // Don't pass a reason; first loop acts as a check that this is valid.
21471 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
2139921472 const gop = field_names.getOrPutAssumeCapacity(field_name);
2140021473 if (gop.found_existing) {
2140121474 // TODO: better source location
21402 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});
21403 }
21404
21405 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21406 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21407 if (layout == .@"packed") {
21408 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});
21409 } else {
21410 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21475 return sema.fail(block, field_names_src, "duplicate union field {f}", .{field_name.fmt(ip)});
2141121476 }
2141221477 }
21413
2141421478 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);
21415 break :tag_ty .{ enum_tag_ty, false };
21479 break :tag .{ enum_tag_ty, false };
2141621480 };
2141721481 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
2141821482
21419 for (loaded_union.field_types.get(ip)) |field_ty_ip| {
21420 const field_ty: Type = .fromInterned(field_ty_ip);
21483 for (0..fields_len) |field_idx| {
21484 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21485 const field_attrs = try sema.interpretBuiltinType(
21486 block,
21487 field_attrs_src,
21488 try field_attrs_arr.elemValue(pt, field_idx),
21489 std.builtin.Type.UnionField.Attributes,
21490 );
21491
2142121492 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
2142221493 return sema.failWithOwnedErrorMsg(block, msg: {
21423 const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
21494 const msg = try sema.errMsg(field_types_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
2142421495 errdefer msg.destroy(gpa);
21425
2142621496 try sema.addDeclaredHereNote(msg, field_ty);
2142721497 break :msg msg;
2142821498 });
2142921499 }
21430 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
21431 return sema.failWithOwnedErrorMsg(block, msg: {
21432 const msg = try sema.errMsg(src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21433 errdefer msg.destroy(gpa);
2143421500
21435 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .union_field);
21501 switch (layout) {
21502 .auto => {},
21503 .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) {
21504 return sema.failWithOwnedErrorMsg(block, msg: {
21505 const msg = try sema.errMsg(field_types_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21506 errdefer msg.destroy(gpa);
21507
21508 try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .union_field);
2143621509
21437 try sema.addDeclaredHereNote(msg, field_ty);
21438 break :msg msg;
21439 });
21440 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21441 return sema.failWithOwnedErrorMsg(block, msg: {
21442 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21443 errdefer msg.destroy(gpa);
21510 try sema.addDeclaredHereNote(msg, field_ty);
21511 break :msg msg;
21512 });
21513 },
21514 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
21515 return sema.failWithOwnedErrorMsg(block, msg: {
21516 const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21517 errdefer msg.destroy(gpa);
2144421518
21445 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
21519 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
2144621520
21447 try sema.addDeclaredHereNote(msg, field_ty);
21448 break :msg msg;
21449 });
21521 try sema.addDeclaredHereNote(msg, field_ty);
21522 break :msg msg;
21523 });
21524 },
21525 }
21526
21527 loaded_union.field_types.get(ip)[field_idx] = field_ty.toIntern();
21528 if (field_attrs.@"align") |bytes| {
21529 assert(layout != .@"packed");
21530 const a = try sema.validateAlign(block, field_attrs_src, bytes);
21531 loaded_union.field_aligns.get(ip)[field_idx] = a;
21532 } else if (any_aligned_fields) {
21533 assert(layout != .@"packed");
21534 loaded_union.field_aligns.get(ip)[field_idx] = .none;
2145021535 }
2145121536 }
2145221537
......@@ -21471,116 +21556,94 @@ fn reifyUnion(
2147121556 try sema.declareDependency(.{ .interned = wip_ty.index });
2147221557 try sema.addTypeReferenceEntry(src, wip_ty.index);
2147321558 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21474 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
21559 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
2147521560}
2147621561
21477fn reifyTuple(
21562fn zirReifyEnum(
2147821563 sema: *Sema,
2147921564 block: *Block,
21480 src: LazySrcLoc,
21481 fields_val: Value,
21565 extended: Zir.Inst.Extended.InstData,
21566 inst: Zir.Inst.Index,
2148221567) CompileError!Air.Inst.Ref {
2148321568 const pt = sema.pt;
2148421569 const zcu = pt.zcu;
2148521570 const gpa = sema.gpa;
2148621571 const ip = &zcu.intern_pool;
2148721572
21488 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));
21489
21490 const types = try sema.arena.alloc(InternPool.Index, fields_len);
21491 const inits = try sema.arena.alloc(InternPool.Index, fields_len);
21492
21493 for (types, inits, 0..) |*field_ty, *field_init, field_idx| {
21494 const field_info = try fields_val.elemValue(pt, field_idx);
21495
21496 const field_name_val = try field_info.fieldValue(pt, 0);
21497 const field_type_val = try field_info.fieldValue(pt, 1);
21498 const field_default_value_val = try field_info.fieldValue(pt, 2);
21499 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21500 const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4));
21501
21502 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .tuple_field_name });
21503 const field_type = field_type_val.toType();
21504 const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: {
21505 const ptr_ty = try pt.singleConstPtrType(field_type_val.toType());
21506 // We need to do this deref here, so we won't check for this error case later on.
21507 const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21508 block,
21509 src,
21510 .{ .simple = .tuple_field_default_value },
21511 );
21512 if (val.canMutateComptimeVarState(zcu)) {
21513 return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21514 }
21515 // Resolve the value so that lazy values do not create distinct types.
21516 break :d (try sema.resolveLazyValue(val)).toIntern();
21517 } else .none;
21573 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
21574 const extra = sema.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
21575 const tracked_inst = try block.trackZir(inst);
21576 const src: LazySrcLoc = .{
21577 .base_node_inst = tracked_inst,
21578 .offset = .nodeOffset(.zero),
21579 };
2151821580
21519 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(
21520 block,
21521 src,
21522 "tuple cannot have non-numeric field '{f}'",
21523 .{field_name.fmt(ip)},
21524 );
21525 if (field_name_index != field_idx) {
21526 return sema.fail(
21527 block,
21528 src,
21529 "tuple field name '{d}' does not match field index {d}",
21530 .{ field_name_index, field_idx },
21531 );
21532 }
21581 const tag_ty_src: LazySrcLoc = .{
21582 .base_node_inst = tracked_inst,
21583 .offset = .{ .node_offset_builtin_call_arg = .{
21584 .builtin_call_node = .zero,
21585 .arg_index = 0,
21586 } },
21587 };
21588 const mode_src: LazySrcLoc = .{
21589 .base_node_inst = tracked_inst,
21590 .offset = .{ .node_offset_builtin_call_arg = .{
21591 .builtin_call_node = .zero,
21592 .arg_index = 1,
21593 } },
21594 };
21595 const field_names_src: LazySrcLoc = .{
21596 .base_node_inst = tracked_inst,
21597 .offset = .{ .node_offset_builtin_call_arg = .{
21598 .builtin_call_node = .zero,
21599 .arg_index = 2,
21600 } },
21601 };
21602 const field_values_src: LazySrcLoc = .{
21603 .base_node_inst = tracked_inst,
21604 .offset = .{ .node_offset_builtin_call_arg = .{
21605 .builtin_call_node = .zero,
21606 .arg_index = 3,
21607 } },
21608 };
2153321609
21534 try sema.validateTupleFieldType(block, field_type, src);
21610 const enum_mode_ty = try sema.getBuiltinType(mode_src, .@"Type.Enum.Mode");
2153521611
21536 {
21537 const alignment_ok = ok: {
21538 if (field_alignment_val.toIntern() == .zero) break :ok true;
21539 const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false;
21540 const abi_align = (try field_type.abiAlignmentSema(pt)).toByteUnits() orelse 0;
21541 break :ok abi_align == given_align;
21542 };
21543 if (!alignment_ok) {
21544 return sema.fail(block, src, "tuple fields cannot specify alignment", .{});
21545 }
21546 }
21612 const tag_ty = try sema.resolveType(block, tag_ty_src, extra.tag_ty);
21613 if (tag_ty.zigTypeTag(zcu) != .int) {
21614 return sema.fail(block, tag_ty_src, "tag type must be an integer type", .{});
21615 }
2154721616
21548 if (field_is_comptime_val.toBool() and field_default_value == .none) {
21549 return sema.fail(block, src, "comptime field without default initialization value", .{});
21550 }
21617 const mode_uncoerced = try sema.resolveInst(extra.mode);
21618 const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src);
21619 const mode_val = try sema.resolveConstDefinedValue(block, mode_src, mode_coerced, .{ .simple = .type });
21620 const nonexhaustive = switch (try sema.interpretBuiltinType(block, mode_src, mode_val, std.builtin.Type.Enum.Mode)) {
21621 .exhaustive => false,
21622 .nonexhaustive => true,
21623 };
2155121624
21552 if (!field_is_comptime_val.toBool() and field_default_value != .none) {
21553 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});
21554 }
21625 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
21626 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
21627 const field_names_slice = try sema.resolveConstDefinedValue(block, field_names_src, field_names_coerced, .{ .simple = .enum_field_names });
21628 const field_names_arr = try sema.derefSliceAsArray(block, field_names_src, field_names_slice, .{ .simple = .enum_field_names });
2155521629
21556 field_ty.* = field_type.toIntern();
21557 field_init.* = field_default_value;
21558 }
21630 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
2155921631
21560 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{
21561 .types = types,
21562 .values = inits,
21632 const field_values_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21633 .len = fields_len,
21634 .child = tag_ty.toIntern(),
2156321635 }));
21564}
21565
21566fn reifyStruct(
21567 sema: *Sema,
21568 block: *Block,
21569 inst: Zir.Inst.Index,
21570 src: LazySrcLoc,
21571 layout: std.builtin.Type.ContainerLayout,
21572 opt_backing_int_val: Value,
21573 fields_val: Value,
21574 name_strategy: Zir.Inst.NameStrategy,
21575) CompileError!Air.Inst.Ref {
21576 const pt = sema.pt;
21577 const zcu = pt.zcu;
21578 const gpa = sema.gpa;
21579 const ip = &zcu.intern_pool;
2158021636
21581 // This logic must stay in sync with the structure of `std.builtin.Type.Struct` - search for `fieldValue`.
21637 const field_values_uncoerced = try sema.resolveInst(extra.field_values);
21638 const field_values_coerced = try sema.coerce(block, field_values_ty, field_values_uncoerced, field_values_src);
21639 const field_values_slice = try sema.resolveConstDefinedValue(block, field_values_src, field_values_coerced, .{ .simple = .enum_field_values });
21640 const field_values_arr = try sema.derefSliceAsArray(block, field_values_src, field_values_slice, .{ .simple = .enum_field_values });
2158221641
21583 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));
21642 // Before we begin, check for undefs...
21643 if (try sema.anyUndef(block, field_values_src, field_values_arr)) {
21644 return sema.failWithUseOfUndef(block, field_values_src, null);
21645 }
21646 // We don't need to check `field_names_arr`, because `sliceToIpString` will check that for us.
2158421647
2158521648 // The validation work here is non-trivial, and it's possible the type already exists.
2158621649 // So in this first pass, let's just construct a hash to optimize for this case. If the
......@@ -21589,62 +21652,23 @@ fn reifyStruct(
2158921652 // For deduplication purposes, we must create a hash including all details of this type.
2159021653 // TODO: use a longer hash!
2159121654 var hasher = std.hash.Wyhash.init(0);
21592 std.hash.autoHash(&hasher, layout);
21593 std.hash.autoHash(&hasher, opt_backing_int_val.toIntern());
21655 std.hash.autoHash(&hasher, tag_ty.toIntern());
21656 std.hash.autoHash(&hasher, nonexhaustive);
2159421657 std.hash.autoHash(&hasher, fields_len);
21595
21596 var any_comptime_fields = false;
21597 var any_default_inits = false;
21598
21658 // `field_values_arr` is already deduplicated by the InternPool!
21659 std.hash.autoHash(&hasher, field_values_arr);
21660 // However, for field names, we need to iterate the individual fields, because the pointers (the
21661 // names are slices) mean that distinct values could ultimately result in the same enum type.
2159921662 for (0..fields_len) |field_idx| {
21600 const field_info = try fields_val.elemValue(pt, field_idx);
21601
21602 const field_name_val = try field_info.fieldValue(pt, 0);
21603 const field_type_val = try field_info.fieldValue(pt, 1);
21604 const field_default_value_val = try field_info.fieldValue(pt, 2);
21605 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21606 const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 4));
21607
21608 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .struct_field_name });
21609 const field_is_comptime = field_is_comptime_val.toBool();
21610 const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(zcu)) |ptr_val| d: {
21611 const ptr_ty = try pt.singleConstPtrType(field_type_val.toType());
21612 // We need to do this deref here, so we won't check for this error case later on.
21613 const val = try sema.pointerDeref(block, src, ptr_val, ptr_ty) orelse return sema.failWithNeededComptime(
21614 block,
21615 src,
21616 .{ .simple = .struct_field_default_value },
21617 );
21618 if (val.canMutateComptimeVarState(zcu)) {
21619 return sema.failWithContainsReferenceToComptimeVar(block, src, field_name, "field default value", val);
21620 }
21621 // Resolve the value so that lazy values do not create distinct types.
21622 break :d (try sema.resolveLazyValue(val)).toIntern();
21623 } else .none;
21624
21625 std.hash.autoHash(&hasher, .{
21626 field_name,
21627 field_type_val.toIntern(),
21628 field_default_value,
21629 field_is_comptime,
21630 field_alignment_val.toIntern(),
21631 });
21632
21633 if (field_is_comptime) any_comptime_fields = true;
21634 if (field_default_value != .none) any_default_inits = true;
21663 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21664 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .enum_field_names });
21665 std.hash.autoHash(&hasher, field_name);
2163521666 }
2163621667
21637 const tracked_inst = try block.trackZir(inst);
21638
21639 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
21640 .layout = layout,
21641 .fields_len = fields_len,
21642 .known_non_opv = false,
21643 .requires_comptime = .unknown,
21644 .any_comptime_fields = any_comptime_fields,
21645 .any_default_inits = any_default_inits,
21646 .any_aligned_fields = layout != .@"packed",
21647 .inits_resolved = true,
21668 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{
21669 .has_values = true,
21670 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,
21671 .fields_len = @intCast(fields_len),
2164821672 .key = .{ .reified = .{
2164921673 .zir_index = tracked_inst,
2165021674 .type_hash = hasher.final(),
......@@ -21654,152 +21678,66 @@ fn reifyStruct(
2165421678 .existing => |ty| {
2165521679 try sema.declareDependency(.{ .interned = ty });
2165621680 try sema.addTypeReferenceEntry(src, ty);
21657 return Air.internedToRef(ty);
21681 return .fromIntern(ty);
2165821682 },
2165921683 };
21660 errdefer wip_ty.cancel(ip, pt.tid);
21684 var done = false;
21685 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
2166121686
2166221687 const type_name = try sema.createTypeName(
2166321688 block,
2166421689 name_strategy,
21665 "struct",
21690 "enum",
2166621691 inst,
2166721692 wip_ty.index,
2166821693 );
2166921694 wip_ty.setName(ip, type_name.name, type_name.nav);
2167021695
21671 const struct_type = ip.loadStructType(wip_ty.index);
21672
21673 for (0..fields_len) |field_idx| {
21674 const field_info = try fields_val.elemValue(pt, field_idx);
21675
21676 const field_name_val = try field_info.fieldValue(pt, 0);
21677 const field_type_val = try field_info.fieldValue(pt, 1);
21678 const field_default_value_val = try field_info.fieldValue(pt, 2);
21679 const field_is_comptime_val = try field_info.fieldValue(pt, 3);
21680 const field_alignment_val = try field_info.fieldValue(pt, 4);
21681
21682 const field_ty = field_type_val.toType();
21683 // Don't pass a reason; first loop acts as an assertion that this is valid.
21684 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);
21685 if (struct_type.addFieldName(ip, field_name)) |prev_index| {
21686 _ = prev_index; // TODO: better source location
21687 return sema.fail(block, src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
21688 }
21689
21690 if (!try sema.intFitsInType(field_alignment_val, align_ty, null)) {
21691 return sema.fail(block, src, "alignment must fit in '{f}'", .{align_ty.fmt(pt)});
21692 }
21693 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);
21694 if (layout == .@"packed") {
21695 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed struct field must be set to 0", .{});
21696 } else {
21697 struct_type.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21698 }
21699
21700 const field_is_comptime = field_is_comptime_val.toBool();
21701 if (field_is_comptime) {
21702 assert(any_comptime_fields);
21703 switch (layout) {
21704 .@"extern" => return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}),
21705 .@"packed" => return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}),
21706 .auto => struct_type.setFieldComptime(ip, field_idx),
21707 }
21708 }
21709
21710 const field_default: InternPool.Index = d: {
21711 if (!any_default_inits) break :d .none;
21712 const ptr_val = field_default_value_val.optionalValue(zcu) orelse break :d .none;
21713 const ptr_ty = try pt.singleConstPtrType(field_ty);
21714 // Asserted comptime-dereferencable above.
21715 const val = (try sema.pointerDeref(block, src, ptr_val, ptr_ty)).?;
21716 // We already resolved this for deduplication, so we may as well do it now.
21717 break :d (try sema.resolveLazyValue(val)).toIntern();
21718 };
21719
21720 if (field_is_comptime and field_default == .none) {
21721 return sema.fail(block, src, "comptime field without default initialization value", .{});
21722 }
21723
21724 struct_type.field_types.get(ip)[field_idx] = field_type_val.toIntern();
21725 if (field_default != .none) {
21726 struct_type.field_inits.get(ip)[field_idx] = field_default;
21727 }
21728
21729 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
21730 return sema.failWithOwnedErrorMsg(block, msg: {
21731 const msg = try sema.errMsg(src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
21732 errdefer msg.destroy(gpa);
21733
21734 try sema.addDeclaredHereNote(msg, field_ty);
21735 break :msg msg;
21736 });
21737 }
21738 if (field_ty.zigTypeTag(zcu) == .noreturn) {
21739 return sema.failWithOwnedErrorMsg(block, msg: {
21740 const msg = try sema.errMsg(src, "struct fields cannot be 'noreturn'", .{});
21741 errdefer msg.destroy(gpa);
21742
21743 try sema.addDeclaredHereNote(msg, field_ty);
21744 break :msg msg;
21745 });
21746 }
21747 if (layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
21748 return sema.failWithOwnedErrorMsg(block, msg: {
21749 const msg = try sema.errMsg(src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21750 errdefer msg.destroy(gpa);
21696 const new_namespace_index = try pt.createNamespace(.{
21697 .parent = block.namespace.toOptional(),
21698 .owner_type = wip_ty.index,
21699 .file_scope = block.getFileScopeIndex(zcu),
21700 .generation = zcu.generation,
21701 });
2175121702
21752 try sema.explainWhyTypeIsNotExtern(msg, src, field_ty, .struct_field);
21703 try sema.declareDependency(.{ .interned = wip_ty.index });
21704 try sema.addTypeReferenceEntry(src, wip_ty.index);
21705 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21706 wip_ty.prepare(ip, new_namespace_index);
21707 wip_ty.setTagTy(ip, tag_ty.toIntern());
21708 done = true;
2175321709
21754 try sema.addDeclaredHereNote(msg, field_ty);
21755 break :msg msg;
21756 });
21757 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {
21758 return sema.failWithOwnedErrorMsg(block, msg: {
21759 const msg = try sema.errMsg(src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
21760 errdefer msg.destroy(gpa);
21710 for (0..fields_len) |field_idx| {
21711 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21712 // Don't pass a reason; first loop acts as a check that this is valid.
21713 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
2176121714
21762 try sema.explainWhyTypeIsNotPacked(msg, src, field_ty);
21715 const field_val = try field_values_arr.elemValue(pt, field_idx);
2176321716
21764 try sema.addDeclaredHereNote(msg, field_ty);
21765 break :msg msg;
21717 if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| {
21718 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21719 .name => msg: {
21720 const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21721 errdefer msg.destroy(gpa);
21722 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21723 try sema.errNote(field_names_src, msg, "other field here", .{});
21724 break :msg msg;
21725 },
21726 .value => msg: {
21727 const msg = try sema.errMsg(field_values_src, "enum tag value {f} already taken", .{field_val.fmtValueSema(pt, sema)});
21728 errdefer msg.destroy(gpa);
21729 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21730 try sema.errNote(field_values_src, msg, "other enum tag value here", .{});
21731 break :msg msg;
21732 },
2176621733 });
2176721734 }
2176821735 }
2176921736
21770 if (layout == .@"packed") {
21771 var fields_bit_sum: u64 = 0;
21772 for (0..struct_type.field_types.len) |field_idx| {
21773 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_idx]);
21774 field_ty.resolveLayout(pt) catch |err| switch (err) {
21775 error.AnalysisFail => {
21776 const msg = sema.err orelse return err;
21777 try sema.errNote(src, msg, "while checking a field of this struct", .{});
21778 return err;
21779 },
21780 else => return err,
21781 };
21782 fields_bit_sum += field_ty.bitSize(zcu);
21783 }
21784
21785 if (opt_backing_int_val.optionalValue(zcu)) |backing_int_val| {
21786 const backing_int_ty = backing_int_val.toType();
21787 try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum);
21788 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
21789 } else {
21790 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
21791 struct_type.setBackingIntType(ip, backing_int_ty.toIntern());
21792 }
21737 if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {
21738 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});
2179321739 }
2179421740
21795 const new_namespace_index = try pt.createNamespace(.{
21796 .parent = block.namespace.toOptional(),
21797 .owner_type = wip_ty.index,
21798 .file_scope = block.getFileScopeIndex(zcu),
21799 .generation = zcu.generation,
21800 });
21801
21802 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
2180321741 codegen_type: {
2180421742 if (zcu.comp.config.use_llvm) break :codegen_type;
2180521743 if (block.ownerModule().strip) break :codegen_type;
......@@ -21807,10 +21745,7 @@ fn reifyStruct(
2180721745 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2180821746 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2180921747 }
21810 try sema.declareDependency(.{ .interned = wip_ty.index });
21811 try sema.addTypeReferenceEntry(src, wip_ty.index);
21812 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21813 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
21748 return Air.internedToRef(wip_ty.index);
2181421749}
2181521750
2181621751fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
......@@ -25541,7 +25476,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2554125476 extra_index += body.len;
2554225477 if (extra.data.bits.ret_ty_is_generic) break :blk .generic_poison;
2554325478
25544 const val = try sema.resolveGenericBody(block, ret_src, body, inst, .type, .{ .simple = .function_ret_ty });
25479 const val = try sema.resolveGenericBody(block, ret_src, body, inst, .type, .{ .simple = .fn_ret_ty });
2554525480 const ty = val.toType();
2554625481 break :blk ty;
2554725482 } else if (extra.data.bits.has_ret_ty_ref) blk: {
......@@ -25968,21 +25903,26 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2596825903 const src = block.nodeOffset(src_node);
2596925904 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2597025905
25971 const ty = switch (value) {
25906 const builtin_type: Zcu.BuiltinDecl = switch (value) {
2597225907 // zig fmt: off
25973 .atomic_order => try sema.getBuiltinType(src, .AtomicOrder),
25974 .atomic_rmw_op => try sema.getBuiltinType(src, .AtomicRmwOp),
25975 .calling_convention => try sema.getBuiltinType(src, .CallingConvention),
25976 .address_space => try sema.getBuiltinType(src, .AddressSpace),
25977 .float_mode => try sema.getBuiltinType(src, .FloatMode),
25978 .reduce_op => try sema.getBuiltinType(src, .ReduceOp),
25979 .call_modifier => try sema.getBuiltinType(src, .CallModifier),
25980 .prefetch_options => try sema.getBuiltinType(src, .PrefetchOptions),
25981 .export_options => try sema.getBuiltinType(src, .ExportOptions),
25982 .extern_options => try sema.getBuiltinType(src, .ExternOptions),
25983 .type_info => try sema.getBuiltinType(src, .Type),
25984 .branch_hint => try sema.getBuiltinType(src, .BranchHint),
25985 .clobbers => try sema.getBuiltinType(src, .@"assembly.Clobbers"),
25908 .atomic_order => .AtomicOrder,
25909 .atomic_rmw_op => .AtomicRmwOp,
25910 .calling_convention => .CallingConvention,
25911 .address_space => .AddressSpace,
25912 .float_mode => .FloatMode,
25913 .signedness => .Signedness,
25914 .reduce_op => .ReduceOp,
25915 .call_modifier => .CallModifier,
25916 .prefetch_options => .PrefetchOptions,
25917 .export_options => .ExportOptions,
25918 .extern_options => .ExternOptions,
25919 .branch_hint => .BranchHint,
25920 .clobbers => .@"assembly.Clobbers",
25921 .pointer_size => .@"Type.Pointer.Size",
25922 .pointer_attributes => .@"Type.Pointer.Attributes",
25923 .fn_attributes, => .@"Type.Fn.Attributes",
25924 .container_layout => .@"Type.ContainerLayout",
25925 .enum_mode => .@"Type.Enum.Mode",
2598625926 // zig fmt: on
2598725927
2598825928 // Values are handled here.
......@@ -26009,7 +25949,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2600925949 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
2601025950 },
2601125951 };
26012 return Air.internedToRef(ty.toIntern());
25952 return .fromType(try sema.getBuiltinType(src, builtin_type));
2601325953}
2601425954
2601525955fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
......@@ -35259,7 +35199,7 @@ fn structFields(
3525935199 .base_node_inst = struct_type.zir_index,
3526035200 .offset = .nodeOffset(.zero),
3526135201 },
35262 .r = .{ .simple = .struct_fields },
35202 .r = .{ .simple = .type },
3526335203 } },
3526435204 .src_base_inst = struct_type.zir_index,
3526535205 .type_name_ctx = struct_type.name,
......@@ -35614,7 +35554,7 @@ fn unionFields(
3561435554 .inlining = null,
3561535555 .comptime_reason = .{ .reason = .{
3561635556 .src = src,
35617 .r = .{ .simple = .union_fields },
35557 .r = .{ .simple = .type },
3561835558 } },
3561935559 .src_base_inst = union_type.zir_index,
3562035560 .type_name_ctx = union_type.name,
......@@ -36077,8 +36017,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3607736017 .manyptr_u8_type,
3607836018 .manyptr_const_u8_type,
3607936019 .manyptr_const_u8_sentinel_0_type,
36020 .manyptr_const_slice_const_u8_type,
3608036021 .slice_const_u8_type,
3608136022 .slice_const_u8_sentinel_0_type,
36023 .slice_const_slice_const_u8_type,
36024 .optional_type_type,
36025 .manyptr_const_type_type,
36026 .slice_const_type_type,
3608236027 .vector_8_i8_type,
3608336028 .vector_16_i8_type,
3608436029 .vector_32_i8_type,
......@@ -37230,7 +37175,7 @@ fn sliceToIpString(
3723037175
3723137176/// Given a slice value, attempts to dereference it into a comptime-known array.
3723237177/// Emits a compile error if the contents of the slice are not comptime-known.
37233/// Asserts that `slice_val` is a slice.
37178/// Asserts that `slice_val` is a slice or a pointer to an array.
3723437179fn derefSliceAsArray(
3723537180 sema: *Sema,
3723637181 block: *Block,
......@@ -37247,7 +37192,7 @@ fn derefSliceAsArray(
3724737192
3724837193/// Given a slice value, attempts to dereference it into a comptime-known array.
3724937194/// Returns `null` if the contents of the slice are not comptime-known.
37250/// Asserts that `slice_val` is a slice.
37195/// Asserts that `slice_val` is a slice or a pointer to an array.
3725137196fn maybeDerefSliceAsArray(
3725237197 sema: *Sema,
3725337198 block: *Block,
......@@ -37257,7 +37202,13 @@ fn maybeDerefSliceAsArray(
3725737202 const pt = sema.pt;
3725837203 const zcu = pt.zcu;
3725937204 const ip = &zcu.intern_pool;
37260 assert(slice_val.typeOf(zcu).isSlice(zcu));
37205 const slice_ty = slice_val.typeOf(zcu);
37206 assert(slice_ty.zigTypeTag(zcu) == .pointer);
37207 switch (slice_ty.ptrInfo(zcu).flags.size) {
37208 .slice => {},
37209 .one => return sema.pointerDeref(block, src, slice_val, slice_ty),
37210 .many, .c => unreachable,
37211 }
3726137212 const slice = switch (ip.indexToKey(slice_val.toIntern())) {
3726237213 .undef => return sema.failWithUseOfUndef(block, src, null),
3726337214 .slice => |slice| slice,
......@@ -37393,7 +37344,7 @@ pub fn resolveDeclaredEnum(
3739337344 .inlining = null,
3739437345 .comptime_reason = .{ .reason = .{
3739537346 .src = src,
37396 .r = .{ .simple = .enum_fields },
37347 .r = .{ .simple = .enum_field_values },
3739737348 } },
3739837349 .src_base_inst = tracked_inst,
3739937350 .type_name_ctx = type_name,
src/Type.zig+8-2
......@@ -317,7 +317,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
317317 .undefined,
318318 => try writer.print("@TypeOf({s})", .{@tagName(s)}),
319319
320 .enum_literal => try writer.writeAll("@Type(.enum_literal)"),
320 .enum_literal => try writer.writeAll("@EnumLiteral()"),
321321
322322 .generic_poison => unreachable,
323323 },
......@@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
35093509 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
35103510 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
35113511 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
3512 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,
3512 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line,
3513 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line,
3514 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line,
35133515 else => unreachable,
35143516 },
35153517 else => unreachable,
......@@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
42804282pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
42814283pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
42824284pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
4285pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type };
4286pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type };
4287pub const optional_type: Type = .{ .ip_index = .optional_type_type };
4288pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type };
42834289
42844290pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };
42854291pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };
src/Value.zig+23
......@@ -2824,6 +2824,29 @@ pub fn resolveLazy(
28242824 .val = resolved_val,
28252825 }));
28262826 },
2827 .error_union => |eu| switch (eu.val) {
2828 .err_name => return val,
2829 .payload => |payload| {
2830 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2831 if (resolved_payload.toIntern() == payload) return val;
2832 return .fromInterned(try pt.intern(.{ .error_union = .{
2833 .ty = eu.ty,
2834 .val = .{ .payload = resolved_payload.toIntern() },
2835 } }));
2836 },
2837 },
2838 .opt => |opt| switch (opt.val) {
2839 .none => return val,
2840 else => |payload| {
2841 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2842 if (resolved_payload.toIntern() == payload) return val;
2843 return .fromInterned(try pt.intern(.{ .opt = .{
2844 .ty = opt.ty,
2845 .val = resolved_payload.toIntern(),
2846 } }));
2847 },
2848 },
2849
28272850 else => return val,
28282851 }
28292852}
src/Zcu.zig+19-5
......@@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {
416416 Type,
417417 @"Type.Fn",
418418 @"Type.Fn.Param",
419 @"Type.Fn.Param.Attributes",
420 @"Type.Fn.Attributes",
419421 @"Type.Int",
420422 @"Type.Float",
421423 @"Type.Pointer",
422424 @"Type.Pointer.Size",
425 @"Type.Pointer.Attributes",
423426 @"Type.Array",
424427 @"Type.Vector",
425428 @"Type.Optional",
......@@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {
427430 @"Type.ErrorUnion",
428431 @"Type.EnumField",
429432 @"Type.Enum",
433 @"Type.Enum.Mode",
430434 @"Type.Union",
431435 @"Type.UnionField",
436 @"Type.UnionField.Attributes",
432437 @"Type.Struct",
433438 @"Type.StructField",
439 @"Type.StructField.Attributes",
434440 @"Type.ContainerLayout",
435441 @"Type.Opaque",
436442 @"Type.Declaration",
......@@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {
495501 .Type,
496502 .@"Type.Fn",
497503 .@"Type.Fn.Param",
504 .@"Type.Fn.Param.Attributes",
505 .@"Type.Fn.Attributes",
498506 .@"Type.Int",
499507 .@"Type.Float",
500508 .@"Type.Pointer",
501509 .@"Type.Pointer.Size",
510 .@"Type.Pointer.Attributes",
502511 .@"Type.Array",
503512 .@"Type.Vector",
504513 .@"Type.Optional",
......@@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {
506515 .@"Type.ErrorUnion",
507516 .@"Type.EnumField",
508517 .@"Type.Enum",
518 .@"Type.Enum.Mode",
509519 .@"Type.Union",
510520 .@"Type.UnionField",
521 .@"Type.UnionField.Attributes",
511522 .@"Type.Struct",
512523 .@"Type.StructField",
524 .@"Type.StructField.Attributes",
513525 .@"Type.ContainerLayout",
514526 .@"Type.Opaque",
515527 .@"Type.Declaration",
......@@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {
17451757 const node = node_off.toAbsolute(src_loc.base_node);
17461758 var buf: [1]Ast.Node.Index = undefined;
17471759 const full = tree.fullFnProto(&buf, node).?;
1748 return tree.nodeToSpan(full.ast.align_expr.unwrap().?);
1760 return tree.nodeToSpan(full.ast.align_expr.unwrap() orelse node);
17491761 },
17501762 .node_offset_fn_type_addrspace => |node_off| {
17511763 const tree = try src_loc.file_scope.getTree(zcu);
17521764 const node = node_off.toAbsolute(src_loc.base_node);
17531765 var buf: [1]Ast.Node.Index = undefined;
17541766 const full = tree.fullFnProto(&buf, node).?;
1755 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?);
1767 return tree.nodeToSpan(full.ast.addrspace_expr.unwrap() orelse node);
17561768 },
17571769 .node_offset_fn_type_section => |node_off| {
17581770 const tree = try src_loc.file_scope.getTree(zcu);
17591771 const node = node_off.toAbsolute(src_loc.base_node);
17601772 var buf: [1]Ast.Node.Index = undefined;
17611773 const full = tree.fullFnProto(&buf, node).?;
1762 return tree.nodeToSpan(full.ast.section_expr.unwrap().?);
1774 return tree.nodeToSpan(full.ast.section_expr.unwrap() orelse node);
17631775 },
17641776 .node_offset_fn_type_cc => |node_off| {
17651777 const tree = try src_loc.file_scope.getTree(zcu);
17661778 const node = node_off.toAbsolute(src_loc.base_node);
17671779 var buf: [1]Ast.Node.Index = undefined;
17681780 const full = tree.fullFnProto(&buf, node).?;
1769 return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?);
1781 return tree.nodeToSpan(full.ast.callconv_expr.unwrap() orelse node);
17701782 },
17711783
17721784 .node_offset_fn_type_ret_ty => |node_off| {
......@@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {
26842696 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
26852697 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,
26862698 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,
2687 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node,
2699 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node,
2700 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node,
2701 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node,
26882702 else => unreachable,
26892703 },
26902704 else => unreachable,
src/codegen/c/Type.zig+70
......@@ -1416,6 +1416,9 @@ pub const Pool = struct {
14161416 .null_type,
14171417 .undefined_type,
14181418 .enum_literal_type,
1419 .optional_type_type,
1420 .manyptr_const_type_type,
1421 .slice_const_type_type,
14191422 => return .void,
14201423 .u1_type, .u8_type => return .u8,
14211424 .i8_type => return .i8,
......@@ -1525,6 +1528,73 @@ pub const Pool = struct {
15251528 return pool.fromFields(allocator, .@"struct", &fields, kind);
15261529 },
15271530
1531 .manyptr_const_slice_const_u8_type => {
1532 const target = &mod.resolved_target.result;
1533 var fields: [2]Info.Field = .{
1534 .{
1535 .name = .{ .index = .ptr },
1536 .ctype = try pool.getPointer(allocator, .{
1537 .elem_ctype = .u8,
1538 .@"const" = true,
1539 .nonstring = true,
1540 }),
1541 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1542 },
1543 .{
1544 .name = .{ .index = .len },
1545 .ctype = .usize,
1546 .alignas = AlignAs.fromAbiAlignment(
1547 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1548 ),
1549 },
1550 };
1551 const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, kind);
1552 return pool.getPointer(allocator, .{
1553 .elem_ctype = slice_const_u8,
1554 .@"const" = true,
1555 });
1556 },
1557 .slice_const_slice_const_u8_type => {
1558 const target = &mod.resolved_target.result;
1559 var fields: [2]Info.Field = .{
1560 .{
1561 .name = .{ .index = .ptr },
1562 .ctype = try pool.getPointer(allocator, .{
1563 .elem_ctype = .u8,
1564 .@"const" = true,
1565 .nonstring = true,
1566 }),
1567 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1568 },
1569 .{
1570 .name = .{ .index = .len },
1571 .ctype = .usize,
1572 .alignas = AlignAs.fromAbiAlignment(
1573 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1574 ),
1575 },
1576 };
1577 const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, .forward);
1578 fields = .{
1579 .{
1580 .name = .{ .index = .ptr },
1581 .ctype = try pool.getPointer(allocator, .{
1582 .elem_ctype = slice_const_u8,
1583 .@"const" = true,
1584 }),
1585 .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
1586 },
1587 .{
1588 .name = .{ .index = .len },
1589 .ctype = .usize,
1590 .alignas = AlignAs.fromAbiAlignment(
1591 .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
1592 ),
1593 },
1594 };
1595 return pool.fromFields(allocator, .@"struct", &fields, kind);
1596 },
1597
15281598 .vector_8_i8_type => {
15291599 const vector_ctype = try pool.getVector(allocator, .{
15301600 .elem_ctype = .i8,
src/link/Dwarf.zig+6-1
......@@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(
44904490 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
44914491 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
44924492 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4493 .reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)),
4493
4494 .reify_enum,
4495 .reify_struct,
4496 .reify_union,
4497 => @enumFromInt(decl_inst.data.extended.small),
4498
44944499 else => unreachable,
44954500 },
44964501 else => unreachable,
src/print_zir.zig+93-11
......@@ -399,6 +399,7 @@ const Writer = struct {
399399 .splat,
400400 .reduce,
401401 .bitcast,
402 .reify_int,
402403 .vector_type,
403404 .max,
404405 .min,
......@@ -568,6 +569,8 @@ const Writer = struct {
568569 .work_group_id,
569570 .branch_hint,
570571 .float_op_result_ty,
572 .reify_tuple,
573 .reify_pointer_sentinel_ty,
571574 => {
572575 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
573576 try self.writeInstRef(stream, inst_data.operand);
......@@ -575,23 +578,13 @@ const Writer = struct {
575578 try self.writeSrcNode(stream, inst_data.node);
576579 },
577580
578 .reify => {
579 const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data;
580 try stream.print("line({d}), ", .{inst_data.src_line});
581 try self.writeInstRef(stream, inst_data.operand);
582 try stream.writeAll(")) ");
583 const prev_parent_decl_node = self.parent_decl_node;
584 self.parent_decl_node = inst_data.node;
585 defer self.parent_decl_node = prev_parent_decl_node;
586 try self.writeSrcNode(stream, .zero);
587 },
588
589581 .builtin_extern,
590582 .c_define,
591583 .error_cast,
592584 .wasm_memory_grow,
593585 .prefetch,
594586 .c_va_arg,
587 .reify_enum_value_slice_ty,
595588 => {
596589 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
597590 try self.writeInstRef(stream, inst_data.lhs);
......@@ -601,6 +594,95 @@ const Writer = struct {
601594 try self.writeSrcNode(stream, inst_data.node);
602595 },
603596
597 .reify_slice_arg_ty => {
598 const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.operand);
599 const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
600 try stream.print("{t}, ", .{reify_slice_arg_info});
601 try self.writeInstRef(stream, extra.operand);
602 try stream.writeAll(")) ");
603 try self.writeSrcNode(stream, extra.node);
604 },
605
606 .reify_pointer => {
607 const extra = self.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
608 try self.writeInstRef(stream, extra.size);
609 try stream.writeAll(", ");
610 try self.writeInstRef(stream, extra.attrs);
611 try stream.writeAll(", ");
612 try self.writeInstRef(stream, extra.elem_ty);
613 try stream.writeAll(", ");
614 try self.writeInstRef(stream, extra.sentinel);
615 try stream.writeAll(")) ");
616 try self.writeSrcNode(stream, extra.node);
617 },
618 .reify_fn => {
619 const extra = self.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
620 try self.writeInstRef(stream, extra.param_types);
621 try stream.writeAll(", ");
622 try self.writeInstRef(stream, extra.param_attrs);
623 try stream.writeAll(", ");
624 try self.writeInstRef(stream, extra.ret_ty);
625 try stream.writeAll(", ");
626 try self.writeInstRef(stream, extra.fn_attrs);
627 try stream.writeAll(")) ");
628 try self.writeSrcNode(stream, extra.node);
629 },
630 .reify_struct => {
631 const extra = self.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
632 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
633 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
634 try self.writeInstRef(stream, extra.layout);
635 try stream.writeAll(", ");
636 try self.writeInstRef(stream, extra.backing_ty);
637 try stream.writeAll(", ");
638 try self.writeInstRef(stream, extra.field_names);
639 try stream.writeAll(", ");
640 try self.writeInstRef(stream, extra.field_types);
641 try stream.writeAll(", ");
642 try self.writeInstRef(stream, extra.field_attrs);
643 try stream.writeAll(")) ");
644 const prev_parent_decl_node = self.parent_decl_node;
645 self.parent_decl_node = extra.node;
646 defer self.parent_decl_node = prev_parent_decl_node;
647 try self.writeSrcNode(stream, .zero);
648 },
649 .reify_union => {
650 const extra = self.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
651 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
652 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
653 try self.writeInstRef(stream, extra.layout);
654 try stream.writeAll(", ");
655 try self.writeInstRef(stream, extra.arg_ty);
656 try stream.writeAll(", ");
657 try self.writeInstRef(stream, extra.field_names);
658 try stream.writeAll(", ");
659 try self.writeInstRef(stream, extra.field_types);
660 try stream.writeAll(", ");
661 try self.writeInstRef(stream, extra.field_attrs);
662 try stream.writeAll(")) ");
663 const prev_parent_decl_node = self.parent_decl_node;
664 self.parent_decl_node = extra.node;
665 defer self.parent_decl_node = prev_parent_decl_node;
666 try self.writeSrcNode(stream, .zero);
667 },
668 .reify_enum => {
669 const extra = self.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
670 const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
671 try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
672 try self.writeInstRef(stream, extra.tag_ty);
673 try stream.writeAll(", ");
674 try self.writeInstRef(stream, extra.mode);
675 try stream.writeAll(", ");
676 try self.writeInstRef(stream, extra.field_names);
677 try stream.writeAll(", ");
678 try self.writeInstRef(stream, extra.field_values);
679 try stream.writeAll(")) ");
680 const prev_parent_decl_node = self.parent_decl_node;
681 self.parent_decl_node = extra.node;
682 defer self.parent_decl_node = prev_parent_decl_node;
683 try self.writeSrcNode(stream, .zero);
684 },
685
604686 .cmpxchg => try self.writeCmpxchg(stream, extended),
605687 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
606688 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),