diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-08-18 17:57:28 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-08-18 18:10:59 +0100 |
| commit | de49a9a17352a36a0888b03905f207b0584fc269 (patch) | |
| tree | ebda829424b7df833084bc0f8275815d42a6eeec /lib/std | |
| parent | a239d8d4e2c0e5a7f3eb4b9973f869afdb3bbe05 (diff) | |
| download | zig-de49a9a17352a36a0888b03905f207b0584fc269.tar.gz zig-de49a9a17352a36a0888b03905f207b0584fc269.zip | |
Zir: add instructions to fetch std.builtin types
This replaces the constant `Zir.Inst.Ref` tags (and the analagous tags
in `Air.Inst.Ref`, `InternPool.Index`) referring to types in
`std.builtin` with a ZIR instruction `extended(builtin_type(...))` which
instructs Sema to fetch such a type, effectively as if it were a
shorthand for the ZIR for `@import("std").builtin.xyz`.
Previously, this was achieved through constant tags in `Ref`. The
analagous `InternPool` indices began as `simple_type` values, and were
later rewritten to the correct type information. This system was kind of
brittle, and more importantly, isn't compatible with incremental
compilation of std, since incremental compilation relies on the ability
to recreate types at different indices when they change. Replacing the
old system with this instruction slightly increases the size of ZIR, but
it simplifies logic and allows incremental compilation to work correctly
on the standard library.
This shouldn't have a significant impact on ZIR size or compiler
performance, but I will take measurements in the PR to confirm this.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/AstGen.zig | 103 | ||||
| -rw-r--r-- | lib/std/zig/Zir.zig | 38 |
2 files changed, 81 insertions, 60 deletions
diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index d73c83bb41..d0f1c73fc8 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -366,7 +366,6 @@ const ResultInfo = struct { }; const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; -const coerced_addrspace_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .address_space_type } }; const coerced_linksection_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }; const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } }; const coerced_bool_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .bool_type } }; @@ -1387,7 +1386,7 @@ fn fnProtoExpr( try expr( &block_scope, scope, - .{ .rl = .{ .coerced_ty = .calling_convention_type } }, + .{ .rl = .{ .coerced_ty = try block_scope.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, fn_proto.ast.callconv_expr, ) else @@ -3804,7 +3803,8 @@ fn ptrType( gz.astgen.source_line = source_line; gz.astgen.source_column = source_column; - addrspace_ref = try expr(gz, scope, coerced_addrspace_ri, ptr_info.ast.addrspace_node); + const addrspace_ty = try gz.addBuiltinValue(ptr_info.ast.addrspace_node, .address_space); + addrspace_ref = try expr(gz, scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, ptr_info.ast.addrspace_node); trailing_count += 1; } if (ptr_info.ast.align_node != 0) { @@ -4202,7 +4202,8 @@ fn fnDecl( var addrspace_gz = decl_gz.makeSubBlock(params_scope); defer addrspace_gz.unstack(); const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, coerced_addrspace_ri, fn_proto.ast.addrspace_expr); + const addrspace_ty = try decl_gz.addBuiltinValue(fn_proto.ast.addrspace_expr, .address_space); + const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = addrspace_ty } }, fn_proto.ast.addrspace_expr); if (addrspace_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -4235,9 +4236,9 @@ fn fnDecl( ); } const inst = try expr( - &decl_gz, + &cc_gz, params_scope, - .{ .rl = .{ .coerced_ty = .calling_convention_type } }, + .{ .rl = .{ .coerced_ty = try cc_gz.addBuiltinValue(fn_proto.ast.callconv_expr, .calling_convention) } }, fn_proto.ast.callconv_expr, ); if (cc_gz.instructionsSlice().len == 0) { @@ -4247,10 +4248,13 @@ fn fnDecl( _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst); break :blk inst; } else if (is_extern) { - // note: https://github.com/ziglang/zig/issues/5269 - break :blk .calling_convention_c; + const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_c); + _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst); + break :blk inst; } else if (has_inline_keyword) { - break :blk .calling_convention_inline; + const inst = try cc_gz.addBuiltinValue(decl_node, .calling_convention_inline); + _ = try cc_gz.addBreak(.break_inline, @enumFromInt(0), inst); + break :blk inst; } else { break :blk .none; } @@ -4525,7 +4529,8 @@ fn globalVarDecl( var addrspace_gz = linksection_gz.makeSubBlock(scope); if (var_decl.ast.addrspace_node != 0) { - const addrspace_inst = try fullBodyExpr(&addrspace_gz, &addrspace_gz.base, coerced_addrspace_ri, var_decl.ast.addrspace_node); + const addrspace_ty = try addrspace_gz.addBuiltinValue(var_decl.ast.addrspace_node, .address_space); + const addrspace_inst = try fullBodyExpr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, var_decl.ast.addrspace_node); _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node); } @@ -9169,6 +9174,7 @@ fn builtinCall( // zig fmt: on .@"export" => { + const export_options_ty = try gz.addBuiltinValue(node, .export_options); const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); // This function causes a Decl to be exported. The first parameter is not an expression, @@ -9192,7 +9198,7 @@ fn builtinCall( local_val.used = ident_token; _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ .operand = local_val.inst, - .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), + .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1]), }); return rvalue(gz, ri, .void_value, node); } @@ -9207,7 +9213,7 @@ fn builtinCall( const loaded = try gz.addUnNode(.load, local_ptr.ptr, node); _ = try gz.addPlNode(.export_value, node, Zir.Inst.ExportValue{ .operand = loaded, - .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]), + .options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1]), }); return rvalue(gz, ri, .void_value, node); } @@ -9245,7 +9251,7 @@ fn builtinCall( }, else => return astgen.failNode(params[0], "symbol to export must identify a declaration", .{}), } - const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .export_options_type } }, params[1]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1]); _ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{ .namespace = namespace, .decl_name = decl_name, @@ -9255,7 +9261,8 @@ fn builtinCall( }, .@"extern" => { const type_inst = try typeExpr(gz, scope, params[0]); - const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .extern_options_type } }, params[1]); + const extern_options_ty = try gz.addBuiltinValue(node, .extern_options); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = extern_options_ty } }, params[1]); const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = type_inst, @@ -9264,7 +9271,8 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .fence => { - const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[0]); + const atomic_order_ty = try gz.addBuiltinValue(node, .atomic_order); + const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_ty } }, params[0]); _ = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, @@ -9272,7 +9280,8 @@ fn builtinCall( return rvalue(gz, ri, .void_value, node); }, .set_float_mode => { - const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .float_mode_type } }, params[0]); + const float_mode_ty = try gz.addBuiltinValue(node, .float_mode); + const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_mode_ty } }, params[0]); _ = try gz.addExtendedPayload(.set_float_mode, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, @@ -9365,7 +9374,8 @@ fn builtinCall( }, .Type => { - const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .type_info_type } }, params[0]); + const type_info_ty = try gz.addBuiltinValue(node, .type_info); + const operand = try expr(gz, scope, .{ .rl = .{ .coerced_ty = type_info_ty } }, params[0]); const gpa = gz.astgen.gpa; @@ -9502,7 +9512,8 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .reduce => { - const op = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .reduce_op_type } }, params[0]); + const reduce_op_ty = try gz.addBuiltinValue(node, .reduce_op); + const op = try expr(gz, scope, .{ .rl = .{ .coerced_ty = reduce_op_ty } }, params[0]); const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{ .lhs = op, @@ -9517,34 +9528,38 @@ fn builtinCall( .shl_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .shl_with_overflow), .atomic_load => { + const atomic_order_type = try gz.addBuiltinValue(node, .atomic_order); const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{ // zig fmt: off - .elem_type = try typeExpr(gz, scope, params[0]), - .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]), - .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[2]), + .elem_type = try typeExpr(gz, scope, params[0]), + .ptr = try expr (gz, scope, .{ .rl = .none }, params[1]), + .ordering = try expr (gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_type } }, params[2]), // zig fmt: on }); return rvalue(gz, ri, result, node); }, .atomic_rmw => { + const atomic_order_type = try gz.addBuiltinValue(node, .atomic_order); + const atomic_rmw_op_type = try gz.addBuiltinValue(node, .atomic_rmw_op); const int_type = try typeExpr(gz, scope, params[0]); const result = try gz.addPlNode(.atomic_rmw, node, Zir.Inst.AtomicRmw{ // zig fmt: off - .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), - .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_rmw_op_type } }, params[2]), - .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]), - .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .operation = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_rmw_op_type } }, params[2]), + .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[3]), + .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_type } }, params[4]), // zig fmt: on }); return rvalue(gz, ri, result, node); }, .atomic_store => { + const atomic_order_type = try gz.addBuiltinValue(node, .atomic_order); const int_type = try typeExpr(gz, scope, params[0]); _ = try gz.addPlNode(.atomic_store, node, Zir.Inst.AtomicStore{ // zig fmt: off - .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), - .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), - .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[3]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .operand = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), + .ordering = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_type } }, params[3]), // zig fmt: on }); return rvalue(gz, ri, .void_value, node); @@ -9562,7 +9577,8 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .call => { - const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .call_modifier_type } }, params[0]); + const call_modifier_ty = try gz.addBuiltinValue(node, .call_modifier); + const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = call_modifier_ty } }, params[0]); const callee = try expr(gz, scope, .{ .rl = .none }, params[1]); const args = try expr(gz, scope, .{ .rl = .none }, params[2]); const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{ @@ -9641,8 +9657,9 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .prefetch => { + const prefetch_options_ty = try gz.addBuiltinValue(node, .prefetch_options); const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]); - const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .prefetch_options_type } }, params[1]); + const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = prefetch_options_ty } }, params[1]); _ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), .lhs = ptr, @@ -9812,14 +9829,15 @@ fn cmpxchg( small: u16, ) InnerError!Zir.Inst.Ref { const int_type = try typeExpr(gz, scope, params[0]); + const atomic_order_type = try gz.addBuiltinValue(node, .atomic_order); const result = try gz.addExtendedPayloadSmall(.cmpxchg, small, Zir.Inst.Cmpxchg{ // zig fmt: off .node = gz.nodeIndexToRelative(node), - .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), - .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), - .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]), - .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[4]), - .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .atomic_order_type } }, params[5]), + .ptr = try expr(gz, scope, .{ .rl = .none }, params[1]), + .expected_value = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]), + .new_value = try expr(gz, scope, .{ .rl = .{ .coerced_ty = int_type } }, params[3]), + .success_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_type } }, params[4]), + .failure_order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_type } }, params[5]), // zig fmt: on }); return rvalue(gz, ri, result, node); @@ -11106,17 +11124,6 @@ fn rvalueInner( as_ty | @intFromEnum(Zir.Inst.Ref.null_type), as_ty | @intFromEnum(Zir.Inst.Ref.undefined_type), as_ty | @intFromEnum(Zir.Inst.Ref.enum_literal_type), - as_ty | @intFromEnum(Zir.Inst.Ref.atomic_order_type), - as_ty | @intFromEnum(Zir.Inst.Ref.atomic_rmw_op_type), - as_ty | @intFromEnum(Zir.Inst.Ref.calling_convention_type), - as_ty | @intFromEnum(Zir.Inst.Ref.address_space_type), - as_ty | @intFromEnum(Zir.Inst.Ref.float_mode_type), - as_ty | @intFromEnum(Zir.Inst.Ref.reduce_op_type), - as_ty | @intFromEnum(Zir.Inst.Ref.call_modifier_type), - as_ty | @intFromEnum(Zir.Inst.Ref.prefetch_options_type), - as_ty | @intFromEnum(Zir.Inst.Ref.export_options_type), - as_ty | @intFromEnum(Zir.Inst.Ref.extern_options_type), - as_ty | @intFromEnum(Zir.Inst.Ref.type_info_type), as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_u8_type), as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_type), as_ty | @intFromEnum(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type), @@ -12572,6 +12579,10 @@ const GenZir = struct { return new_index; } + fn addBuiltinValue(gz: *GenZir, src_node: Ast.Node.Index, val: Zir.Inst.BuiltinValue) !Zir.Inst.Ref { + return addExtendedNodeSmall(gz, .builtin_value, src_node, @intFromEnum(val)); + } + fn addExtendedPayload(gz: *GenZir, opcode: Zir.Inst.Extended, extra: anytype) !Zir.Inst.Ref { return addExtendedPayloadSmall(gz, opcode, undefined, extra); } diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 7349677a22..8318a5a345 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2055,6 +2055,10 @@ pub const Inst = struct { /// Guaranteed to not have the `ptr_cast` flag. /// Uses the `pl_node` union field with payload `FieldParentPtr`. field_parent_ptr, + /// Get a type or value from `std.builtin`. + /// `operand` is `src_node: i32`. + /// `small` is an `Inst.BuiltinValue`. + builtin_value, pub const InstData = struct { opcode: Extended, @@ -2071,7 +2075,7 @@ pub const Inst = struct { ref_start_index = static_len, _, - pub const static_len = 84; + pub const static_len = 71; pub fn toRef(i: Index) Inst.Ref { return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i)); @@ -2148,17 +2152,6 @@ pub const Inst = struct { null_type, undefined_type, enum_literal_type, - atomic_order_type, - atomic_rmw_op_type, - calling_convention_type, - address_space_type, - float_mode_type, - reduce_op_type, - call_modifier_type, - prefetch_options_type, - export_options_type, - extern_options_type, - type_info_type, manyptr_u8_type, manyptr_const_u8_type, manyptr_const_u8_sentinel_0_type, @@ -2179,8 +2172,6 @@ pub const Inst = struct { one_u8, four_u8, negative_one, - calling_convention_c, - calling_convention_inline, void_value, unreachable_value, null_value, @@ -3146,6 +3137,24 @@ pub const Inst = struct { } }; + pub const BuiltinValue = enum(u16) { + // Types + atomic_order, + atomic_rmw_op, + calling_convention, + address_space, + float_mode, + reduce_op, + call_modifier, + prefetch_options, + export_options, + extern_options, + type_info, + // Values + calling_convention_c, + calling_convention_inline, + }; + /// Trailing: /// 0. tag_type: Ref, // if has_tag_type /// 1. captures_len: u32, // if has_captures_len @@ -3977,6 +3986,7 @@ fn findDeclsInner( .restore_err_ret_index, .closure_get, .field_parent_ptr, + .builtin_value, => return, // `@TypeOf` has a body. |
