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 @@...@@ -638,7 +638,7 @@
638 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an638 {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
639 integer type is {#syntax#}65535{#endsyntax#}.639 integer type is {#syntax#}65535{#endsyntax#}.
640 </p>640 </p>
641 {#see_also|Integers|Floats|void|Errors|@Type#}641 {#see_also|Integers|Floats|void|Errors|@Int#}
642 {#header_close#}642 {#header_close#}
643 {#header_open|Primitive Values#}643 {#header_open|Primitive Values#}
644 <div class="table-wrapper">644 <div class="table-wrapper">
...@@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {...@@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {
3723 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>3723 <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>
3724 </tr>3724 </tr>
3725 <tr>3725 <tr>
3726 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>3726 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
3727 <td>-</td>3727 <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>
3729 </tr>3729 </tr>
3730 <tr>3730 <tr>
3731 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>3731 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
...@@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {...@@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {
3839 <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>3839 <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>
3840 </tr>3840 </tr>
3841 <tr>3841 <tr>
3842 <th scope="row">{#syntax#}@Type(x){#endsyntax#}</th>3842 <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
3843 <td>{#syntax#}ptr{#endsyntax#}</td>3843 <td>-</td>
3844 <td>{#syntax#}x{#endsyntax#} has no result location</td>3844 <td>{#syntax#}x{#endsyntax#} and {#syntax#}y{#endsyntax#} do not have result locations</td>
3845 </tr>3845 </tr>
3846 <tr>3846 <tr>
3847 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>3847 <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
...@@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
5755 </p>5755 </p>
5756 {#header_close#}5756 {#header_close#}
57575757
5758 {#header_open|@Type#}5758 {#header_open|@EnumLiteral#}
5759 <pre>{#syntax#}@Type(comptime info: std.builtin.Type) type{#endsyntax#}</pre>5759 <pre>{#syntax#}@EnumLiteral() type{#endsyntax#}</pre>
5760 <p>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 This function is the inverse of {#link|@typeInfo#}. It reifies type information5761 {#header_close#}
5762 into a {#syntax#}type{#endsyntax#}.5762
5763 </p>5763 {#header_open|@Int#}
5764 <p>5764 <pre>{#syntax#}@Int(comptime signedness: std.builtin.Signedness, comptime bits: u16) type{#endsyntax#}</pre>
5765 It is available for the following types:5765 <p>Returns an integer type with the given signedness and bit width.</p>
5766 </p>5766 <p>For instance, {#syntax#}@Int(.unsigned, 18){#endsyntax#} returns the type {#syntax#}u18{#endsyntax#}.</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>
5792 {#header_close#}5767 {#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
5793 {#header_open|@typeInfo#}5827 {#header_open|@typeInfo#}
5794 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>5828 <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>
5795 <p>5829 <p>
lib/std/builtin.zig+50-9
...@@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);...@@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);
548/// This data structure is used by the Zig language code generation and548/// This data structure is used by the Zig language code generation and
549/// therefore must be kept in sync with the compiler implementation.549/// therefore must be kept in sync with the compiler implementation.
550pub const Type = union(enum) {550pub const Type = union(enum) {
551 type: void,551 type,
552 void: void,552 void,
553 bool: void,553 bool,
554 noreturn: void,554 noreturn,
555 int: Int,555 int: Int,
556 float: Float,556 float: Float,
557 pointer: Pointer,557 pointer: Pointer,
558 array: Array,558 array: Array,
559 @"struct": Struct,559 @"struct": Struct,
560 comptime_float: void,560 comptime_float,
561 comptime_int: void,561 comptime_int,
562 undefined: void,562 undefined,
563 null: void,563 null,
564 optional: Optional,564 optional: Optional,
565 error_union: ErrorUnion,565 error_union: ErrorUnion,
566 error_set: ErrorSet,566 error_set: ErrorSet,
...@@ -571,7 +571,7 @@ pub const Type = union(enum) {...@@ -571,7 +571,7 @@ pub const Type = union(enum) {
571 frame: Frame,571 frame: Frame,
572 @"anyframe": AnyFrame,572 @"anyframe": AnyFrame,
573 vector: Vector,573 vector: Vector,
574 enum_literal: void,574 enum_literal,
575575
576 /// This data structure is used by the Zig language code generation and576 /// This data structure is used by the Zig language code generation and
577 /// therefore must be kept in sync with the compiler implementation.577 /// therefore must be kept in sync with the compiler implementation.
...@@ -619,6 +619,16 @@ pub const Type = union(enum) {...@@ -619,6 +619,16 @@ pub const Type = union(enum) {
619 slice,619 slice,
620 c,620 c,
621 };621 };
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 };
622 };632 };
623633
624 /// This data structure is used by the Zig language code generation and634 /// This data structure is used by the Zig language code generation and
...@@ -668,6 +678,14 @@ pub const Type = union(enum) {...@@ -668,6 +678,14 @@ pub const Type = union(enum) {
668 const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));678 const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));
669 return dp.*;679 return dp.*;
670 }680 }
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 };
671 };689 };
672690
673 /// This data structure is used by the Zig language code generation and691 /// This data structure is used by the Zig language code generation and
...@@ -718,6 +736,10 @@ pub const Type = union(enum) {...@@ -718,6 +736,10 @@ pub const Type = union(enum) {
718 fields: []const EnumField,736 fields: []const EnumField,
719 decls: []const Declaration,737 decls: []const Declaration,
720 is_exhaustive: bool,738 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 };
721 };743 };
722744
723 /// This data structure is used by the Zig language code generation and745 /// This data structure is used by the Zig language code generation and
...@@ -726,6 +748,12 @@ pub const Type = union(enum) {...@@ -726,6 +748,12 @@ pub const Type = union(enum) {
726 name: [:0]const u8,748 name: [:0]const u8,
727 type: type,749 type: type,
728 alignment: comptime_int,750 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 };
729 };757 };
730758
731 /// This data structure is used by the Zig language code generation and759 /// This data structure is used by the Zig language code generation and
...@@ -753,6 +781,19 @@ pub const Type = union(enum) {...@@ -753,6 +781,19 @@ pub const Type = union(enum) {
753 is_generic: bool,781 is_generic: bool,
754 is_noalias: bool,782 is_noalias: bool,
755 type: ?type,783 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,
756 };797 };
757 };798 };
758799
lib/std/zig.zig+40-24
...@@ -773,7 +773,6 @@ pub const EnvVar = enum {...@@ -773,7 +773,6 @@ pub const EnvVar = enum {
773pub const SimpleComptimeReason = enum(u32) {773pub const SimpleComptimeReason = enum(u32) {
774 // Evaluating at comptime because a builtin operand must be comptime-known.774 // Evaluating at comptime because a builtin operand must be comptime-known.
775 // These messages all mention a specific builtin.775 // These messages all mention a specific builtin.
776 operand_Type,
777 operand_setEvalBranchQuota,776 operand_setEvalBranchQuota,
778 operand_setFloatMode,777 operand_setFloatMode,
779 operand_branchHint,778 operand_branchHint,
...@@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {
809 // Evaluating at comptime because types must be comptime-known.808 // Evaluating at comptime because types must be comptime-known.
810 // Reasons other than `.type` are just more specific messages.809 // Reasons other than `.type` are just more specific messages.
811 type,810 type,
811 int_signedness,
812 int_bit_width,
812 array_sentinel,813 array_sentinel,
814 array_length,
815 pointer_size,
816 pointer_attrs,
813 pointer_sentinel,817 pointer_sentinel,
814 slice_sentinel,818 slice_sentinel,
815 array_length,
816 vector_length,819 vector_length,
817 error_set_contents,820 fn_ret_ty,
818 struct_fields,821 fn_param_types,
819 enum_fields,822 fn_param_attrs,
820 union_fields,823 fn_attrs,
821 function_ret_ty,824 struct_layout,
822 function_parameters,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
824 // Evaluating at comptime because decl/field name must be comptime-known.836 // Evaluating at comptime because decl/field name must be comptime-known.
825 decl_name,837 decl_name,
826 field_name,838 field_name,
827 struct_field_name,
828 enum_field_name,
829 union_field_name,
830 tuple_field_name,
831 tuple_field_index,839 tuple_field_index,
832840
833 // Evaluating at comptime because it is an attribute of a global declaration.841 // Evaluating at comptime because it is an attribute of a global declaration.
...@@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {
856 pub fn message(r: SimpleComptimeReason) []const u8 {864 pub fn message(r: SimpleComptimeReason) []const u8 {
857 return switch (r) {865 return switch (r) {
858 // zig fmt: off866 // zig fmt: off
859 .operand_Type => "operand to '@Type' must be comptime-known",
860 .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",867 .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
861 .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",868 .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
862 .operand_branchHint => "operand to '@branchHint' must be comptime-known",869 .operand_branchHint => "operand to '@branchHint' must be comptime-known",
...@@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {...@@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {
888 .clobber => "clobber must be comptime-known",895 .clobber => "clobber must be comptime-known",
889896
890 .type => "types must be comptime-known",897 .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",
891 .array_sentinel => "array sentinel value must be comptime-known",900 .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",
892 .pointer_sentinel => "pointer sentinel value must be comptime-known",904 .pointer_sentinel => "pointer sentinel value must be comptime-known",
893 .slice_sentinel => "slice sentinel value must be comptime-known",905 .slice_sentinel => "slice sentinel value must be comptime-known",
894 .array_length => "array length must be comptime-known",
895 .vector_length => "vector length must be comptime-known",906 .vector_length => "vector length must be comptime-known",
896 .error_set_contents => "error set contents must be comptime-known",907 .fn_ret_ty => "function return type must be comptime-known",
897 .struct_fields => "struct fields must be comptime-known",908 .fn_param_types => "function parameter types must be comptime-known",
898 .enum_fields => "enum fields must be comptime-known",909 .fn_param_attrs => "function parameter attributes must be comptime-known",
899 .union_fields => "union fields must be comptime-known",910 .fn_attrs => "function attributes must be comptime-known",
900 .function_ret_ty => "function return type must be comptime-known",911 .struct_layout => "struct layout must be comptime-known",
901 .function_parameters => "function parameters 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
903 .decl_name => "declaration name must be comptime-known",923 .decl_name => "declaration name must be comptime-known",
904 .field_name => "field name must be comptime-known",924 .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",
909 .tuple_field_index => "tuple field index must be comptime-known",925 .tuple_field_index => "tuple field index must be comptime-known",
910926
911 .container_var_init => "initializer of container-level variable must be comptime-known",927 .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...@@ -833,7 +833,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
833 => {833 => {
834 var buf: [2]Ast.Node.Index = undefined;834 var buf: [2]Ast.Node.Index = undefined;
835 const params = tree.builtinCallParams(&buf, node).?;835 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);
837 },837 },
838838
839 .call_one,839 .call_one,
...@@ -1194,14 +1194,20 @@ fn nameStratExpr(...@@ -1194,14 +1194,20 @@ fn nameStratExpr(
1194 },1194 },
1195 .builtin_call_two,1195 .builtin_call_two,
1196 .builtin_call_two_comma,1196 .builtin_call_two_comma,
1197 .builtin_call,
1198 .builtin_call_comma,
1197 => {1199 => {
1198 const builtin_token = tree.nodeMainToken(node);1200 const builtin_token = tree.nodeMainToken(node);
1199 const builtin_name = tree.tokenSlice(builtin_token);1201 const builtin_name = tree.tokenSlice(builtin_token);
1200 if (!std.mem.eql(u8, builtin_name, "@Type")) return null;1202 const info = BuiltinFn.list.get(builtin_name) orelse return null;
1201 var buf: [2]Ast.Node.Index = undefined;1203 switch (info.tag) {
1202 const params = tree.builtinCallParams(&buf, node).?;1204 .Enum, .Struct, .Union => {
1203 if (params.len != 1) return null; // let `builtinCall` error1205 var buf: [2]Ast.Node.Index = undefined;
1204 return try builtinReify(gz, scope, ri, node, params[0], name_strat);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 }
1205 },1211 },
1206 else => return null,1212 else => return null,
1207 }1213 }
...@@ -1406,7 +1412,7 @@ fn fnProtoExprInner(...@@ -1406,7 +1412,7 @@ fn fnProtoExprInner(
1406 .none;1412 .none;
14071413
1408 const ret_ty_node = fn_proto.ast.return_type.unwrap().?;1414 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
1411 const result = try block_scope.addFunc(.{1417 const result = try block_scope.addFunc(.{
1412 .src_node = fn_proto.ast.proto_node,1418 .src_node = fn_proto.ast.proto_node,
...@@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod...@@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
2629 const params = tree.builtinCallParams(&buf, inner_node).?;2635 const params = tree.builtinCallParams(&buf, inner_node).?;
26302636
2631 try emitDbgNode(gz, inner_node);2637 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);
2633 noreturn_src_node = try addEnsureResult(gz, result, inner_node);2639 noreturn_src_node = try addEnsureResult(gz, result, inner_node);
2634 },2640 },
26352641
...@@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2707 .elem_type,2713 .elem_type,
2708 .indexable_ptr_elem_type,2714 .indexable_ptr_elem_type,
2709 .splat_op_result_ty,2715 .splat_op_result_ty,
2716 .reify_int,
2710 .vector_type,2717 .vector_type,
2711 .indexable_ptr_len,2718 .indexable_ptr_len,
2712 .anyframe_type,2719 .anyframe_type,
...@@ -8942,7 +8949,7 @@ fn unionInit(...@@ -8942,7 +8949,7 @@ fn unionInit(
8942 params: []const Ast.Node.Index,8949 params: []const Ast.Node.Index,
8943) InnerError!Zir.Inst.Ref {8950) InnerError!Zir.Inst.Ref {
8944 const union_type = try typeExpr(gz, scope, params[0]);8951 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);
8946 const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{8953 const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
8947 .container_type = union_type,8954 .container_type = union_type,
8948 .field_name = field_name,8955 .field_name = field_name,
...@@ -9210,6 +9217,7 @@ fn builtinCall(...@@ -9210,6 +9217,7 @@ fn builtinCall(
9210 node: Ast.Node.Index,9217 node: Ast.Node.Index,
9211 params: []const Ast.Node.Index,9218 params: []const Ast.Node.Index,
9212 allow_branch_hint: bool,9219 allow_branch_hint: bool,
9220 reify_name_strat: Zir.Inst.NameStrategy,
9213) InnerError!Zir.Inst.Ref {9221) InnerError!Zir.Inst.Ref {
9214 const astgen = gz.astgen;9222 const astgen = gz.astgen;
9215 const tree = astgen.tree;9223 const tree = astgen.tree;
...@@ -9443,9 +9451,140 @@ fn builtinCall(...@@ -9443,9 +9451,140 @@ fn builtinCall(
9443 return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);9451 return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);
9444 },9452 },
94459453
9446 .Type => {9454 .EnumLiteral => return rvalue(gz, ri, .enum_literal_type, node),
9447 return builtinReify(gz, scope, ri, node, params[0], .anon);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);
9448 },9489 },
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
9449 .panic => {9588 .panic => {
9450 try emitDbgNode(gz, node);9589 try emitDbgNode(gz, node);
9451 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);9590 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);
...@@ -9764,41 +9903,6 @@ fn builtinCall(...@@ -9764,41 +9903,6 @@ fn builtinCall(
9764 },9903 },
9765 }9904 }
9766}9905}
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
9803fn hasDeclOrField(9907fn hasDeclOrField(
9804 gz: *GenZir,9908 gz: *GenZir,
lib/std/zig/AstRlAnnotate.zig+44-1
...@@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
866 // These builtins take no args and do not consume the result pointer.866 // These builtins take no args and do not consume the result pointer.
867 .src,867 .src,
868 .This,868 .This,
869 .EnumLiteral,
869 .return_address,870 .return_address,
870 .error_return_trace,871 .error_return_trace,
871 .frame,872 .frame,
...@@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
906 .embed_file,907 .embed_file,
907 .error_name,908 .error_name,
908 .set_runtime_safety,909 .set_runtime_safety,
909 .Type,910 .Tuple,
910 .c_undef,911 .c_undef,
911 .c_include,912 .c_include,
912 .wasm_memory_size,913 .wasm_memory_size,
...@@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast....@@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
1058 _ = try astrl.expr(args[3], block, ResultInfo.none);1059 _ = try astrl.expr(args[3], block, ResultInfo.none);
1059 return false;1060 return false;
1060 },1061 },
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 },
1061 .Vector => {1104 .Vector => {
1062 _ = try astrl.expr(args[0], block, ResultInfo.type_only);1105 _ = try astrl.expr(args[0], block, ResultInfo.type_only);
1063 _ = try astrl.expr(args[1], block, ResultInfo.type_only);1106 _ = try astrl.expr(args[1], block, ResultInfo.type_only);
lib/std/zig/BuiltinFn.zig+59-3
...@@ -110,7 +110,14 @@ pub const Tag = enum {...@@ -110,7 +110,14 @@ pub const Tag = enum {
110 This,110 This,
111 trap,111 trap,
112 truncate,112 truncate,
113 Type,113 EnumLiteral,
114 Int,
115 Tuple,
116 Pointer,
117 Fn,
118 Struct,
119 Union,
120 Enum,
114 type_info,121 type_info,
115 type_name,122 type_name,
116 TypeOf,123 TypeOf,
...@@ -937,12 +944,61 @@ pub const list = list: {...@@ -937,12 +944,61 @@ pub const list = list: {
937 },944 },
938 },945 },
939 .{946 .{
940 "@Type",947 "@EnumLiteral",
941 .{948 .{
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,
943 .param_count = 1,964 .param_count = 1,
944 },965 },
945 },966 },
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 },
946 .{1002 .{
947 "@typeInfo",1003 "@typeInfo",
948 .{1004 .{
lib/std/zig/Zir.zig+131-8
...@@ -260,6 +260,10 @@ pub const Inst = struct {...@@ -260,6 +260,10 @@ pub const Inst = struct {
260 /// `[N:S]T` syntax. Source location is the array type expression node.260 /// `[N:S]T` syntax. Source location is the array type expression node.
261 /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.261 /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.
262 array_type_sentinel,262 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,
263 /// `@Vector` builtin.267 /// `@Vector` builtin.
264 /// Uses the `pl_node` union field with `Bin` payload.268 /// Uses the `pl_node` union field with `Bin` payload.
265 /// lhs is length, rhs is element type.269 /// lhs is length, rhs is element type.
...@@ -1112,6 +1116,7 @@ pub const Inst = struct {...@@ -1112,6 +1116,7 @@ pub const Inst = struct {
1112 .array_mul,1116 .array_mul,
1113 .array_type,1117 .array_type,
1114 .array_type_sentinel,1118 .array_type_sentinel,
1119 .reify_int,
1115 .vector_type,1120 .vector_type,
1116 .elem_type,1121 .elem_type,
1117 .indexable_ptr_elem_type,1122 .indexable_ptr_elem_type,
...@@ -1409,6 +1414,7 @@ pub const Inst = struct {...@@ -1409,6 +1414,7 @@ pub const Inst = struct {
1409 .array_mul,1414 .array_mul,
1410 .array_type,1415 .array_type,
1411 .array_type_sentinel,1416 .array_type_sentinel,
1417 .reify_int,
1412 .vector_type,1418 .vector_type,
1413 .elem_type,1419 .elem_type,
1414 .indexable_ptr_elem_type,1420 .indexable_ptr_elem_type,
...@@ -1644,6 +1650,7 @@ pub const Inst = struct {...@@ -1644,6 +1650,7 @@ pub const Inst = struct {
1644 .array_mul = .pl_node,1650 .array_mul = .pl_node,
1645 .array_type = .pl_node,1651 .array_type = .pl_node,
1646 .array_type_sentinel = .pl_node,1652 .array_type_sentinel = .pl_node,
1653 .reify_int = .pl_node,
1647 .vector_type = .pl_node,1654 .vector_type = .pl_node,
1648 .elem_type = .un_node,1655 .elem_type = .un_node,
1649 .indexable_ptr_elem_type = .un_node,1656 .indexable_ptr_elem_type = .un_node,
...@@ -2035,10 +2042,43 @@ pub const Inst = struct {...@@ -2035,10 +2042,43 @@ pub const Inst = struct {
2035 /// Implement builtin `@errorFromInt`.2042 /// Implement builtin `@errorFromInt`.
2036 /// `operand` is payload index to `UnNode`.2043 /// `operand` is payload index to `UnNode`.
2037 error_from_int,2044 error_from_int,
2038 /// Implement builtin `@Type`.2045 /// Given a comptime-known operand of type `[]const A`, returns the type `*const [operand.len]B`.
2039 /// `operand` is payload index to `Reify`.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`.
2040 /// `small` contains `NameStrategy`.2080 /// `small` contains `NameStrategy`.
2041 reify,2081 reify_enum,
2042 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.2082 /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
2043 /// `small` 0=>weak 1=>strong2083 /// `small` 0=>weak 1=>strong
2044 /// `operand` is payload index to `Cmpxchg`.2084 /// `operand` is payload index to `Cmpxchg`.
...@@ -2226,6 +2266,11 @@ pub const Inst = struct {...@@ -2226,6 +2266,11 @@ pub const Inst = struct {
2226 manyptr_const_u8_sentinel_0_type,2266 manyptr_const_u8_sentinel_0_type,
2227 slice_const_u8_type,2267 slice_const_u8_type,
2228 slice_const_u8_sentinel_0_type,2268 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,
2229 vector_8_i8_type,2274 vector_8_i8_type,
2230 vector_16_i8_type,2275 vector_16_i8_type,
2231 vector_32_i8_type,2276 vector_32_i8_type,
...@@ -3169,6 +3214,23 @@ pub const Inst = struct {...@@ -3169,6 +3214,23 @@ pub const Inst = struct {
3169 rhs: Ref,3214 rhs: Ref,
3170 };3215 };
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
3172 pub const UnNode = struct {3234 pub const UnNode = struct {
3173 node: Ast.Node.Offset,3235 node: Ast.Node.Offset,
3174 operand: Ref,3236 operand: Ref,
...@@ -3179,12 +3241,55 @@ pub const Inst = struct {...@@ -3179,12 +3241,55 @@ pub const Inst = struct {
3179 index: u32,3241 index: u32,
3180 };3242 };
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,
3183 /// This node is absolute, because `reify` instructions are tracked across updates, and3262 /// This node is absolute, because `reify` instructions are tracked across updates, and
3184 /// this simplifies the logic for getting source locations for types.3263 /// this simplifies the logic for getting source locations for types.
3185 node: Ast.Node.Index,3264 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 {
3187 src_line: u32,3273 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,
3188 };3293 };
31893294
3190 /// Trailing:3295 /// Trailing:
...@@ -3496,14 +3601,19 @@ pub const Inst = struct {...@@ -3496,14 +3601,19 @@ pub const Inst = struct {
3496 calling_convention,3601 calling_convention,
3497 address_space,3602 address_space,
3498 float_mode,3603 float_mode,
3604 signedness,
3499 reduce_op,3605 reduce_op,
3500 call_modifier,3606 call_modifier,
3501 prefetch_options,3607 prefetch_options,
3502 export_options,3608 export_options,
3503 extern_options,3609 extern_options,
3504 type_info,
3505 branch_hint,3610 branch_hint,
3506 clobbers,3611 clobbers,
3612 pointer_size,
3613 pointer_attributes,
3614 fn_attributes,
3615 container_layout,
3616 enum_mode,
3507 // Values3617 // Values
3508 calling_convention_c,3618 calling_convention_c,
3509 calling_convention_inline,3619 calling_convention_inline,
...@@ -4190,6 +4300,7 @@ fn findTrackableInner(...@@ -4190,6 +4300,7 @@ fn findTrackableInner(
4190 .array_mul,4300 .array_mul,
4191 .array_type,4301 .array_type,
4192 .array_type_sentinel,4302 .array_type_sentinel,
4303 .reify_int,
4193 .vector_type,4304 .vector_type,
4194 .elem_type,4305 .elem_type,
4195 .indexable_ptr_elem_type,4306 .indexable_ptr_elem_type,
...@@ -4432,6 +4543,12 @@ fn findTrackableInner(...@@ -4432,6 +4543,12 @@ fn findTrackableInner(
4432 .select,4543 .select,
4433 .int_from_error,4544 .int_from_error,
4434 .error_from_int,4545 .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,
4435 .cmpxchg,4552 .cmpxchg,
4436 .c_va_arg,4553 .c_va_arg,
4437 .c_va_copy,4554 .c_va_copy,
...@@ -4463,7 +4580,11 @@ fn findTrackableInner(...@@ -4463,7 +4580,11 @@ fn findTrackableInner(
4463 },4580 },
44644581
4465 // Reifications and opaque declarations need tracking, but have no body.4582 // 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
4468 // Struct declarations need tracking and have bodies.4589 // Struct declarations need tracking and have bodies.
4469 .struct_decl => {4590 .struct_decl => {
...@@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {...@@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
5246 .union_decl,5367 .union_decl,
5247 .enum_decl,5368 .enum_decl,
5248 .opaque_decl,5369 .opaque_decl,
5249 .reify,5370 .reify_enum,
5371 .reify_struct,
5372 .reify_union,
5250 => {}, // tracked in order, as the owner instructions of explicit container types5373 => {}, // tracked in order, as the owner instructions of explicit container types
5251 else => unreachable, // assertion failure; not trackable5374 else => unreachable, // assertion failure; not trackable
5252 },5375 },
src/Air.zig+5
...@@ -1062,6 +1062,11 @@ pub const Inst = struct {...@@ -1062,6 +1062,11 @@ pub const Inst = struct {
1062 manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),1062 manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
1063 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),1063 slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
1064 slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),1064 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),
1065 vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),1070 vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),
1066 vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),1071 vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),
1067 vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type),1072 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) {...@@ -2017,8 +2017,7 @@ pub const Key = union(enum) {
2017 error_union_type: ErrorUnionType,2017 error_union_type: ErrorUnionType,
2018 simple_type: SimpleType,2018 simple_type: SimpleType,
2019 /// This represents a struct that has been explicitly declared in source code,2019 /// 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.2020 /// or was created with `@Struct`. It is unique and based on a declaration.
2021 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
2022 struct_type: NamespaceType,2021 struct_type: NamespaceType,
2023 /// This is a tuple type. Tuples are logically similar to structs, but have some2022 /// This is a tuple type. Tuples are logically similar to structs, but have some
2024 /// important differences in semantics; they do not undergo staged type resolution,2023 /// important differences in semantics; they do not undergo staged type resolution,
...@@ -2175,7 +2174,7 @@ pub const Key = union(enum) {...@@ -2175,7 +2174,7 @@ pub const Key = union(enum) {
2175 /// The union for which this is a tag type.2174 /// The union for which this is a tag type.
2176 union_type: Index,2175 union_type: Index,
2177 },2176 },
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.
2179 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.2178 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
2180 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.2179 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.
2181 reified: struct {2180 reified: struct {
...@@ -4641,6 +4640,13 @@ pub const Index = enum(u32) {...@@ -4641,6 +4640,13 @@ pub const Index = enum(u32) {
4641 slice_const_u8_type,4640 slice_const_u8_type,
4642 slice_const_u8_sentinel_0_type,4641 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
4644 vector_8_i8_type,4650 vector_8_i8_type,
4645 vector_16_i8_type,4651 vector_16_i8_type,
4646 vector_32_i8_type,4652 vector_32_i8_type,
...@@ -5201,6 +5207,45 @@ pub const static_keys: [static_len]Key = .{...@@ -5201,6 +5207,45 @@ pub const static_keys: [static_len]Key = .{
5201 },5207 },
5202 } },5208 } },
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
5204 // @Vector(8, i8)5249 // @Vector(8, i8)
5205 .{ .vector_type = .{ .len = 8, .child = .i8_type } },5250 .{ .vector_type = .{ .len = 8, .child = .i8_type } },
5206 // @Vector(16, i8)5251 // @Vector(16, i8)
...@@ -10225,16 +10270,8 @@ pub fn getGeneratedTagEnumType(...@@ -10225,16 +10270,8 @@ pub fn getGeneratedTagEnumType(
10225}10270}
1022610271
10227pub const OpaqueTypeInit = struct {10272pub const OpaqueTypeInit = struct {
10228 key: union(enum) {10273 zir_index: TrackedInst.Index,
10229 declared: struct {10274 captures: []const CaptureValue,
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 },
10238};10275};
1023910276
10240pub fn getOpaqueType(10277pub fn getOpaqueType(
...@@ -10243,16 +10280,10 @@ pub fn getOpaqueType(...@@ -10243,16 +10280,10 @@ pub fn getOpaqueType(
10243 tid: Zcu.PerThread.Id,10280 tid: Zcu.PerThread.Id,
10244 ini: OpaqueTypeInit,10281 ini: OpaqueTypeInit,
10245) Allocator.Error!WipNamespaceType.Result {10282) Allocator.Error!WipNamespaceType.Result {
10246 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = switch (ini.key) {10283 var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{
10247 .declared => |d| .{ .declared = .{10284 .zir_index = ini.zir_index,
10248 .zir_index = d.zir_index,10285 .captures = .{ .external = ini.captures },
10249 .captures = .{ .external = d.captures },10286 } } });
10250 } },
10251 .reified => |r| .{ .reified = .{
10252 .zir_index = r.zir_index,
10253 .type_hash = 0,
10254 } },
10255 } });
10256 defer gop.deinit();10287 defer gop.deinit();
10257 if (gop == .existing) return .{ .existing = gop.existing };10288 if (gop == .existing) return .{ .existing = gop.existing };
1025810289
...@@ -10261,30 +10292,19 @@ pub fn getOpaqueType(...@@ -10261,30 +10292,19 @@ pub fn getOpaqueType(
10261 const extra = local.getMutableExtra(gpa);10292 const extra = local.getMutableExtra(gpa);
10262 try items.ensureUnusedCapacity(1);10293 try items.ensureUnusedCapacity(1);
1026310294
10264 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + switch (ini.key) {10295 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
10265 .declared => |d| d.captures.len,
10266 .reified => 0,
10267 });
10268 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{10296 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
10269 .name = undefined, // set by `finish`10297 .name = undefined, // set by `finish`
10270 .name_nav = undefined, // set by `finish`10298 .name_nav = undefined, // set by `finish`
10271 .namespace = undefined, // set by `finish`10299 .namespace = undefined, // set by `finish`
10272 .zir_index = switch (ini.key) {10300 .zir_index = ini.zir_index,
10273 inline else => |x| x.zir_index,10301 .captures_len = @intCast(ini.captures.len),
10274 },
10275 .captures_len = switch (ini.key) {
10276 .declared => |d| @intCast(d.captures.len),
10277 .reified => std.math.maxInt(u32),
10278 },
10279 });10302 });
10280 items.appendAssumeCapacity(.{10303 items.appendAssumeCapacity(.{
10281 .tag = .type_opaque,10304 .tag = .type_opaque,
10282 .data = extra_index,10305 .data = extra_index,
10283 });10306 });
10284 switch (ini.key) {10307 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
10285 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
10286 .reified => {},
10287 }
10288 return .{10308 return .{
10289 .wip = .{10309 .wip = .{
10290 .tid = tid,10310 .tid = tid,
...@@ -10555,6 +10575,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {...@@ -10555,6 +10575,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {
10555 switch (index) {10575 switch (index) {
10556 .slice_const_u8_type => return .manyptr_const_u8_type,10576 .slice_const_u8_type => return .manyptr_const_u8_type,
10557 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,10577 .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,
10558 else => {},10580 else => {},
10559 }10581 }
10560 const item = index.unwrap(ip).getItem(ip);10582 const item = index.unwrap(ip).getItem(ip);
...@@ -12013,8 +12035,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -12013,8 +12035,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
12013 .manyptr_u8_type,12035 .manyptr_u8_type,
12014 .manyptr_const_u8_type,12036 .manyptr_const_u8_type,
12015 .manyptr_const_u8_sentinel_0_type,12037 .manyptr_const_u8_sentinel_0_type,
12038 .manyptr_const_slice_const_u8_type,
12016 .slice_const_u8_type,12039 .slice_const_u8_type,
12017 .slice_const_u8_sentinel_0_type,12040 .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,
12018 .vector_8_i8_type,12045 .vector_8_i8_type,
12019 .vector_16_i8_type,12046 .vector_16_i8_type,
12020 .vector_32_i8_type,12047 .vector_32_i8_type,
...@@ -12355,8 +12382,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {...@@ -12355,8 +12382,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
12355 .manyptr_u8_type,12382 .manyptr_u8_type,
12356 .manyptr_const_u8_type,12383 .manyptr_const_u8_type,
12357 .manyptr_const_u8_sentinel_0_type,12384 .manyptr_const_u8_sentinel_0_type,
12385 .manyptr_const_slice_const_u8_type,
12358 .slice_const_u8_type,12386 .slice_const_u8_type,
12359 .slice_const_u8_sentinel_0_type,12387 .slice_const_u8_sentinel_0_type,
12388 .slice_const_slice_const_u8_type,
12389 .manyptr_const_type_type,
12390 .slice_const_type_type,
12360 => .pointer,12391 => .pointer,
1236112392
12362 .vector_8_i8_type,12393 .vector_8_i8_type,
...@@ -12408,6 +12439,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {...@@ -12408,6 +12439,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
12408 .vector_8_f64_type,12439 .vector_8_f64_type,
12409 => .vector,12440 => .vector,
1241012441
12442 .optional_type_type => .optional,
12411 .optional_noreturn_type => .optional,12443 .optional_noreturn_type => .optional,
12412 .anyerror_void_error_union_type => .error_union,12444 .anyerror_void_error_union_type => .error_union,
12413 .empty_tuple_type => .@"struct",12445 .empty_tuple_type => .@"struct",
src/Sema.zig+1192-1241
...@@ -1167,6 +1167,7 @@ fn analyzeBodyInner(...@@ -1167,6 +1167,7 @@ fn analyzeBodyInner(
1167 .array_mul => try sema.zirArrayMul(block, inst),1167 .array_mul => try sema.zirArrayMul(block, inst),
1168 .array_type => try sema.zirArrayType(block, inst),1168 .array_type => try sema.zirArrayType(block, inst),
1169 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),1169 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst),
1170 .reify_int => try sema.zirReifyInt(block, inst),
1170 .vector_type => try sema.zirVectorType(block, inst),1171 .vector_type => try sema.zirVectorType(block, inst),
1171 .as_node => try sema.zirAsNode(block, inst),1172 .as_node => try sema.zirAsNode(block, inst),
1172 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),1173 .as_shift_operand => try sema.zirAsShiftOperand(block, inst),
...@@ -1411,7 +1412,6 @@ fn analyzeBodyInner(...@@ -1411,7 +1412,6 @@ fn analyzeBodyInner(
1411 .select => try sema.zirSelect( block, extended),1412 .select => try sema.zirSelect( block, extended),
1412 .int_from_error => try sema.zirIntFromError( block, extended),1413 .int_from_error => try sema.zirIntFromError( block, extended),
1413 .error_from_int => try sema.zirErrorFromInt( block, extended),1414 .error_from_int => try sema.zirErrorFromInt( block, extended),
1414 .reify => try sema.zirReify( block, extended, inst),
1415 .cmpxchg => try sema.zirCmpxchg( block, extended),1415 .cmpxchg => try sema.zirCmpxchg( block, extended),
1416 .c_va_arg => try sema.zirCVaArg( block, extended),1416 .c_va_arg => try sema.zirCVaArg( block, extended),
1417 .c_va_copy => try sema.zirCVaCopy( block, extended),1417 .c_va_copy => try sema.zirCVaCopy( block, extended),
...@@ -1424,6 +1424,16 @@ fn analyzeBodyInner(...@@ -1424,6 +1424,16 @@ fn analyzeBodyInner(
1424 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),1424 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode),
1425 .in_comptime => try sema.zirInComptime( block),1425 .in_comptime => try sema.zirInComptime( block),
1426 .closure_get => try sema.zirClosureGet( block, extended),1426 .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),
1427 // zig fmt: on1437 // zig fmt: on
14281438
1429 .set_float_mode => {1439 .set_float_mode => {
...@@ -3517,10 +3527,8 @@ fn zirOpaqueDecl(...@@ -3517,10 +3527,8 @@ fn zirOpaqueDecl(
3517 extra_index += captures_len * 2;3527 extra_index += captures_len * 2;
35183528
3519 const opaque_init: InternPool.OpaqueTypeInit = .{3529 const opaque_init: InternPool.OpaqueTypeInit = .{
3520 .key = .{ .declared = .{3530 .zir_index = tracked_inst,
3521 .zir_index = tracked_inst,3531 .captures = captures,
3522 .captures = captures,
3523 } },
3524 };3532 };
3525 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {3533 const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) {
3526 .existing => |ty| {3534 .existing => |ty| {
...@@ -7386,7 +7394,7 @@ fn analyzeCall(...@@ -7386,7 +7394,7 @@ fn analyzeCall(
7386 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);7394 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len);
73877395
7388 generic_block.comptime_reason = .{ .reason = .{7396 generic_block.comptime_reason = .{ .reason = .{
7389 .r = .{ .simple = .function_parameters },7397 .r = .{ .simple = .fn_param_types },
7390 .src = param_src,7398 .src = param_src,
7391 } };7399 } };
73927400
...@@ -7470,7 +7478,7 @@ fn analyzeCall(...@@ -7470,7 +7478,7 @@ fn analyzeCall(
7470 sema.inst_map = generic_inst_map;7478 sema.inst_map = generic_inst_map;
74717479
7472 generic_block.comptime_reason = .{ .reason = .{7480 generic_block.comptime_reason = .{ .reason = .{
7473 .r = .{ .simple = .function_ret_ty },7481 .r = .{ .simple = .fn_ret_ty },
7474 .src = func_ret_ty_src,7482 .src = func_ret_ty_src,
7475 } };7483 } };
74767484
...@@ -8927,7 +8935,7 @@ fn zirFunc(...@@ -8927,7 +8935,7 @@ fn zirFunc(
8927 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);8935 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len);
8928 extra_index += ret_ty_body.len;8936 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 });
8931 break :blk ret_ty_val.toType();8939 break :blk ret_ty_val.toType();
8932 },8940 },
8933 };8941 };
...@@ -9171,6 +9179,181 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:...@@ -9171,6 +9179,181 @@ fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc:
9171 }9179 }
9172}9180}
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
9174fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {9357fn callConvIsCallable(cc: std.builtin.CallingConvention.Tag) bool {
9175 return switch (cc) {9358 return switch (cc) {
9176 .naked,9359 .naked,
...@@ -9259,7 +9442,6 @@ fn funcCommon(...@@ -9259,7 +9442,6 @@ fn funcCommon(
9259 const pt = sema.pt;9442 const pt = sema.pt;
9260 const zcu = pt.zcu;9443 const zcu = pt.zcu;
9261 const gpa = sema.gpa;9444 const gpa = sema.gpa;
9262 const target = zcu.getTarget();
9263 const ip = &zcu.intern_pool;9445 const ip = &zcu.intern_pool;
9264 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });9446 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });
9265 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });9447 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
...@@ -9293,26 +9475,14 @@ fn funcCommon(...@@ -9293,26 +9475,14 @@ fn funcCommon(
9293 if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) {9475 if (param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc)) {
9294 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});9476 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
9295 }9477 }
9296 if (!param_ty.isValidParamType(zcu)) {9478 try sema.checkParamTypeCommon(
9297 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else "";9479 block,
9298 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{9480 @intCast(i),
9299 opaque_str, param_ty.fmt(pt),9481 param_ty,
9300 });9482 is_noalias,
9301 }9483 param_src,
9302 if (!param_ty_generic and !target_util.fnCallConvAllowsZigTypes(cc) and !try sema.validateExternType(param_ty, .param_ty)) {9484 cc,
9303 const msg = msg: {9485 );
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 }
9316 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {9486 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9317 const msg = msg: {9487 const msg = msg: {
9318 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{9488 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
...@@ -9327,209 +9497,40 @@ fn funcCommon(...@@ -9327,209 +9497,40 @@ fn funcCommon(
9327 };9497 };
9328 return sema.failWithOwnedErrorMsg(block, msg);9498 return sema.failWithOwnedErrorMsg(block, msg);
9329 }9499 }
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 );
9415 }9500 }
94169501
9417 const func_ty = try ip.getFuncType(gpa, pt.tid, .{9502 if (var_args and is_generic) {
9418 .param_types = param_types,9503 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
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 );
9454 }9504 }
94559505
9456 return finishFunc(9506 try sema.checkReturnTypeAndCallConvCommon(
9457 sema,
9458 block,9507 block,
9459 .none,
9460 func_ty,
9461 ret_poison,
9462 bare_return_type,9508 bare_return_type,
9463 ret_ty_src,9509 ret_ty_src,
9464 cc,9510 cc,
9465 ret_ty_requires_comptime,
9466 func_inst,
9467 cc_src,9511 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,
9468 is_noinline,9517 is_noinline,
9469 );9518 );
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
9519 // If the return type is comptime-only but not dependent on parameters then9520 // If the return type is comptime-only but not dependent on parameters then
9520 // all parameter types also need to be comptime.9521 // 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: {
9522 for (block.params.items(.is_comptime)) |is_comptime| {9523 for (block.params.items(.is_comptime)) |is_comptime| {
9523 if (!is_comptime) break;9524 if (!is_comptime) break;
9524 } else break :comptime_check;9525 } else break :comptime_check;
95259526 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
9526 const msg = try sema.errMsg(9527 const msg = try sema.errMsg(
9527 ret_ty_src,9528 ret_ty_src,
9528 "function with comptime-only return type '{f}' requires all parameters to be comptime",9529 "function with comptime-only return type '{s}{f}' requires all parameters to be comptime",
9529 .{return_type.fmt(pt)},9530 .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) },
9530 );9531 );
9531 errdefer msg.destroy(sema.gpa);9532 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
9534 const tags = sema.code.instructions.items(.tag);9535 const tags = sema.code.instructions.items(.tag);
9535 const data = sema.code.instructions.items(.data);9536 const data = sema.code.instructions.items(.data);
...@@ -9556,68 +9557,56 @@ fn finishFunc(...@@ -9556,68 +9557,56 @@ fn finishFunc(
9556 return sema.failWithOwnedErrorMsg(block, msg);9557 return sema.failWithOwnedErrorMsg(block, msg);
9557 }9558 }
95589559
9559 validate_incoming_stack_align: {9560 const param_types = block.params.items(.ty);
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 }
95709561
9571 switch (cc_resolved) {9562 if (inferred_error_set) {
9572 .x86_64_interrupt,9563 assert(has_body);
9573 .x86_interrupt,9564 return .fromIntern(try ip.getFuncDeclIes(gpa, pt.tid, .{
9574 .arm_interrupt,9565 .owner_nav = sema.owner.unwrap().nav_val,
9575 .mips64_interrupt,9566
9576 .mips_interrupt,9567 .param_types = param_types,
9577 .riscv64_interrupt,9568 .noalias_bits = noalias_bits,
9578 .riscv32_interrupt,9569 .comptime_bits = comptime_bits,
9579 .sh_interrupt,9570 .bare_return_type = bare_return_type.toIntern(),
9580 .arc_interrupt,9571 .cc = cc,
9581 .avr_interrupt,9572 .is_var_args = var_args,
9582 .csky_interrupt,9573 .is_generic = is_generic,
9583 .m68k_interrupt,9574 .is_noinline = is_noinline,
9584 .microblaze_interrupt,9575
9585 .msp430_interrupt,9576 .zir_body_inst = try block.trackZir(func_inst),
9586 .avr_signal,9577 .lbrace_line = src_locs.lbrace_line,
9587 => if (return_type.zigTypeTag(zcu) != .void and return_type.zigTypeTag(zcu) != .noreturn) {9578 .rbrace_line = src_locs.rbrace_line,
9588 return sema.fail(block, ret_ty_src, "function with calling convention '{s}' must return 'void' or 'noreturn'", .{@tagName(cc_resolved)});9579 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9589 },9580 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9590 .@"inline" => if (is_noinline) {9581 }));
9591 return sema.fail(block, cc_src, "'noinline' function cannot have calling convention 'inline'", .{});
9592 },
9593 else => {},
9594 }9582 }
95959583
9596 switch (zcu.callconvSupported(cc_resolved)) {9584 const func_ty = try ip.getFuncType(gpa, pt.tid, .{
9597 .ok => {},9585 .param_types = param_types,
9598 .bad_arch => |allowed_archs| {9586 .noalias_bits = noalias_bits,
9599 const ArchListFormatter = struct {9587 .comptime_bits = comptime_bits,
9600 archs: []const std.Target.Cpu.Arch,9588 .return_type = bare_return_type.toIntern(),
9601 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void {9589 .cc = cc,
9602 for (formatter.archs, 0..) |arch, i| {9590 .is_var_args = var_args,
9603 if (i != 0)9591 .is_generic = is_generic,
9604 try w.writeAll(", ");9592 .is_noinline = is_noinline,
9605 try w.print("'{s}'", .{@tagName(arch)});9593 });
9606 }9594
9607 }9595 if (has_body) {
9608 };9596 return .fromIntern(try ip.getFuncDecl(gpa, pt.tid, .{
9609 return sema.fail(block, cc_src, "calling convention '{s}' only available on architectures {f}", .{9597 .owner_nav = sema.owner.unwrap().nav_val,
9610 @tagName(cc_resolved),9598 .ty = func_ty,
9611 ArchListFormatter{ .archs = allowed_archs },9599 .cc = cc,
9612 });9600 .is_noinline = is_noinline,
9613 },9601 .zir_body_inst = try block.trackZir(func_inst),
9614 .bad_backend => |bad_backend| return sema.fail(block, cc_src, "calling convention '{s}' not supported by compiler backend '{s}'", .{9602 .lbrace_line = src_locs.lbrace_line,
9615 @tagName(cc_resolved),9603 .rbrace_line = src_locs.rbrace_line,
9616 @tagName(bad_backend),9604 .lbrace_column = @as(u16, @truncate(src_locs.columns)),
9617 }),9605 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)),
9606 }));
9618 }9607 }
96199608
9620 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);9609 return .fromIntern(func_ty);
9621}9610}
96229611
9623fn zirParam(9612fn zirParam(
...@@ -19395,7 +19384,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -19395,7 +19384,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
19395 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {19384 if (union_ty.zigTypeTag(pt.zcu) != .@"union") {
19396 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});19385 return sema.fail(block, ty_src, "expected union type, found '{f}'", .{union_ty.fmt(pt)});
19397 }19386 }
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 });
19399 const init = try sema.resolveInst(extra.init);19388 const init = try sema.resolveInst(extra.init);
19400 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);19389 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);
19401}19390}
...@@ -20553,589 +20542,529 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20553,589 +20542,529 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20553 return block.addUnOp(.tag_name, casted_operand);20542 return block.addUnOp(.tag_name, casted_operand);
20554}20543}
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(
20557 sema: *Sema,20556 sema: *Sema,
20558 block: *Block,20557 block: *Block,
20559 extended: Zir.Inst.Extended.InstData,20558 extended: Zir.Inst.Extended.InstData,
20560 inst: Zir.Inst.Index,
20561) CompileError!Air.Inst.Ref {20559) CompileError!Air.Inst.Ref {
20562 const pt = sema.pt;20560 const pt = sema.pt;
20563 const zcu = pt.zcu;20561 const zcu = pt.zcu;
20564 const gpa = sema.gpa;20562
20565 const ip = &zcu.intern_pool;20563 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20566 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);20564 const info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.small);
20567 const extra = sema.code.extraData(Zir.Inst.Reify, extended.operand).data;20565
20568 const tracked_inst = try block.trackZir(inst);20566 const src = block.nodeOffset(extra.node);
20569 const src: LazySrcLoc = .{20567
20570 .base_node_inst = tracked_inst,20568 const comptime_reason: std.zig.SimpleComptimeReason, const in_scalar_ty: Type, const out_scalar_ty: Type = switch (info) {
20571 .offset = LazySrcLoc.Offset.nodeOffset(.zero),20569 // zig fmt: off
20572 };20570 .type_to_fn_param_attrs => .{ .fn_param_attrs, .type, try sema.getBuiltinType(src, .@"Type.Fn.Param.Attributes") },
20573 const operand_src: LazySrcLoc = .{20571 .string_to_struct_field_type => .{ .struct_field_types, .slice_const_u8, .type },
20574 .base_node_inst = tracked_inst,20572 .string_to_union_field_type => .{ .union_field_types, .slice_const_u8, .type },
20575 .offset = .{20573 .string_to_struct_field_attrs => .{ .struct_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.StructField.Attributes") },
20576 .node_offset_builtin_call_arg = .{20574 .string_to_union_field_attrs => .{ .union_field_attrs, .slice_const_u8, try sema.getBuiltinType(src, .@"Type.UnionField.Attributes") },
20577 .builtin_call_node = .zero, // `tracked_inst` is precisely the `reify` instruction, so offset is 020575 // zig fmt: on
20578 .arg_index = 0,
20579 },
20580 },
20581 };20576 };
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) {20578 const operand_ty = try pt.ptrTypeSema(.{
20709 return sema.fail(block, src, "pointer to noreturn not allowed", .{});20579 .child = in_scalar_ty.toIntern(),
20710 } else if (elem_ty.zigTypeTag(zcu) == .@"fn") {20580 .flags = .{ .size = .slice, .is_const = true },
20711 if (ptr_size != .one) {20581 });
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);
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);20590 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20725 break :msg msg;20591 .len = len,
20726 };20592 .child = out_scalar_ty.toIntern(),
20727 return sema.failWithOwnedErrorMsg(block, msg);20593 })));
20728 }20594}
20729 }
2073020595
20731 const ty = try pt.ptrTypeSema(.{20596fn zirReifyEnumValueSliceTy(
20732 .child = elem_ty.toIntern(),20597 sema: *Sema,
20733 .sentinel = actual_sentinel,20598 block: *Block,
20734 .flags = .{20599 extended: Zir.Inst.Extended.InstData,
20735 .size = ptr_size,20600) CompileError!Air.Inst.Ref {
20736 .is_const = is_const_val.toBool(),20601 const pt = sema.pt;
20737 .is_volatile = is_volatile_val.toBool(),20602 const zcu = pt.zcu;
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 ).?);
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());20606 const int_tag_ty_src = block.builtinCallArgSrc(extra.node, 0);
20790 return Air.internedToRef(ty.toIntern());20607 const field_names_src = block.builtinCallArgSrc(extra.node, 2);
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 ).?);
2080220608
20803 const error_set_ty = error_set_val.toType();20609 const int_tag_ty = try sema.resolveType(block, int_tag_ty_src, extra.lhs);
20804 const payload_ty = payload_val.toType();
2080520610
20806 if (error_set_ty.zigTypeTag(zcu) != .error_set) {20611 const operand_uncoerced = try sema.resolveInst(extra.rhs);
20807 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});20612 const operand_coerced = try sema.coerce(block, .slice_const_slice_const_u8, operand_uncoerced, field_names_src);
20808 }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);20618 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
20811 return Air.internedToRef(ty.toIntern());20619 .len = len,
20812 },20620 .child = int_tag_ty.toIntern(),
20813 .error_set => {20621 })));
20814 const payload_val = Value.fromInterned(union_val.val).optionalValue(zcu) orelse20622}
20815 return .anyerror_type;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));20650 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
20820 var names: InferredErrorSet.NameMap = .{};20651 const operand_src = block.builtinCallArgSrc(extra.node, 0);
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 }
2083920652
20840 const ty = try pt.errorSetFromUnsortedNames(names.keys());20653 const types_uncoerced = try sema.resolveInst(extra.operand);
20841 return Air.internedToRef(ty.toIntern());20654 const types_coerced = try sema.coerce(block, .slice_const_type, types_uncoerced, operand_src);
20842 },20655 const types_slice_val = try sema.resolveConstDefinedValue(block, operand_src, types_coerced, .{ .simple = .tuple_field_types });
20843 .@"struct" => {20656 const types_array_val = try sema.derefSliceAsArray(block, operand_src, types_slice_val, .{ .simple = .tuple_field_types });
20844 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20657 const fields_len: u32 = @intCast(types_array_val.typeOf(zcu).arrayLen(zcu));
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 ).?);
2092320658
20924 // Decls20659 const field_types = try sema.arena.alloc(InternPool.Index, fields_len);
20925 if (try decls_val.sliceLen(pt) > 0) {20660 for (field_types, 0..) |*field_ty, field_idx| {
20926 return sema.fail(block, src, "reified opaque must have no decls", .{});20661 const field_ty_val = try types_array_val.elemValue(pt, field_idx);
20927 }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, .{20668 const field_values = try sema.arena.alloc(InternPool.Index, fields_len);
20930 .key = .{ .reified = .{20669 @memset(field_values, .none);
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);
2094120670
20942 const type_name = try sema.createTypeName(20671 return .fromIntern(try zcu.intern_pool.getTupleType(zcu.gpa, pt.tid, .{
20943 block,20672 .types = field_types,
20944 name_strategy,20673 .values = field_values,
20945 "opaque",20674 }));
20946 inst,20675}
20947 wip_ty.index,
20948 );
20949 wip_ty.setName(ip, type_name.name, type_name.nav);
2095020676
20951 const new_namespace_index = try pt.createNamespace(.{20677fn zirReifyPointer(
20952 .parent = block.namespace.toOptional(),20678 sema: *Sema,
20953 .owner_type = wip_ty.index,20679 block: *Block,
20954 .file_scope = block.getFileScopeIndex(zcu),20680 extended: Zir.Inst.Extended.InstData,
20955 .generation = zcu.generation,20681) CompileError!Air.Inst.Ref {
20956 });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);20687 const extra = sema.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
20959 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);20688 const src = block.nodeOffset(extra.node);
20960 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));20689 const size_src = block.builtinCallArgSrc(extra.node, 0);
20961 },20690 const attrs_src = block.builtinCallArgSrc(extra.node, 1);
20962 .@"union" => {20691 const elem_ty_src = block.builtinCallArgSrc(extra.node, 2);
20963 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20692 const sentinel_src = block.builtinCallArgSrc(extra.node, 3);
20964 const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20693
20965 ip,20694 const size_ty = try sema.getBuiltinType(size_src, .@"Type.Pointer.Size");
20966 try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),20695 const attrs_ty = try sema.getBuiltinType(attrs_src, .@"Type.Pointer.Attributes");
20967 ).?);20696
20968 const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20697 const size_uncoerced = try sema.resolveInst(extra.size);
20969 ip,20698 const size_coerced = try sema.coerce(block, size_ty, size_uncoerced, size_src);
20970 try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),20699 const size_val = try sema.resolveConstDefinedValue(block, size_src, size_coerced, .{ .simple = .pointer_size });
20971 ).?);20700 const size = try sema.interpretBuiltinType(block, size_src, size_val, std.builtin.Type.Pointer.Size);
20972 const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20701
20973 ip,20702 const attrs_uncoerced = try sema.resolveInst(extra.attrs);
20974 try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),20703 const attrs_coerced = try sema.coerce(block, attrs_ty, attrs_uncoerced, attrs_src);
20975 ).?);20704 const attrs_val = try sema.resolveConstDefinedValue(block, attrs_src, attrs_coerced, .{ .simple = .pointer_attrs });
20976 const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(20705 const attrs = try sema.interpretBuiltinType(block, attrs_src, attrs_val, std.builtin.Type.Pointer.Attributes);
20977 ip,20706
20978 try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),20707 const @"align": Alignment = if (attrs.@"align") |bytes| a: {
20979 ).?);20708 break :a try sema.validateAlign(block, attrs_src, bytes);
20709 } else .none;
2098020710
20981 if (try decls_val.sliceLen(pt) > 0) {20711 const elem_ty = try sema.resolveType(block, elem_ty_src, extra.elem_ty);
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);
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) {20730 if (size == .c and !try sema.validateExternType(elem_ty, .other)) {
20989 switch (layout) {20731 return sema.failWithOwnedErrorMsg(block, msg: {
20990 .@"extern" => return sema.fail(block, src, "extern union does not support enum tag type", .{}),20732 const msg = try sema.errMsg(src, "C pointers cannot point to non-C-ABI-compatible type '{f}'", .{elem_ty.fmt(pt)});
20991 .@"packed" => return sema.fail(block, src, "packed union does not support enum tag type", .{}),20733 errdefer msg.destroy(gpa);
20992 .auto => {},20734 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src, elem_ty, .other);
20993 }20735 try sema.addDeclaredHereNote(msg, elem_ty);
20994 }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",
20999 },20770 },
21000 .@"fn" => {20771 }));
21001 const struct_type = ip.loadStructType(ip.typeOf(union_val.val));20772}
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);
2104120773
21042 var noalias_bits: u32 = 0;20774fn zirReifyFn(
21043 for (param_types, 0..) |*param_type, i| {20775 sema: *Sema,
21044 const elem_val = try params_val.elemValue(pt, i);20776 block: *Block,
21045 const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));20777 extended: Zir.Inst.Extended.InstData,
21046 const param_is_generic_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20778) CompileError!Air.Inst.Ref {
21047 ip,20779 const pt = sema.pt;
21048 try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),20780 const zcu = pt.zcu;
21049 ).?);20781 const gpa = zcu.gpa;
21050 const param_is_noalias_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20782 const ip = &zcu.intern_pool;
21051 ip,20783
21052 try ip.getOrPutString(gpa, pt.tid, "is_noalias", .no_embedded_nulls),20784 const extra = sema.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
21053 ).?);20785 const param_types_src = block.builtinCallArgSrc(extra.node, 0);
21054 const opt_param_type_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(20786 const param_attrs_src = block.builtinCallArgSrc(extra.node, 1);
21055 ip,20787 const ret_ty_src = block.builtinCallArgSrc(extra.node, 2);
21056 try ip.getOrPutString(gpa, pt.tid, "type", .no_embedded_nulls),20788 const fn_attrs_src = block.builtinCallArgSrc(extra.node, 3);
21057 ).?);20789
2105820790 const single_param_attrs_ty = try sema.getBuiltinType(param_attrs_src, .@"Type.Fn.Param.Attributes");
21059 if (param_is_generic_val.toBool()) {20791 const fn_attrs_ty = try sema.getBuiltinType(fn_attrs_src, .@"Type.Fn.Attributes");
21060 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});20792
21061 }20793 const param_types_uncoerced = try sema.resolveInst(extra.param_types);
2106220794 const param_types_coerced = try sema.coerce(block, .slice_const_type, param_types_uncoerced, param_types_src);
21063 const param_type_val = opt_param_type_val.optionalValue(zcu) orelse20795 const param_types_slice = try sema.resolveConstDefinedValue(block, param_types_src, param_types_coerced, .{ .simple = .fn_param_types });
21064 return sema.fail(block, src, "Type.Fn.Param.type must be non-null for @Type", .{});20796 const param_types_arr = try sema.derefSliceAsArray(block, param_types_src, param_types_slice, .{ .simple = .fn_param_types });
21065 param_type.* = param_type_val.toIntern();20797
2106620798 const params_len = param_types_arr.typeOf(zcu).arrayLen(zcu);
21067 if (param_is_noalias_val.toBool()) {20799
21068 if (!Type.fromInterned(param_type.*).isPtrAtRuntime(zcu)) {20800 const param_attrs_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21069 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});20801 .len = params_len,
21070 }20802 .child = single_param_attrs_ty.toIntern(),
21071 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse20803 }));
21072 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));20804 const param_attrs_uncoerced = try sema.resolveInst(extra.param_attrs);
21073 }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", .{});
21074 }20840 }
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(.{20846 if (fn_attrs.varargs) {
21077 .param_types = param_types,20847 try sema.checkCallConvSupportsVarArgs(block, fn_attrs_src, fn_attrs.@"callconv");
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),
21086 }20848 }
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 }));
21087}20874}
2108820875
21089fn reifyEnum(20876fn zirReifyStruct(
21090 sema: *Sema,20877 sema: *Sema,
21091 block: *Block,20878 block: *Block,
20879 extended: Zir.Inst.Extended.InstData,
21092 inst: Zir.Inst.Index,20880 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,
21098) CompileError!Air.Inst.Ref {20881) CompileError!Air.Inst.Ref {
21099 const pt = sema.pt;20882 const pt = sema.pt;
21100 const zcu = pt.zcu;20883 const zcu = pt.zcu;
21101 const gpa = sema.gpa;20884 const gpa = sema.gpa;
21102 const ip = &zcu.intern_pool;20885 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
21108 // The validation work here is non-trivial, and it's possible the type already exists.20981 // The validation work here is non-trivial, and it's possible the type already exists.
21109 // So in this first pass, let's just construct a hash to optimize for this case. If the20982 // So in this first pass, let's just construct a hash to optimize for this case. If the
21110 // inputs turn out to be invalid, we can cancel the WIP type later.20983 // 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
21112 // For deduplication purposes, we must create a hash including all details of this type.20989 // For deduplication purposes, we must create a hash including all details of this type.
21113 // TODO: use a longer hash!20990 // TODO: use a longer hash!
21114 var hasher = std.hash.Wyhash.init(0);20991 var hasher = std.hash.Wyhash.init(0);
21115 std.hash.autoHash(&hasher, tag_ty.toIntern());20992 std.hash.autoHash(&hasher, layout);
21116 std.hash.autoHash(&hasher, is_exhaustive);20993 std.hash.autoHash(&hasher, backing_int_ty_val);
21117 std.hash.autoHash(&hasher, fields_len);20994 // The field *type* array has already been deduplicated for us thanks to the InternPool!
2111820995 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.
21119 for (0..fields_len) |field_idx| {21000 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);21019 const field_default: InternPool.Index = d: {
21123 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));21020 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
2112421021 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21125 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .enum_field_name });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
21127 std.hash.autoHash(&hasher, .{21032 std.hash.autoHash(&hasher, .{
21128 field_name,21033 field_name,
21129 field_value_val.toIntern(),21034 field_attr_comptime,
21035 field_attr_align,
21036 field_default,
21130 });21037 });
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;
21131 }21042 }
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, .{21059 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
21136 .has_values = true,21060 .layout = layout,
21137 .tag_mode = if (is_exhaustive) .explicit else .nonexhaustive,21061 .fields_len = @intCast(fields_len),
21138 .fields_len = 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,
21139 .key = .{ .reified = .{21068 .key = .{ .reified = .{
21140 .zir_index = tracked_inst,21069 .zir_index = tracked_inst,
21141 .type_hash = hasher.final(),21070 .type_hash = hasher.final(),
...@@ -21148,79 +21077,144 @@ fn reifyEnum(...@@ -21148,79 +21077,144 @@ fn reifyEnum(
21148 return Air.internedToRef(ty);21077 return Air.internedToRef(ty);
21149 },21078 },
21150 };21079 };
21151 var done = false;21080 errdefer wip_ty.cancel(ip, pt.tid);
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 }
2115721081
21158 const type_name = try sema.createTypeName(21082 const type_name = try sema.createTypeName(
21159 block,21083 block,
21160 name_strategy,21084 name_strategy,
21161 "enum",21085 "struct",
21162 inst,21086 inst,
21163 wip_ty.index,21087 wip_ty.index,
21164 );21088 );
21165 wip_ty.setName(ip, type_name.name, type_name.nav);21089 wip_ty.setName(ip, type_name.name, type_name.nav);
2116621090
21167 const new_namespace_index = try pt.createNamespace(.{21091 const wip_struct_type = ip.loadStructType(wip_ty.index);
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;
2118021092
21181 for (0..fields_len) |field_idx| {21093 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);21097 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
21185 const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(pt, 1));
2118621098
21187 // Don't pass a reason; first loop acts as an assertion that this is valid.21099 // Don't pass a reason; first loop acts as a check that this is valid.
21188 const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined);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)) {21129 const field_default: InternPool.Index = d: {
21191 // TODO: better source location21130 const ptr_val = field_attr_default_value_ptr.optionalValue(zcu) orelse break :d .none;
21192 return sema.fail(block, src, "field '{f}' with enumeration value '{f}' is too large for backing int type '{f}'", .{21131 assert(any_default_inits);
21193 field_name.fmt(ip),21132 const ptr_ty = try pt.singleConstPtrType(field_ty);
21194 field_value_val.fmtValueSema(pt, sema),21133 // The first loop checked that this is comptime-dereferencable.
21195 tag_ty.fmt(pt),21134 const deref_val = (try sema.pointerDeref(block, field_attrs_src, ptr_val, ptr_ty)).?;
21196 });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);
21197 }21148 }
2119821149
21199 const coerced_field_val = try pt.getCoerced(field_value_val, tag_ty);21150 wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern();
21200 if (wip_ty.nextField(ip, field_name, coerced_field_val.toIntern())) |conflict| {21151 if (field_default != .none) {
21201 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {21152 wip_struct_type.field_inits.get(ip)[field_idx] = field_default;
21202 .name => msg: {21153 }
21203 const msg = try sema.errMsg(src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});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)});
21204 errdefer msg.destroy(gpa);21176 errdefer msg.destroy(gpa);
21205 _ = conflict.prev_field_idx; // TODO: this note is incorrect21177 try sema.explainWhyTypeIsNotExtern(msg, field_types_src, field_ty, .struct_field);
21206 try sema.errNote(src, msg, "other field here", .{});21178 try sema.addDeclaredHereNote(msg, field_ty);
21207 break :msg msg;21179 break :msg msg;
21208 },21180 });
21209 .value => msg: {21181 },
21210 const msg = try sema.errMsg(src, "enum tag value {f} already taken", .{field_value_val.fmtValueSema(pt, sema)});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)});
21211 errdefer msg.destroy(gpa);21185 errdefer msg.destroy(gpa);
21212 _ = conflict.prev_field_idx; // TODO: this note is incorrect21186 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
21213 try sema.errNote(src, msg, "other enum tag value here", .{});21187 try sema.addDeclaredHereNote(msg, field_ty);
21214 break :msg msg;21188 break :msg msg;
21215 },21189 });
21216 });21190 },
21217 }21191 }
21218 }21192 }
2121921193
21220 if (!is_exhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {21194 if (layout == .@"packed") {
21221 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});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 }
21222 }21208 }
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 });
21224 codegen_type: {21218 codegen_type: {
21225 if (zcu.comp.config.use_llvm) break :codegen_type;21219 if (zcu.comp.config.use_llvm) break :codegen_type;
21226 if (block.ownerModule().strip) break :codegen_type;21220 if (block.ownerModule().strip) break :codegen_type;
...@@ -21228,75 +21222,177 @@ fn reifyEnum(...@@ -21228,75 +21222,177 @@ fn reifyEnum(
21228 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);21222 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21229 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21223 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21230 }21224 }
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));
21232}21229}
2123321230
21234fn reifyUnion(21231fn zirReifyUnion(
21235 sema: *Sema,21232 sema: *Sema,
21236 block: *Block,21233 block: *Block,
21234 extended: Zir.Inst.Extended.InstData,
21237 inst: Zir.Inst.Index,21235 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,
21243) CompileError!Air.Inst.Ref {21236) CompileError!Air.Inst.Ref {
21244 const pt = sema.pt;21237 const pt = sema.pt;
21245 const zcu = pt.zcu;21238 const zcu = pt.zcu;
21246 const gpa = sema.gpa;21239 const gpa = sema.gpa;
21247 const ip = &zcu.intern_pool;21240 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
21253 // The validation work here is non-trivial, and it's possible the type already exists.21336 // The validation work here is non-trivial, and it's possible the type already exists.
21254 // So in this first pass, let's just construct a hash to optimize for this case. If the21337 // So in this first pass, let's just construct a hash to optimize for this case. If the
21255 // inputs turn out to be invalid, we can cancel the WIP type later.21338 // inputs turn out to be invalid, we can cancel the WIP type later.
2125621339
21340 var any_aligned_fields = false;
21341
21257 // For deduplication purposes, we must create a hash including all details of this type.21342 // For deduplication purposes, we must create a hash including all details of this type.
21258 // TODO: use a longer hash!21343 // TODO: use a longer hash!
21259 var hasher = std.hash.Wyhash.init(0);21344 var hasher = std.hash.Wyhash.init(0);
21260 std.hash.autoHash(&hasher, layout);21345 std.hash.autoHash(&hasher, layout);
21261 std.hash.autoHash(&hasher, opt_tag_type_val.toIntern());21346 std.hash.autoHash(&hasher, arg_ty_val);
21262 std.hash.autoHash(&hasher, fields_len);21347 // `field_types_arr` and `field_attrs_arr` are already deduplicated by the InternPool!
2126321348 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.
21264 for (0..fields_len) |field_idx| {21352 for (0..fields_len) |field_idx| {
21265 const field_info = try fields_val.elemValue(pt, field_idx);21353 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2126621354 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .union_field_names });
21267 const field_name_val = try field_info.fieldValue(pt, 0);21355 std.hash.autoHash(&hasher, field_name);
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));
2127021356
21271 const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ .simple = .union_field_name });21357 const field_attrs = try sema.interpretBuiltinType(
21272 std.hash.autoHash(&hasher, .{21358 block,
21273 field_name,21359 field_attrs_src,
21274 field_type_val.toIntern(),21360 try field_attrs_arr.elemValue(pt, field_idx),
21275 field_align_val.toIntern(),21361 std.builtin.Type.UnionField.Attributes,
21276 });21362 );
21363 if (field_attrs.@"align" != null) {
21364 any_aligned_fields = true;
21365 }
21277 }21366 }
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
21281 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{21380 const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, .{
21282 .flags = .{21381 .flags = .{
21283 .layout = layout,21382 .layout = layout,
21284 .status = .none,21383 .status = .none,
21285 .runtime_tag = if (opt_tag_type_val.optionalValue(zcu) != null)21384 .runtime_tag = rt: {
21286 .tagged21385 if (explicit_tag_ty != null) break :rt .tagged;
21287 else if (layout != .auto)21386 if (layout == .auto and block.wantSafeTypes()) break :rt .safety;
21288 .none21387 break :rt .none;
21289 else switch (block.wantSafeTypes()) {
21290 true => .safety,
21291 false => .none,
21292 },21388 },
21293 .any_aligned_fields = layout != .@"packed",21389 .any_aligned_fields = any_aligned_fields,
21294 .requires_comptime = .unknown,21390 .requires_comptime = .unknown,
21295 .assumed_runtime_bits = false,21391 .assumed_runtime_bits = false,
21296 .assumed_pointer_aligned = false,21392 .assumed_pointer_aligned = false,
21297 .alignment = .none,21393 .alignment = .none,
21298 },21394 },
21299 .fields_len = fields_len,21395 .fields_len = @intCast(fields_len),
21300 .enum_tag_ty = .none, // set later because not yet validated21396 .enum_tag_ty = .none, // set later because not yet validated
21301 .field_types = &.{}, // set later21397 .field_types = &.{}, // set later
21302 .field_aligns = &.{}, // set later21398 .field_aligns = &.{}, // set later
...@@ -21325,128 +21421,117 @@ fn reifyUnion(...@@ -21325,128 +21421,117 @@ fn reifyUnion(
2132521421
21326 const loaded_union = ip.loadUnionType(wip_ty.index);21422 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: {21424 const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: {
21329 switch (ip.indexToKey(tag_type_val.toIntern())) {21425 if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") {
21330 .enum_type => {},21426 return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{});
21331 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
21332 }21427 }
21333 const enum_tag_ty = tag_type_val.toType();
2133421428
21335 // We simply track which fields of the tag type have been seen.
21336 const tag_ty_fields_len = enum_tag_ty.enumFieldCount(zcu);21429 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
21339 for (0..fields_len) |field_idx| {21431 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);21436 if (field_idx >= tag_ty_fields_len) {
21343 const field_type_val = try field_info.fieldValue(pt, 1);21437 return sema.fail(block, field_names_src, "no field named '{f}' in enum '{f}'", .{
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}'", .{
21352 field_name.fmt(ip), enum_tag_ty.fmt(pt),21438 field_name.fmt(ip), enum_tag_ty.fmt(pt),
21353 });21439 });
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)});
21358 }21440 }
21359 seen_tags.set(enum_index);
2136021441
21361 loaded_union.field_types.get(ip)[field_idx] = field_type_val.toIntern();21442 const enum_field_name = enum_tag_ty.enumFieldName(field_idx, zcu);
21362 const byte_align = try field_alignment_val.toUnsignedIntSema(pt);21443 if (enum_field_name != field_name) {
21363 if (layout == .@"packed") {21444 return sema.fail(block, field_names_src, "union field name '{f}' does not match enum field name '{f}'", .{
21364 if (byte_align != 0) return sema.fail(block, src, "alignment of a packed union field must be set to 0", .{});21445 field_name.fmt(ip), enum_field_name.fmt(ip),
21365 } else {21446 });
21366 loaded_union.field_aligns.get(ip)[field_idx] = try sema.validateAlign(block, src, byte_align);
21367 }21447 }
21368 }21448 }
21369
21370 if (tag_ty_fields_len > fields_len) return sema.failWithOwnedErrorMsg(block, msg: {21449 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 });
21372 errdefer msg.destroy(gpa);21453 errdefer msg.destroy(gpa);
21373 var it = seen_tags.iterator(.{ .kind = .unset });21454 for (fields_len..tag_ty_fields_len) |enum_field_idx| {
21374 while (it.next()) |enum_index| {21455 try sema.addFieldErrNote(enum_tag_ty, enum_field_idx, msg, "field '{f}' missing, declared here", .{
21375 const field_name = enum_tag_ty.enumFieldName(enum_index, zcu);21456 enum_tag_ty.enumFieldName(enum_field_idx, zcu).fmt(ip),
21376 try sema.addFieldErrNote(enum_tag_ty, enum_index, msg, "field '{f}' missing, declared here", .{
21377 field_name.fmt(ip),
21378 });21457 });
21379 }21458 }
21380 try sema.addDeclaredHereNote(msg, enum_tag_ty);21459 try sema.addDeclaredHereNote(msg, enum_tag_ty);
21381 break :msg msg;21460 break :msg msg;
21382 });21461 });
2138321462 break :tag .{ enum_tag_ty.toIntern(), true };
21384 break :tag_ty .{ enum_tag_ty.toIntern(), true };21463 } else tag: {
21385 } else tag_ty: {
21386 // We must track field names and set up the tag type ourselves.21464 // We must track field names and set up the tag type ourselves.
21387 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;21465 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
21388 try field_names.ensureTotalCapacity(sema.arena, fields_len);21466 try field_names.ensureTotalCapacity(sema.arena, fields_len);
2138921467
21390 for (0..fields_len) |field_idx| {21468 for (0..fields_len) |field_idx| {
21391 const field_info = try fields_val.elemValue(pt, field_idx);21469 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2139221470 // Don't pass a reason; first loop acts as a check that this is valid.
21393 const field_name_val = try field_info.fieldValue(pt, 0);21471 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
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);
21399 const gop = field_names.getOrPutAssumeCapacity(field_name);21472 const gop = field_names.getOrPutAssumeCapacity(field_name);
21400 if (gop.found_existing) {21473 if (gop.found_existing) {
21401 // TODO: better source location21474 // TODO: better source location
21402 return sema.fail(block, src, "duplicate union field {f}", .{field_name.fmt(ip)});21475 return sema.fail(block, field_names_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);
21411 }21476 }
21412 }21477 }
21413
21414 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);21478 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 };
21416 };21480 };
21417 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error21481 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| {21483 for (0..fields_len) |field_idx| {
21420 const field_ty: Type = .fromInterned(field_ty_ip);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
21421 if (field_ty.zigTypeTag(zcu) == .@"opaque") {21492 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
21422 return sema.failWithOwnedErrorMsg(block, msg: {21493 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", .{});
21424 errdefer msg.destroy(gpa);21495 errdefer msg.destroy(gpa);
21425
21426 try sema.addDeclaredHereNote(msg, field_ty);21496 try sema.addDeclaredHereNote(msg, field_ty);
21427 break :msg msg;21497 break :msg msg;
21428 });21498 });
21429 }21499 }
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);21510 try sema.addDeclaredHereNote(msg, field_ty);
21438 break :msg msg;21511 break :msg msg;
21439 });21512 });
21440 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21513 },
21441 return sema.failWithOwnedErrorMsg(block, msg: {21514 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
21442 const msg = try sema.errMsg(src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});21515 return sema.failWithOwnedErrorMsg(block, msg: {
21443 errdefer msg.destroy(gpa);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);21521 try sema.addDeclaredHereNote(msg, field_ty);
21448 break :msg msg;21522 break :msg msg;
21449 });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;
21450 }21535 }
21451 }21536 }
2145221537
...@@ -21471,116 +21556,94 @@ fn reifyUnion(...@@ -21471,116 +21556,94 @@ fn reifyUnion(
21471 try sema.declareDependency(.{ .interned = wip_ty.index });21556 try sema.declareDependency(.{ .interned = wip_ty.index });
21472 try sema.addTypeReferenceEntry(src, wip_ty.index);21557 try sema.addTypeReferenceEntry(src, wip_ty.index);
21473 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);21558 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));
21475}21560}
2147621561
21477fn reifyTuple(21562fn zirReifyEnum(
21478 sema: *Sema,21563 sema: *Sema,
21479 block: *Block,21564 block: *Block,
21480 src: LazySrcLoc,21565 extended: Zir.Inst.Extended.InstData,
21481 fields_val: Value,21566 inst: Zir.Inst.Index,
21482) CompileError!Air.Inst.Ref {21567) CompileError!Air.Inst.Ref {
21483 const pt = sema.pt;21568 const pt = sema.pt;
21484 const zcu = pt.zcu;21569 const zcu = pt.zcu;
21485 const gpa = sema.gpa;21570 const gpa = sema.gpa;
21486 const ip = &zcu.intern_pool;21571 const ip = &zcu.intern_pool;
2148721572
21488 const fields_len: u32 = @intCast(fields_val.typeOf(zcu).arrayLen(zcu));21573 const name_strategy: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
2148921574 const extra = sema.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
21490 const types = try sema.arena.alloc(InternPool.Index, fields_len);21575 const tracked_inst = try block.trackZir(inst);
21491 const inits = try sema.arena.alloc(InternPool.Index, fields_len);21576 const src: LazySrcLoc = .{
2149221577 .base_node_inst = tracked_inst,
21493 for (types, inits, 0..) |*field_ty, *field_init, field_idx| {21578 .offset = .nodeOffset(.zero),
21494 const field_info = try fields_val.elemValue(pt, field_idx);21579 };
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;
2151821580
21519 const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail(21581 const tag_ty_src: LazySrcLoc = .{
21520 block,21582 .base_node_inst = tracked_inst,
21521 src,21583 .offset = .{ .node_offset_builtin_call_arg = .{
21522 "tuple cannot have non-numeric field '{f}'",21584 .builtin_call_node = .zero,
21523 .{field_name.fmt(ip)},21585 .arg_index = 0,
21524 );21586 } },
21525 if (field_name_index != field_idx) {21587 };
21526 return sema.fail(21588 const mode_src: LazySrcLoc = .{
21527 block,21589 .base_node_inst = tracked_inst,
21528 src,21590 .offset = .{ .node_offset_builtin_call_arg = .{
21529 "tuple field name '{d}' does not match field index {d}",21591 .builtin_call_node = .zero,
21530 .{ field_name_index, field_idx },21592 .arg_index = 1,
21531 );21593 } },
21532 }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 {21612 const tag_ty = try sema.resolveType(block, tag_ty_src, extra.tag_ty);
21537 const alignment_ok = ok: {21613 if (tag_ty.zigTypeTag(zcu) != .int) {
21538 if (field_alignment_val.toIntern() == .zero) break :ok true;21614 return sema.fail(block, tag_ty_src, "tag type must be an integer type", .{});
21539 const given_align = try field_alignment_val.getUnsignedIntSema(pt) orelse break :ok false;21615 }
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 }
2154721616
21548 if (field_is_comptime_val.toBool() and field_default_value == .none) {21617 const mode_uncoerced = try sema.resolveInst(extra.mode);
21549 return sema.fail(block, src, "comptime field without default initialization value", .{});21618 const mode_coerced = try sema.coerce(block, enum_mode_ty, mode_uncoerced, mode_src);
21550 }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) {21625 const field_names_uncoerced = try sema.resolveInst(extra.field_names);
21553 return sema.fail(block, src, "non-comptime tuple fields cannot specify default initialization value", .{});21626 const field_names_coerced = try sema.coerce(block, .slice_const_slice_const_u8, field_names_uncoerced, field_names_src);
21554 }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();21630 const fields_len = try sema.usizeCast(block, src, field_names_arr.typeOf(zcu).arrayLen(zcu));
21557 field_init.* = field_default_value;
21558 }
2155921631
21560 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, pt.tid, .{21632 const field_values_ty = try pt.singleConstPtrType(try pt.arrayType(.{
21561 .types = types,21633 .len = fields_len,
21562 .values = inits,21634 .child = tag_ty.toIntern(),
21563 }));21635 }));
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
21585 // The validation work here is non-trivial, and it's possible the type already exists.21648 // The validation work here is non-trivial, and it's possible the type already exists.
21586 // So in this first pass, let's just construct a hash to optimize for this case. If the21649 // So in this first pass, let's just construct a hash to optimize for this case. If the
...@@ -21589,62 +21652,23 @@ fn reifyStruct(...@@ -21589,62 +21652,23 @@ fn reifyStruct(
21589 // For deduplication purposes, we must create a hash including all details of this type.21652 // For deduplication purposes, we must create a hash including all details of this type.
21590 // TODO: use a longer hash!21653 // TODO: use a longer hash!
21591 var hasher = std.hash.Wyhash.init(0);21654 var hasher = std.hash.Wyhash.init(0);
21592 std.hash.autoHash(&hasher, layout);21655 std.hash.autoHash(&hasher, tag_ty.toIntern());
21593 std.hash.autoHash(&hasher, opt_backing_int_val.toIntern());21656 std.hash.autoHash(&hasher, nonexhaustive);
21594 std.hash.autoHash(&hasher, fields_len);21657 std.hash.autoHash(&hasher, fields_len);
2159521658 // `field_values_arr` is already deduplicated by the InternPool!
21596 var any_comptime_fields = false;21659 std.hash.autoHash(&hasher, field_values_arr);
21597 var any_default_inits = false;21660 // However, for field names, we need to iterate the individual fields, because the pointers (the
2159821661 // names are slices) mean that distinct values could ultimately result in the same enum type.
21599 for (0..fields_len) |field_idx| {21662 for (0..fields_len) |field_idx| {
21600 const field_info = try fields_val.elemValue(pt, field_idx);21663 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2160121664 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, .{ .simple = .enum_field_names });
21602 const field_name_val = try field_info.fieldValue(pt, 0);21665 std.hash.autoHash(&hasher, field_name);
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;
21635 }21666 }
2163621667
21637 const tracked_inst = try block.trackZir(inst);21668 const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, .{
2163821669 .has_values = true,
21639 const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{21670 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,
21640 .layout = layout,21671 .fields_len = @intCast(fields_len),
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,
21648 .key = .{ .reified = .{21672 .key = .{ .reified = .{
21649 .zir_index = tracked_inst,21673 .zir_index = tracked_inst,
21650 .type_hash = hasher.final(),21674 .type_hash = hasher.final(),
...@@ -21654,152 +21678,66 @@ fn reifyStruct(...@@ -21654,152 +21678,66 @@ fn reifyStruct(
21654 .existing => |ty| {21678 .existing => |ty| {
21655 try sema.declareDependency(.{ .interned = ty });21679 try sema.declareDependency(.{ .interned = ty });
21656 try sema.addTypeReferenceEntry(src, ty);21680 try sema.addTypeReferenceEntry(src, ty);
21657 return Air.internedToRef(ty);21681 return .fromIntern(ty);
21658 },21682 },
21659 };21683 };
21660 errdefer wip_ty.cancel(ip, pt.tid);21684 var done = false;
21685 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
2166121686
21662 const type_name = try sema.createTypeName(21687 const type_name = try sema.createTypeName(
21663 block,21688 block,
21664 name_strategy,21689 name_strategy,
21665 "struct",21690 "enum",
21666 inst,21691 inst,
21667 wip_ty.index,21692 wip_ty.index,
21668 );21693 );
21669 wip_ty.setName(ip, type_name.name, type_name.nav);21694 wip_ty.setName(ip, type_name.name, type_name.nav);
2167021695
21671 const struct_type = ip.loadStructType(wip_ty.index);21696 const new_namespace_index = try pt.createNamespace(.{
2167221697 .parent = block.namespace.toOptional(),
21673 for (0..fields_len) |field_idx| {21698 .owner_type = wip_ty.index,
21674 const field_info = try fields_val.elemValue(pt, field_idx);21699 .file_scope = block.getFileScopeIndex(zcu),
2167521700 .generation = zcu.generation,
21676 const field_name_val = try field_info.fieldValue(pt, 0);21701 });
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);
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);21710 for (0..fields_len) |field_idx| {
21755 break :msg msg;21711 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
21756 });21712 // Don't pass a reason; first loop acts as a check that this is valid.
21757 } else if (layout == .@"packed" and !try sema.validatePackedType(field_ty)) {21713 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
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);
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);21717 if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| {
21765 break :msg msg;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 },
21766 });21733 });
21767 }21734 }
21768 }21735 }
2176921736
21770 if (layout == .@"packed") {21737 if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {
21771 var fields_bit_sum: u64 = 0;21738 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});
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 }
21793 }21739 }
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 });
21803 codegen_type: {21741 codegen_type: {
21804 if (zcu.comp.config.use_llvm) break :codegen_type;21742 if (zcu.comp.config.use_llvm) break :codegen_type;
21805 if (block.ownerModule().strip) break :codegen_type;21743 if (block.ownerModule().strip) break :codegen_type;
...@@ -21807,10 +21745,7 @@ fn reifyStruct(...@@ -21807,10 +21745,7 @@ fn reifyStruct(
21807 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);21745 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
21808 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });21746 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
21809 }21747 }
21810 try sema.declareDependency(.{ .interned = wip_ty.index });21748 return Air.internedToRef(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));
21814}21749}
2181521750
21816fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {21751fn 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...@@ -25541,7 +25476,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25541 extra_index += body.len;25476 extra_index += body.len;
25542 if (extra.data.bits.ret_ty_is_generic) break :blk .generic_poison;25477 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 });
25545 const ty = val.toType();25480 const ty = val.toType();
25546 break :blk ty;25481 break :blk ty;
25547 } else if (extra.data.bits.has_ret_ty_ref) blk: {25482 } 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...@@ -25968,21 +25903,26 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
25968 const src = block.nodeOffset(src_node);25903 const src = block.nodeOffset(src_node);
25969 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);25904 const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
2597025905
25971 const ty = switch (value) {25906 const builtin_type: Zcu.BuiltinDecl = switch (value) {
25972 // zig fmt: off25907 // zig fmt: off
25973 .atomic_order => try sema.getBuiltinType(src, .AtomicOrder),25908 .atomic_order => .AtomicOrder,
25974 .atomic_rmw_op => try sema.getBuiltinType(src, .AtomicRmwOp),25909 .atomic_rmw_op => .AtomicRmwOp,
25975 .calling_convention => try sema.getBuiltinType(src, .CallingConvention),25910 .calling_convention => .CallingConvention,
25976 .address_space => try sema.getBuiltinType(src, .AddressSpace),25911 .address_space => .AddressSpace,
25977 .float_mode => try sema.getBuiltinType(src, .FloatMode),25912 .float_mode => .FloatMode,
25978 .reduce_op => try sema.getBuiltinType(src, .ReduceOp),25913 .signedness => .Signedness,
25979 .call_modifier => try sema.getBuiltinType(src, .CallModifier),25914 .reduce_op => .ReduceOp,
25980 .prefetch_options => try sema.getBuiltinType(src, .PrefetchOptions),25915 .call_modifier => .CallModifier,
25981 .export_options => try sema.getBuiltinType(src, .ExportOptions),25916 .prefetch_options => .PrefetchOptions,
25982 .extern_options => try sema.getBuiltinType(src, .ExternOptions),25917 .export_options => .ExportOptions,
25983 .type_info => try sema.getBuiltinType(src, .Type),25918 .extern_options => .ExternOptions,
25984 .branch_hint => try sema.getBuiltinType(src, .BranchHint),25919 .branch_hint => .BranchHint,
25985 .clobbers => try sema.getBuiltinType(src, .@"assembly.Clobbers"),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",
25986 // zig fmt: on25926 // zig fmt: on
2598725927
25988 // Values are handled here.25928 // Values are handled here.
...@@ -26009,7 +25949,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -26009,7 +25949,7 @@ fn zirBuiltinValue(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
26009 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);25949 return sema.coerce(block, callconv_ty, Air.internedToRef(inline_tag_val.toIntern()), src);
26010 },25950 },
26011 };25951 };
26012 return Air.internedToRef(ty.toIntern());25952 return .fromType(try sema.getBuiltinType(src, builtin_type));
26013}25953}
2601425954
26015fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {25955fn zirInplaceArithResultTy(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
...@@ -35259,7 +35199,7 @@ fn structFields(...@@ -35259,7 +35199,7 @@ fn structFields(
35259 .base_node_inst = struct_type.zir_index,35199 .base_node_inst = struct_type.zir_index,
35260 .offset = .nodeOffset(.zero),35200 .offset = .nodeOffset(.zero),
35261 },35201 },
35262 .r = .{ .simple = .struct_fields },35202 .r = .{ .simple = .type },
35263 } },35203 } },
35264 .src_base_inst = struct_type.zir_index,35204 .src_base_inst = struct_type.zir_index,
35265 .type_name_ctx = struct_type.name,35205 .type_name_ctx = struct_type.name,
...@@ -35614,7 +35554,7 @@ fn unionFields(...@@ -35614,7 +35554,7 @@ fn unionFields(
35614 .inlining = null,35554 .inlining = null,
35615 .comptime_reason = .{ .reason = .{35555 .comptime_reason = .{ .reason = .{
35616 .src = src,35556 .src = src,
35617 .r = .{ .simple = .union_fields },35557 .r = .{ .simple = .type },
35618 } },35558 } },
35619 .src_base_inst = union_type.zir_index,35559 .src_base_inst = union_type.zir_index,
35620 .type_name_ctx = union_type.name,35560 .type_name_ctx = union_type.name,
...@@ -36077,8 +36017,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36077,8 +36017,13 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36077 .manyptr_u8_type,36017 .manyptr_u8_type,
36078 .manyptr_const_u8_type,36018 .manyptr_const_u8_type,
36079 .manyptr_const_u8_sentinel_0_type,36019 .manyptr_const_u8_sentinel_0_type,
36020 .manyptr_const_slice_const_u8_type,
36080 .slice_const_u8_type,36021 .slice_const_u8_type,
36081 .slice_const_u8_sentinel_0_type,36022 .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,
36082 .vector_8_i8_type,36027 .vector_8_i8_type,
36083 .vector_16_i8_type,36028 .vector_16_i8_type,
36084 .vector_32_i8_type,36029 .vector_32_i8_type,
...@@ -37230,7 +37175,7 @@ fn sliceToIpString(...@@ -37230,7 +37175,7 @@ fn sliceToIpString(
3723037175
37231/// Given a slice value, attempts to dereference it into a comptime-known array.37176/// Given a slice value, attempts to dereference it into a comptime-known array.
37232/// Emits a compile error if the contents of the slice are not comptime-known.37177/// 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.
37234fn derefSliceAsArray(37179fn derefSliceAsArray(
37235 sema: *Sema,37180 sema: *Sema,
37236 block: *Block,37181 block: *Block,
...@@ -37247,7 +37192,7 @@ fn derefSliceAsArray(...@@ -37247,7 +37192,7 @@ fn derefSliceAsArray(
3724737192
37248/// Given a slice value, attempts to dereference it into a comptime-known array.37193/// Given a slice value, attempts to dereference it into a comptime-known array.
37249/// Returns `null` if the contents of the slice are not comptime-known.37194/// 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.
37251fn maybeDerefSliceAsArray(37196fn maybeDerefSliceAsArray(
37252 sema: *Sema,37197 sema: *Sema,
37253 block: *Block,37198 block: *Block,
...@@ -37257,7 +37202,13 @@ fn maybeDerefSliceAsArray(...@@ -37257,7 +37202,13 @@ fn maybeDerefSliceAsArray(
37257 const pt = sema.pt;37202 const pt = sema.pt;
37258 const zcu = pt.zcu;37203 const zcu = pt.zcu;
37259 const ip = &zcu.intern_pool;37204 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 }
37261 const slice = switch (ip.indexToKey(slice_val.toIntern())) {37212 const slice = switch (ip.indexToKey(slice_val.toIntern())) {
37262 .undef => return sema.failWithUseOfUndef(block, src, null),37213 .undef => return sema.failWithUseOfUndef(block, src, null),
37263 .slice => |slice| slice,37214 .slice => |slice| slice,
...@@ -37393,7 +37344,7 @@ pub fn resolveDeclaredEnum(...@@ -37393,7 +37344,7 @@ pub fn resolveDeclaredEnum(
37393 .inlining = null,37344 .inlining = null,
37394 .comptime_reason = .{ .reason = .{37345 .comptime_reason = .{ .reason = .{
37395 .src = src,37346 .src = src,
37396 .r = .{ .simple = .enum_fields },37347 .r = .{ .simple = .enum_field_values },
37397 } },37348 } },
37398 .src_base_inst = tracked_inst,37349 .src_base_inst = tracked_inst,
37399 .type_name_ctx = type_name,37350 .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...@@ -317,7 +317,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
317 .undefined,317 .undefined,
318 => try writer.print("@TypeOf({s})", .{@tagName(s)}),318 => 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
322 .generic_poison => unreachable,322 .generic_poison => unreachable,
323 },323 },
...@@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {...@@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
3509 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,3509 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3510 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,3510 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3511 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,3511 .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,
3513 else => unreachable,3515 else => unreachable,
3514 },3516 },
3515 else => unreachable,3517 else => unreachable,
...@@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };...@@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
4280pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };4282pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
4281pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };4283pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
4282pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };4284pub 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
4284pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };4290pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };
4285pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };4291pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };
src/Value.zig+23
...@@ -2824,6 +2824,29 @@ pub fn resolveLazy(...@@ -2824,6 +2824,29 @@ pub fn resolveLazy(
2824 .val = resolved_val,2824 .val = resolved_val,
2825 }));2825 }));
2826 },2826 },
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
2827 else => return val,2850 else => return val,
2828 }2851 }
2829}2852}
src/Zcu.zig+19-5
...@@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {...@@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {
416 Type,416 Type,
417 @"Type.Fn",417 @"Type.Fn",
418 @"Type.Fn.Param",418 @"Type.Fn.Param",
419 @"Type.Fn.Param.Attributes",
420 @"Type.Fn.Attributes",
419 @"Type.Int",421 @"Type.Int",
420 @"Type.Float",422 @"Type.Float",
421 @"Type.Pointer",423 @"Type.Pointer",
422 @"Type.Pointer.Size",424 @"Type.Pointer.Size",
425 @"Type.Pointer.Attributes",
423 @"Type.Array",426 @"Type.Array",
424 @"Type.Vector",427 @"Type.Vector",
425 @"Type.Optional",428 @"Type.Optional",
...@@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {...@@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {
427 @"Type.ErrorUnion",430 @"Type.ErrorUnion",
428 @"Type.EnumField",431 @"Type.EnumField",
429 @"Type.Enum",432 @"Type.Enum",
433 @"Type.Enum.Mode",
430 @"Type.Union",434 @"Type.Union",
431 @"Type.UnionField",435 @"Type.UnionField",
436 @"Type.UnionField.Attributes",
432 @"Type.Struct",437 @"Type.Struct",
433 @"Type.StructField",438 @"Type.StructField",
439 @"Type.StructField.Attributes",
434 @"Type.ContainerLayout",440 @"Type.ContainerLayout",
435 @"Type.Opaque",441 @"Type.Opaque",
436 @"Type.Declaration",442 @"Type.Declaration",
...@@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {...@@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {
495 .Type,501 .Type,
496 .@"Type.Fn",502 .@"Type.Fn",
497 .@"Type.Fn.Param",503 .@"Type.Fn.Param",
504 .@"Type.Fn.Param.Attributes",
505 .@"Type.Fn.Attributes",
498 .@"Type.Int",506 .@"Type.Int",
499 .@"Type.Float",507 .@"Type.Float",
500 .@"Type.Pointer",508 .@"Type.Pointer",
501 .@"Type.Pointer.Size",509 .@"Type.Pointer.Size",
510 .@"Type.Pointer.Attributes",
502 .@"Type.Array",511 .@"Type.Array",
503 .@"Type.Vector",512 .@"Type.Vector",
504 .@"Type.Optional",513 .@"Type.Optional",
...@@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {...@@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {
506 .@"Type.ErrorUnion",515 .@"Type.ErrorUnion",
507 .@"Type.EnumField",516 .@"Type.EnumField",
508 .@"Type.Enum",517 .@"Type.Enum",
518 .@"Type.Enum.Mode",
509 .@"Type.Union",519 .@"Type.Union",
510 .@"Type.UnionField",520 .@"Type.UnionField",
521 .@"Type.UnionField.Attributes",
511 .@"Type.Struct",522 .@"Type.Struct",
512 .@"Type.StructField",523 .@"Type.StructField",
524 .@"Type.StructField.Attributes",
513 .@"Type.ContainerLayout",525 .@"Type.ContainerLayout",
514 .@"Type.Opaque",526 .@"Type.Opaque",
515 .@"Type.Declaration",527 .@"Type.Declaration",
...@@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {...@@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {
1745 const node = node_off.toAbsolute(src_loc.base_node);1757 const node = node_off.toAbsolute(src_loc.base_node);
1746 var buf: [1]Ast.Node.Index = undefined;1758 var buf: [1]Ast.Node.Index = undefined;
1747 const full = tree.fullFnProto(&buf, node).?;1759 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);
1749 },1761 },
1750 .node_offset_fn_type_addrspace => |node_off| {1762 .node_offset_fn_type_addrspace => |node_off| {
1751 const tree = try src_loc.file_scope.getTree(zcu);1763 const tree = try src_loc.file_scope.getTree(zcu);
1752 const node = node_off.toAbsolute(src_loc.base_node);1764 const node = node_off.toAbsolute(src_loc.base_node);
1753 var buf: [1]Ast.Node.Index = undefined;1765 var buf: [1]Ast.Node.Index = undefined;
1754 const full = tree.fullFnProto(&buf, node).?;1766 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);
1756 },1768 },
1757 .node_offset_fn_type_section => |node_off| {1769 .node_offset_fn_type_section => |node_off| {
1758 const tree = try src_loc.file_scope.getTree(zcu);1770 const tree = try src_loc.file_scope.getTree(zcu);
1759 const node = node_off.toAbsolute(src_loc.base_node);1771 const node = node_off.toAbsolute(src_loc.base_node);
1760 var buf: [1]Ast.Node.Index = undefined;1772 var buf: [1]Ast.Node.Index = undefined;
1761 const full = tree.fullFnProto(&buf, node).?;1773 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);
1763 },1775 },
1764 .node_offset_fn_type_cc => |node_off| {1776 .node_offset_fn_type_cc => |node_off| {
1765 const tree = try src_loc.file_scope.getTree(zcu);1777 const tree = try src_loc.file_scope.getTree(zcu);
1766 const node = node_off.toAbsolute(src_loc.base_node);1778 const node = node_off.toAbsolute(src_loc.base_node);
1767 var buf: [1]Ast.Node.Index = undefined;1779 var buf: [1]Ast.Node.Index = undefined;
1768 const full = tree.fullFnProto(&buf, node).?;1780 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);
1770 },1782 },
17711783
1772 .node_offset_fn_type_ret_ty => |node_off| {1784 .node_offset_fn_type_ret_ty => |node_off| {
...@@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {...@@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {
2684 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,2696 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
2685 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,2697 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,
2686 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,2698 .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,
2688 else => unreachable,2702 else => unreachable,
2689 },2703 },
2690 else => unreachable,2704 else => unreachable,
src/codegen/c/Type.zig+70
...@@ -1416,6 +1416,9 @@ pub const Pool = struct {...@@ -1416,6 +1416,9 @@ pub const Pool = struct {
1416 .null_type,1416 .null_type,
1417 .undefined_type,1417 .undefined_type,
1418 .enum_literal_type,1418 .enum_literal_type,
1419 .optional_type_type,
1420 .manyptr_const_type_type,
1421 .slice_const_type_type,
1419 => return .void,1422 => return .void,
1420 .u1_type, .u8_type => return .u8,1423 .u1_type, .u8_type => return .u8,
1421 .i8_type => return .i8,1424 .i8_type => return .i8,
...@@ -1525,6 +1528,73 @@ pub const Pool = struct {...@@ -1525,6 +1528,73 @@ pub const Pool = struct {
1525 return pool.fromFields(allocator, .@"struct", &fields, kind);1528 return pool.fromFields(allocator, .@"struct", &fields, kind);
1526 },1529 },
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
1528 .vector_8_i8_type => {1598 .vector_8_i8_type => {
1529 const vector_ctype = try pool.getVector(allocator, .{1599 const vector_ctype = try pool.getVector(allocator, .{
1530 .elem_ctype = .i8,1600 .elem_ctype = .i8,
src/link/Dwarf.zig+6-1
...@@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(...@@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(
4490 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4490 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4491 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4491 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4492 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,4492 .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
4494 else => unreachable,4499 else => unreachable,
4495 },4500 },
4496 else => unreachable,4501 else => unreachable,
src/print_zir.zig+93-11
...@@ -399,6 +399,7 @@ const Writer = struct {...@@ -399,6 +399,7 @@ const Writer = struct {
399 .splat,399 .splat,
400 .reduce,400 .reduce,
401 .bitcast,401 .bitcast,
402 .reify_int,
402 .vector_type,403 .vector_type,
403 .max,404 .max,
404 .min,405 .min,
...@@ -568,6 +569,8 @@ const Writer = struct {...@@ -568,6 +569,8 @@ const Writer = struct {
568 .work_group_id,569 .work_group_id,
569 .branch_hint,570 .branch_hint,
570 .float_op_result_ty,571 .float_op_result_ty,
572 .reify_tuple,
573 .reify_pointer_sentinel_ty,
571 => {574 => {
572 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;575 const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
573 try self.writeInstRef(stream, inst_data.operand);576 try self.writeInstRef(stream, inst_data.operand);
...@@ -575,23 +578,13 @@ const Writer = struct {...@@ -575,23 +578,13 @@ const Writer = struct {
575 try self.writeSrcNode(stream, inst_data.node);578 try self.writeSrcNode(stream, inst_data.node);
576 },579 },
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
589 .builtin_extern,581 .builtin_extern,
590 .c_define,582 .c_define,
591 .error_cast,583 .error_cast,
592 .wasm_memory_grow,584 .wasm_memory_grow,
593 .prefetch,585 .prefetch,
594 .c_va_arg,586 .c_va_arg,
587 .reify_enum_value_slice_ty,
595 => {588 => {
596 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;589 const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
597 try self.writeInstRef(stream, inst_data.lhs);590 try self.writeInstRef(stream, inst_data.lhs);
...@@ -601,6 +594,95 @@ const Writer = struct {...@@ -601,6 +594,95 @@ const Writer = struct {
601 try self.writeSrcNode(stream, inst_data.node);594 try self.writeSrcNode(stream, inst_data.node);
602 },595 },
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
604 .cmpxchg => try self.writeCmpxchg(stream, extended),686 .cmpxchg => try self.writeCmpxchg(stream, extended),
605 .ptr_cast_full => try self.writePtrCastFull(stream, extended),687 .ptr_cast_full => try self.writePtrCastFull(stream, extended),
606 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),688 .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),