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
This commit is contained in:
Matthew Lugg 2025-11-22 21:59:46 +00:00
parent 3f2cf1c002
commit c5383173a0
No known key found for this signature in database
GPG Key ID: 3F5B7DCCBF4AF02E
16 changed files with 2076 additions and 1471 deletions

View File

@ -638,7 +638,7 @@
{#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an {#syntax#}i7{#endsyntax#} refers to a signed 7-bit integer. The maximum allowed bit-width of an
integer type is {#syntax#}65535{#endsyntax#}. integer type is {#syntax#}65535{#endsyntax#}.
</p> </p>
{#see_also|Integers|Floats|void|Errors|@Type#} {#see_also|Integers|Floats|void|Errors|@Int#}
{#header_close#} {#header_close#}
{#header_open|Primitive Values#} {#header_open|Primitive Values#}
<div class="table-wrapper"> <div class="table-wrapper">
@ -3723,9 +3723,9 @@ void do_a_thing(struct Foo *foo) {
<td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td> <td>{#syntax#}x{#endsyntax#} is a {#syntax#}@FieldType(T, "a"){#endsyntax#}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{#syntax#}@Type(x){#endsyntax#}</th> <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
<td>-</td> <td>-</td>
<td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Type{#endsyntax#}</td> <td>{#syntax#}x{#endsyntax#} is a {#syntax#}std.builtin.Signedness{#endsyntax#}, {#syntax#}y{#endsyntax#} is a {#syntax#}u16{#endsyntax#}</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th> <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
@ -3839,9 +3839,9 @@ void do_a_thing(struct Foo *foo) {
<td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td> <td>{#syntax#}x{#endsyntax#} has no result location (typed initializers do not propagate result locations)</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{#syntax#}@Type(x){#endsyntax#}</th> <th scope="row">{#syntax#}@Int(x, y){#endsyntax#}</th>
<td>{#syntax#}ptr{#endsyntax#}</td> <td>-</td>
<td>{#syntax#}x{#endsyntax#} has no result location</td> <td>{#syntax#}x{#endsyntax#} and {#syntax#}y{#endsyntax#} do not have result locations</td>
</tr> </tr>
<tr> <tr>
<th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th> <th scope="row">{#syntax#}@typeInfo(x){#endsyntax#}</th>
@ -5755,41 +5755,75 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
</p> </p>
{#header_close#} {#header_close#}
{#header_open|@Type#} {#header_open|@EnumLiteral#}
<pre>{#syntax#}@Type(comptime info: std.builtin.Type) type{#endsyntax#}</pre> <pre>{#syntax#}@EnumLiteral() type{#endsyntax#}</pre>
<p> <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>
This function is the inverse of {#link|@typeInfo#}. It reifies type information
into a {#syntax#}type{#endsyntax#}.
</p>
<p>
It is available for the following types:
</p>
<ul>
<li>{#syntax#}type{#endsyntax#}</li>
<li>{#syntax#}noreturn{#endsyntax#}</li>
<li>{#syntax#}void{#endsyntax#}</li>
<li>{#syntax#}bool{#endsyntax#}</li>
<li>{#link|Integers#} - The maximum bit count for an integer type is {#syntax#}65535{#endsyntax#}.</li>
<li>{#link|Floats#}</li>
<li>{#link|Pointers#}</li>
<li>{#syntax#}comptime_int{#endsyntax#}</li>
<li>{#syntax#}comptime_float{#endsyntax#}</li>
<li>{#syntax#}@TypeOf(undefined){#endsyntax#}</li>
<li>{#syntax#}@TypeOf(null){#endsyntax#}</li>
<li>{#link|Arrays#}</li>
<li>{#link|Optionals#}</li>
<li>{#link|Error Set Type#}</li>
<li>{#link|Error Union Type#}</li>
<li>{#link|Vectors#}</li>
<li>{#link|opaque#}</li>
<li>{#syntax#}anyframe{#endsyntax#}</li>
<li>{#link|struct#}</li>
<li>{#link|enum#}</li>
<li>{#link|Enum Literals#}</li>
<li>{#link|union#}</li>
<li>{#link|Functions#}</li>
</ul>
{#header_close#} {#header_close#}
{#header_open|@Int#}
<pre>{#syntax#}@Int(comptime signedness: std.builtin.Signedness, comptime bits: u16) type{#endsyntax#}</pre>
<p>Returns an integer type with the given signedness and bit width.</p>
<p>For instance, {#syntax#}@Int(.unsigned, 18){#endsyntax#} returns the type {#syntax#}u18{#endsyntax#}.</p>
{#header_close#}
{#header_open|@Tuple#}
<pre>{#syntax#}@Tuple(comptime field_types: []const type) type{#endsyntax#}</pre>
<p>Returns a {#link|tuple|Tuples#} type with the given field types.</p>
{#header_close#}
{#header_open|@Pointer#}
<pre>{#syntax#}@Pointer(
comptime size: std.builtin.Type.Pointer.Size,
comptime attrs: std.builtin.Type.Pointer.Attributes,
comptime Element: type,
comptime sentinel: ?Element,
) type{#endsyntax#}</pre>
<p>Returns a {#link|pointer|Pointers#} type with the properties specified by the arguments.</p>
{#header_close#}
{#header_open|@Fn#}
<pre>{#syntax#}@Fn(
comptime param_types: []const type,
comptime param_attrs: *const [param_types.len]std.builtin.Type.Fn.Param.Attributes,
comptime ReturnType: type,
comptime attrs: std.builtin.Type.Fn.Attributes,
) type{#endsyntax#}</pre>
<p>Returns a {#link|function|Functions#} type with the properties specified by the arguments.</p>
{#header_close#}
{#header_open|@Struct#}
<pre>{#syntax#}@Struct(
comptime layout: std.builtin.Type.ContainerLayout,
comptime BackingInt: ?type,
comptime field_names: []const []const u8,
comptime field_types: *const [field_names.len]type,
comptime field_attrs: *const [field_names.len]std.builtin.Type.StructField.Attributes,
) type{#endsyntax#}</pre>
<p>Returns a {#link|struct#} type with the properties specified by the arguments.</p>
{#header_close#}
{#header_open|@Union#}
<pre>{#syntax#}@Union(
comptime layout: std.builtin.Type.ContainerLayout,
/// Either the integer tag type, or the integer backing type, depending on `layout`.
comptime ArgType: ?type,
comptime field_names: []const []const u8,
comptime field_types: *const [field_names.len]type,
comptime field_attrs: *const [field_names.len]std.builtin.Type.UnionField.Attributes,
) type{#endsyntax#}</pre>
<p>Returns a {#link|union#} type with the properties specified by the arguments.</p>
{#header_close#}
{#header_open|@Enum#}
<pre>{#syntax#}@Enum(
comptime TagInt: type,
comptime mode: std.builtin.Type.Enum.Mode,
comptime field_names: []const []const u8,
comptime field_values: *const [field_names.len]TagInt,
) type{#endsyntax#}</pre>
<p>Returns an {#link|enum#} type with the properties specified by the arguments.</p>
{#header_close#}
{#header_open|@typeInfo#} {#header_open|@typeInfo#}
<pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre> <pre>{#syntax#}@typeInfo(comptime T: type) std.builtin.Type{#endsyntax#}</pre>
<p> <p>

View File

@ -548,19 +548,19 @@ pub const TypeId = std.meta.Tag(Type);
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation. /// therefore must be kept in sync with the compiler implementation.
pub const Type = union(enum) { pub const Type = union(enum) {
type: void, type,
void: void, void,
bool: void, bool,
noreturn: void, noreturn,
int: Int, int: Int,
float: Float, float: Float,
pointer: Pointer, pointer: Pointer,
array: Array, array: Array,
@"struct": Struct, @"struct": Struct,
comptime_float: void, comptime_float,
comptime_int: void, comptime_int,
undefined: void, undefined,
null: void, null,
optional: Optional, optional: Optional,
error_union: ErrorUnion, error_union: ErrorUnion,
error_set: ErrorSet, error_set: ErrorSet,
@ -571,7 +571,7 @@ pub const Type = union(enum) {
frame: Frame, frame: Frame,
@"anyframe": AnyFrame, @"anyframe": AnyFrame,
vector: Vector, vector: Vector,
enum_literal: void, enum_literal,
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation. /// therefore must be kept in sync with the compiler implementation.
@ -619,6 +619,16 @@ pub const Type = union(enum) {
slice, slice,
c, c,
}; };
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"const": bool = false,
@"volatile": bool = false,
@"allowzero": bool = false,
@"addrspace": ?AddressSpace = null,
@"align": ?usize = null,
};
}; };
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
@ -668,6 +678,14 @@ pub const Type = union(enum) {
const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null)); const dp: *const sf.type = @ptrCast(@alignCast(sf.default_value_ptr orelse return null));
return dp.*; return dp.*;
} }
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"comptime": bool = false,
@"align": ?usize = null,
default_value_ptr: ?*const anyopaque = null,
};
}; };
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
@ -718,6 +736,10 @@ pub const Type = union(enum) {
fields: []const EnumField, fields: []const EnumField,
decls: []const Declaration, decls: []const Declaration,
is_exhaustive: bool, is_exhaustive: bool,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Mode = enum { exhaustive, nonexhaustive };
}; };
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
@ -726,6 +748,12 @@ pub const Type = union(enum) {
name: [:0]const u8, name: [:0]const u8,
type: type, type: type,
alignment: comptime_int, alignment: comptime_int,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"align": ?usize = null,
};
}; };
/// This data structure is used by the Zig language code generation and /// This data structure is used by the Zig language code generation and
@ -753,6 +781,19 @@ pub const Type = union(enum) {
is_generic: bool, is_generic: bool,
is_noalias: bool, is_noalias: bool,
type: ?type, type: ?type,
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"noalias": bool = false,
};
};
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
pub const Attributes = struct {
@"callconv": CallingConvention = .auto,
varargs: bool = false,
}; };
}; };

View File

@ -773,7 +773,6 @@ pub const EnvVar = enum {
pub const SimpleComptimeReason = enum(u32) { pub const SimpleComptimeReason = enum(u32) {
// Evaluating at comptime because a builtin operand must be comptime-known. // Evaluating at comptime because a builtin operand must be comptime-known.
// These messages all mention a specific builtin. // These messages all mention a specific builtin.
operand_Type,
operand_setEvalBranchQuota, operand_setEvalBranchQuota,
operand_setFloatMode, operand_setFloatMode,
operand_branchHint, operand_branchHint,
@ -809,25 +808,34 @@ pub const SimpleComptimeReason = enum(u32) {
// Evaluating at comptime because types must be comptime-known. // Evaluating at comptime because types must be comptime-known.
// Reasons other than `.type` are just more specific messages. // Reasons other than `.type` are just more specific messages.
type, type,
int_signedness,
int_bit_width,
array_sentinel, array_sentinel,
array_length,
pointer_size,
pointer_attrs,
pointer_sentinel, pointer_sentinel,
slice_sentinel, slice_sentinel,
array_length,
vector_length, vector_length,
error_set_contents, fn_ret_ty,
struct_fields, fn_param_types,
enum_fields, fn_param_attrs,
union_fields, fn_attrs,
function_ret_ty, struct_layout,
function_parameters, struct_field_names,
struct_field_types,
struct_field_attrs,
union_layout,
union_field_names,
union_field_types,
union_field_attrs,
tuple_field_types,
enum_field_names,
enum_field_values,
// Evaluating at comptime because decl/field name must be comptime-known. // Evaluating at comptime because decl/field name must be comptime-known.
decl_name, decl_name,
field_name, field_name,
struct_field_name,
enum_field_name,
union_field_name,
tuple_field_name,
tuple_field_index, tuple_field_index,
// Evaluating at comptime because it is an attribute of a global declaration. // Evaluating at comptime because it is an attribute of a global declaration.
@ -856,7 +864,6 @@ pub const SimpleComptimeReason = enum(u32) {
pub fn message(r: SimpleComptimeReason) []const u8 { pub fn message(r: SimpleComptimeReason) []const u8 {
return switch (r) { return switch (r) {
// zig fmt: off // zig fmt: off
.operand_Type => "operand to '@Type' must be comptime-known",
.operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known", .operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
.operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known", .operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
.operand_branchHint => "operand to '@branchHint' must be comptime-known", .operand_branchHint => "operand to '@branchHint' must be comptime-known",
@ -888,24 +895,33 @@ pub const SimpleComptimeReason = enum(u32) {
.clobber => "clobber must be comptime-known", .clobber => "clobber must be comptime-known",
.type => "types must be comptime-known", .type => "types must be comptime-known",
.int_signedness => "integer signedness must be comptime-known",
.int_bit_width => "integer bit width must be comptime-known",
.array_sentinel => "array sentinel value must be comptime-known", .array_sentinel => "array sentinel value must be comptime-known",
.array_length => "array length must be comptime-known",
.pointer_size => "pointer size must be comptime-known",
.pointer_attrs => "pointer attributes must be comptime-known",
.pointer_sentinel => "pointer sentinel value must be comptime-known", .pointer_sentinel => "pointer sentinel value must be comptime-known",
.slice_sentinel => "slice sentinel value must be comptime-known", .slice_sentinel => "slice sentinel value must be comptime-known",
.array_length => "array length must be comptime-known",
.vector_length => "vector length must be comptime-known", .vector_length => "vector length must be comptime-known",
.error_set_contents => "error set contents must be comptime-known", .fn_ret_ty => "function return type must be comptime-known",
.struct_fields => "struct fields must be comptime-known", .fn_param_types => "function parameter types must be comptime-known",
.enum_fields => "enum fields must be comptime-known", .fn_param_attrs => "function parameter attributes must be comptime-known",
.union_fields => "union fields must be comptime-known", .fn_attrs => "function attributes must be comptime-known",
.function_ret_ty => "function return type must be comptime-known", .struct_layout => "struct layout must be comptime-known",
.function_parameters => "function parameters must be comptime-known", .struct_field_names => "struct field names must be comptime-known",
.struct_field_types => "struct field types must be comptime-known",
.struct_field_attrs => "struct field attributes must be comptime-known",
.union_layout => "union layout must be comptime-known",
.union_field_names => "union field names must be comptime-known",
.union_field_types => "union field types must be comptime-known",
.union_field_attrs => "union field attributes must be comptime-known",
.tuple_field_types => "tuple field types must be comptime-known",
.enum_field_names => "enum field names must be comptime-known",
.enum_field_values => "enum field values must be comptime-known",
.decl_name => "declaration name must be comptime-known", .decl_name => "declaration name must be comptime-known",
.field_name => "field name must be comptime-known", .field_name => "field name must be comptime-known",
.struct_field_name => "struct field name must be comptime-known",
.enum_field_name => "enum field name must be comptime-known",
.union_field_name => "union field name must be comptime-known",
.tuple_field_name => "tuple field name must be comptime-known",
.tuple_field_index => "tuple field index must be comptime-known", .tuple_field_index => "tuple field index must be comptime-known",
.container_var_init => "initializer of container-level variable must be comptime-known", .container_var_init => "initializer of container-level variable must be comptime-known",

View File

@ -833,7 +833,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
=> { => {
var buf: [2]Ast.Node.Index = undefined; var buf: [2]Ast.Node.Index = undefined;
const params = tree.builtinCallParams(&buf, node).?; const params = tree.builtinCallParams(&buf, node).?;
return builtinCall(gz, scope, ri, node, params, false); return builtinCall(gz, scope, ri, node, params, false, .anon);
}, },
.call_one, .call_one,
@ -1194,14 +1194,20 @@ fn nameStratExpr(
}, },
.builtin_call_two, .builtin_call_two,
.builtin_call_two_comma, .builtin_call_two_comma,
.builtin_call,
.builtin_call_comma,
=> { => {
const builtin_token = tree.nodeMainToken(node); const builtin_token = tree.nodeMainToken(node);
const builtin_name = tree.tokenSlice(builtin_token); const builtin_name = tree.tokenSlice(builtin_token);
if (!std.mem.eql(u8, builtin_name, "@Type")) return null; const info = BuiltinFn.list.get(builtin_name) orelse return null;
var buf: [2]Ast.Node.Index = undefined; switch (info.tag) {
const params = tree.builtinCallParams(&buf, node).?; .Enum, .Struct, .Union => {
if (params.len != 1) return null; // let `builtinCall` error var buf: [2]Ast.Node.Index = undefined;
return try builtinReify(gz, scope, ri, node, params[0], name_strat); const params = tree.builtinCallParams(&buf, node).?;
return try builtinCall(gz, scope, ri, node, params, false, name_strat);
},
else => return null,
}
}, },
else => return null, else => return null,
} }
@ -1406,7 +1412,7 @@ fn fnProtoExprInner(
.none; .none;
const ret_ty_node = fn_proto.ast.return_type.unwrap().?; const ret_ty_node = fn_proto.ast.return_type.unwrap().?;
const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .function_ret_ty); const ret_ty = try comptimeExpr(&block_scope, scope, coerced_type_ri, ret_ty_node, .fn_ret_ty);
const result = try block_scope.addFunc(.{ const result = try block_scope.addFunc(.{
.src_node = fn_proto.ast.proto_node, .src_node = fn_proto.ast.proto_node,
@ -2629,7 +2635,7 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
const params = tree.builtinCallParams(&buf, inner_node).?; const params = tree.builtinCallParams(&buf, inner_node).?;
try emitDbgNode(gz, inner_node); try emitDbgNode(gz, inner_node);
const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint); const result = try builtinCall(gz, scope, .{ .rl = .none }, inner_node, params, allow_branch_hint, .anon);
noreturn_src_node = try addEnsureResult(gz, result, inner_node); noreturn_src_node = try addEnsureResult(gz, result, inner_node);
}, },
@ -2707,6 +2713,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
.elem_type, .elem_type,
.indexable_ptr_elem_type, .indexable_ptr_elem_type,
.splat_op_result_ty, .splat_op_result_ty,
.reify_int,
.vector_type, .vector_type,
.indexable_ptr_len, .indexable_ptr_len,
.anyframe_type, .anyframe_type,
@ -8942,7 +8949,7 @@ fn unionInit(
params: []const Ast.Node.Index, params: []const Ast.Node.Index,
) InnerError!Zir.Inst.Ref { ) InnerError!Zir.Inst.Ref {
const union_type = try typeExpr(gz, scope, params[0]); const union_type = try typeExpr(gz, scope, params[0]);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_name); const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_names);
const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{ const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
.container_type = union_type, .container_type = union_type,
.field_name = field_name, .field_name = field_name,
@ -9210,6 +9217,7 @@ fn builtinCall(
node: Ast.Node.Index, node: Ast.Node.Index,
params: []const Ast.Node.Index, params: []const Ast.Node.Index,
allow_branch_hint: bool, allow_branch_hint: bool,
reify_name_strat: Zir.Inst.NameStrategy,
) InnerError!Zir.Inst.Ref { ) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen; const astgen = gz.astgen;
const tree = astgen.tree; const tree = astgen.tree;
@ -9443,9 +9451,140 @@ fn builtinCall(
return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node); return rvalue(gz, ri, try gz.addNodeExtended(.in_comptime, node), node);
}, },
.Type => { .EnumLiteral => return rvalue(gz, ri, .enum_literal_type, node),
return builtinReify(gz, scope, ri, node, params[0], .anon); .Int => {
const signedness_ty = try gz.addBuiltinValue(node, .signedness);
const result = try gz.addPlNode(.reify_int, node, Zir.Inst.Bin{
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = signedness_ty } }, params[0], .int_signedness),
.rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u16_type } }, params[1], .int_bit_width),
});
return rvalue(gz, ri, result, node);
}, },
.Tuple => {
const result = try gz.addExtendedPayload(.reify_tuple, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .tuple_field_types),
});
return rvalue(gz, ri, result, node);
},
.Pointer => {
const ptr_size_ty = try gz.addBuiltinValue(node, .pointer_size);
const ptr_attrs_ty = try gz.addBuiltinValue(node, .pointer_attributes);
const size = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_size_ty } }, params[0], .pointer_size);
const attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = ptr_attrs_ty } }, params[1], .pointer_attrs);
const elem_ty = try typeExpr(gz, scope, params[2]);
const sentinel_ty = try gz.addExtendedPayload(.reify_pointer_sentinel_ty, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(params[2]),
.operand = elem_ty,
});
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = sentinel_ty } }, params[3], .pointer_sentinel);
const result = try gz.addExtendedPayload(.reify_pointer, Zir.Inst.ReifyPointer{
.node = gz.nodeIndexToRelative(node),
.size = size,
.attrs = attrs,
.elem_ty = elem_ty,
.sentinel = sentinel,
});
return rvalue(gz, ri, result, node);
},
.Fn => {
const fn_attrs_ty = try gz.addBuiltinValue(node, .fn_attributes);
const param_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_type_type } }, params[0], .fn_param_types);
const param_attrs_ty = try gz.addExtendedPayloadSmall(
.reify_slice_arg_ty,
@intFromEnum(Zir.Inst.ReifySliceArgInfo.type_to_fn_param_attrs),
Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[0]), .operand = param_types },
);
const param_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = param_attrs_ty } }, params[1], .fn_param_attrs);
const ret_ty = try comptimeExpr(gz, scope, coerced_type_ri, params[2], .fn_ret_ty);
const fn_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = fn_attrs_ty } }, params[3], .fn_attrs);
const result = try gz.addExtendedPayload(.reify_fn, Zir.Inst.ReifyFn{
.node = gz.nodeIndexToRelative(node),
.param_types = param_types,
.param_attrs = param_attrs,
.ret_ty = ret_ty,
.fn_attrs = fn_attrs,
});
return rvalue(gz, ri, result, node);
},
.Struct => {
const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .struct_layout);
const backing_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .struct_field_names);
const field_types_ty = try gz.addExtendedPayloadSmall(
.reify_slice_arg_ty,
@intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_type),
Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
);
const field_attrs_ty = try gz.addExtendedPayloadSmall(
.reify_slice_arg_ty,
@intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_struct_field_attrs),
Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
);
const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .struct_field_types);
const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .struct_field_attrs);
const result = try gz.addExtendedPayloadSmall(.reify_struct, @intFromEnum(reify_name_strat), Zir.Inst.ReifyStruct{
.src_line = gz.astgen.source_line,
.node = node,
.layout = layout,
.backing_ty = backing_ty,
.field_names = field_names,
.field_types = field_types,
.field_attrs = field_attrs,
});
return rvalue(gz, ri, result, node);
},
.Union => {
const container_layout_ty = try gz.addBuiltinValue(node, .container_layout);
const layout = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = container_layout_ty } }, params[0], .union_layout);
const arg_ty = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .optional_type_type } }, params[1], .type);
const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .union_field_names);
const field_types_ty = try gz.addExtendedPayloadSmall(
.reify_slice_arg_ty,
@intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_type),
Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
);
const field_attrs_ty = try gz.addExtendedPayloadSmall(
.reify_slice_arg_ty,
@intFromEnum(Zir.Inst.ReifySliceArgInfo.string_to_union_field_attrs),
Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(params[2]), .operand = field_names },
);
const field_types = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_types_ty } }, params[3], .union_field_types);
const field_attrs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_attrs_ty } }, params[4], .union_field_attrs);
const result = try gz.addExtendedPayloadSmall(.reify_union, @intFromEnum(reify_name_strat), Zir.Inst.ReifyUnion{
.src_line = gz.astgen.source_line,
.node = node,
.layout = layout,
.arg_ty = arg_ty,
.field_names = field_names,
.field_types = field_types,
.field_attrs = field_attrs,
});
return rvalue(gz, ri, result, node);
},
.Enum => {
const enum_mode_ty = try gz.addBuiltinValue(node, .enum_mode);
const tag_ty = try typeExpr(gz, scope, params[0]);
const mode = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = enum_mode_ty } }, params[1], .type);
const field_names = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_slice_const_u8_type } }, params[2], .enum_field_names);
const field_values_ty = try gz.addExtendedPayload(.reify_enum_value_slice_ty, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = tag_ty,
.rhs = field_names,
});
const field_values = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_values_ty } }, params[3], .enum_field_values);
const result = try gz.addExtendedPayloadSmall(.reify_enum, @intFromEnum(reify_name_strat), Zir.Inst.ReifyEnum{
.src_line = gz.astgen.source_line,
.node = node,
.tag_ty = tag_ty,
.mode = mode,
.field_names = field_names,
.field_values = field_values,
});
return rvalue(gz, ri, result, node);
},
.panic => { .panic => {
try emitDbgNode(gz, node); try emitDbgNode(gz, node);
return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic); return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic);
@ -9764,41 +9903,6 @@ fn builtinCall(
}, },
} }
} }
fn builtinReify(
gz: *GenZir,
scope: *Scope,
ri: ResultInfo,
node: Ast.Node.Index,
arg_node: Ast.Node.Index,
name_strat: Zir.Inst.NameStrategy,
) InnerError!Zir.Inst.Ref {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const type_info_ty = try gz.addBuiltinValue(node, .type_info);
const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = type_info_ty } }, arg_node);
try gz.instructions.ensureUnusedCapacity(gpa, 1);
try astgen.instructions.ensureUnusedCapacity(gpa, 1);
const payload_index = try astgen.addExtra(Zir.Inst.Reify{
.node = node, // Absolute node index -- see the definition of `Reify`.
.operand = operand,
.src_line = astgen.source_line,
});
const new_index: Zir.Inst.Index = @enumFromInt(astgen.instructions.len);
astgen.instructions.appendAssumeCapacity(.{
.tag = .extended,
.data = .{ .extended = .{
.opcode = .reify,
.small = @intFromEnum(name_strat),
.operand = payload_index,
} },
});
gz.instructions.appendAssumeCapacity(new_index);
const result = new_index.toRef();
return rvalue(gz, ri, result, node);
}
fn hasDeclOrField( fn hasDeclOrField(
gz: *GenZir, gz: *GenZir,

View File

@ -866,6 +866,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
// These builtins take no args and do not consume the result pointer. // These builtins take no args and do not consume the result pointer.
.src, .src,
.This, .This,
.EnumLiteral,
.return_address, .return_address,
.error_return_trace, .error_return_trace,
.frame, .frame,
@ -906,7 +907,7 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
.embed_file, .embed_file,
.error_name, .error_name,
.set_runtime_safety, .set_runtime_safety,
.Type, .Tuple,
.c_undef, .c_undef,
.c_include, .c_include,
.wasm_memory_size, .wasm_memory_size,
@ -1058,6 +1059,48 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.
_ = try astrl.expr(args[3], block, ResultInfo.none); _ = try astrl.expr(args[3], block, ResultInfo.none);
return false; return false;
}, },
.Int => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
return false;
},
.Pointer => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
_ = try astrl.expr(args[2], block, ResultInfo.type_only);
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
return false;
},
.Fn => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
_ = try astrl.expr(args[2], block, ResultInfo.type_only);
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
return false;
},
.Struct => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
_ = try astrl.expr(args[2], block, ResultInfo.type_only);
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
_ = try astrl.expr(args[4], block, ResultInfo.type_only);
return false;
},
.Union => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
_ = try astrl.expr(args[2], block, ResultInfo.type_only);
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
_ = try astrl.expr(args[4], block, ResultInfo.type_only);
return false;
},
.Enum => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only);
_ = try astrl.expr(args[2], block, ResultInfo.type_only);
_ = try astrl.expr(args[3], block, ResultInfo.type_only);
return false;
},
.Vector => { .Vector => {
_ = try astrl.expr(args[0], block, ResultInfo.type_only); _ = try astrl.expr(args[0], block, ResultInfo.type_only);
_ = try astrl.expr(args[1], block, ResultInfo.type_only); _ = try astrl.expr(args[1], block, ResultInfo.type_only);

View File

@ -110,7 +110,14 @@ pub const Tag = enum {
This, This,
trap, trap,
truncate, truncate,
Type, EnumLiteral,
Int,
Tuple,
Pointer,
Fn,
Struct,
Union,
Enum,
type_info, type_info,
type_name, type_name,
TypeOf, TypeOf,
@ -937,12 +944,61 @@ pub const list = list: {
}, },
}, },
.{ .{
"@Type", "@EnumLiteral",
.{ .{
.tag = .Type, .tag = .EnumLiteral,
.param_count = 0,
},
},
.{
"@Int",
.{
.tag = .Int,
.param_count = 2,
},
},
.{
"@Tuple",
.{
.tag = .Tuple,
.param_count = 1, .param_count = 1,
}, },
}, },
.{
"@Pointer",
.{
.tag = .Pointer,
.param_count = 4,
},
},
.{
"@Fn",
.{
.tag = .Fn,
.param_count = 4,
},
},
.{
"@Struct",
.{
.tag = .Struct,
.param_count = 5,
},
},
.{
"@Union",
.{
.tag = .Union,
.param_count = 5,
},
},
.{
"@Enum",
.{
.tag = .Enum,
.param_count = 4,
},
},
.{ .{
"@typeInfo", "@typeInfo",
.{ .{

View File

@ -260,6 +260,10 @@ pub const Inst = struct {
/// `[N:S]T` syntax. Source location is the array type expression node. /// `[N:S]T` syntax. Source location is the array type expression node.
/// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`. /// Uses the `pl_node` union field. Payload is `ArrayTypeSentinel`.
array_type_sentinel, array_type_sentinel,
/// `@Int` builtin.
/// Uses the `pl_node` union field with `Bin` payload.
/// lhs is signedness, rhs is bit count.
reify_int,
/// `@Vector` builtin. /// `@Vector` builtin.
/// Uses the `pl_node` union field with `Bin` payload. /// Uses the `pl_node` union field with `Bin` payload.
/// lhs is length, rhs is element type. /// lhs is length, rhs is element type.
@ -1112,6 +1116,7 @@ pub const Inst = struct {
.array_mul, .array_mul,
.array_type, .array_type,
.array_type_sentinel, .array_type_sentinel,
.reify_int,
.vector_type, .vector_type,
.elem_type, .elem_type,
.indexable_ptr_elem_type, .indexable_ptr_elem_type,
@ -1409,6 +1414,7 @@ pub const Inst = struct {
.array_mul, .array_mul,
.array_type, .array_type,
.array_type_sentinel, .array_type_sentinel,
.reify_int,
.vector_type, .vector_type,
.elem_type, .elem_type,
.indexable_ptr_elem_type, .indexable_ptr_elem_type,
@ -1644,6 +1650,7 @@ pub const Inst = struct {
.array_mul = .pl_node, .array_mul = .pl_node,
.array_type = .pl_node, .array_type = .pl_node,
.array_type_sentinel = .pl_node, .array_type_sentinel = .pl_node,
.reify_int = .pl_node,
.vector_type = .pl_node, .vector_type = .pl_node,
.elem_type = .un_node, .elem_type = .un_node,
.indexable_ptr_elem_type = .un_node, .indexable_ptr_elem_type = .un_node,
@ -2035,10 +2042,43 @@ pub const Inst = struct {
/// Implement builtin `@errorFromInt`. /// Implement builtin `@errorFromInt`.
/// `operand` is payload index to `UnNode`. /// `operand` is payload index to `UnNode`.
error_from_int, error_from_int,
/// Implement builtin `@Type`. /// Given a comptime-known operand of type `[]const A`, returns the type `*const [operand.len]B`.
/// `operand` is payload index to `Reify`. /// The types `A` and `B` are determined from `ReifySliceArgInfo`.
/// This instruction is used to provide result types to arguments of `@Fn`, `@Struct`, etc.
/// `operand` is payload index to `UnNode`.
/// `small` is a bitcast `ReifySliceArgInfo`.
reify_slice_arg_ty,
/// Like `reify_slice_arg_ty` for the specific case of `[]const []const u8` to `[]const TagInt`,
/// as needed for `@Enum`.
/// `operand` is payload index to `BinNode`. lhs is the type `TagInt`. rhs is the `[]const []const u8` value.
/// `small` is unused.
reify_enum_value_slice_ty,
/// Given a comptime-known operand of type `type`, returns the type `?operand` if possible, otherwise `?noreturn`.
/// Used for the final arg of `@Pointer` to allow reifying pointers to opaque types.
/// `operand` is payload index to `UnNode`.
/// `small` is unused.
reify_pointer_sentinel_ty,
/// Implements builtin `@Tuple`.
/// `operand` is payload index to `UnNode`.
reify_tuple,
/// Implements builtin `@Pointer`.
/// `operand` is payload index to `ReifyPointer`.
reify_pointer,
/// Implements builtin `@Fn`.
/// `operand` is payload index to `ReifyFn`.
reify_fn,
/// Implements builtin `@Struct`.
/// `operand` is payload index to `ReifyStruct`.
/// `small` contains `NameStrategy`. /// `small` contains `NameStrategy`.
reify, reify_struct,
/// Implements builtin `@Union`.
/// `operand` is payload index to `ReifyUnion`.
/// `small` contains `NameStrategy`.
reify_union,
/// Implements builtin `@Enum`.
/// `operand` is payload index to `ReifyEnum`.
/// `small` contains `NameStrategy`.
reify_enum,
/// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins. /// Implements the `@cmpxchgStrong` and `@cmpxchgWeak` builtins.
/// `small` 0=>weak 1=>strong /// `small` 0=>weak 1=>strong
/// `operand` is payload index to `Cmpxchg`. /// `operand` is payload index to `Cmpxchg`.
@ -2226,6 +2266,11 @@ pub const Inst = struct {
manyptr_const_u8_sentinel_0_type, manyptr_const_u8_sentinel_0_type,
slice_const_u8_type, slice_const_u8_type,
slice_const_u8_sentinel_0_type, slice_const_u8_sentinel_0_type,
manyptr_const_slice_const_u8_type,
slice_const_slice_const_u8_type,
optional_type_type,
manyptr_const_type_type,
slice_const_type_type,
vector_8_i8_type, vector_8_i8_type,
vector_16_i8_type, vector_16_i8_type,
vector_32_i8_type, vector_32_i8_type,
@ -3169,6 +3214,23 @@ pub const Inst = struct {
rhs: Ref, rhs: Ref,
}; };
pub const ReifySliceArgInfo = enum(u16) {
/// Input element type is `type`.
/// Output element type is `std.builtin.Type.Fn.Param.Attributes`.
type_to_fn_param_attrs,
/// Input element type is `[]const u8`.
/// Output element type is `type`.
string_to_struct_field_type,
/// Identical to `string_to_struct_field_type` aside from emitting slightly different error messages.
string_to_union_field_type,
/// Input element type is `[]const u8`.
/// Output element type is `std.builtin.Type.StructField.Attributes`.
string_to_struct_field_attrs,
/// Input element type is `[]const u8`.
/// Output element type is `std.builtin.Type.UnionField.Attributes`.
string_to_union_field_attrs,
};
pub const UnNode = struct { pub const UnNode = struct {
node: Ast.Node.Offset, node: Ast.Node.Offset,
operand: Ref, operand: Ref,
@ -3179,12 +3241,55 @@ pub const Inst = struct {
index: u32, index: u32,
}; };
pub const Reify = struct { pub const ReifyPointer = struct {
node: Ast.Node.Offset,
size: Ref,
attrs: Ref,
elem_ty: Ref,
sentinel: Ref,
};
pub const ReifyFn = struct {
node: Ast.Node.Offset,
param_types: Ref,
param_attrs: Ref,
ret_ty: Ref,
fn_attrs: Ref,
};
pub const ReifyStruct = struct {
src_line: u32,
/// This node is absolute, because `reify` instructions are tracked across updates, and /// This node is absolute, because `reify` instructions are tracked across updates, and
/// this simplifies the logic for getting source locations for types. /// this simplifies the logic for getting source locations for types.
node: Ast.Node.Index, node: Ast.Node.Index,
operand: Ref, layout: Ref,
backing_ty: Ref,
field_names: Ref,
field_types: Ref,
field_attrs: Ref,
};
pub const ReifyUnion = struct {
src_line: u32, src_line: u32,
/// This node is absolute, because `reify` instructions are tracked across updates, and
/// this simplifies the logic for getting source locations for types.
node: Ast.Node.Index,
layout: Ref,
arg_ty: Ref,
field_names: Ref,
field_types: Ref,
field_attrs: Ref,
};
pub const ReifyEnum = struct {
src_line: u32,
/// This node is absolute, because `reify` instructions are tracked across updates, and
/// this simplifies the logic for getting source locations for types.
node: Ast.Node.Index,
tag_ty: Ref,
mode: Ref,
field_names: Ref,
field_values: Ref,
}; };
/// Trailing: /// Trailing:
@ -3496,14 +3601,19 @@ pub const Inst = struct {
calling_convention, calling_convention,
address_space, address_space,
float_mode, float_mode,
signedness,
reduce_op, reduce_op,
call_modifier, call_modifier,
prefetch_options, prefetch_options,
export_options, export_options,
extern_options, extern_options,
type_info,
branch_hint, branch_hint,
clobbers, clobbers,
pointer_size,
pointer_attributes,
fn_attributes,
container_layout,
enum_mode,
// Values // Values
calling_convention_c, calling_convention_c,
calling_convention_inline, calling_convention_inline,
@ -4190,6 +4300,7 @@ fn findTrackableInner(
.array_mul, .array_mul,
.array_type, .array_type,
.array_type_sentinel, .array_type_sentinel,
.reify_int,
.vector_type, .vector_type,
.elem_type, .elem_type,
.indexable_ptr_elem_type, .indexable_ptr_elem_type,
@ -4432,6 +4543,12 @@ fn findTrackableInner(
.select, .select,
.int_from_error, .int_from_error,
.error_from_int, .error_from_int,
.reify_slice_arg_ty,
.reify_enum_value_slice_ty,
.reify_pointer_sentinel_ty,
.reify_tuple,
.reify_pointer,
.reify_fn,
.cmpxchg, .cmpxchg,
.c_va_arg, .c_va_arg,
.c_va_copy, .c_va_copy,
@ -4463,7 +4580,11 @@ fn findTrackableInner(
}, },
// Reifications and opaque declarations need tracking, but have no body. // Reifications and opaque declarations need tracking, but have no body.
.reify, .opaque_decl => return contents.other.append(gpa, inst), .reify_enum,
.reify_struct,
.reify_union,
.opaque_decl,
=> return contents.other.append(gpa, inst),
// Struct declarations need tracking and have bodies. // Struct declarations need tracking and have bodies.
.struct_decl => { .struct_decl => {
@ -5246,7 +5367,9 @@ pub fn assertTrackable(zir: Zir, inst_idx: Zir.Inst.Index) void {
.union_decl, .union_decl,
.enum_decl, .enum_decl,
.opaque_decl, .opaque_decl,
.reify, .reify_enum,
.reify_struct,
.reify_union,
=> {}, // tracked in order, as the owner instructions of explicit container types => {}, // tracked in order, as the owner instructions of explicit container types
else => unreachable, // assertion failure; not trackable else => unreachable, // assertion failure; not trackable
}, },

View File

@ -1062,6 +1062,11 @@ pub const Inst = struct {
manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type), manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type), slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type),
slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type),
manyptr_const_slice_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_slice_const_u8_type),
slice_const_slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_slice_const_u8_type),
optional_type_type = @intFromEnum(InternPool.Index.optional_type_type),
manyptr_const_type_type = @intFromEnum(InternPool.Index.manyptr_const_type_type),
slice_const_type_type = @intFromEnum(InternPool.Index.slice_const_type_type),
vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type), vector_8_i8_type = @intFromEnum(InternPool.Index.vector_8_i8_type),
vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type), vector_16_i8_type = @intFromEnum(InternPool.Index.vector_16_i8_type),
vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type), vector_32_i8_type = @intFromEnum(InternPool.Index.vector_32_i8_type),

View File

@ -2017,8 +2017,7 @@ pub const Key = union(enum) {
error_union_type: ErrorUnionType, error_union_type: ErrorUnionType,
simple_type: SimpleType, simple_type: SimpleType,
/// This represents a struct that has been explicitly declared in source code, /// This represents a struct that has been explicitly declared in source code,
/// or was created with `@Type`. It is unique and based on a declaration. /// or was created with `@Struct`. It is unique and based on a declaration.
/// It may be a tuple, if declared like this: `struct {A, B, C}`.
struct_type: NamespaceType, struct_type: NamespaceType,
/// This is a tuple type. Tuples are logically similar to structs, but have some /// This is a tuple type. Tuples are logically similar to structs, but have some
/// important differences in semantics; they do not undergo staged type resolution, /// important differences in semantics; they do not undergo staged type resolution,
@ -2175,7 +2174,7 @@ pub const Key = union(enum) {
/// The union for which this is a tag type. /// The union for which this is a tag type.
union_type: Index, union_type: Index,
}, },
/// This type originates from a reification via `@Type`, or from an anonymous initialization. /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization.
/// It is hashed based on its ZIR instruction index and fields, attributes, etc. /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
/// To avoid making this key overly complex, the type-specific data is hashed by Sema. /// To avoid making this key overly complex, the type-specific data is hashed by Sema.
reified: struct { reified: struct {
@ -4641,6 +4640,13 @@ pub const Index = enum(u32) {
slice_const_u8_type, slice_const_u8_type,
slice_const_u8_sentinel_0_type, slice_const_u8_sentinel_0_type,
manyptr_const_slice_const_u8_type,
slice_const_slice_const_u8_type,
optional_type_type,
manyptr_const_type_type,
slice_const_type_type,
vector_8_i8_type, vector_8_i8_type,
vector_16_i8_type, vector_16_i8_type,
vector_32_i8_type, vector_32_i8_type,
@ -5201,6 +5207,45 @@ pub const static_keys: [static_len]Key = .{
}, },
} }, } },
// [*]const []const u8
.{ .ptr_type = .{
.child = .slice_const_u8_type,
.flags = .{
.size = .many,
.is_const = true,
},
} },
// []const []const u8
.{ .ptr_type = .{
.child = .slice_const_u8_type,
.flags = .{
.size = .slice,
.is_const = true,
},
} },
// ?type
.{ .opt_type = .type_type },
// [*]const type
.{ .ptr_type = .{
.child = .type_type,
.flags = .{
.size = .many,
.is_const = true,
},
} },
// []const type
.{ .ptr_type = .{
.child = .type_type,
.flags = .{
.size = .slice,
.is_const = true,
},
} },
// @Vector(8, i8) // @Vector(8, i8)
.{ .vector_type = .{ .len = 8, .child = .i8_type } }, .{ .vector_type = .{ .len = 8, .child = .i8_type } },
// @Vector(16, i8) // @Vector(16, i8)
@ -10225,16 +10270,8 @@ pub fn getGeneratedTagEnumType(
} }
pub const OpaqueTypeInit = struct { pub const OpaqueTypeInit = struct {
key: union(enum) { zir_index: TrackedInst.Index,
declared: struct { captures: []const CaptureValue,
zir_index: TrackedInst.Index,
captures: []const CaptureValue,
},
reified: struct {
zir_index: TrackedInst.Index,
// No type hash since reifid opaques have no data other than the `@Type` location
},
},
}; };
pub fn getOpaqueType( pub fn getOpaqueType(
@ -10243,16 +10280,10 @@ pub fn getOpaqueType(
tid: Zcu.PerThread.Id, tid: Zcu.PerThread.Id,
ini: OpaqueTypeInit, ini: OpaqueTypeInit,
) Allocator.Error!WipNamespaceType.Result { ) Allocator.Error!WipNamespaceType.Result {
var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = switch (ini.key) { var gop = try ip.getOrPutKey(gpa, tid, .{ .opaque_type = .{ .declared = .{
.declared => |d| .{ .declared = .{ .zir_index = ini.zir_index,
.zir_index = d.zir_index, .captures = .{ .external = ini.captures },
.captures = .{ .external = d.captures }, } } });
} },
.reified => |r| .{ .reified = .{
.zir_index = r.zir_index,
.type_hash = 0,
} },
} });
defer gop.deinit(); defer gop.deinit();
if (gop == .existing) return .{ .existing = gop.existing }; if (gop == .existing) return .{ .existing = gop.existing };
@ -10261,30 +10292,19 @@ pub fn getOpaqueType(
const extra = local.getMutableExtra(gpa); const extra = local.getMutableExtra(gpa);
try items.ensureUnusedCapacity(1); try items.ensureUnusedCapacity(1);
try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + switch (ini.key) { try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
.declared => |d| d.captures.len,
.reified => 0,
});
const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{ const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
.name = undefined, // set by `finish` .name = undefined, // set by `finish`
.name_nav = undefined, // set by `finish` .name_nav = undefined, // set by `finish`
.namespace = undefined, // set by `finish` .namespace = undefined, // set by `finish`
.zir_index = switch (ini.key) { .zir_index = ini.zir_index,
inline else => |x| x.zir_index, .captures_len = @intCast(ini.captures.len),
},
.captures_len = switch (ini.key) {
.declared => |d| @intCast(d.captures.len),
.reified => std.math.maxInt(u32),
},
}); });
items.appendAssumeCapacity(.{ items.appendAssumeCapacity(.{
.tag = .type_opaque, .tag = .type_opaque,
.data = extra_index, .data = extra_index,
}); });
switch (ini.key) { extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
.declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
.reified => {},
}
return .{ return .{
.wip = .{ .wip = .{
.tid = tid, .tid = tid,
@ -10555,6 +10575,8 @@ pub fn slicePtrType(ip: *const InternPool, index: Index) Index {
switch (index) { switch (index) {
.slice_const_u8_type => return .manyptr_const_u8_type, .slice_const_u8_type => return .manyptr_const_u8_type,
.slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type, .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
.slice_const_slice_const_u8_type => return .manyptr_const_slice_const_u8_type,
.slice_const_type_type => return .manyptr_const_type_type,
else => {}, else => {},
} }
const item = index.unwrap(ip).getItem(ip); const item = index.unwrap(ip).getItem(ip);
@ -12013,8 +12035,13 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
.manyptr_u8_type, .manyptr_u8_type,
.manyptr_const_u8_type, .manyptr_const_u8_type,
.manyptr_const_u8_sentinel_0_type, .manyptr_const_u8_sentinel_0_type,
.manyptr_const_slice_const_u8_type,
.slice_const_u8_type, .slice_const_u8_type,
.slice_const_u8_sentinel_0_type, .slice_const_u8_sentinel_0_type,
.slice_const_slice_const_u8_type,
.optional_type_type,
.manyptr_const_type_type,
.slice_const_type_type,
.vector_8_i8_type, .vector_8_i8_type,
.vector_16_i8_type, .vector_16_i8_type,
.vector_32_i8_type, .vector_32_i8_type,
@ -12355,8 +12382,12 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
.manyptr_u8_type, .manyptr_u8_type,
.manyptr_const_u8_type, .manyptr_const_u8_type,
.manyptr_const_u8_sentinel_0_type, .manyptr_const_u8_sentinel_0_type,
.manyptr_const_slice_const_u8_type,
.slice_const_u8_type, .slice_const_u8_type,
.slice_const_u8_sentinel_0_type, .slice_const_u8_sentinel_0_type,
.slice_const_slice_const_u8_type,
.manyptr_const_type_type,
.slice_const_type_type,
=> .pointer, => .pointer,
.vector_8_i8_type, .vector_8_i8_type,
@ -12408,6 +12439,7 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
.vector_8_f64_type, .vector_8_f64_type,
=> .vector, => .vector,
.optional_type_type => .optional,
.optional_noreturn_type => .optional, .optional_noreturn_type => .optional,
.anyerror_void_error_union_type => .error_union, .anyerror_void_error_union_type => .error_union,
.empty_tuple_type => .@"struct", .empty_tuple_type => .@"struct",

File diff suppressed because it is too large Load Diff

View File

@ -317,7 +317,7 @@ pub fn print(ty: Type, writer: *std.Io.Writer, pt: Zcu.PerThread, ctx: ?*Compari
.undefined, .undefined,
=> try writer.print("@TypeOf({s})", .{@tagName(s)}), => try writer.print("@TypeOf({s})", .{@tagName(s)}),
.enum_literal => try writer.writeAll("@Type(.enum_literal)"), .enum_literal => try writer.writeAll("@EnumLiteral()"),
.generic_poison => unreachable, .generic_poison => unreachable,
}, },
@ -3509,7 +3509,9 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
.union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line, .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
.enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line, .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
.opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line, .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
.reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line, .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line,
.reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line,
.reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line,
else => unreachable, else => unreachable,
}, },
else => unreachable, else => unreachable,
@ -4280,6 +4282,10 @@ pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type };
pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type };
pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type };
pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type };
pub const optional_type: Type = .{ .ip_index = .optional_type_type };
pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type };
pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type }; pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type };
pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type }; pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type };

