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 /src/Sema.zig | |
| 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 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 91 |
1 files changed, 52 insertions, 39 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 756e0ac9ca..c8e2f2ae15 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -76,10 +76,6 @@ no_partial_func_ty: bool = false, /// here so the values can be dropped without any cleanup. unresolved_inferred_allocs: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{}, -/// While analyzing a type which has a special InternPool index, this is set to the index at which -/// the struct/enum/union type created should be placed. Otherwise, it is `.none`. -builtin_type_target_index: InternPool.Index = .none, - /// Links every pointer derived from a base `alloc` back to that `alloc`. Used /// to detect comptime-known `const`s. /// TODO: ZIR liveness analysis would allow us to remove elements from this map. @@ -1327,6 +1323,7 @@ fn analyzeBodyInner( }, .value_placeholder => unreachable, // never appears in a body .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), + .builtin_value => try sema.zirBuiltinValue(extended), }; }, @@ -2712,17 +2709,6 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us return captures; } -/// Given an `InternPool.WipNamespaceType` or `InternPool.WipEnumType`, apply -/// `sema.builtin_type_target_index` to it if necessary. -fn wrapWipTy(sema: *Sema, wip_ty: anytype) @TypeOf(wip_ty) { - const pt = sema.pt; - if (sema.builtin_type_target_index == .none) return wip_ty; - var new = wip_ty; - new.index = sema.builtin_type_target_index; - pt.zcu.intern_pool.resolveBuiltinType(pt.tid, new.index, wip_ty.index); - return new; -} - fn zirStructDecl( sema: *Sema, block: *Block, @@ -2788,7 +2774,7 @@ fn zirStructDecl( .captures = captures, } }, }; - const wip_ty = sema.wrapWipTy(switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) { + const wip_ty = switch (try ip.getStructType(gpa, pt.tid, struct_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty, false); @@ -2801,7 +2787,7 @@ fn zirStructDecl( return Air.internedToRef(new_ty); }, .wip => |wip| wip, - }); + }; errdefer wip_ty.cancel(ip, pt.tid); wip_ty.setName(ip, try sema.createTypeName( @@ -3017,7 +3003,7 @@ fn zirEnumDecl( .captures = captures, } }, }; - const wip_ty = sema.wrapWipTy(switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) { + const wip_ty = switch (try ip.getEnumType(gpa, pt.tid, enum_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty, false); @@ -3030,7 +3016,7 @@ fn zirEnumDecl( return Air.internedToRef(new_ty); }, .wip => |wip| wip, - }); + }; // Once this is `true`, we will not delete the decl or type even upon failure, since we // have finished constructing the type and are in the process of analyzing it. @@ -3161,7 +3147,7 @@ fn zirUnionDecl( .captures = captures, } }, }; - const wip_ty = sema.wrapWipTy(switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) { + const wip_ty = switch (try ip.getUnionType(gpa, pt.tid, union_init, false)) { .existing => |ty| { const new_ty = try pt.ensureTypeUpToDate(ty, false); @@ -3174,7 +3160,7 @@ fn zirUnionDecl( return Air.internedToRef(new_ty); }, .wip => |wip| wip, - }); + }; errdefer wip_ty.cancel(ip, pt.tid); wip_ty.setName(ip, try sema.createTypeName( @@ -3259,7 +3245,6 @@ fn zirOpaqueDecl( .captures = captures, } }, }; - // No `wrapWipTy` needed as no std.builtin types are opaque. const wip_ty = switch (try ip.getOpaqueType(gpa, pt.tid, opaque_init)) { .existing => |ty| { // Make sure we update the namespace if the declaration is re-analyzed, to pick @@ -26179,7 +26164,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A const body = sema.code.bodySlice(extra_index, body_len); extra_index += body.len; - const addrspace_ty = Type.fromInterned(.address_space_type); + const addrspace_ty = try pt.getBuiltinType("AddressSpace"); const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, .{ .needed_comptime_reason = "addrspace must be comptime-known", }); @@ -26190,7 +26175,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } else if (extra.data.bits.has_addrspace_ref) blk: { const addrspace_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; - const addrspace_ty = Type.fromInterned(.address_space_type); + const addrspace_ty = try pt.getBuiltinType("AddressSpace"); const uncoerced_addrspace = sema.resolveInst(addrspace_ref) catch |err| switch (err) { error.GenericPoison => break :blk null, else => |e| return e, @@ -26255,7 +26240,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } else if (extra.data.bits.has_cc_ref) blk: { const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; - const cc_ty = Type.fromInterned(.calling_convention_type); + const cc_ty = try pt.getBuiltinType("CallingConvention"); const uncoerced_cc = sema.resolveInst(cc_ref) catch |err| switch (err) { error.GenericPoison => break :blk null, else => |e| return e, @@ -26713,6 +26698,46 @@ fn zirInComptime( return if (block.is_comptime) .bool_true else .bool_false; } +fn zirBuiltinValue(sema: *Sema, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const value: Zir.Inst.BuiltinValue = @enumFromInt(extended.small); + const type_name = switch (value) { + .atomic_order => "AtomicOrder", + .atomic_rmw_op => "AtomicRmwOp", + .calling_convention => "CallingConvention", + .address_space => "AddressSpace", + .float_mode => "FloatMode", + .reduce_op => "ReduceOp", + .call_modifier => "CallModifier", + .prefetch_options => "PrefetchOptions", + .export_options => "ExportOptions", + .extern_options => "ExternOptions", + .type_info => "Type", + + // Values are handled here. + .calling_convention_c => { + const callconv_ty = try pt.getBuiltinType("CallingConvention"); + comptime assert(@intFromEnum(std.builtin.CallingConvention.C) == 1); + const val = try pt.intern(.{ .enum_tag = .{ + .ty = callconv_ty.toIntern(), + .int = .one_u8, + } }); + return Air.internedToRef(val); + }, + .calling_convention_inline => { + const callconv_ty = try pt.getBuiltinType("CallingConvention"); + comptime assert(@intFromEnum(std.builtin.CallingConvention.Inline) == 4); + const val = try pt.intern(.{ .enum_tag = .{ + .ty = callconv_ty.toIntern(), + .int = .four_u8, + } }); + return Air.internedToRef(val); + }, + }; + const ty = try pt.getBuiltinType(type_name); + return Air.internedToRef(ty.toIntern()); +} + fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src: ?LazySrcLoc) !void { if (block.is_comptime) { const msg = msg: { @@ -36899,17 +36924,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { .comptime_int_type, .comptime_float_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, @@ -36936,8 +36950,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { .one_u8, .four_u8, .negative_one, - .calling_convention_c, - .calling_convention_inline, .void_value, .unreachable_value, .null_value, @@ -37291,7 +37303,8 @@ pub fn analyzeAsAddressSpace( ) !std.builtin.AddressSpace { const pt = sema.pt; const mod = pt.zcu; - const coerced = try sema.coerce(block, Type.fromInterned(.address_space_type), air_ref, src); + const addrspace_ty = try pt.getBuiltinType("AddressSpace"); + const coerced = try sema.coerce(block, addrspace_ty, air_ref, src); const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{ .needed_comptime_reason = "address space must be comptime-known", }); |
