Commit de49a9a173

mlugg <mlugg@mlugg.co.uk>
2024-08-18 18:57:28
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.
1 parent a239d8d
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);
     }
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.
src/codegen/c/Type.zig
@@ -1389,21 +1389,6 @@ pub const Pool = struct {
             .anyframe_type,
             .generic_poison_type,
             => unreachable,
-            .atomic_order_type,
-            .atomic_rmw_op_type,
-            .calling_convention_type,
-            .address_space_type,
-            .float_mode_type,
-            .reduce_op_type,
-            .call_modifier_type,
-            => |ip_index| return pool.fromType(
-                allocator,
-                scratch,
-                Type.fromInterned(ip.loadEnumType(ip_index).tag_ty),
-                pt,
-                mod,
-                kind,
-            ),
             .anyerror_type,
             .anyerror_void_error_union_type,
             .adhoc_inferred_error_set_type,
@@ -1459,8 +1444,6 @@ pub const Pool = struct {
             .one_u8,
             .four_u8,
             .negative_one,
-            .calling_convention_c,
-            .calling_convention_inline,
             .void_value,
             .unreachable_value,
             .null_value,
@@ -1471,12 +1454,7 @@ pub const Pool = struct {
             .none,
             => unreachable,
 
-            //.prefetch_options_type,
-            //.export_options_type,
-            //.extern_options_type,
-            //.type_info_type,
-            //_,
-            else => |ip_index| switch (ip.indexToKey(ip_index)) {
+            _ => |ip_index| switch (ip.indexToKey(ip_index)) {
                 .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind),
                 .ptr_type => |ptr_info| switch (ptr_info.flags.size) {
                     .One, .Many, .C => {
src/codegen/llvm.zig
@@ -3194,8 +3194,6 @@ pub const Object = struct {
             .one_u8,
             .four_u8,
             .negative_one,
-            .calling_convention_c,
-            .calling_convention_inline,
             .void_value,
             .unreachable_value,
             .null_value,
src/link/Dwarf.zig
@@ -2565,19 +2565,7 @@ fn updateType(
                 try wip_nav.strp(if (type_index == .generic_poison_type) "anytype" else name);
             },
             .anyerror => return, // delay until flush
-            .atomic_order,
-            .atomic_rmw_op,
-            .calling_convention,
-            .address_space,
-            .float_mode,
-            .reduce_op,
-            .call_modifier,
-            .prefetch_options,
-            .export_options,
-            .extern_options,
-            .type_info,
-            .adhoc_inferred_error_set,
-            => unreachable,
+            .adhoc_inferred_error_set => unreachable,
         },
         .struct_type,
         .union_type,
src/Zcu/PerThread.zig
@@ -1102,12 +1102,9 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
     // We are about to re-analyze this `Cau`; drop its depenndencies.
     zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
 
-    const builtin_type_target_index: InternPool.Index = switch (cau.owner.unwrap()) {
-        .none => ip_index: {
-            // `comptime` decl -- we will re-analyze its body.
-            // This declaration has no value so is definitely not a std.builtin type.
-            break :ip_index .none;
-        },
+    switch (cau.owner.unwrap()) {
+        .none => {}, // `comptime` decl -- we will re-analyze its body.
+        .nav => {}, // Other decl -- we will re-analyze its value.
         .type => |ty| {
             // This is an incremental update, and this type is being re-analyzed because it is outdated.
             // Create a new type in its place, and mark the old one as outdated so that use sites will
@@ -1119,53 +1116,7 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
                 .invalidate_decl_ref = true,
             };
         },
-        .nav => |nav| ip_index: {
-            // Other decl -- we will re-analyze its value.
-            // This might be a type in `builtin.zig` -- check.
-            if (file.mod != zcu.std_mod) break :ip_index .none;
-            // We're in the std module.
-            const nav_name = ip.getNav(nav).name;
-            const std_file_imported = try pt.importPkg(zcu.std_mod);
-            const std_type = Type.fromInterned(zcu.fileRootType(std_file_imported.file_index));
-            const std_namespace = zcu.namespacePtr(std_type.getNamespace(zcu).unwrap().?);
-            const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
-            const builtin_nav = ip.getNav(std_namespace.pub_decls.getKeyAdapted(builtin_str, Zcu.Namespace.NameAdapter{ .zcu = zcu }) orelse break :ip_index .none);
-            const builtin_namespace = switch (builtin_nav.status) {
-                .unresolved => break :ip_index .none,
-                .resolved => |r| Type.fromInterned(r.val).getNamespace(zcu).unwrap().?,
-            };
-            if (cau.namespace != builtin_namespace) break :ip_index .none;
-            // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index.
-            for ([_][]const u8{
-                "AtomicOrder",
-                "AtomicRmwOp",
-                "CallingConvention",
-                "AddressSpace",
-                "FloatMode",
-                "ReduceOp",
-                "CallModifier",
-                "PrefetchOptions",
-                "ExportOptions",
-                "ExternOptions",
-                "Type",
-            }, [_]InternPool.Index{
-                .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,
-            }) |type_name, type_ip| {
-                if (nav_name.eqlSlice(type_name, ip)) break :ip_index type_ip;
-            }
-            break :ip_index .none;
-        },
-    };
+    }
 
     const is_usingnamespace = switch (cau.owner.unwrap()) {
         .nav => |nav| ip.getNav(nav).is_usingnamespace,
@@ -1194,7 +1145,6 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
         .fn_ret_ty = Type.void,
         .fn_ret_ty_ies = null,
         .comptime_err_ret_trace = &comptime_err_ret_trace,
-        .builtin_type_target_index = builtin_type_target_index,
     };
     defer sema.deinit();
 
@@ -1249,9 +1199,6 @@ fn semaCau(pt: Zcu.PerThread, cau_index: InternPool.Cau.Index) !SemaCauResult {
         .type => unreachable, // Handled at top of function.
     };
 
-    // We'll do more work with the Sema. Clear the target type index just in case we analyze any type.
-    sema.builtin_type_target_index = .none;
-
     const align_src = block.src(.{ .node_offset_var_decl_align = 0 });
     const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
     const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
@@ -3349,7 +3296,7 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat
                 break :o o;
             };
             if (!outdated) return ty;
-            return pt.recreateStructType(ty, key, struct_obj);
+            return pt.recreateStructType(key, struct_obj);
         },
         .union_type => |key| {
             const union_obj = ip.loadUnionType(ty);
@@ -3364,7 +3311,7 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat
                 break :o o;
             };
             if (!outdated) return ty;
-            return pt.recreateUnionType(ty, key, union_obj);
+            return pt.recreateUnionType(key, union_obj);
         },
         .enum_type => |key| {
             const enum_obj = ip.loadEnumType(ty);
@@ -3379,7 +3326,7 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat
                 break :o o;
             };
             if (!outdated) return ty;
-            return pt.recreateEnumType(ty, key, enum_obj);
+            return pt.recreateEnumType(key, enum_obj);
         },
         .opaque_type => {
             assert(!already_updating);
@@ -3391,7 +3338,6 @@ pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index, already_updat
 
 fn recreateStructType(
     pt: Zcu.PerThread,
-    ty: InternPool.Index,
     full_key: InternPool.Key.NamespaceType,
     struct_obj: InternPool.LoadedStructType,
 ) Zcu.SemaError!InternPool.Index {
@@ -3406,10 +3352,6 @@ fn recreateStructType(
         .declared => |d| d,
     };
 
-    if (@intFromEnum(ty) <= InternPool.static_len) {
-        @panic("TODO: recreate resolved builtin type");
-    }
-
     const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
     const file = zcu.fileByIndex(inst_info.file);
     if (file.status != .success_zir) return error.AnalysisFail;
@@ -3482,7 +3424,6 @@ fn recreateStructType(
 
 fn recreateUnionType(
     pt: Zcu.PerThread,
-    ty: InternPool.Index,
     full_key: InternPool.Key.NamespaceType,
     union_obj: InternPool.LoadedUnionType,
 ) Zcu.SemaError!InternPool.Index {
@@ -3497,10 +3438,6 @@ fn recreateUnionType(
         .declared => |d| d,
     };
 
-    if (@intFromEnum(ty) <= InternPool.static_len) {
-        @panic("TODO: recreate resolved builtin type");
-    }
-
     const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
     const file = zcu.fileByIndex(inst_info.file);
     if (file.status != .success_zir) return error.AnalysisFail;
@@ -3581,7 +3518,6 @@ fn recreateUnionType(
 
 fn recreateEnumType(
     pt: Zcu.PerThread,
-    ty: InternPool.Index,
     full_key: InternPool.Key.NamespaceType,
     enum_obj: InternPool.LoadedEnumType,
 ) Zcu.SemaError!InternPool.Index {
@@ -3596,10 +3532,6 @@ fn recreateEnumType(
         .declared => |d| d,
     };
 
-    if (@intFromEnum(ty) <= InternPool.static_len) {
-        @panic("TODO: recreate resolved builtin type");
-    }
-
     const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
     const file = zcu.fileByIndex(inst_info.file);
     if (file.status != .success_zir) return error.AnalysisFail;
src/Air.zig
@@ -938,17 +938,6 @@ pub const Inst = struct {
         null_type = @intFromEnum(InternPool.Index.null_type),
         undefined_type = @intFromEnum(InternPool.Index.undefined_type),
         enum_literal_type = @intFromEnum(InternPool.Index.enum_literal_type),
-        atomic_order_type = @intFromEnum(InternPool.Index.atomic_order_type),
-        atomic_rmw_op_type = @intFromEnum(InternPool.Index.atomic_rmw_op_type),
-        calling_convention_type = @intFromEnum(InternPool.Index.calling_convention_type),
-        address_space_type = @intFromEnum(InternPool.Index.address_space_type),
-        float_mode_type = @intFromEnum(InternPool.Index.float_mode_type),
-        reduce_op_type = @intFromEnum(InternPool.Index.reduce_op_type),
-        call_modifier_type = @intFromEnum(InternPool.Index.call_modifier_type),
-        prefetch_options_type = @intFromEnum(InternPool.Index.prefetch_options_type),
-        export_options_type = @intFromEnum(InternPool.Index.export_options_type),
-        extern_options_type = @intFromEnum(InternPool.Index.extern_options_type),
-        type_info_type = @intFromEnum(InternPool.Index.type_info_type),
         manyptr_u8_type = @intFromEnum(InternPool.Index.manyptr_u8_type),
         manyptr_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_u8_type),
         manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type),
@@ -969,8 +958,6 @@ pub const Inst = struct {
         one_u8 = @intFromEnum(InternPool.Index.one_u8),
         four_u8 = @intFromEnum(InternPool.Index.four_u8),
         negative_one = @intFromEnum(InternPool.Index.negative_one),
-        calling_convention_c = @intFromEnum(InternPool.Index.calling_convention_c),
-        calling_convention_inline = @intFromEnum(InternPool.Index.calling_convention_inline),
         void_value = @intFromEnum(InternPool.Index.void_value),
         unreachable_value = @intFromEnum(InternPool.Index.unreachable_value),
         null_value = @intFromEnum(InternPool.Index.null_value),
src/InternPool.zig
@@ -4411,17 +4411,6 @@ pub const Index = enum(u32) {
     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,
@@ -4454,10 +4443,6 @@ pub const Index = enum(u32) {
     four_u8,
     /// `-1` (comptime_int)
     negative_one,
-    /// `std.builtin.CallingConvention.C`
-    calling_convention_c,
-    /// `std.builtin.CallingConvention.Inline`
-    calling_convention_inline,
     /// `{}`
     void_value,
     /// `unreachable` (noreturn type)
@@ -4837,17 +4822,6 @@ pub const static_keys = [_]Key{
     .{ .simple_type = .null },
     .{ .simple_type = .undefined },
     .{ .simple_type = .enum_literal },
-    .{ .simple_type = .atomic_order },
-    .{ .simple_type = .atomic_rmw_op },
-    .{ .simple_type = .calling_convention },
-    .{ .simple_type = .address_space },
-    .{ .simple_type = .float_mode },
-    .{ .simple_type = .reduce_op },
-    .{ .simple_type = .call_modifier },
-    .{ .simple_type = .prefetch_options },
-    .{ .simple_type = .export_options },
-    .{ .simple_type = .extern_options },
-    .{ .simple_type = .type_info },
 
     // [*]u8
     .{ .ptr_type = .{
@@ -4876,7 +4850,7 @@ pub const static_keys = [_]Key{
         },
     } },
 
-    // comptime_int
+    // *const comptime_int
     .{ .ptr_type = .{
         .child = .comptime_int_type,
         .flags = .{
@@ -4967,16 +4941,6 @@ pub const static_keys = [_]Key{
         .ty = .comptime_int_type,
         .storage = .{ .i64 = -1 },
     } },
-    // calling_convention_c
-    .{ .enum_tag = .{
-        .ty = .calling_convention_type,
-        .int = .one_u8,
-    } },
-    // calling_convention_inline
-    .{ .enum_tag = .{
-        .ty = .calling_convention_type,
-        .int = .four_u8,
-    } },
 
     .{ .simple_value = .void },
     .{ .simple_value = .@"unreachable" },
@@ -5690,18 +5654,6 @@ pub const SimpleType = enum(u32) {
     undefined = @intFromEnum(Index.undefined_type),
     enum_literal = @intFromEnum(Index.enum_literal_type),
 
-    atomic_order = @intFromEnum(Index.atomic_order_type),
-    atomic_rmw_op = @intFromEnum(Index.atomic_rmw_op_type),
-    calling_convention = @intFromEnum(Index.calling_convention_type),
-    address_space = @intFromEnum(Index.address_space_type),
-    float_mode = @intFromEnum(Index.float_mode_type),
-    reduce_op = @intFromEnum(Index.reduce_op_type),
-    call_modifier = @intFromEnum(Index.call_modifier_type),
-    prefetch_options = @intFromEnum(Index.prefetch_options_type),
-    export_options = @intFromEnum(Index.export_options_type),
-    extern_options = @intFromEnum(Index.extern_options_type),
-    type_info = @intFromEnum(Index.type_info_type),
-
     adhoc_inferred_error_set = @intFromEnum(Index.adhoc_inferred_error_set_type),
     generic_poison = @intFromEnum(Index.generic_poison_type),
 };
@@ -6281,18 +6233,6 @@ pub fn init(ip: *InternPool, gpa: Allocator, available_threads: usize) !void {
         // Sanity check.
         assert(ip.indexToKey(.bool_true).simple_value == .true);
         assert(ip.indexToKey(.bool_false).simple_value == .false);
-
-        const cc_inline = ip.indexToKey(.calling_convention_inline).enum_tag.int;
-        const cc_c = ip.indexToKey(.calling_convention_c).enum_tag.int;
-
-        assert(ip.indexToKey(cc_inline).int.storage.u64 ==
-            @intFromEnum(std.builtin.CallingConvention.Inline));
-
-        assert(ip.indexToKey(cc_c).int.storage.u64 ==
-            @intFromEnum(std.builtin.CallingConvention.C));
-
-        assert(ip.indexToKey(ip.typeOf(cc_inline)).int_type.bits ==
-            @typeInfo(@typeInfo(std.builtin.CallingConvention).Enum.tag_type).Int.bits);
     }
 }
 
@@ -9743,14 +9683,6 @@ fn addMap(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, cap: usize) Al
 /// Invalidates all references to this index.
 pub fn remove(ip: *InternPool, tid: Zcu.PerThread.Id, index: Index) void {
     const unwrapped_index = index.unwrap(ip);
-    if (@intFromEnum(index) < static_keys.len) {
-        // The item being removed replaced a special index via `InternPool.resolveBuiltinType`.
-        // Restore the original item at this index.
-        assert(static_keys[@intFromEnum(index)] == .simple_type);
-        const items = ip.getLocalShared(unwrapped_index.tid).items.acquire().view();
-        @atomicStore(Tag, &items.items(.tag)[unwrapped_index.index], .simple_type, .unordered);
-        return;
-    }
 
     if (unwrapped_index.tid == tid) {
         const items_len = &ip.getLocal(unwrapped_index.tid).mutate.items.len;
@@ -10390,17 +10322,7 @@ pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {
 
 /// does not include .enum_literal_type
 pub fn isEnumType(ip: *const InternPool, ty: Index) bool {
-    return switch (ty) {
-        .atomic_order_type,
-        .atomic_rmw_op_type,
-        .calling_convention_type,
-        .address_space_type,
-        .float_mode_type,
-        .reduce_op_type,
-        .call_modifier_type,
-        => true,
-        else => ip.indexToKey(ty) == .enum_type,
-    };
+    return ip.indexToKey(ty) == .enum_type;
 }
 
 pub fn isUnion(ip: *const InternPool, ty: Index) bool {
@@ -11401,17 +11323,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
         .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,
@@ -11429,7 +11340,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
         .zero, .one, .negative_one => .comptime_int_type,
         .zero_usize, .one_usize => .usize_type,
         .zero_u8, .one_u8, .four_u8 => .u8_type,
-        .calling_convention_c, .calling_convention_inline => .calling_convention_type,
         .void_value => .void_type,
         .unreachable_value => .noreturn_type,
         .null_value => .null_type,
@@ -11725,22 +11635,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
         .undefined_type => .Undefined,
         .enum_literal_type => .EnumLiteral,
 
-        .atomic_order_type,
-        .atomic_rmw_op_type,
-        .calling_convention_type,
-        .address_space_type,
-        .float_mode_type,
-        .reduce_op_type,
-        .call_modifier_type,
-        => .Enum,
-
-        .prefetch_options_type,
-        .export_options_type,
-        .extern_options_type,
-        => .Struct,
-
-        .type_info_type => .Union,
-
         .manyptr_u8_type,
         .manyptr_const_u8_type,
         .manyptr_const_u8_sentinel_0_type,
@@ -11765,8 +11659,6 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
         .one_u8 => unreachable,
         .four_u8 => unreachable,
         .negative_one => unreachable,
-        .calling_convention_c => unreachable,
-        .calling_convention_inline => unreachable,
         .void_value => unreachable,
         .unreachable_value => unreachable,
         .null_value => unreachable,
@@ -12085,34 +11977,6 @@ pub fn unwrapCoercedFunc(ip: *const InternPool, index: Index) Index {
     };
 }
 
-/// Having resolved a builtin type to a real struct/union/enum (which is now at `resolverd_index`),
-/// make `want_index` refer to this type instead. This invalidates `resolved_index`, so must be
-/// called only when it is guaranteed that no reference to `resolved_index` exists.
-pub fn resolveBuiltinType(
-    ip: *InternPool,
-    tid: Zcu.PerThread.Id,
-    want_index: Index,
-    resolved_index: Index,
-) void {
-    assert(@intFromEnum(want_index) >= @intFromEnum(Index.first_type));
-    assert(@intFromEnum(want_index) <= @intFromEnum(Index.last_type));
-
-    // Make sure the type isn't already resolved!
-    assert(ip.indexToKey(want_index) == .simple_type);
-
-    // Make sure it's the same kind of type
-    assert((ip.zigTypeTagOrPoison(want_index) catch unreachable) ==
-        (ip.zigTypeTagOrPoison(resolved_index) catch unreachable));
-
-    // Copy the data
-    const item = resolved_index.unwrap(ip).getItem(ip);
-    const unwrapped_index = want_index.unwrap(ip);
-    var items = ip.getLocalShared(unwrapped_index.tid).items.acquire().view().slice();
-    items.items(.data)[unwrapped_index.index] = item.data;
-    @atomicStore(Tag, &items.items(.tag)[unwrapped_index.index], item.tag, .release);
-    ip.remove(tid, resolved_index);
-}
-
 pub fn anonStructFieldTypes(ip: *const InternPool, i: Index) []const Index {
     return ip.indexToKey(i).anon_struct_type.types;
 }
src/print_zir.zig
@@ -615,6 +615,7 @@ const Writer = struct {
             .restore_err_ret_index => try self.writeRestoreErrRetIndex(stream, extended),
             .closure_get => try self.writeClosureGet(stream, extended),
             .field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
+            .builtin_value => try self.writeBuiltinValue(stream, extended),
         }
     }
 
@@ -2782,6 +2783,12 @@ const Writer = struct {
         try self.writeSrcNode(stream, @bitCast(extended.operand));
     }
 
+    fn writeBuiltinValue(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
+        const val: Zir.Inst.BuiltinValue = @enumFromInt(extended.small);
+        try stream.print("{s})) ", .{@tagName(val)});
+        try self.writeSrcNode(stream, @bitCast(extended.operand));
+    }
+
     fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
         if (ref == .none) {
             return stream.writeAll(".none");
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",
     });
src/Type.zig
@@ -316,17 +316,6 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
             => try writer.print("@TypeOf({s})", .{@tagName(s)}),
 
             .enum_literal => try writer.print("@TypeOf(.{s})", .{@tagName(s)}),
-            .atomic_order => try writer.writeAll("std.builtin.AtomicOrder"),
-            .atomic_rmw_op => try writer.writeAll("std.builtin.AtomicRmwOp"),
-            .calling_convention => try writer.writeAll("std.builtin.CallingConvention"),
-            .address_space => try writer.writeAll("std.builtin.AddressSpace"),
-            .float_mode => try writer.writeAll("std.builtin.FloatMode"),
-            .reduce_op => try writer.writeAll("std.builtin.ReduceOp"),
-            .call_modifier => try writer.writeAll("std.builtin.CallModifier"),
-            .prefetch_options => try writer.writeAll("std.builtin.PrefetchOptions"),
-            .export_options => try writer.writeAll("std.builtin.ExportOptions"),
-            .extern_options => try writer.writeAll("std.builtin.ExternOptions"),
-            .type_info => try writer.writeAll("std.builtin.Type"),
 
             .generic_poison => unreachable,
         },
@@ -544,16 +533,6 @@ pub fn hasRuntimeBitsAdvanced(
                 .anyerror,
                 .adhoc_inferred_error_set,
                 .anyopaque,
-                .atomic_order,
-                .atomic_rmw_op,
-                .calling_convention,
-                .address_space,
-                .float_mode,
-                .reduce_op,
-                .call_modifier,
-                .prefetch_options,
-                .export_options,
-                .extern_options,
                 => true,
 
                 // These are false because they are comptime-only types.
@@ -565,7 +544,6 @@ pub fn hasRuntimeBitsAdvanced(
                 .null,
                 .undefined,
                 .enum_literal,
-                .type_info,
                 => false,
 
                 .generic_poison => unreachable,
@@ -711,16 +689,6 @@ pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
             .anyerror,
             .adhoc_inferred_error_set,
             .anyopaque,
-            .atomic_order,
-            .atomic_rmw_op,
-            .calling_convention,
-            .address_space,
-            .float_mode,
-            .reduce_op,
-            .call_modifier,
-            .prefetch_options,
-            .export_options,
-            .extern_options,
             .type,
             .comptime_int,
             .comptime_float,
@@ -728,7 +696,6 @@ pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
             .null,
             .undefined,
             .enum_literal,
-            .type_info,
             .generic_poison,
             => false,
         },
@@ -972,14 +939,6 @@ pub fn abiAlignmentAdvanced(
 
             .simple_type => |t| switch (t) {
                 .bool,
-                .atomic_order,
-                .atomic_rmw_op,
-                .calling_convention,
-                .address_space,
-                .float_mode,
-                .reduce_op,
-                .call_modifier,
-                .prefetch_options,
                 .anyopaque,
                 => return .{ .scalar = .@"1" },
 
@@ -987,11 +946,6 @@ pub fn abiAlignmentAdvanced(
                 .isize,
                 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
 
-                .export_options,
-                .extern_options,
-                .type_info,
-                => return .{ .scalar = ptrAbiAlignment(target) },
-
                 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
                 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
                 .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) },
@@ -1352,15 +1306,7 @@ pub fn abiSizeAdvanced(
             },
             .func_type => unreachable, // represents machine code; not a pointer
             .simple_type => |t| switch (t) {
-                .bool,
-                .atomic_order,
-                .atomic_rmw_op,
-                .calling_convention,
-                .address_space,
-                .float_mode,
-                .reduce_op,
-                .call_modifier,
-                => return .{ .scalar = 1 },
+                .bool => return .{ .scalar = 1 },
 
                 .f16 => return .{ .scalar = 2 },
                 .f32 => return .{ .scalar = 4 },
@@ -1402,11 +1348,6 @@ pub fn abiSizeAdvanced(
                     return .{ .scalar = intAbiSize(bits, target, use_llvm) };
                 },
 
-                .prefetch_options => unreachable, // missing call to resolveTypeFields
-                .export_options => unreachable, // missing call to resolveTypeFields
-                .extern_options => unreachable, // missing call to resolveTypeFields
-
-                .type_info => unreachable,
                 .noreturn => unreachable,
                 .generic_poison => unreachable,
             },
@@ -1751,18 +1692,6 @@ pub fn bitSizeAdvanced(
             .undefined => unreachable,
             .enum_literal => unreachable,
             .generic_poison => unreachable,
-
-            .atomic_order => unreachable,
-            .atomic_rmw_op => unreachable,
-            .calling_convention => unreachable,
-            .address_space => unreachable,
-            .float_mode => unreachable,
-            .reduce_op => unreachable,
-            .call_modifier => unreachable,
-            .prefetch_options => unreachable,
-            .export_options => unreachable,
-            .extern_options => unreachable,
-            .type_info => unreachable,
         },
         .struct_type => {
             const struct_type = ip.loadStructType(ty.toIntern());
@@ -2565,17 +2494,6 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
                 .comptime_int,
                 .comptime_float,
                 .enum_literal,
-                .atomic_order,
-                .atomic_rmw_op,
-                .calling_convention,
-                .address_space,
-                .float_mode,
-                .reduce_op,
-                .call_modifier,
-                .prefetch_options,
-                .export_options,
-                .extern_options,
-                .type_info,
                 .adhoc_inferred_error_set,
                 => return null,
 
@@ -2782,16 +2700,6 @@ pub fn comptimeOnlyAdvanced(ty: Type, pt: Zcu.PerThread, comptime strat: Resolve
                 .adhoc_inferred_error_set,
                 .noreturn,
                 .generic_poison,
-                .atomic_order,
-                .atomic_rmw_op,
-                .calling_convention,
-                .address_space,
-                .float_mode,
-                .reduce_op,
-                .call_modifier,
-                .prefetch_options,
-                .export_options,
-                .extern_options,
                 => false,
 
                 .type,
@@ -2800,7 +2708,6 @@ pub fn comptimeOnlyAdvanced(ty: Type, pt: Zcu.PerThread, comptime strat: Resolve
                 .null,
                 .undefined,
                 .enum_literal,
-                .type_info,
                 => true,
             },
             .struct_type => {
@@ -3534,10 +3441,6 @@ pub fn packedStructFieldPtrInfo(struct_ty: Type, parent_ptr_ty: Type, field_idx:
 pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
-    switch (ip.indexToKey(ty.toIntern())) {
-        .simple_type => |simple_type| return resolveSimpleType(simple_type, pt),
-        else => {},
-    }
     switch (ty.zigTypeTag(zcu)) {
         .Struct => switch (ip.indexToKey(ty.toIntern())) {
             .anon_struct_type => |anon_struct_type| for (0..anon_struct_type.types.len) |i| {
@@ -3651,8 +3554,6 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
         .one_u8 => unreachable,
         .four_u8 => unreachable,
         .negative_one => unreachable,
-        .calling_convention_c => unreachable,
-        .calling_convention_inline => unreachable,
         .void_value => unreachable,
         .unreachable_value => unreachable,
         .null_value => unreachable,
@@ -3669,8 +3570,6 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
 
             .type_union => return ty.resolveUnionInner(pt, .fields),
 
-            .simple_type => return resolveSimpleType(ip.indexToKey(ty_ip).simple_type, pt),
-
             else => {},
         },
     }
@@ -3680,11 +3579,6 @@ pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void {
     const zcu = pt.zcu;
     const ip = &zcu.intern_pool;
 
-    switch (ip.indexToKey(ty.toIntern())) {
-        .simple_type => |simple_type| return resolveSimpleType(simple_type, pt),
-        else => {},
-    }
-
     switch (ty.zigTypeTag(zcu)) {
         .Type,
         .Void,
@@ -3850,28 +3744,6 @@ fn resolveUnionInner(
     };
 }
 
-/// Fully resolves a simple type. This is usually a nop, but for builtin types with
-/// special InternPool indices (such as std.builtin.Type) it will analyze and fully
-/// resolve the type.
-fn resolveSimpleType(simple_type: InternPool.SimpleType, pt: Zcu.PerThread) Allocator.Error!void {
-    const builtin_type_name: []const u8 = switch (simple_type) {
-        .atomic_order => "AtomicOrder",
-        .atomic_rmw_op => "AtomicRmwOp",
-        .calling_convention => "CallingConvention",
-        .address_space => "AddressSpace",
-        .float_mode => "FloatMode",
-        .reduce_op => "ReduceOp",
-        .call_modifier => "CallModifer",
-        .prefetch_options => "PrefetchOptions",
-        .export_options => "ExportOptions",
-        .extern_options => "ExternOptions",
-        .type_info => "Type",
-        else => return,
-    };
-    // This will fully resolve the type.
-    _ = try pt.getBuiltinType(builtin_type_name);
-}
-
 /// Returns the type of a pointer to an element.
 /// Asserts that the type is a pointer, and that the element type is indexable.
 /// If the element index is comptime-known, it must be passed in `offset`.