View File

@ -2824,6 +2824,29 @@ pub fn resolveLazy(
.val = resolved_val, .val = resolved_val,
})); }));
}, },
.error_union => |eu| switch (eu.val) {
.err_name => return val,
.payload => |payload| {
const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
if (resolved_payload.toIntern() == payload) return val;
return .fromInterned(try pt.intern(.{ .error_union = .{
.ty = eu.ty,
.val = .{ .payload = resolved_payload.toIntern() },
} }));
},
},
.opt => |opt| switch (opt.val) {
.none => return val,
else => |payload| {
const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
if (resolved_payload.toIntern() == payload) return val;
return .fromInterned(try pt.intern(.{ .opt = .{
.ty = opt.ty,
.val = resolved_payload.toIntern(),
} }));
},
},
else => return val, else => return val,
} }
} }

View File

@ -416,10 +416,13 @@ pub const BuiltinDecl = enum {
Type, Type,
@"Type.Fn", @"Type.Fn",
@"Type.Fn.Param", @"Type.Fn.Param",
@"Type.Fn.Param.Attributes",
@"Type.Fn.Attributes",
@"Type.Int", @"Type.Int",
@"Type.Float", @"Type.Float",
@"Type.Pointer", @"Type.Pointer",
@"Type.Pointer.Size", @"Type.Pointer.Size",
@"Type.Pointer.Attributes",
@"Type.Array", @"Type.Array",
@"Type.Vector", @"Type.Vector",
@"Type.Optional", @"Type.Optional",
@ -427,10 +430,13 @@ pub const BuiltinDecl = enum {
@"Type.ErrorUnion", @"Type.ErrorUnion",
@"Type.EnumField", @"Type.EnumField",
@"Type.Enum", @"Type.Enum",
@"Type.Enum.Mode",
@"Type.Union", @"Type.Union",
@"Type.UnionField", @"Type.UnionField",
@"Type.UnionField.Attributes",
@"Type.Struct", @"Type.Struct",
@"Type.StructField", @"Type.StructField",
@"Type.StructField.Attributes",
@"Type.ContainerLayout", @"Type.ContainerLayout",
@"Type.Opaque", @"Type.Opaque",
@"Type.Declaration", @"Type.Declaration",
@ -495,10 +501,13 @@ pub const BuiltinDecl = enum {
.Type, .Type,
.@"Type.Fn", .@"Type.Fn",
.@"Type.Fn.Param", .@"Type.Fn.Param",
.@"Type.Fn.Param.Attributes",
.@"Type.Fn.Attributes",
.@"Type.Int", .@"Type.Int",
.@"Type.Float", .@"Type.Float",
.@"Type.Pointer", .@"Type.Pointer",
.@"Type.Pointer.Size", .@"Type.Pointer.Size",
.@"Type.Pointer.Attributes",
.@"Type.Array", .@"Type.Array",
.@"Type.Vector", .@"Type.Vector",
.@"Type.Optional", .@"Type.Optional",
@ -506,10 +515,13 @@ pub const BuiltinDecl = enum {
.@"Type.ErrorUnion", .@"Type.ErrorUnion",
.@"Type.EnumField", .@"Type.EnumField",
.@"Type.Enum", .@"Type.Enum",
.@"Type.Enum.Mode",
.@"Type.Union", .@"Type.Union",
.@"Type.UnionField", .@"Type.UnionField",
.@"Type.UnionField.Attributes",
.@"Type.Struct", .@"Type.Struct",
.@"Type.StructField", .@"Type.StructField",
.@"Type.StructField.Attributes",
.@"Type.ContainerLayout", .@"Type.ContainerLayout",
.@"Type.Opaque", .@"Type.Opaque",
.@"Type.Declaration", .@"Type.Declaration",
@ -1745,28 +1757,28 @@ pub const SrcLoc = struct {
const node = node_off.toAbsolute(src_loc.base_node); const node = node_off.toAbsolute(src_loc.base_node);
var buf: [1]Ast.Node.Index = undefined; var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?; const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.align_expr.unwrap().?); return tree.nodeToSpan(full.ast.align_expr.unwrap() orelse node);
}, },
.node_offset_fn_type_addrspace => |node_off| { .node_offset_fn_type_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(zcu); const tree = try src_loc.file_scope.getTree(zcu);
const node = node_off.toAbsolute(src_loc.base_node); const node = node_off.toAbsolute(src_loc.base_node);
var buf: [1]Ast.Node.Index = undefined; var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?; const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.addrspace_expr.unwrap().?); return tree.nodeToSpan(full.ast.addrspace_expr.unwrap() orelse node);
}, },
.node_offset_fn_type_section => |node_off| { .node_offset_fn_type_section => |node_off| {
const tree = try src_loc.file_scope.getTree(zcu); const tree = try src_loc.file_scope.getTree(zcu);
const node = node_off.toAbsolute(src_loc.base_node); const node = node_off.toAbsolute(src_loc.base_node);
var buf: [1]Ast.Node.Index = undefined; var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?; const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.section_expr.unwrap().?); return tree.nodeToSpan(full.ast.section_expr.unwrap() orelse node);
}, },
.node_offset_fn_type_cc => |node_off| { .node_offset_fn_type_cc => |node_off| {
const tree = try src_loc.file_scope.getTree(zcu); const tree = try src_loc.file_scope.getTree(zcu);
const node = node_off.toAbsolute(src_loc.base_node); const node = node_off.toAbsolute(src_loc.base_node);
var buf: [1]Ast.Node.Index = undefined; var buf: [1]Ast.Node.Index = undefined;
const full = tree.fullFnProto(&buf, node).?; const full = tree.fullFnProto(&buf, node).?;
return tree.nodeToSpan(full.ast.callconv_expr.unwrap().?); return tree.nodeToSpan(full.ast.callconv_expr.unwrap() orelse node);
}, },
.node_offset_fn_type_ret_ty => |node_off| { .node_offset_fn_type_ret_ty => |node_off| {
@ -2684,7 +2696,9 @@ pub const LazySrcLoc = struct {
.union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node, .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
.enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node, .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,
.opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node, .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,
.reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.node, .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node,
.reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node,
.reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node,
else => unreachable, else => unreachable,
}, },
else => unreachable, else => unreachable,

View File

@ -1416,6 +1416,9 @@ pub const Pool = struct {
.null_type, .null_type,
.undefined_type, .undefined_type,
.enum_literal_type, .enum_literal_type,
.optional_type_type,
.manyptr_const_type_type,
.slice_const_type_type,
=> return .void, => return .void,
.u1_type, .u8_type => return .u8, .u1_type, .u8_type => return .u8,
.i8_type => return .i8, .i8_type => return .i8,
@ -1525,6 +1528,73 @@ pub const Pool = struct {
return pool.fromFields(allocator, .@"struct", &fields, kind); return pool.fromFields(allocator, .@"struct", &fields, kind);
}, },
.manyptr_const_slice_const_u8_type => {
const target = &mod.resolved_target.result;
var fields: [2]Info.Field = .{
.{
.name = .{ .index = .ptr },
.ctype = try pool.getPointer(allocator, .{
.elem_ctype = .u8,
.@"const" = true,
.nonstring = true,
}),
.alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
},
.{
.name = .{ .index = .len },
.ctype = .usize,
.alignas = AlignAs.fromAbiAlignment(
.fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
),
},
};
const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, kind);
return pool.getPointer(allocator, .{
.elem_ctype = slice_const_u8,
.@"const" = true,
});
},
.slice_const_slice_const_u8_type => {
const target = &mod.resolved_target.result;
var fields: [2]Info.Field = .{
.{
.name = .{ .index = .ptr },
.ctype = try pool.getPointer(allocator, .{
.elem_ctype = .u8,
.@"const" = true,
.nonstring = true,
}),
.alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
},
.{
.name = .{ .index = .len },
.ctype = .usize,
.alignas = AlignAs.fromAbiAlignment(
.fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
),
},
};
const slice_const_u8 = try pool.fromFields(allocator, .@"struct", &fields, .forward);
fields = .{
.{
.name = .{ .index = .ptr },
.ctype = try pool.getPointer(allocator, .{
.elem_ctype = slice_const_u8,
.@"const" = true,
}),
.alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target)),
},
.{
.name = .{ .index = .len },
.ctype = .usize,
.alignas = AlignAs.fromAbiAlignment(
.fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
),
},
};
return pool.fromFields(allocator, .@"struct", &fields, kind);
},
.vector_8_i8_type => { .vector_8_i8_type => {
const vector_ctype = try pool.getVector(allocator, .{ const vector_ctype = try pool.getVector(allocator, .{
.elem_ctype = .i8, .elem_ctype = .i8,

View File

@ -4490,7 +4490,12 @@ fn updateContainerTypeWriterError(
.enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
.union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
.opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy, .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
.reify => @as(Zir.Inst.NameStrategy, @enumFromInt(decl_inst.data.extended.small)),
.reify_enum,
.reify_struct,
.reify_union,
=> @enumFromInt(decl_inst.data.extended.small),
else => unreachable, else => unreachable,
}, },
else => unreachable, else => unreachable,

View File

@ -399,6 +399,7 @@ const Writer = struct {
.splat, .splat,
.reduce, .reduce,
.bitcast, .bitcast,
.reify_int,
.vector_type, .vector_type,
.max, .max,
.min, .min,
@ -568,6 +569,8 @@ const Writer = struct {
.work_group_id, .work_group_id,
.branch_hint, .branch_hint,
.float_op_result_ty, .float_op_result_ty,
.reify_tuple,
.reify_pointer_sentinel_ty,
=> { => {
const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data; const inst_data = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
try self.writeInstRef(stream, inst_data.operand); try self.writeInstRef(stream, inst_data.operand);
@ -575,23 +578,13 @@ const Writer = struct {
try self.writeSrcNode(stream, inst_data.node); try self.writeSrcNode(stream, inst_data.node);
}, },
.reify => {
const inst_data = self.code.extraData(Zir.Inst.Reify, extended.operand).data;
try stream.print("line({d}), ", .{inst_data.src_line});
try self.writeInstRef(stream, inst_data.operand);
try stream.writeAll(")) ");
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = inst_data.node;
defer self.parent_decl_node = prev_parent_decl_node;
try self.writeSrcNode(stream, .zero);
},
.builtin_extern, .builtin_extern,
.c_define, .c_define,
.error_cast, .error_cast,
.wasm_memory_grow, .wasm_memory_grow,
.prefetch, .prefetch,
.c_va_arg, .c_va_arg,
.reify_enum_value_slice_ty,
=> { => {
const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data; const inst_data = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
try self.writeInstRef(stream, inst_data.lhs); try self.writeInstRef(stream, inst_data.lhs);
@ -601,6 +594,95 @@ const Writer = struct {
try self.writeSrcNode(stream, inst_data.node); try self.writeSrcNode(stream, inst_data.node);
}, },
.reify_slice_arg_ty => {
const reify_slice_arg_info: Zir.Inst.ReifySliceArgInfo = @enumFromInt(extended.operand);
const extra = self.code.extraData(Zir.Inst.UnNode, extended.operand).data;
try stream.print("{t}, ", .{reify_slice_arg_info});
try self.writeInstRef(stream, extra.operand);
try stream.writeAll(")) ");
try self.writeSrcNode(stream, extra.node);
},
.reify_pointer => {
const extra = self.code.extraData(Zir.Inst.ReifyPointer, extended.operand).data;
try self.writeInstRef(stream, extra.size);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.attrs);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.elem_ty);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.sentinel);
try stream.writeAll(")) ");
try self.writeSrcNode(stream, extra.node);
},
.reify_fn => {
const extra = self.code.extraData(Zir.Inst.ReifyFn, extended.operand).data;
try self.writeInstRef(stream, extra.param_types);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.param_attrs);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.ret_ty);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.fn_attrs);
try stream.writeAll(")) ");
try self.writeSrcNode(stream, extra.node);
},
.reify_struct => {
const extra = self.code.extraData(Zir.Inst.ReifyStruct, extended.operand).data;
const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
try self.writeInstRef(stream, extra.layout);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.backing_ty);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_names);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_types);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_attrs);
try stream.writeAll(")) ");
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.node;
defer self.parent_decl_node = prev_parent_decl_node;
try self.writeSrcNode(stream, .zero);
},
.reify_union => {
const extra = self.code.extraData(Zir.Inst.ReifyUnion, extended.operand).data;
const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
try self.writeInstRef(stream, extra.layout);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.arg_ty);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_names);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_types);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_attrs);
try stream.writeAll(")) ");
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.node;
defer self.parent_decl_node = prev_parent_decl_node;
try self.writeSrcNode(stream, .zero);
},
.reify_enum => {
const extra = self.code.extraData(Zir.Inst.ReifyEnum, extended.operand).data;
const name_strat: Zir.Inst.NameStrategy = @enumFromInt(extended.small);
try stream.print("line({d}), {t}, ", .{ extra.src_line, name_strat });
try self.writeInstRef(stream, extra.tag_ty);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.mode);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_names);
try stream.writeAll(", ");
try self.writeInstRef(stream, extra.field_values);
try stream.writeAll(")) ");
const prev_parent_decl_node = self.parent_decl_node;
self.parent_decl_node = extra.node;
defer self.parent_decl_node = prev_parent_decl_node;
try self.writeSrcNode(stream, .zero);
},
.cmpxchg => try self.writeCmpxchg(stream, extended), .cmpxchg => try self.writeCmpxchg(stream, extended),
.ptr_cast_full => try self.writePtrCastFull(stream, extended), .ptr_cast_full => try self.writePtrCastFull(stream, extended),
.ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended), .ptr_cast_no_dest => try self.writePtrCastNoDest(stream, extended),