authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-01-15 14:01:15+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2026-03-10 10:26:07+00:00
log510ea6f61f93c722c4cb2c2b39605201cc2f9c32
tree476e4e20e0f9a872c13033c800212f7540eb06f5
parent5e8397d5e03269d8a39efb22605ea20102848084
signaturelock-open Commit is signed but in an unrecognized format.

type resolution progress


29 files changed, 7266 insertions(+), 11278 deletions(-)

lib/std/math/big/int.zig+12-2
......@@ -924,7 +924,12 @@ pub const Mutable = struct {
924924 /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by
925925 /// r is `calcTwosCompLimbCount(bit_count)`.
926926 pub fn bitReverse(r: *Mutable, a: Const, signedness: Signedness, bit_count: usize) void {
927 if (bit_count == 0) return;
927 if (bit_count == 0) {
928 r.limbs[0] = 0;
929 r.len = 1;
930 r.positive = true;
931 return;
932 }
928933
929934 r.copy(a);
930935
......@@ -986,7 +991,12 @@ pub const Mutable = struct {
986991 /// Asserts the result fits in `r`. Upper bound on the number of limbs needed by
987992 /// r is `calcTwosCompLimbCount(8*byte_count)`.
988993 pub fn byteSwap(r: *Mutable, a: Const, signedness: Signedness, byte_count: usize) void {
989 if (byte_count == 0) return;
994 if (byte_count == 0) {
995 r.limbs[0] = 0;
996 r.len = 1;
997 r.positive = true;
998 return;
999 }
9901000
9911001 r.copy(a);
9921002 const limbs_required = calcTwosCompLimbCount(8 * byte_count);
lib/std/zig/Zir.zig+1-15
......@@ -3710,7 +3710,7 @@ pub const Inst = struct {
37103710 };
37113711 }
37123712
3713 pub fn layout(k: Kind) std.builtin.ContainerLayout {
3713 pub fn layout(k: Kind) std.builtin.Type.ContainerLayout {
37143714 return switch (k) {
37153715 .auto, .tagged_explicit, .tagged_enum, .tagged_enum_explicit => .auto,
37163716 .@"extern" => .@"extern",
......@@ -4008,20 +4008,6 @@ pub const Inst = struct {
40084008 };
40094009};
40104010
4011/// MLUGG TODO: delete this!
4012pub const DeclIterator = struct {
4013 decls: []const Inst.Index,
4014 index: usize,
4015 pub fn next(it: *DeclIterator) ?Inst.Index {
4016 if (it.index == it.decls.len) return null;
4017 defer it.index += 1;
4018 return it.decls[it.index];
4019 }
4020};
4021pub fn declIterator(zir: Zir, decl_inst: Zir.Inst.Index) DeclIterator {
4022 return .{ .decls = zir.typeDecls(decl_inst), .index = 0 };
4023}
4024
40254011/// `DeclContents` contains all "interesting" instructions found within a declaration by `findTrackable`.
40264012/// These instructions are partitioned into a few different sets, since this makes ZIR instruction mapping
40274013/// more effective.
lib/std/zig/target.zig+2-4
......@@ -503,8 +503,7 @@ pub fn intByteSize(target: *const std.Target, bits: u16) u16 {
503503pub fn intAlignment(target: *const std.Target, bits: u16) u16 {
504504 return switch (target.cpu.arch) {
505505 .x86 => switch (bits) {
506 0 => 0,
507 1...8 => 1,
506 0...8 => 1,
508507 9...16 => 2,
509508 17...32 => 4,
510509 33...64 => switch (target.os.tag) {
......@@ -514,8 +513,7 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 {
514513 else => 16,
515514 },
516515 .x86_64 => switch (bits) {
517 0 => 0,
518 1...8 => 1,
516 0...8 => 1,
519517 9...16 => 2,
520518 17...32 => 4,
521519 33...64 => 8,
src/Air.zig+5-8
......@@ -14,7 +14,6 @@ const Type = @import("Type.zig");
1414const Value = @import("Value.zig");
1515const Zcu = @import("Zcu.zig");
1616const print = @import("Air/print.zig");
17const types_resolved = @import("Air/types_resolved.zig");
1817
1918pub const Legalize = @import("Air/Legalize.zig");
2019pub const Liveness = @import("Air/Liveness.zig");
......@@ -173,8 +172,8 @@ pub const Inst = struct {
173172 /// outside the provenance of the operand, the result is undefined.
174173 ///
175174 /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer,
176 /// rhs is the offset. Result type is the same as lhs. The operand may
177 /// be a slice.
175 /// rhs is the offset. Result type is the same as lhs. The operand type's
176 /// pointer size may be `.slice`, `.many`, or `.c`.
178177 ptr_add,
179178 /// Subtract an offset, in element type units, from a pointer,
180179 /// returning a new pointer. Element type may not be zero bits.
......@@ -183,8 +182,8 @@ pub const Inst = struct {
183182 /// outside the provenance of the operand, the result is undefined.
184183 ///
185184 /// Uses the `ty_pl` field. Payload is `Bin`. The lhs is the pointer,
186 /// rhs is the offset. Result type is the same as lhs. The operand may
187 /// be a slice.
185 /// rhs is the offset. Result type is the same as lhs. The operand type's
186 /// pointer size may be `.slice`, `.many`, or `.c`.
188187 ptr_sub,
189188 /// Given two operands which can be floats, integers, or vectors, returns the
190189 /// greater of the operands. For vectors it operates element-wise.
......@@ -693,6 +692,7 @@ pub const Inst = struct {
693692 /// Uses the `ty_pl` field with payload `Bin`.
694693 slice_elem_ptr,
695694 /// Given a pointer value, and element index, return the element value at that index.
695 /// The pointer size is either `.c` or `.many`.
696696 /// Result type is the element type of the pointer operand.
697697 /// Uses the `bin_op` field.
698698 ptr_elem_val,
......@@ -2440,9 +2440,6 @@ pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index
24402440 };
24412441}
24422442
2443pub const typesFullyResolved = types_resolved.typesFullyResolved;
2444pub const typeFullyResolved = types_resolved.checkType;
2445pub const valFullyResolved = types_resolved.checkVal;
24462443pub const legalize = Legalize.legalize;
24472444pub const write = print.write;
24482445pub const writeInst = print.writeInst;
src/Air/types_resolved.zig deleted-536
......@@ -1,536 +0,0 @@
1const Air = @import("../Air.zig");
2const Zcu = @import("../Zcu.zig");
3const Type = @import("../Type.zig");
4const Value = @import("../Value.zig");
5const InternPool = @import("../InternPool.zig");
6
7/// Given a body of AIR instructions, returns whether all type resolution necessary for codegen is complete.
8/// If `false`, then type resolution must have failed, so codegen cannot proceed.
9pub fn typesFullyResolved(air: Air, zcu: *Zcu) bool {
10 return checkBody(air, air.getMainBody(), zcu);
11}
12
13fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
14 const tags = air.instructions.items(.tag);
15 const datas = air.instructions.items(.data);
16
17 for (body) |inst| {
18 const data = datas[@intFromEnum(inst)];
19 switch (tags[@intFromEnum(inst)]) {
20 .inferred_alloc, .inferred_alloc_comptime => unreachable,
21
22 .arg => {
23 if (!checkType(data.arg.ty.toType(), zcu)) return false;
24 },
25
26 .add,
27 .add_safe,
28 .add_optimized,
29 .add_wrap,
30 .add_sat,
31 .sub,
32 .sub_safe,
33 .sub_optimized,
34 .sub_wrap,
35 .sub_sat,
36 .mul,
37 .mul_safe,
38 .mul_optimized,
39 .mul_wrap,
40 .mul_sat,
41 .div_float,
42 .div_float_optimized,
43 .div_trunc,
44 .div_trunc_optimized,
45 .div_floor,
46 .div_floor_optimized,
47 .div_exact,
48 .div_exact_optimized,
49 .rem,
50 .rem_optimized,
51 .mod,
52 .mod_optimized,
53 .max,
54 .min,
55 .bit_and,
56 .bit_or,
57 .shr,
58 .shr_exact,
59 .shl,
60 .shl_exact,
61 .shl_sat,
62 .xor,
63 .cmp_lt,
64 .cmp_lt_optimized,
65 .cmp_lte,
66 .cmp_lte_optimized,
67 .cmp_eq,
68 .cmp_eq_optimized,
69 .cmp_gte,
70 .cmp_gte_optimized,
71 .cmp_gt,
72 .cmp_gt_optimized,
73 .cmp_neq,
74 .cmp_neq_optimized,
75 .bool_and,
76 .bool_or,
77 .store,
78 .store_safe,
79 .set_union_tag,
80 .array_elem_val,
81 .slice_elem_val,
82 .ptr_elem_val,
83 .memset,
84 .memset_safe,
85 .memcpy,
86 .memmove,
87 .atomic_store_unordered,
88 .atomic_store_monotonic,
89 .atomic_store_release,
90 .atomic_store_seq_cst,
91 .legalize_vec_elem_val,
92 => {
93 if (!checkRef(data.bin_op.lhs, zcu)) return false;
94 if (!checkRef(data.bin_op.rhs, zcu)) return false;
95 },
96
97 .not,
98 .bitcast,
99 .clz,
100 .ctz,
101 .popcount,
102 .byte_swap,
103 .bit_reverse,
104 .abs,
105 .load,
106 .fptrunc,
107 .fpext,
108 .intcast,
109 .intcast_safe,
110 .trunc,
111 .optional_payload,
112 .optional_payload_ptr,
113 .optional_payload_ptr_set,
114 .wrap_optional,
115 .unwrap_errunion_payload,
116 .unwrap_errunion_err,
117 .unwrap_errunion_payload_ptr,
118 .unwrap_errunion_err_ptr,
119 .errunion_payload_ptr_set,
120 .wrap_errunion_payload,
121 .wrap_errunion_err,
122 .struct_field_ptr_index_0,
123 .struct_field_ptr_index_1,
124 .struct_field_ptr_index_2,
125 .struct_field_ptr_index_3,
126 .get_union_tag,
127 .slice_len,
128 .slice_ptr,
129 .ptr_slice_len_ptr,
130 .ptr_slice_ptr_ptr,
131 .array_to_slice,
132 .int_from_float,
133 .int_from_float_optimized,
134 .int_from_float_safe,
135 .int_from_float_optimized_safe,
136 .float_from_int,
137 .splat,
138 .error_set_has_value,
139 .addrspace_cast,
140 .c_va_arg,
141 .c_va_copy,
142 => {
143 if (!checkType(data.ty_op.ty.toType(), zcu)) return false;
144 if (!checkRef(data.ty_op.operand, zcu)) return false;
145 },
146
147 .alloc,
148 .ret_ptr,
149 .c_va_start,
150 => {
151 if (!checkType(data.ty, zcu)) return false;
152 },
153
154 .ptr_add,
155 .ptr_sub,
156 .add_with_overflow,
157 .sub_with_overflow,
158 .mul_with_overflow,
159 .shl_with_overflow,
160 .slice,
161 .slice_elem_ptr,
162 .ptr_elem_ptr,
163 => {
164 const bin = air.extraData(Air.Bin, data.ty_pl.payload).data;
165 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
166 if (!checkRef(bin.lhs, zcu)) return false;
167 if (!checkRef(bin.rhs, zcu)) return false;
168 },
169
170 .block,
171 .loop,
172 => {
173 const block = air.unwrapBlock(inst);
174 if (!checkType(block.ty, zcu)) return false;
175 if (!checkBody(
176 air,
177 block.body,
178 zcu,
179 )) return false;
180 },
181
182 .dbg_inline_block => {
183 const block = air.unwrapDbgBlock(inst);
184 if (!checkType(block.ty, zcu)) return false;
185 if (!checkBody(
186 air,
187 block.body,
188 zcu,
189 )) return false;
190 },
191
192 .sqrt,
193 .sin,
194 .cos,
195 .tan,
196 .exp,
197 .exp2,
198 .log,
199 .log2,
200 .log10,
201 .floor,
202 .ceil,
203 .round,
204 .trunc_float,
205 .neg,
206 .neg_optimized,
207 .is_null,
208 .is_non_null,
209 .is_null_ptr,
210 .is_non_null_ptr,
211 .is_err,
212 .is_non_err,
213 .is_err_ptr,
214 .is_non_err_ptr,
215 .ret,
216 .ret_safe,
217 .ret_load,
218 .is_named_enum_value,
219 .tag_name,
220 .error_name,
221 .cmp_lt_errors_len,
222 .c_va_end,
223 .set_err_return_trace,
224 => {
225 if (!checkRef(data.un_op, zcu)) return false;
226 },
227
228 .br, .switch_dispatch => {
229 if (!checkRef(data.br.operand, zcu)) return false;
230 },
231
232 .cmp_vector,
233 .cmp_vector_optimized,
234 => {
235 const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data;
236 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
237 if (!checkRef(extra.lhs, zcu)) return false;
238 if (!checkRef(extra.rhs, zcu)) return false;
239 },
240
241 .reduce,
242 .reduce_optimized,
243 => {
244 if (!checkRef(data.reduce.operand, zcu)) return false;
245 },
246
247 .struct_field_ptr,
248 .struct_field_val,
249 => {
250 const extra = air.extraData(Air.StructField, data.ty_pl.payload).data;
251 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
252 if (!checkRef(extra.struct_operand, zcu)) return false;
253 },
254
255 .shuffle_one => {
256 const unwrapped = air.unwrapShuffleOne(zcu, inst);
257 if (!checkType(unwrapped.result_ty, zcu)) return false;
258 if (!checkRef(unwrapped.operand, zcu)) return false;
259 for (unwrapped.mask) |m| switch (m.unwrap()) {
260 .elem => {},
261 .value => |val| if (!checkVal(.fromInterned(val), zcu)) return false,
262 };
263 },
264
265 .shuffle_two => {
266 const unwrapped = air.unwrapShuffleTwo(zcu, inst);
267 if (!checkType(unwrapped.result_ty, zcu)) return false;
268 if (!checkRef(unwrapped.operand_a, zcu)) return false;
269 if (!checkRef(unwrapped.operand_b, zcu)) return false;
270 // No values to check because there are no comptime-known values other than undef
271 },
272
273 .cmpxchg_weak,
274 .cmpxchg_strong,
275 => {
276 const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data;
277 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
278 if (!checkRef(extra.ptr, zcu)) return false;
279 if (!checkRef(extra.expected_value, zcu)) return false;
280 if (!checkRef(extra.new_value, zcu)) return false;
281 },
282
283 .aggregate_init => {
284 const ty = data.ty_pl.ty.toType();
285 const elems_len: usize = @intCast(ty.arrayLen(zcu));
286 const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]);
287 if (!checkType(ty, zcu)) return false;
288 if (ty.zigTypeTag(zcu) == .@"struct") {
289 for (elems, 0..) |elem, elem_idx| {
290 if (ty.structFieldIsComptime(elem_idx, zcu)) continue;
291 if (!checkRef(elem, zcu)) return false;
292 }
293 } else {
294 for (elems) |elem| {
295 if (!checkRef(elem, zcu)) return false;
296 }
297 }
298 },
299
300 .union_init => {
301 const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data;
302 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
303 if (!checkRef(extra.init, zcu)) return false;
304 },
305
306 .field_parent_ptr => {
307 const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data;
308 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
309 if (!checkRef(extra.field_ptr, zcu)) return false;
310 },
311
312 .atomic_load => {
313 if (!checkRef(data.atomic_load.ptr, zcu)) return false;
314 },
315
316 .prefetch => {
317 if (!checkRef(data.prefetch.ptr, zcu)) return false;
318 },
319
320 .runtime_nav_ptr => {
321 if (!checkType(.fromInterned(data.ty_nav.ty), zcu)) return false;
322 },
323
324 .select,
325 .mul_add,
326 .legalize_vec_store_elem,
327 => {
328 const bin = air.extraData(Air.Bin, data.pl_op.payload).data;
329 if (!checkRef(data.pl_op.operand, zcu)) return false;
330 if (!checkRef(bin.lhs, zcu)) return false;
331 if (!checkRef(bin.rhs, zcu)) return false;
332 },
333
334 .atomic_rmw => {
335 const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data;
336 if (!checkRef(data.pl_op.operand, zcu)) return false;
337 if (!checkRef(extra.operand, zcu)) return false;
338 },
339
340 .call,
341 .call_always_tail,
342 .call_never_tail,
343 .call_never_inline,
344 => {
345 const call = air.unwrapCall(inst);
346 const args = call.args;
347 if (!checkRef(call.callee, zcu)) return false;
348 for (args) |arg| if (!checkRef(arg, zcu)) return false;
349 },
350
351 .dbg_var_ptr,
352 .dbg_var_val,
353 .dbg_arg_inline,
354 => {
355 if (!checkRef(data.pl_op.operand, zcu)) return false;
356 },
357
358 .@"try", .try_cold => {
359 const unwrapped_try = air.unwrapTry(inst);
360 if (!checkRef(unwrapped_try.error_union, zcu)) return false;
361 if (!checkBody(
362 air,
363 unwrapped_try.else_body,
364 zcu,
365 )) return false;
366 },
367
368 .try_ptr, .try_ptr_cold => {
369 const unwrapped_try = air.unwrapTryPtr(inst);
370 if (!checkType(unwrapped_try.error_union_payload_ptr_ty.toType(), zcu)) return false;
371 if (!checkRef(unwrapped_try.error_union_ptr, zcu)) return false;
372 if (!checkBody(
373 air,
374 unwrapped_try.else_body,
375 zcu,
376 )) return false;
377 },
378
379 .cond_br => {
380 const cond_br = air.unwrapCondBr(inst);
381 if (!checkRef(cond_br.condition, zcu)) return false;
382 if (!checkBody(
383 air,
384 cond_br.then_body,
385 zcu,
386 )) return false;
387 if (!checkBody(
388 air,
389 cond_br.else_body,
390 zcu,
391 )) return false;
392 },
393
394 .switch_br, .loop_switch_br => {
395 const switch_br = air.unwrapSwitch(inst);
396 if (!checkRef(switch_br.operand, zcu)) return false;
397 var it = switch_br.iterateCases();
398 while (it.next()) |case| {
399 for (case.items) |item| if (!checkRef(item, zcu)) return false;
400 for (case.ranges) |range| {
401 if (!checkRef(range[0], zcu)) return false;
402 if (!checkRef(range[1], zcu)) return false;
403 }
404 if (!checkBody(air, case.body, zcu)) return false;
405 }
406 if (!checkBody(air, it.elseBody(), zcu)) return false;
407 },
408
409 .assembly => {
410 const unwrapped_asm = air.unwrapAsm(inst);
411 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
412 // Luckily, we only care about the inputs and outputs, so we don't have to do
413 // the whole null-terminated string dance.
414 const outputs = unwrapped_asm.outputs;
415 const inputs = unwrapped_asm.inputs;
416
417 for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false;
418 for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false;
419 },
420
421 .legalize_compiler_rt_call => {
422 const rt_call = air.unwrapCompilerRtCall(inst);
423 const args = rt_call.args;
424 for (args) |arg| if (!checkRef(arg, zcu)) return false;
425 },
426
427 .trap,
428 .breakpoint,
429 .ret_addr,
430 .frame_addr,
431 .unreach,
432 .wasm_memory_size,
433 .wasm_memory_grow,
434 .work_item_id,
435 .work_group_size,
436 .work_group_id,
437 .dbg_stmt,
438 .dbg_empty_stmt,
439 .err_return_trace,
440 .save_err_return_trace_index,
441 .repeat,
442 => {},
443 }
444 }
445 return true;
446}
447
448fn checkRef(ref: Air.Inst.Ref, zcu: *Zcu) bool {
449 const ip_index = ref.toInterned() orelse {
450 // This operand refers back to a previous instruction.
451 // We have already checked that instruction's type.
452 // So, there's no need to check this operand's type.
453 return true;
454 };
455 return checkVal(Value.fromInterned(ip_index), zcu);
456}
457
458pub fn checkVal(val: Value, zcu: *Zcu) bool {
459 const ty = val.typeOf(zcu);
460 if (!checkType(ty, zcu)) return false;
461 if (val.isUndef(zcu)) return true;
462 if (ty.toIntern() == .type_type and !checkType(val.toType(), zcu)) return false;
463 // Check for lazy values
464 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
465 .int => |int| switch (int.storage) {
466 .u64, .i64, .big_int => return true,
467 .lazy_align, .lazy_size => |ty_index| {
468 return checkType(Type.fromInterned(ty_index), zcu);
469 },
470 },
471 else => return true,
472 }
473}
474
475pub fn checkType(ty: Type, zcu: *Zcu) bool {
476 const ip = &zcu.intern_pool;
477 if (ty.isGenericPoison()) return true;
478 return switch (ty.zigTypeTag(zcu)) {
479 .type,
480 .void,
481 .bool,
482 .noreturn,
483 .int,
484 .float,
485 .error_set,
486 .@"enum",
487 .@"opaque",
488 .vector,
489 // These types can appear due to some dummy instructions Sema introduces and expects to be omitted by Liveness.
490 // It's a little silly -- but fine, we'll return `true`.
491 .comptime_float,
492 .comptime_int,
493 .undefined,
494 .null,
495 .enum_literal,
496 => true,
497
498 .frame,
499 .@"anyframe",
500 => @panic("TODO Air.types_resolved.checkType async frames"),
501
502 .optional => checkType(ty.childType(zcu), zcu),
503 .error_union => checkType(ty.errorUnionPayload(zcu), zcu),
504 .pointer => checkType(ty.childType(zcu), zcu),
505 .array => checkType(ty.childType(zcu), zcu),
506
507 .@"fn" => {
508 const info = zcu.typeToFunc(ty).?;
509 for (0..info.param_types.len) |i| {
510 const param_ty = info.param_types.get(ip)[i];
511 if (!checkType(Type.fromInterned(param_ty), zcu)) return false;
512 }
513 return checkType(Type.fromInterned(info.return_type), zcu);
514 },
515 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
516 .struct_type => {
517 const struct_obj = zcu.typeToStruct(ty).?;
518 return switch (struct_obj.layout) {
519 .@"packed" => struct_obj.backingIntTypeUnordered(ip) != .none,
520 .auto, .@"extern" => struct_obj.flagsUnordered(ip).fully_resolved,
521 };
522 },
523 .tuple_type => |tuple| {
524 for (0..tuple.types.len) |i| {
525 const field_is_comptime = tuple.values.get(ip)[i] != .none;
526 if (field_is_comptime) continue;
527 const field_ty = tuple.types.get(ip)[i];
528 if (!checkType(Type.fromInterned(field_ty), zcu)) return false;
529 }
530 return true;
531 },
532 else => unreachable,
533 },
534 .@"union" => return zcu.typeToUnion(ty).?.flagsUnordered(ip).status == .fully_resolved,
535 };
536}
src/Compilation.zig+89-96
......@@ -126,15 +126,7 @@ oneshot_prelink_tasks: std.ArrayList(link.PrelinkTask),
126126/// work is queued or not.
127127queued_jobs: QueuedJobs,
128128
129work_queues: [
130 len: {
131 var len: usize = 0;
132 for (std.enums.values(Job.Tag)) |tag| {
133 len = @max(Job.stage(tag) + 1, len);
134 }
135 break :len len;
136 }
137]std.Deque(Job),
129work_queues: [2]std.Deque(Job),
138130
139131/// These jobs are to invoke the Clang compiler to create an object file, which
140132/// gets linked with the Compilation.
......@@ -990,35 +982,27 @@ const Job = union(enum) {
990982 update_line_number: InternPool.TrackedInst.Index,
991983 /// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
992984 /// This may be its first time being analyzed, or it may be outdated.
993 /// If the unit is a test function, an `analyze_func` job will then be queued.
994 analyze_comptime_unit: InternPool.AnalUnit,
995 /// This function must be semantically analyzed.
996 /// This may be its first time being analyzed, or it may be outdated.
997 /// After analysis, a `codegen_func` job will be queued.
998 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.
999 /// This job is separate from `analyze_comptime_unit` because it has a different priority.
1000 analyze_func: InternPool.Index,
985 /// If the unit is a function, a `codegen_func` job will be queued after analysis completes.
986 /// If the unit is a *test* function, an `analyze_func` job will also be queued.
987 analyze_unit: InternPool.AnalUnit,
1001988 /// The main source file for the module needs to be analyzed.
1002989 analyze_mod: *Package.Module,
1003 /// Fully resolve the given `struct` or `union` type.
1004 resolve_type_fully: InternPool.Index,
1005990
1006991 /// The value is the index into `windows_libs`.
1007992 windows_import_lib: usize,
1008993
1009 const Tag = @typeInfo(Job).@"union".tag_type.?;
1010 fn stage(tag: Tag) usize {
1011 return switch (tag) {
1012 // Prioritize functions so that codegen can get to work on them on a
1013 // separate thread, while Sema goes back to its own work.
1014 .resolve_type_fully, .analyze_func, .codegen_func => 0,
994 fn stage(job: *const Job) usize {
995 // Prioritize functions so that codegen can get to work on them on a
996 // separate thread, while Sema goes back to its own work.
997 return switch (job.*) {
998 .codegen_func => 0,
999 .analyze_unit => |unit| switch (unit.unwrap()) {
1000 .func => 0,
1001 else => 1,
1002 },
10151003 else => 1,
10161004 };
10171005 }
1018 comptime {
1019 // Job dependencies
1020 assert(stage(.resolve_type_fully) <= stage(.codegen_func));
1021 }
10221006};
10231007
10241008pub const CObject = struct {
......@@ -3728,7 +3712,9 @@ const Header = extern struct {
37283712 src_hash_deps_len: u32,
37293713 nav_val_deps_len: u32,
37303714 nav_ty_deps_len: u32,
3731 interned_deps_len: u32,
3715 type_layout_deps_len: u32,
3716 type_inits_deps_len: u32,
3717 func_ies_deps_len: u32,
37323718 zon_file_deps_len: u32,
37333719 embed_file_deps_len: u32,
37343720 namespace_deps_len: u32,
......@@ -3776,7 +3762,9 @@ pub fn saveState(comp: *Compilation) !void {
37763762 .src_hash_deps_len = @intCast(ip.src_hash_deps.count()),
37773763 .nav_val_deps_len = @intCast(ip.nav_val_deps.count()),
37783764 .nav_ty_deps_len = @intCast(ip.nav_ty_deps.count()),
3779 .interned_deps_len = @intCast(ip.interned_deps.count()),
3765 .type_layout_deps_len = @intCast(ip.type_layout_deps.count()),
3766 .type_inits_deps_len = @intCast(ip.type_inits_deps.count()),
3767 .func_ies_deps_len = @intCast(ip.func_ies_deps.count()),
37803768 .zon_file_deps_len = @intCast(ip.zon_file_deps.count()),
37813769 .embed_file_deps_len = @intCast(ip.embed_file_deps.count()),
37823770 .namespace_deps_len = @intCast(ip.namespace_deps.count()),
......@@ -3800,7 +3788,7 @@ pub fn saveState(comp: *Compilation) !void {
38003788 },
38013789 });
38023790
3803 try bufs.ensureTotalCapacityPrecise(22 + 9 * pt_headers.items.len);
3791 try bufs.ensureTotalCapacityPrecise(26 + 9 * pt_headers.items.len);
38043792 addBuf(&bufs, mem.asBytes(&header));
38053793 addBuf(&bufs, @ptrCast(pt_headers.items));
38063794
......@@ -3810,8 +3798,12 @@ pub fn saveState(comp: *Compilation) !void {
38103798 addBuf(&bufs, @ptrCast(ip.nav_val_deps.values()));
38113799 addBuf(&bufs, @ptrCast(ip.nav_ty_deps.keys()));
38123800 addBuf(&bufs, @ptrCast(ip.nav_ty_deps.values()));
3813 addBuf(&bufs, @ptrCast(ip.interned_deps.keys()));
3814 addBuf(&bufs, @ptrCast(ip.interned_deps.values()));
3801 addBuf(&bufs, @ptrCast(ip.type_layout_deps.keys()));
3802 addBuf(&bufs, @ptrCast(ip.type_layout_deps.values()));
3803 addBuf(&bufs, @ptrCast(ip.type_inits_deps.keys()));
3804 addBuf(&bufs, @ptrCast(ip.type_inits_deps.values()));
3805 addBuf(&bufs, @ptrCast(ip.func_ies_deps.keys()));
3806 addBuf(&bufs, @ptrCast(ip.func_ies_deps.values()));
38153807 addBuf(&bufs, @ptrCast(ip.zon_file_deps.keys()));
38163808 addBuf(&bufs, @ptrCast(ip.zon_file_deps.values()));
38173809 addBuf(&bufs, @ptrCast(ip.embed_file_deps.keys()));
......@@ -4489,7 +4481,7 @@ pub fn addModuleErrorMsg(
44894481 const root_name: ?[]const u8 = switch (ref.referencer.unwrap()) {
44904482 .@"comptime" => "comptime",
44914483 .nav_val, .nav_ty => |nav| ip.getNav(nav).name.toSlice(ip),
4492 .type => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
4484 .type_layout, .type_inits => |ty| Type.fromInterned(ty).containerTypeName(ip).toSlice(ip),
44934485 .func => |f| ip.getNav(zcu.funcInfo(f).owner_nav).name.toSlice(ip),
44944486 .memoized_state => null,
44954487 };
......@@ -4900,15 +4892,7 @@ fn performAllTheWork(
49004892 // If there's no work queued, check if there's anything outdated
49014893 // which we need to work on, and queue it if so.
49024894 if (try zcu.findOutdatedToAnalyze()) |outdated| {
4903 try comp.queueJob(switch (outdated.unwrap()) {
4904 .func => |f| .{ .analyze_func = f },
4905 .memoized_state,
4906 .@"comptime",
4907 .nav_ty,
4908 .nav_val,
4909 .type,
4910 => .{ .analyze_comptime_unit = outdated },
4911 });
4895 try comp.queueJob(.{ .analyze_unit = outdated });
49124896 continue;
49134897 }
49144898 zcu.sema_prog_node.end();
......@@ -5151,7 +5135,7 @@ fn dispatchPrelinkWork(comp: *Compilation, main_progress_node: std.Progress.Node
51515135const JobError = Allocator.Error || Io.Cancelable;
51525136
51535137pub fn queueJob(comp: *Compilation, job: Job) !void {
5154 try comp.work_queues[Job.stage(job)].pushBack(comp.gpa, job);
5138 try comp.work_queues[job.stage()].pushBack(comp.gpa, job);
51555139}
51565140
51575141pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
......@@ -5166,13 +5150,24 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
51665150 var owned_air: ?Air = func.air;
51675151 defer if (owned_air) |*air| air.deinit(gpa);
51685152
5169 if (!owned_air.?.typesFullyResolved(zcu)) {
5170 // Type resolution failed in a way which affects this function. This is a transitive
5171 // failure, but it doesn't need recording, because this function semantically depends
5172 // on the failed type, so when it is changed the function is updated.
5173 zcu.codegen_prog_node.completeOne();
5174 comp.link_prog_node.completeOne();
5175 return;
5153 {
5154 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5155 defer pt.deactivate();
5156 pt.resolveAirTypesForCodegen(&owned_air.?) catch |err| switch (err) {
5157 error.OutOfMemory,
5158 error.Canceled,
5159 => |e| return e,
5160
5161 error.AnalysisFail => {
5162 // Type resolution failed, making codegen of this function impossible. This
5163 // is a transitive failure, but it doesn't need recording, because this
5164 // function semantically depends on the failed type, so when it is changed
5165 // the function will be updated.
5166 zcu.codegen_prog_node.completeOne();
5167 comp.link_prog_node.completeOne();
5168 return;
5169 },
5170 };
51765171 }
51775172
51785173 // Some linkers need to refer to the AIR. In that case, the linker is not running
......@@ -5198,45 +5193,54 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
51985193 }
51995194 }
52005195 assert(nav.status == .fully_resolved);
5201 if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
5202 // Type resolution failed in a way which affects this `Nav`. This is a transitive
5203 // failure, but it doesn't need recording, because this `Nav` semantically depends
5204 // on the failed type, so when it is changed the `Nav` will be updated.
5205 comp.link_prog_node.completeOne();
5206 return;
5196 {
5197 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5198 defer pt.deactivate();
5199 pt.resolveValueTypesForCodegen(zcu.navValue(nav_index)) catch |err| switch (err) {
5200 error.OutOfMemory,
5201 error.Canceled,
5202 => |e| return e,
5203
5204 error.AnalysisFail => {
5205 // Type resolution failed, making codegen of this `Nav` impossible. This is
5206 // a transitive failure, but it doesn't need recording, because this `Nav`
5207 // semantically depends on the failed type, so when it is changed the value
5208 // of the `Nav` will be updated.
5209 comp.link_prog_node.completeOne();
5210 return;
5211 },
5212 };
52075213 }
52085214 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_nav = nav_index });
52095215 },
52105216 .link_type => |ty| {
52115217 const zcu = comp.zcu.?;
52125218 if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa);
5213 if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) {
5214 // Type resolution failed in a way which affects this type. This is a transitive
5215 // failure, but it doesn't need recording, because this type semantically depends
5216 // on the failed type, so when that is changed, this type will be updated.
5217 comp.link_prog_node.completeOne();
5218 return;
5219 {
5220 const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
5221 defer pt.deactivate();
5222 pt.resolveTypeForCodegen(.fromInterned(ty)) catch |err| switch (err) {
5223 error.OutOfMemory,
5224 error.Canceled,
5225 => |e| return e,
5226
5227 error.AnalysisFail => {
5228 // Type resolution failed, making codegen of this type impossible. This is
5229 // a transitive failure, but it doesn't need recording, because this type
5230 // semantically depends on the failed type, so when it is changed the type
5231 // will be updated appropriately.
5232 comp.link_prog_node.completeOne();
5233 return;
5234 },
5235 };
52195236 }
52205237 try comp.link_queue.enqueueZcu(comp, tid, .{ .link_type = ty });
52215238 },
52225239 .update_line_number => |tracked_inst| {
52235240 try comp.link_queue.enqueueZcu(comp, tid, .{ .update_line_number = tracked_inst });
52245241 },
5225 .analyze_func => |func| {
5226 const tracy_trace = traceNamed(@src(), "analyze_func");
5227 defer tracy_trace.end();
5228
5229 const pt: Zcu.PerThread = .activate(comp.zcu.?, tid);
5230 defer pt.deactivate();
5231
5232 pt.ensureFuncBodyUpToDate(func) catch |err| switch (err) {
5233 error.OutOfMemory => |e| return e,
5234 error.Canceled => |e| return e,
5235 error.AnalysisFail => return,
5236 };
5237 },
5238 .analyze_comptime_unit => |unit| {
5239 const tracy_trace = traceNamed(@src(), "analyze_comptime_unit");
5242 .analyze_unit => |unit| {
5243 const tracy_trace = traceNamed(@src(), "analyze_unit");
52405244 defer tracy_trace.end();
52415245
52425246 const pt: Zcu.PerThread = .activate(comp.zcu.?, tid);
......@@ -5246,9 +5250,10 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
52465250 .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu),
52475251 .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav),
52485252 .nav_val => |nav| pt.ensureNavValUpToDate(nav),
5249 .type => |ty| if (pt.ensureTypeUpToDate(ty)) |_| {} else |err| err,
5253 .type_layout => |ty| pt.ensureTypeLayoutUpToDate(.fromInterned(ty)),
5254 .type_inits => |ty| pt.ensureTypeInitsUpToDate(.fromInterned(ty)),
52505255 .memoized_state => |stage| pt.ensureMemoizedStateUpToDate(stage),
5251 .func => unreachable,
5256 .func => |func| pt.ensureFuncBodyUpToDate(func),
52525257 };
52535258 maybe_err catch |err| switch (err) {
52545259 error.OutOfMemory => |e| return e,
......@@ -5275,27 +5280,15 @@ fn processOneJob(tid: Zcu.PerThread.Id, comp: *Compilation, job: Job) JobError!v
52755280 try pt.zcu.ensureFuncBodyAnalysisQueued(ip.getNav(nav).status.fully_resolved.val);
52765281 }
52775282 },
5278 .resolve_type_fully => |ty| {
5279 const tracy_trace = traceNamed(@src(), "resolve_type_fully");
5280 defer tracy_trace.end();
5281
5282 const pt: Zcu.PerThread = .activate(comp.zcu.?, tid);
5283 defer pt.deactivate();
5284 Type.fromInterned(ty).resolveFully(pt) catch |err| switch (err) {
5285 error.OutOfMemory, error.Canceled => |e| return e,
5286 error.AnalysisFail => return,
5287 };
5288 },
52895283 .analyze_mod => |mod| {
52905284 const tracy_trace = traceNamed(@src(), "analyze_mod");
52915285 defer tracy_trace.end();
52925286
52935287 const pt: Zcu.PerThread = .activate(comp.zcu.?, tid);
52945288 defer pt.deactivate();
5295 pt.semaMod(mod) catch |err| switch (err) {
5296 error.OutOfMemory, error.Canceled => |e| return e,
5297 error.AnalysisFail => return,
5298 };
5289
5290 const mod_root_file = pt.zcu.module_roots.get(mod).?.unwrap().?;
5291 try pt.ensureFileAnalyzed(mod_root_file);
52995292 },
53005293 .windows_import_lib => |index| {
53015294 const tracy_trace = traceNamed(@src(), "windows_import_lib");
src/IncrementalDebugServer.zig+6-8
......@@ -306,12 +306,8 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const
306306 try w.print("[{d}] ", .{i});
307307 switch (dependee) {
308308 .src_hash, .namespace, .namespace_name, .zon_file, .embed_file => try w.print("{f}", .{zcu.fmtDependee(dependee)}),
309 .nav_val, .nav_ty => |nav| try w.print("{s} {d}", .{ @tagName(dependee), @intFromEnum(nav) }),
310 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
311 .struct_type, .union_type, .enum_type => try w.print("type {d}", .{@intFromEnum(ip_index)}),
312 .func => try w.print("func {d}", .{@intFromEnum(ip_index)}),
313 else => unreachable,
314 },
309 .nav_val, .nav_ty => |nav| try w.print("{t} {d}", .{ dependee, @intFromEnum(nav) }),
310 .type_layout, .type_inits, .func_ies => |ip_index| try w.print("{t} {d}", .{ dependee, @intFromEnum(ip_index) }),
315311 .memoized_state => |stage| try w.print("memoized_state {s}", .{@tagName(stage)}),
316312 }
317313 try w.writeByte('\n');
......@@ -376,8 +372,10 @@ fn parseAnalUnit(str: []const u8) ?AnalUnit {
376372 return .wrap(.{ .nav_val = @enumFromInt(parseIndex(idx_str) orelse return null) });
377373 } else if (std.mem.eql(u8, kind, "nav_ty")) {
378374 return .wrap(.{ .nav_ty = @enumFromInt(parseIndex(idx_str) orelse return null) });
379 } else if (std.mem.eql(u8, kind, "type")) {
380 return .wrap(.{ .type = @enumFromInt(parseIndex(idx_str) orelse return null) });
375 } else if (std.mem.eql(u8, kind, "type_layout")) {
376 return .wrap(.{ .type_layout = @enumFromInt(parseIndex(idx_str) orelse return null) });
377 } else if (std.mem.eql(u8, kind, "type_inits")) {
378 return .wrap(.{ .type_inits = @enumFromInt(parseIndex(idx_str) orelse return null) });
381379 } else if (std.mem.eql(u8, kind, "func")) {
382380 return .wrap(.{ .func = @enumFromInt(parseIndex(idx_str) orelse return null) });
383381 } else if (std.mem.eql(u8, kind, "memoized_state")) {
src/InternPool.zig+1942-2736
......@@ -47,11 +47,15 @@ nav_val_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
4747/// Dependencies on the type of a Nav.
4848/// Value is index into `dep_entries` of the first dependency on this Nav value.
4949nav_ty_deps: std.AutoArrayHashMapUnmanaged(Nav.Index, DepEntry.Index),
50/// Dependencies on an interned value, either:
51/// * a runtime function (invalidated when its IES changes)
52/// * a container type requiring resolution (invalidated when the type must be recreated at a new index)
53/// Value is index into `dep_entries` of the first dependency on this interned value.
54interned_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
50/// Dependencies on a function's inferred error set. Key is the function body, not the IES.
51/// Value is index into `dep_entries` of the first dependency on this function's IES.
52func_ies_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
53/// Dependencies on the resolved layout of a `struct` or `union` type.
54/// Value is index into `dep_entries` of the first dependency on this type's layout.
55type_layout_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
56/// Dependencies on the resolved initializers of a `struct` or `enum` type.
57/// Value is index into `dep_entries` of the first dependency on this type's inits.
58type_inits_deps: std.AutoArrayHashMapUnmanaged(Index, DepEntry.Index),
5559/// Dependencies on a ZON file. Triggered by `@import` of ZON.
5660/// Value is index into `dep_entries` of the first dependency on this ZON file.
5761zon_file_deps: std.AutoArrayHashMapUnmanaged(FileIndex, DepEntry.Index),
......@@ -104,7 +108,9 @@ pub const empty: InternPool = .{
104108 .src_hash_deps = .empty,
105109 .nav_val_deps = .empty,
106110 .nav_ty_deps = .empty,
107 .interned_deps = .empty,
111 .func_ies_deps = .empty,
112 .type_layout_deps = .empty,
113 .type_inits_deps = .empty,
108114 .zon_file_deps = .empty,
109115 .embed_file_deps = .empty,
110116 .namespace_deps = .empty,
......@@ -415,7 +421,8 @@ pub const AnalUnit = packed struct(u64) {
415421 @"comptime",
416422 nav_val,
417423 nav_ty,
418 type,
424 type_layout,
425 type_inits,
419426 func,
420427 memoized_state,
421428 };
......@@ -427,9 +434,11 @@ pub const AnalUnit = packed struct(u64) {
427434 nav_val: Nav.Index,
428435 /// This `AnalUnit` resolves the type of the given `Nav`.
429436 nav_ty: Nav.Index,
430 /// This `AnalUnit` resolves the given `struct`/`union`/`enum` type.
431 /// Generated tag enums are never used here (they do not undergo type resolution).
432 type: InternPool.Index,
437 /// This `AnalUnit` resolves the layout of the given `struct` or `union` type.
438 type_layout: InternPool.Index,
439 /// This `AnalUnit` resolves the field inits of the given `struct` or `enum` type.
440 /// The type may be a union's auto-generated tag enum, if the union has explicit field values.
441 type_inits: InternPool.Index,
433442 /// This `AnalUnit` analyzes the body of the given runtime function.
434443 func: InternPool.Index,
435444 /// This `AnalUnit` resolves all state which is memoized in fields on `Zcu`.
......@@ -840,7 +849,10 @@ pub const Dependee = union(enum) {
840849 src_hash: TrackedInst.Index,
841850 nav_val: Nav.Index,
842851 nav_ty: Nav.Index,
843 interned: Index,
852 /// Index is the function, not its IES.
853 func_ies: Index,
854 type_layout: Index,
855 type_inits: Index,
844856 zon_file: FileIndex,
845857 embed_file: Zcu.EmbedFile.Index,
846858 namespace: TrackedInst.Index,
......@@ -892,7 +904,9 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
892904 .src_hash => |x| ip.src_hash_deps.get(x),
893905 .nav_val => |x| ip.nav_val_deps.get(x),
894906 .nav_ty => |x| ip.nav_ty_deps.get(x),
895 .interned => |x| ip.interned_deps.get(x),
907 .func_ies => |x| ip.func_ies_deps.get(x),
908 .type_layout => |x| ip.type_layout_deps.get(x),
909 .type_inits => |x| ip.type_inits_deps.get(x),
896910 .zon_file => |x| ip.zon_file_deps.get(x),
897911 .embed_file => |x| ip.embed_file_deps.get(x),
898912 .namespace => |x| ip.namespace_deps.get(x),
......@@ -965,7 +979,9 @@ pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, depend
965979 .src_hash => ip.src_hash_deps,
966980 .nav_val => ip.nav_val_deps,
967981 .nav_ty => ip.nav_ty_deps,
968 .interned => ip.interned_deps,
982 .func_ies => ip.func_ies_deps,
983 .type_layout => ip.type_layout_deps,
984 .type_inits => ip.type_inits_deps,
969985 .zon_file => ip.zon_file_deps,
970986 .embed_file => ip.embed_file_deps,
971987 .namespace => ip.namespace_deps,
......@@ -2065,15 +2081,15 @@ pub const Key = union(enum) {
20652081 simple_type: SimpleType,
20662082 /// This represents a struct that has been explicitly declared in source code,
20672083 /// or was created with `@Struct`. It is unique and based on a declaration.
2068 struct_type: NamespaceType,
2084 struct_type: ContainerType,
20692085 /// This is a tuple type. Tuples are logically similar to structs, but have some
20702086 /// important differences in semantics; they do not undergo staged type resolution,
20712087 /// so cannot be self-referential, and they are not considered container/namespace
20722088 /// types, so cannot have declarations and have structural equality properties.
20732089 tuple_type: TupleType,
2074 union_type: NamespaceType,
2075 opaque_type: NamespaceType,
2076 enum_type: NamespaceType,
2090 union_type: ContainerType,
2091 opaque_type: ContainerType,
2092 enum_type: ContainerType,
20772093 func_type: FuncType,
20782094 error_set_type: ErrorSetType,
20792095 /// The payload is the function body, either a `func_decl` or `func_instance`.
......@@ -2211,16 +2227,10 @@ pub const Key = union(enum) {
22112227 /// * `loadUnionType`
22122228 /// * `loadEnumType`
22132229 /// * `loadOpaqueType`
2214 pub const NamespaceType = union(enum) {
2230 pub const ContainerType = union(enum) {
22152231 /// This type corresponds to an actual source declaration, e.g. `struct { ... }`.
22162232 /// It is hashed based on its ZIR instruction index and set of captures.
22172233 declared: Declared,
2218 /// This type is an automatically-generated enum tag type for a union.
2219 /// It is hashed based on the index of the union type it corresponds to.
2220 generated_tag: struct {
2221 /// The union for which this is a tag type.
2222 union_type: Index,
2223 },
22242234 /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization.
22252235 /// It is hashed based on its ZIR instruction index and fields, attributes, etc.
22262236 /// To avoid making this key overly complex, the type-specific data is hashed by Sema.
......@@ -2231,10 +2241,17 @@ pub const Key = union(enum) {
22312241 /// A hash of this type's attributes, fields, etc, generated by Sema.
22322242 type_hash: u64,
22332243 },
2244 /// This type is an automatically-generated enum tag type for this union type.
2245 /// It is hashed based on the index of the union type it corresponds to.
2246 generated_union_tag: Index,
22342247
22352248 pub const Declared = struct {
22362249 /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction.
22372250 zir_index: TrackedInst.Index,
2251 /// If the type declaration had an argument type (tag type or packed backing type), this
2252 /// is that type. Otherwise, this is `.none`. It is always `.none` for `opaque` types as
2253 /// `opaque(T)` does not exist.
2254 arg_ty: Index,
22382255 /// The captured values of this type. These values must be fully resolved per the language spec.
22392256 captures: union(enum) {
22402257 owned: CaptureValue.Slice,
......@@ -2254,7 +2271,6 @@ pub const Key = union(enum) {
22542271 noalias_bits: u32,
22552272 cc: std.builtin.CallingConvention,
22562273 is_var_args: bool,
2257 is_generic: bool,
22582274 is_noinline: bool,
22592275
22602276 pub fn paramIsComptime(self: @This(), i: u5) bool {
......@@ -2273,7 +2289,6 @@ pub const Key = union(enum) {
22732289 a.comptime_bits == b.comptime_bits and
22742290 a.noalias_bits == b.noalias_bits and
22752291 a.is_var_args == b.is_var_args and
2276 a.is_generic == b.is_generic and
22772292 a.is_noinline == b.is_noinline and
22782293 std.meta.eql(a.cc, b.cc);
22792294 }
......@@ -2287,7 +2302,6 @@ pub const Key = union(enum) {
22872302 std.hash.autoHash(hasher, self.noalias_bits);
22882303 std.hash.autoHash(hasher, self.cc);
22892304 std.hash.autoHash(hasher, self.is_var_args);
2290 std.hash.autoHash(hasher, self.is_generic);
22912305 std.hash.autoHash(hasher, self.is_noinline);
22922306 }
22932307 };
......@@ -2471,8 +2485,6 @@ pub const Key = union(enum) {
24712485 u64: u64,
24722486 i64: i64,
24732487 big_int: BigIntConst,
2474 lazy_align: Index,
2475 lazy_size: Index,
24762488
24772489 /// Big enough to fit any non-BigInt value
24782490 pub const BigIntSpace = struct {
......@@ -2485,7 +2497,6 @@ pub const Key = union(enum) {
24852497 return switch (storage) {
24862498 .big_int => |x| x,
24872499 inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
2488 .lazy_align, .lazy_size => unreachable,
24892500 };
24902501 }
24912502 };
......@@ -2734,6 +2745,7 @@ pub const Key = union(enum) {
27342745 switch (namespace_type) {
27352746 .declared => |declared| {
27362747 std.hash.autoHash(&hasher, declared.zir_index);
2748 std.hash.autoHash(&hasher, declared.arg_ty);
27372749 const captures = switch (declared.captures) {
27382750 .owned => |cvs| cvs.get(ip),
27392751 .external => |cvs| cvs,
......@@ -2742,13 +2754,13 @@ pub const Key = union(enum) {
27422754 std.hash.autoHash(&hasher, cv);
27432755 }
27442756 },
2745 .generated_tag => |generated_tag| {
2746 std.hash.autoHash(&hasher, generated_tag.union_type);
2747 },
27482757 .reified => |reified| {
27492758 std.hash.autoHash(&hasher, reified.zir_index);
27502759 std.hash.autoHash(&hasher, reified.type_hash);
27512760 },
2761 .generated_union_tag => |union_type| {
2762 std.hash.autoHash(&hasher, union_type);
2763 },
27522764 }
27532765 return hasher.final();
27542766 },
......@@ -2756,23 +2768,12 @@ pub const Key = union(enum) {
27562768 .int => |int| {
27572769 var hasher = Hash.init(seed);
27582770 // Canonicalize all integers by converting them to BigIntConst.
2759 switch (int.storage) {
2760 .u64, .i64, .big_int => {
2761 var buffer: Key.Int.Storage.BigIntSpace = undefined;
2762 const big_int = int.storage.toBigInt(&buffer);
2763
2764 std.hash.autoHash(&hasher, int.ty);
2765 std.hash.autoHash(&hasher, big_int.positive);
2766 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb);
2767 },
2768 .lazy_align, .lazy_size => |lazy_ty| {
2769 std.hash.autoHash(
2770 &hasher,
2771 @as(@typeInfo(Key.Int.Storage).@"union".tag_type.?, int.storage),
2772 );
2773 std.hash.autoHash(&hasher, lazy_ty);
2774 },
2775 }
2771 var buffer: Key.Int.Storage.BigIntSpace = undefined;
2772 const big_int = int.storage.toBigInt(&buffer);
2773
2774 std.hash.autoHash(&hasher, int.ty);
2775 std.hash.autoHash(&hasher, big_int.positive);
2776 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb);
27762777 return hasher.final();
27772778 },
27782779
......@@ -3102,27 +3103,16 @@ pub const Key = union(enum) {
31023103 .u64 => |bb| aa == bb,
31033104 .i64 => |bb| aa == bb,
31043105 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
3105 .lazy_align, .lazy_size => false,
31063106 },
31073107 .i64 => |aa| switch (b_info.storage) {
31083108 .u64 => |bb| aa == bb,
31093109 .i64 => |bb| aa == bb,
31103110 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
3111 .lazy_align, .lazy_size => false,
31123111 },
31133112 .big_int => |aa| switch (b_info.storage) {
31143113 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,
31153114 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,
31163115 .big_int => |bb| aa.eql(bb),
3117 .lazy_align, .lazy_size => false,
3118 },
3119 .lazy_align => |aa| switch (b_info.storage) {
3120 .u64, .i64, .big_int, .lazy_size => false,
3121 .lazy_align => |bb| aa == bb,
3122 },
3123 .lazy_size => |aa| switch (b_info.storage) {
3124 .u64, .i64, .big_int, .lazy_align => false,
3125 .lazy_size => |bb| aa == bb,
31263116 },
31273117 };
31283118 },
......@@ -3165,6 +3155,7 @@ pub const Key = union(enum) {
31653155 .declared => |a_d| {
31663156 const b_d = b_info.declared;
31673157 if (a_d.zir_index != b_d.zir_index) return false;
3158 if (a_d.arg_ty != b_d.arg_ty) return false;
31683159 const a_captures = switch (a_d.captures) {
31693160 .owned => |s| s.get(ip),
31703161 .external => |cvs| cvs,
......@@ -3175,12 +3166,12 @@ pub const Key = union(enum) {
31753166 };
31763167 return std.mem.eql(u32, @ptrCast(a_captures), @ptrCast(b_captures));
31773168 },
3178 .generated_tag => |a_gt| return a_gt.union_type == b_info.generated_tag.union_type,
31793169 .reified => |a_r| {
31803170 const b_r = b_info.reified;
31813171 return a_r.zir_index == b_r.zir_index and
31823172 a_r.type_hash == b_r.type_hash;
31833173 },
3174 .generated_union_tag => |a_union_ty| return a_union_ty == b_info.generated_union_tag,
31843175 }
31853176 },
31863177 .aggregate => |a_info| {
......@@ -3313,374 +3304,40 @@ pub const Key = union(enum) {
33133304 }
33143305};
33153306
3316pub const RequiresComptime = enum(u2) { no, yes, unknown, wip };
3317
3318// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a
3319// minimal hashmap key, this type is a convenience type that contains info
3320// needed by semantic analysis.
3321pub const LoadedUnionType = struct {
3322 tid: Zcu.PerThread.Id,
3323 /// The index of the `Tag.TypeUnion` payload.
3324 extra_index: u32,
3325 // TODO: the non-fqn will be needed by the new dwarf structure
3326 /// The name of this union type.
3327 name: NullTerminatedString,
3328 /// Represents the declarations inside this union.
3329 namespace: NamespaceIndex,
3330 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3331 /// Otherwise, this is `.none`.
3332 name_nav: Nav.Index.Optional,
3333 /// The enum tag type.
3334 enum_tag_ty: Index,
3335 /// List of field types in declaration order.
3336 /// These are `none` until `status` is `have_field_types` or `have_layout`.
3337 field_types: Index.Slice,
3338 /// List of field alignments in declaration order.
3339 /// `none` means the ABI alignment of the type.
3340 /// If this slice has length 0 it means all elements are `none`.
3341 field_aligns: Alignment.Slice,
3342 /// Index of the union_decl or reify ZIR instruction.
3307pub const LoadedStructType = struct {
3308 /// Index of the `struct_decl` or `reify` ZIR instruction.
33433309 zir_index: TrackedInst.Index,
33443310 captures: CaptureValue.Slice,
33453311
3346 pub const RuntimeTag = enum(u2) {
3347 none,
3348 safety,
3349 tagged,
3350
3351 pub fn hasTag(self: RuntimeTag) bool {
3352 return switch (self) {
3353 .none => false,
3354 .tagged, .safety => true,
3355 };
3356 }
3357 };
3358
3359 pub const Status = enum(u3) {
3360 none,
3361 field_types_wip,
3362 have_field_types,
3363 layout_wip,
3364 have_layout,
3365 fully_resolved_wip,
3366 /// The types and all its fields have had their layout resolved.
3367 /// Even through pointer, which `have_layout` does not ensure.
3368 fully_resolved,
3369
3370 pub fn haveFieldTypes(status: Status) bool {
3371 return switch (status) {
3372 .none,
3373 .field_types_wip,
3374 => false,
3375 .have_field_types,
3376 .layout_wip,
3377 .have_layout,
3378 .fully_resolved_wip,
3379 .fully_resolved,
3380 => true,
3381 };
3382 }
3383
3384 pub fn haveLayout(status: Status) bool {
3385 return switch (status) {
3386 .none,
3387 .field_types_wip,
3388 .have_field_types,
3389 .layout_wip,
3390 => false,
3391 .have_layout,
3392 .fully_resolved_wip,
3393 .fully_resolved,
3394 => true,
3395 };
3396 }
3397 };
3398
3399 pub fn loadTagType(self: LoadedUnionType, ip: *const InternPool) LoadedEnumType {
3400 return ip.loadEnumType(self.enum_tag_ty);
3401 }
3402
3403 /// Pointer to an enum type which is used for the tag of the union.
3404 /// This type is created even for untagged unions, even when the memory
3405 /// layout does not store the tag.
3406 /// Whether zig chooses this type or the user specifies it, it is stored here.
3407 /// This will be set to the null type until status is `have_field_types`.
3408 /// This accessor is provided so that the tag type can be mutated, and so that
3409 /// when it is mutated, the mutations are observed.
3410 /// The returned pointer expires with any addition to the `InternPool`.
3411 fn tagTypePtr(self: LoadedUnionType, ip: *const InternPool) *Index {
3412 const extra = ip.getLocalShared(self.tid).extra.acquire();
3413 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "tag_ty").?;
3414 return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]);
3415 }
3416
3417 pub fn tagTypeUnordered(u: LoadedUnionType, ip: *const InternPool) Index {
3418 return @atomicLoad(Index, u.tagTypePtr(ip), .unordered);
3419 }
3420
3421 pub fn setTagType(u: LoadedUnionType, ip: *InternPool, io: Io, tag_type: Index) void {
3422 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3423 extra_mutex.lockUncancelable(io);
3424 defer extra_mutex.unlock(io);
3425
3426 @atomicStore(Index, u.tagTypePtr(ip), tag_type, .release);
3427 }
3428
3429 /// The returned pointer expires with any addition to the `InternPool`.
3430 fn flagsPtr(self: LoadedUnionType, ip: *const InternPool) *Tag.TypeUnion.Flags {
3431 const extra = ip.getLocalShared(self.tid).extra.acquire();
3432 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
3433 return @ptrCast(&extra.view().items(.@"0")[self.extra_index + field_index]);
3434 }
3435
3436 pub fn flagsUnordered(u: LoadedUnionType, ip: *const InternPool) Tag.TypeUnion.Flags {
3437 return @atomicLoad(Tag.TypeUnion.Flags, u.flagsPtr(ip), .unordered);
3438 }
3439
3440 pub fn setStatus(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void {
3441 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3442 extra_mutex.lockUncancelable(io);
3443 defer extra_mutex.unlock(io);
3444
3445 const flags_ptr = u.flagsPtr(ip);
3446 var flags = flags_ptr.*;
3447 flags.status = status;
3448 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3449 }
3450
3451 pub fn setStatusIfLayoutWip(u: LoadedUnionType, ip: *InternPool, io: Io, status: Status) void {
3452 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3453 extra_mutex.lockUncancelable(io);
3454 defer extra_mutex.unlock(io);
3455
3456 const flags_ptr = u.flagsPtr(ip);
3457 var flags = flags_ptr.*;
3458 if (flags.status == .layout_wip) flags.status = status;
3459 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3460 }
3461
3462 pub fn setAlignment(u: LoadedUnionType, ip: *InternPool, io: Io, alignment: Alignment) void {
3463 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3464 extra_mutex.lockUncancelable(io);
3465 defer extra_mutex.unlock(io);
3466
3467 const flags_ptr = u.flagsPtr(ip);
3468 var flags = flags_ptr.*;
3469 flags.alignment = alignment;
3470 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3471 }
3472
3473 pub fn assumeRuntimeBitsIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io) bool {
3474 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3475 extra_mutex.lockUncancelable(io);
3476 defer extra_mutex.unlock(io);
3477
3478 const flags_ptr = u.flagsPtr(ip);
3479 var flags = flags_ptr.*;
3480 defer if (flags.status == .field_types_wip) {
3481 flags.assumed_runtime_bits = true;
3482 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3483 };
3484 return flags.status == .field_types_wip;
3485 }
3486
3487 pub fn requiresComptime(u: LoadedUnionType, ip: *const InternPool) RequiresComptime {
3488 return u.flagsUnordered(ip).requires_comptime;
3489 }
3490
3491 pub fn setRequiresComptimeWip(u: LoadedUnionType, ip: *InternPool, io: Io) RequiresComptime {
3492 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3493 extra_mutex.lockUncancelable(io);
3494 defer extra_mutex.unlock(io);
3495
3496 const flags_ptr = u.flagsPtr(ip);
3497 var flags = flags_ptr.*;
3498 defer if (flags.requires_comptime == .unknown) {
3499 flags.requires_comptime = .wip;
3500 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3501 };
3502 return flags.requires_comptime;
3503 }
3504
3505 pub fn setRequiresComptime(u: LoadedUnionType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void {
3506 assert(requires_comptime != .wip); // see setRequiresComptimeWip
3507
3508 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3509 extra_mutex.lockUncancelable(io);
3510 defer extra_mutex.unlock(io);
3511
3512 const flags_ptr = u.flagsPtr(ip);
3513 var flags = flags_ptr.*;
3514 flags.requires_comptime = requires_comptime;
3515 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3516 }
3517
3518 pub fn assumePointerAlignedIfFieldTypesWip(u: LoadedUnionType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3519 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3520 extra_mutex.lockUncancelable(io);
3521 defer extra_mutex.unlock(io);
3522
3523 const flags_ptr = u.flagsPtr(ip);
3524 var flags = flags_ptr.*;
3525 defer if (flags.status == .field_types_wip) {
3526 flags.alignment = ptr_align;
3527 flags.assumed_pointer_aligned = true;
3528 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3529 };
3530 return flags.status == .field_types_wip;
3531 }
3532
3533 /// The returned pointer expires with any addition to the `InternPool`.
3534 fn sizePtr(self: LoadedUnionType, ip: *const InternPool) *u32 {
3535 const extra = ip.getLocalShared(self.tid).extra.acquire();
3536 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "size").?;
3537 return &extra.view().items(.@"0")[self.extra_index + field_index];
3538 }
3539
3540 pub fn sizeUnordered(u: LoadedUnionType, ip: *const InternPool) u32 {
3541 return @atomicLoad(u32, u.sizePtr(ip), .unordered);
3542 }
3543
3544 /// The returned pointer expires with any addition to the `InternPool`.
3545 fn paddingPtr(self: LoadedUnionType, ip: *const InternPool) *u32 {
3546 const extra = ip.getLocalShared(self.tid).extra.acquire();
3547 const field_index = std.meta.fieldIndex(Tag.TypeUnion, "padding").?;
3548 return &extra.view().items(.@"0")[self.extra_index + field_index];
3549 }
3550
3551 pub fn paddingUnordered(u: LoadedUnionType, ip: *const InternPool) u32 {
3552 return @atomicLoad(u32, u.paddingPtr(ip), .unordered);
3553 }
3554
3555 pub fn hasTag(self: LoadedUnionType, ip: *const InternPool) bool {
3556 return self.flagsUnordered(ip).runtime_tag.hasTag();
3557 }
3558
3559 pub fn haveFieldTypes(self: LoadedUnionType, ip: *const InternPool) bool {
3560 return self.flagsUnordered(ip).status.haveFieldTypes();
3561 }
3562
3563 pub fn haveLayout(self: LoadedUnionType, ip: *const InternPool) bool {
3564 return self.flagsUnordered(ip).status.haveLayout();
3565 }
3566
3567 pub fn setHaveLayout(u: LoadedUnionType, ip: *InternPool, io: Io, size: u32, padding: u32, alignment: Alignment) void {
3568 const extra_mutex = &ip.getLocal(u.tid).mutate.extra.mutex;
3569 extra_mutex.lockUncancelable(io);
3570 defer extra_mutex.unlock(io);
3571
3572 @atomicStore(u32, u.sizePtr(ip), size, .unordered);
3573 @atomicStore(u32, u.paddingPtr(ip), padding, .unordered);
3574 const flags_ptr = u.flagsPtr(ip);
3575 var flags = flags_ptr.*;
3576 flags.alignment = alignment;
3577 flags.status = .have_layout;
3578 @atomicStore(Tag.TypeUnion.Flags, flags_ptr, flags, .release);
3579 }
3580
3581 pub fn fieldAlign(self: LoadedUnionType, ip: *const InternPool, field_index: usize) Alignment {
3582 if (self.field_aligns.len == 0) return .none;
3583 return self.field_aligns.get(ip)[field_index];
3584 }
3585
3586 /// This does not mutate the field of LoadedUnionType.
3587 pub fn setZirIndex(self: LoadedUnionType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
3588 const flags_field_index = std.meta.fieldIndex(Tag.TypeUnion, "flags").?;
3589 const zir_index_field_index = std.meta.fieldIndex(Tag.TypeUnion, "zir_index").?;
3590 const ptr: *TrackedInst.Index.Optional =
3591 @ptrCast(&ip.extra_.items[self.flags_index - flags_field_index + zir_index_field_index]);
3592 ptr.* = new_zir_index;
3593 }
3594
3595 pub fn setFieldTypes(self: LoadedUnionType, ip: *const InternPool, types: []const Index) void {
3596 @memcpy(self.field_types.get(ip), types);
3597 }
3598
3599 pub fn setFieldAligns(self: LoadedUnionType, ip: *const InternPool, aligns: []const Alignment) void {
3600 if (aligns.len == 0) return;
3601 assert(self.flagsUnordered(ip).any_aligned_fields);
3602 @memcpy(self.field_aligns.get(ip), aligns);
3603 }
3604};
3605
3606pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
3607 const unwrapped_index = index.unwrap(ip);
3608 const extra_list = unwrapped_index.getExtra(ip);
3609 const data = unwrapped_index.getData(ip);
3610 const type_union = extraDataTrail(extra_list, Tag.TypeUnion, data);
3611 const fields_len = type_union.data.fields_len;
3612
3613 var extra_index = type_union.end;
3614 const captures_len = if (type_union.data.flags.any_captures) c: {
3615 const len = extra_list.view().items(.@"0")[extra_index];
3616 extra_index += 1;
3617 break :c len;
3618 } else 0;
3619
3620 const captures: CaptureValue.Slice = .{
3621 .tid = unwrapped_index.tid,
3622 .start = extra_index,
3623 .len = captures_len,
3624 };
3625 extra_index += captures_len;
3626 if (type_union.data.flags.is_reified) {
3627 extra_index += 2; // PackedU64
3628 }
3629
3630 const field_types: Index.Slice = .{
3631 .tid = unwrapped_index.tid,
3632 .start = extra_index,
3633 .len = fields_len,
3634 };
3635 extra_index += fields_len;
3636
3637 const field_aligns = if (type_union.data.flags.any_aligned_fields) a: {
3638 const a: Alignment.Slice = .{
3639 .tid = unwrapped_index.tid,
3640 .start = extra_index,
3641 .len = fields_len,
3642 };
3643 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
3644 break :a a;
3645 } else Alignment.Slice.empty;
3646
3647 return .{
3648 .tid = unwrapped_index.tid,
3649 .extra_index = data,
3650 .name = type_union.data.name,
3651 .name_nav = type_union.data.name_nav,
3652 .namespace = type_union.data.namespace,
3653 .enum_tag_ty = type_union.data.tag_ty,
3654 .field_types = field_types,
3655 .field_aligns = field_aligns,
3656 .zir_index = type_union.data.zir_index,
3657 .captures = captures,
3658 };
3659}
3660
3661pub const LoadedStructType = struct {
3662 tid: Zcu.PerThread.Id,
3663 /// The index of the `Tag.TypeStruct` or `Tag.TypeStructPacked` payload.
3664 extra_index: u32,
36653312 // TODO: the non-fqn will be needed by the new dwarf structure
36663313 /// The name of this struct type.
36673314 name: NullTerminatedString,
3668 namespace: NamespaceIndex,
36693315 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
36703316 /// Otherwise, or if this is a file's root struct type, this is `.none`.
36713317 name_nav: Nav.Index.Optional,
3672 /// Index of the `struct_decl` or `reify` ZIR instruction.
3673 zir_index: TrackedInst.Index,
3318 namespace: NamespaceIndex,
3319
36743320 layout: std.builtin.Type.ContainerLayout,
3321 /// May be `undefined` if `layout != .@"packed"`.
3322 packed_backing_mode: PackedBackingMode,
3323 /// May be `undefined` if `layout != .@"packed",
3324 packed_backing_int_type: Index,
3325
3326 field_name_map: MapIndex,
36753327 field_names: NullTerminatedString.Slice,
36763328 field_types: Index.Slice,
3677 field_inits: Index.Slice,
3329 field_defaults: Index.Slice,
36783330 field_aligns: Alignment.Slice,
3679 runtime_order: RuntimeOrder.Slice,
3680 comptime_bits: ComptimeBits,
3681 offsets: Offsets,
3682 names_map: OptionalMapIndex,
3683 captures: CaptureValue.Slice,
3331 field_is_comptime_bits: ComptimeBits,
3332 field_runtime_order: RuntimeOrder.Slice,
3333 field_offsets: Offsets,
3334
3335 // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`.
3336 has_no_possible_value: bool,
3337 has_one_possible_value: bool,
3338 comptime_only: bool,
3339 size: u32,
3340 alignment: Alignment,
36843341
36853342 pub const ComptimeBits = struct {
36863343 tid: Zcu.PerThread.Id,
......@@ -3690,22 +3347,14 @@ pub const LoadedStructType = struct {
36903347
36913348 pub const empty: ComptimeBits = .{ .tid = .main, .start = 0, .len = 0 };
36923349
3693 pub fn get(this: ComptimeBits, ip: *const InternPool) []u32 {
3350 pub fn getAll(this: ComptimeBits, ip: *const InternPool) []u32 {
36943351 const extra = ip.getLocalShared(this.tid).extra.acquire();
36953352 return extra.view().items(.@"0")[this.start..][0..this.len];
36963353 }
36973354
3698 pub fn getBit(this: ComptimeBits, ip: *const InternPool, i: usize) bool {
3355 pub fn get(this: ComptimeBits, ip: *const InternPool, i: usize) bool {
36993356 if (this.len == 0) return false;
3700 return @as(u1, @truncate(this.get(ip)[i / 32] >> @intCast(i % 32))) != 0;
3701 }
3702
3703 pub fn setBit(this: ComptimeBits, ip: *const InternPool, i: usize) void {
3704 this.get(ip)[i / 32] |= @as(u32, 1) << @intCast(i % 32);
3705 }
3706
3707 pub fn clearBit(this: ComptimeBits, ip: *const InternPool, i: usize) void {
3708 this.get(ip)[i / 32] &= ~(@as(u32, 1) << @intCast(i % 32));
3357 return @as(u1, @truncate(this.getAll(ip)[i / 32] >> @intCast(i % 32))) != 0;
37093358 }
37103359 };
37113360
......@@ -3753,865 +3402,550 @@ pub const LoadedStructType = struct {
37533402
37543403 /// Look up field index based on field name.
37553404 pub fn nameIndex(s: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
3756 const names_map = s.names_map.unwrap() orelse {
3757 const i = name.toUnsigned(ip) orelse return null;
3758 if (i >= s.field_types.len) return null;
3759 return i;
3760 };
3761 const map = names_map.get(ip);
3405 const map = s.field_name_map.get(ip);
37623406 const adapter: NullTerminatedString.Adapter = .{ .strings = s.field_names.get(ip) };
37633407 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
37643408 return @intCast(field_index);
37653409 }
37663410
3767 /// Returns the already-existing field with the same name, if any.
3768 pub fn addFieldName(
3769 s: LoadedStructType,
3770 ip: *InternPool,
3771 name: NullTerminatedString,
3772 ) ?u32 {
3773 const extra = ip.getLocalShared(s.tid).extra.acquire();
3774 return ip.addFieldName(extra, s.names_map.unwrap().?, s.field_names.start, name);
3775 }
3776
3777 pub fn fieldAlign(s: LoadedStructType, ip: *const InternPool, i: usize) Alignment {
3778 if (s.field_aligns.len == 0) return .none;
3779 return s.field_aligns.get(ip)[i];
3780 }
3781
3782 pub fn fieldInit(s: LoadedStructType, ip: *const InternPool, i: usize) Index {
3783 if (s.field_inits.len == 0) return .none;
3784 assert(s.haveFieldInits(ip));
3785 return s.field_inits.get(ip)[i];
3786 }
3787
3788 pub fn fieldName(s: LoadedStructType, ip: *const InternPool, i: usize) NullTerminatedString {
3789 return s.field_names.get(ip)[i];
3790 }
3791
3792 pub fn fieldIsComptime(s: LoadedStructType, ip: *const InternPool, i: usize) bool {
3793 return s.comptime_bits.getBit(ip, i);
3794 }
3795
3796 pub fn setFieldComptime(s: LoadedStructType, ip: *InternPool, i: usize) void {
3797 s.comptime_bits.setBit(ip, i);
3798 }
3799
3800 /// The returned pointer expires with any addition to the `InternPool`.
3411 /// Iterates over non-comptime fields in the order they are laid out in memory at runtime.
3412 /// May or may not include zero-bit fields.
38013413 /// Asserts the struct is not packed.
3802 fn flagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStruct.Flags {
3803 assert(s.layout != .@"packed");
3804 const extra = ip.getLocalShared(s.tid).extra.acquire();
3805 const flags_field_index = std.meta.fieldIndex(Tag.TypeStruct, "flags").?;
3806 return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]);
3807 }
3808
3809 pub fn flagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStruct.Flags {
3810 return @atomicLoad(Tag.TypeStruct.Flags, s.flagsPtr(ip), .unordered);
3811 }
3812
3813 /// The returned pointer expires with any addition to the `InternPool`.
3814 /// Asserts that the struct is packed.
3815 fn packedFlagsPtr(s: LoadedStructType, ip: *const InternPool) *Tag.TypeStructPacked.Flags {
3816 assert(s.layout == .@"packed");
3817 const extra = ip.getLocalShared(s.tid).extra.acquire();
3818 const flags_field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?;
3819 return @ptrCast(&extra.view().items(.@"0")[s.extra_index + flags_field_index]);
3820 }
3821
3822 pub fn packedFlagsUnordered(s: LoadedStructType, ip: *const InternPool) Tag.TypeStructPacked.Flags {
3823 return @atomicLoad(Tag.TypeStructPacked.Flags, s.packedFlagsPtr(ip), .unordered);
3414 pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *InternPool) RuntimeOrderIterator {
3415 switch (s.layout) {
3416 .auto => {
3417 const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted);
3418 return .{
3419 .runtime_order = ro,
3420 .fields_len = @intCast(ro.len),
3421 .next_index = 0,
3422 };
3423 },
3424 .@"extern" => return .{
3425 .runtime_order = null,
3426 .fields_len = s.field_names.len,
3427 .next_index = 0,
3428 },
3429 .@"packed" => unreachable,
3430 }
38243431 }
3432 pub const RuntimeOrderIterator = struct {
3433 runtime_order: ?[]const RuntimeOrder,
3434 fields_len: u32,
3435 next_index: u32,
3436 pub fn next(it: *RuntimeOrderIterator) ?u32 {
3437 const i = it.next_index;
3438 if (i == it.fields_len) return null;
3439 it.next_index = i + 1;
3440 const ro = it.runtime_order orelse return i;
3441 return ro[i].toInt().?;
3442 }
3443 };
38253444
3826 /// Reads the non-opv flag calculated during AstGen. Used to short-circuit more
3827 /// complicated logic.
3828 pub fn knownNonOpv(s: LoadedStructType, ip: *const InternPool) bool {
3829 return switch (s.layout) {
3830 .@"packed" => false,
3831 .auto, .@"extern" => s.flagsUnordered(ip).known_non_opv,
3832 };
3445 pub fn iterateRuntimeOrderReverse(s: *const LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator {
3446 switch (s.layout) {
3447 .auto => {
3448 const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted);
3449 return .{
3450 .runtime_order = ro,
3451 .last_index = @intCast(ro.len),
3452 };
3453 },
3454 .@"extern" => return .{
3455 .runtime_order = null,
3456 .last_index = s.field_names.len,
3457 },
3458 .@"packed" => unreachable,
3459 }
38333460 }
3461 pub const ReverseRuntimeOrderIterator = struct {
3462 runtime_order: ?[]const RuntimeOrder,
3463 last_index: u32,
3464 pub fn next(it: *ReverseRuntimeOrderIterator) ?u32 {
3465 if (it.last_index == 0) return null;
3466 const i = it.last_index - 1;
3467 it.last_index = i;
3468 const ro = it.runtime_order orelse return i;
3469 return ro[i].toInt().?;
3470 }
3471 };
3472};
38343473
3835 pub fn requiresComptime(s: LoadedStructType, ip: *const InternPool) RequiresComptime {
3836 return s.flagsUnordered(ip).requires_comptime;
3837 }
3474/// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a
3475/// minimal hashmap key, this type is a convenience type that contains info
3476/// needed by semantic analysis.
3477pub const LoadedUnionType = struct {
3478 /// Index of the `union_decl` or `reify` ZIR instruction.
3479 zir_index: TrackedInst.Index,
3480 captures: CaptureValue.Slice,
38383481
3839 pub fn setRequiresComptimeWip(s: LoadedStructType, ip: *InternPool, io: Io) RequiresComptime {
3840 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3841 extra_mutex.lockUncancelable(io);
3842 defer extra_mutex.unlock(io);
3482 // TODO: the non-fqn will be needed by the new dwarf structure
3483 /// The name of this union type.
3484 name: NullTerminatedString,
3485 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3486 /// Otherwise, this is `.none`.
3487 name_nav: Nav.Index.Optional,
3488 namespace: NamespaceIndex,
38433489
3844 const flags_ptr = s.flagsPtr(ip);
3845 var flags = flags_ptr.*;
3846 defer if (flags.requires_comptime == .unknown) {
3847 flags.requires_comptime = .wip;
3848 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3849 };
3850 return flags.requires_comptime;
3851 }
3490 layout: std.builtin.Type.ContainerLayout,
3491 runtime_tag: RuntimeTag,
3492 /// Even if `runtime_tag == .none`, this is populated with the union's "hypothetical" tag type.
3493 enum_tag_type: Index,
3494 /// May be `undefined` if `layout != .@"packed"`.
3495 packed_backing_mode: PackedBackingMode,
3496 /// May be `undefined` if `layout != .@"packed",
3497 packed_backing_int_type: Index,
3498
3499 // Field names are not stored here, because fields are guaranteed to map one-to-one to the
3500 // fields of the enum tag type. If you need field names, load them from `enum_tag_type`.
3501 field_types: Index.Slice,
3502 field_aligns: Alignment.Slice,
38523503
3853 pub fn setRequiresComptime(s: LoadedStructType, ip: *InternPool, io: Io, requires_comptime: RequiresComptime) void {
3854 assert(requires_comptime != .wip); // see setRequiresComptimeWip
3504 // These fields are only valid once the layout is resolved, and are never valid for `layout == .@"packed"`.
3505 has_no_possible_value: bool,
3506 has_one_possible_value: bool,
3507 comptime_only: bool,
3508 size: u32,
3509 padding: u32,
3510 alignment: Alignment,
38553511
3856 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3857 extra_mutex.lockUncancelable(io);
3858 defer extra_mutex.unlock(io);
3512 pub const RuntimeTag = enum(u2) {
3513 none,
3514 safety,
3515 tagged,
3516 };
3517};
38593518
3860 const flags_ptr = s.flagsPtr(ip);
3861 var flags = flags_ptr.*;
3862 flags.requires_comptime = requires_comptime;
3863 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3864 }
3519pub const LoadedEnumType = struct {
3520 /// This is `none` iff this is a generated tag type.
3521 /// Otherwise, index of the `enum_decl` or `reify` ZIR instruction.
3522 zir_index: TrackedInst.Index.Optional,
3523 captures: CaptureValue.Slice,
3524 /// If `zir_index` is `.none`, this is the union type for which this enum is the tag type.
3525 owner_union: Index,
38653526
3866 pub fn assumeRuntimeBitsIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3867 if (s.layout == .@"packed") return false;
3527 // TODO: the non-fqn will be needed by the new dwarf structure
3528 /// The name of this enum type.
3529 name: NullTerminatedString,
3530 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3531 /// Otherwise, this is `.none`.
3532 name_nav: Nav.Index.Optional,
3533 namespace: NamespaceIndex,
38683534
3869 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3870 extra_mutex.lockUncancelable(io);
3871 defer extra_mutex.unlock(io);
3535 /// An integer type which is used for the numerical value of the enum. Populated immediately, regardless
3536 /// of whether the integer tag type was explicitly provided or inferred by the compiler.
3537 int_tag_type: Index,
3538 int_tag_is_explicit: bool,
3539 nonexhaustive: bool,
3540
3541 /// Uses `NullTerminatedString.Adapter` with `field_names`.
3542 field_name_map: MapIndex,
3543 /// If this is `.none`, the enum tag type is auto-generated and so the fields are auto-numbered.
3544 /// Otherwise, uses `Index.Adapter` with `field_values`.
3545 field_value_map: OptionalMapIndex,
3546 field_names: NullTerminatedString.Slice,
3547 /// Empty if `field_value_map` is `.none`.
3548 field_values: Index.Slice,
38723549
3873 const flags_ptr = s.flagsPtr(ip);
3874 var flags = flags_ptr.*;
3875 defer if (flags.field_types_wip) {
3876 flags.assumed_runtime_bits = true;
3877 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3878 };
3879 return flags.field_types_wip;
3550 /// Look up field index based on field name.
3551 pub fn nameIndex(e: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
3552 const map = e.field_name_map.get(ip);
3553 const adapter: NullTerminatedString.Adapter = .{ .strings = e.field_names.get(ip) };
3554 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
3555 return @intCast(field_index);
38803556 }
38813557
3882 pub fn setFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3883 if (s.layout == .@"packed") return false;
3884
3885 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3886 extra_mutex.lockUncancelable(io);
3887 defer extra_mutex.unlock(io);
3888
3889 const flags_ptr = s.flagsPtr(ip);
3890 var flags = flags_ptr.*;
3891 defer {
3892 flags.field_types_wip = true;
3893 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3558 /// Look up field index based on integer tag value.
3559 /// Asserts that the type of `tag_val` is `enum_obj.int_tag_type`.
3560 /// Asserts that `tag_val` is not `undefined`.
3561 pub fn tagValueIndex(e: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 {
3562 assert(ip.typeOf(tag_val) == e.int_tag_type);
3563 assert(ip.indexToKey(tag_val) == .int);
3564 if (e.field_value_map.unwrap()) |field_value_map| {
3565 const map = field_value_map.get(ip);
3566 const adapter: Index.Adapter = .{ .indexes = e.field_values.get(ip) };
3567 const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null;
3568 return @intCast(field_index);
38943569 }
3895 return flags.field_types_wip;
3570 // Auto-numbered enum, so convert `tag_val` to field index
3571 const field_index = switch (ip.indexToKey(tag_val).int.storage) {
3572 inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null,
3573 .big_int => |x| x.toInt(u32) catch return null,
3574 };
3575 return if (field_index < e.field_names.len) field_index else null;
38963576 }
3577};
38973578
3898 pub fn clearFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3899 if (s.layout == .@"packed") return;
3579pub const LoadedOpaqueType = struct {
3580 /// Index of the `opaque_decl` instruction.
3581 zir_index: TrackedInst.Index,
3582 captures: CaptureValue.Slice,
39003583
3901 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3902 extra_mutex.lockUncancelable(io);
3903 defer extra_mutex.unlock(io);
3904
3905 const flags_ptr = s.flagsPtr(ip);
3906 var flags = flags_ptr.*;
3907 flags.field_types_wip = false;
3908 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3909 }
3910
3911 pub fn setLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3912 if (s.layout == .@"packed") return false;
3913
3914 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3915 extra_mutex.lockUncancelable(io);
3916 defer extra_mutex.unlock(io);
3917
3918 const flags_ptr = s.flagsPtr(ip);
3919 var flags = flags_ptr.*;
3920 defer {
3921 flags.layout_wip = true;
3922 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3923 }
3924 return flags.layout_wip;
3925 }
3926
3927 pub fn clearLayoutWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3928 if (s.layout == .@"packed") return;
3929
3930 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3931 extra_mutex.lockUncancelable(io);
3932 defer extra_mutex.unlock(io);
3933
3934 const flags_ptr = s.flagsPtr(ip);
3935 var flags = flags_ptr.*;
3936 flags.layout_wip = false;
3937 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3938 }
3939
3940 pub fn setAlignment(s: LoadedStructType, ip: *InternPool, io: Io, alignment: Alignment) void {
3941 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3942 extra_mutex.lockUncancelable(io);
3943 defer extra_mutex.unlock(io);
3944
3945 const flags_ptr = s.flagsPtr(ip);
3946 var flags = flags_ptr.*;
3947 flags.alignment = alignment;
3948 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3949 }
3950
3951 pub fn assumePointerAlignedIfFieldTypesWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3952 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3953 extra_mutex.lockUncancelable(io);
3954 defer extra_mutex.unlock(io);
3955
3956 const flags_ptr = s.flagsPtr(ip);
3957 var flags = flags_ptr.*;
3958 defer if (flags.field_types_wip) {
3959 flags.alignment = ptr_align;
3960 flags.assumed_pointer_aligned = true;
3961 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3962 };
3963 return flags.field_types_wip;
3964 }
3965
3966 pub fn assumePointerAlignedIfWip(s: LoadedStructType, ip: *InternPool, io: Io, ptr_align: Alignment) bool {
3967 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3968 extra_mutex.lockUncancelable(io);
3969 defer extra_mutex.unlock(io);
3970
3971 const flags_ptr = s.flagsPtr(ip);
3972 var flags = flags_ptr.*;
3973 defer {
3974 if (flags.alignment_wip) {
3975 flags.alignment = ptr_align;
3976 flags.assumed_pointer_aligned = true;
3977 } else flags.alignment_wip = true;
3978 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3979 }
3980 return flags.alignment_wip;
3981 }
3982
3983 pub fn clearAlignmentWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
3984 if (s.layout == .@"packed") return;
3985
3986 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3987 extra_mutex.lockUncancelable(io);
3988 defer extra_mutex.unlock(io);
3989
3990 const flags_ptr = s.flagsPtr(ip);
3991 var flags = flags_ptr.*;
3992 flags.alignment_wip = false;
3993 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
3994 }
3995
3996 pub fn setInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) bool {
3997 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
3998 extra_mutex.lockUncancelable(io);
3999 defer extra_mutex.unlock(io);
4000
4001 switch (s.layout) {
4002 .@"packed" => {
4003 const flags_ptr = s.packedFlagsPtr(ip);
4004 var flags = flags_ptr.*;
4005 defer {
4006 flags.field_inits_wip = true;
4007 @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release);
4008 }
4009 return flags.field_inits_wip;
4010 },
4011 .auto, .@"extern" => {
4012 const flags_ptr = s.flagsPtr(ip);
4013 var flags = flags_ptr.*;
4014 defer {
4015 flags.field_inits_wip = true;
4016 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4017 }
4018 return flags.field_inits_wip;
4019 },
4020 }
4021 }
4022
4023 pub fn clearInitsWip(s: LoadedStructType, ip: *InternPool, io: Io) void {
4024 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4025 extra_mutex.lockUncancelable(io);
4026 defer extra_mutex.unlock(io);
4027
4028 switch (s.layout) {
4029 .@"packed" => {
4030 const flags_ptr = s.packedFlagsPtr(ip);
4031 var flags = flags_ptr.*;
4032 flags.field_inits_wip = false;
4033 @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release);
4034 },
4035 .auto, .@"extern" => {
4036 const flags_ptr = s.flagsPtr(ip);
4037 var flags = flags_ptr.*;
4038 flags.field_inits_wip = false;
4039 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4040 },
4041 }
4042 }
4043
4044 pub fn setFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) bool {
4045 if (s.layout == .@"packed") return true;
4046
4047 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4048 extra_mutex.lockUncancelable(io);
4049 defer extra_mutex.unlock(io);
4050
4051 const flags_ptr = s.flagsPtr(ip);
4052 var flags = flags_ptr.*;
4053 defer {
4054 flags.fully_resolved = true;
4055 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4056 }
4057 return flags.fully_resolved;
4058 }
4059
4060 pub fn clearFullyResolved(s: LoadedStructType, ip: *InternPool, io: Io) void {
4061 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4062 extra_mutex.lockUncancelable(io);
4063 defer extra_mutex.unlock(io);
4064
4065 const flags_ptr = s.flagsPtr(ip);
4066 var flags = flags_ptr.*;
4067 flags.fully_resolved = false;
4068 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4069 }
4070
4071 /// The returned pointer expires with any addition to the `InternPool`.
4072 /// Asserts the struct is not packed.
4073 fn sizePtr(s: LoadedStructType, ip: *const InternPool) *u32 {
4074 assert(s.layout != .@"packed");
4075 const extra = ip.getLocalShared(s.tid).extra.acquire();
4076 const size_field_index = std.meta.fieldIndex(Tag.TypeStruct, "size").?;
4077 return @ptrCast(&extra.view().items(.@"0")[s.extra_index + size_field_index]);
4078 }
4079
4080 pub fn sizeUnordered(s: LoadedStructType, ip: *const InternPool) u32 {
4081 return @atomicLoad(u32, s.sizePtr(ip), .unordered);
4082 }
4083
4084 /// The backing integer type of the packed struct. Whether zig chooses
4085 /// this type or the user specifies it, it is stored here. This will be
4086 /// set to `none` until the layout is resolved.
4087 /// Asserts the struct is packed.
4088 fn backingIntTypePtr(s: LoadedStructType, ip: *const InternPool) *Index {
4089 assert(s.layout == .@"packed");
4090 const extra = ip.getLocalShared(s.tid).extra.acquire();
4091 const field_index = std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_ty").?;
4092 return @ptrCast(&extra.view().items(.@"0")[s.extra_index + field_index]);
4093 }
4094
4095 pub fn backingIntTypeUnordered(s: LoadedStructType, ip: *const InternPool) Index {
4096 return @atomicLoad(Index, s.backingIntTypePtr(ip), .unordered);
4097 }
4098
4099 pub fn setBackingIntType(s: LoadedStructType, ip: *InternPool, io: Io, backing_int_ty: Index) void {
4100 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4101 extra_mutex.lockUncancelable(io);
4102 defer extra_mutex.unlock(io);
4103
4104 @atomicStore(Index, s.backingIntTypePtr(ip), backing_int_ty, .release);
4105 }
4106
4107 /// Asserts the struct is not packed.
4108 pub fn setZirIndex(s: LoadedStructType, ip: *InternPool, new_zir_index: TrackedInst.Index.Optional) void {
4109 assert(s.layout != .@"packed");
4110 const field_index = std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?;
4111 ip.extra_.items[s.extra_index + field_index] = @intFromEnum(new_zir_index);
4112 }
4113
4114 pub fn haveFieldTypes(s: LoadedStructType, ip: *const InternPool) bool {
4115 const types = s.field_types.get(ip);
4116 return types.len == 0 or types[types.len - 1] != .none;
4117 }
4118
4119 pub fn haveFieldInits(s: LoadedStructType, ip: *const InternPool) bool {
4120 return switch (s.layout) {
4121 .@"packed" => s.packedFlagsUnordered(ip).inits_resolved,
4122 .auto, .@"extern" => s.flagsUnordered(ip).inits_resolved,
4123 };
4124 }
4125
4126 pub fn setHaveFieldInits(s: LoadedStructType, ip: *InternPool, io: Io) void {
4127 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4128 extra_mutex.lockUncancelable(io);
4129 defer extra_mutex.unlock(io);
4130
4131 switch (s.layout) {
4132 .@"packed" => {
4133 const flags_ptr = s.packedFlagsPtr(ip);
4134 var flags = flags_ptr.*;
4135 flags.inits_resolved = true;
4136 @atomicStore(Tag.TypeStructPacked.Flags, flags_ptr, flags, .release);
4137 },
4138 .auto, .@"extern" => {
4139 const flags_ptr = s.flagsPtr(ip);
4140 var flags = flags_ptr.*;
4141 flags.inits_resolved = true;
4142 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4143 },
4144 }
4145 }
4146
4147 pub fn haveLayout(s: LoadedStructType, ip: *const InternPool) bool {
4148 return switch (s.layout) {
4149 .@"packed" => s.backingIntTypeUnordered(ip) != .none,
4150 .auto, .@"extern" => s.flagsUnordered(ip).layout_resolved,
4151 };
4152 }
4153
4154 pub fn setLayoutResolved(s: LoadedStructType, ip: *InternPool, io: Io, size: u32, alignment: Alignment) void {
4155 const extra_mutex = &ip.getLocal(s.tid).mutate.extra.mutex;
4156 extra_mutex.lockUncancelable(io);
4157 defer extra_mutex.unlock(io);
4158
4159 @atomicStore(u32, s.sizePtr(ip), size, .unordered);
4160 const flags_ptr = s.flagsPtr(ip);
4161 var flags = flags_ptr.*;
4162 flags.alignment = alignment;
4163 flags.layout_resolved = true;
4164 @atomicStore(Tag.TypeStruct.Flags, flags_ptr, flags, .release);
4165 }
4166
4167 pub fn hasReorderedFields(s: LoadedStructType) bool {
4168 return s.layout == .auto;
4169 }
4170
4171 pub const RuntimeOrderIterator = struct {
4172 ip: *InternPool,
4173 field_index: u32,
4174 struct_type: InternPool.LoadedStructType,
4175
4176 pub fn next(it: *@This()) ?u32 {
4177 var i = it.field_index;
4178
4179 if (i >= it.struct_type.field_types.len)
4180 return null;
4181
4182 if (it.struct_type.hasReorderedFields()) {
4183 it.field_index += 1;
4184 return it.struct_type.runtime_order.get(it.ip)[i].toInt();
4185 }
4186
4187 while (it.struct_type.fieldIsComptime(it.ip, i)) {
4188 i += 1;
4189 if (i >= it.struct_type.field_types.len)
4190 return null;
4191 }
4192
4193 it.field_index = i + 1;
4194 return i;
4195 }
4196 };
4197
4198 /// Iterates over non-comptime fields in the order they are laid out in memory at runtime.
4199 /// May or may not include zero-bit fields.
4200 /// Asserts the struct is not packed.
4201 pub fn iterateRuntimeOrder(s: LoadedStructType, ip: *InternPool) RuntimeOrderIterator {
4202 assert(s.layout != .@"packed");
4203 return .{
4204 .ip = ip,
4205 .field_index = 0,
4206 .struct_type = s,
4207 };
4208 }
4209
4210 pub const ReverseRuntimeOrderIterator = struct {
4211 ip: *InternPool,
4212 last_index: u32,
4213 struct_type: InternPool.LoadedStructType,
4214
4215 pub fn next(it: *@This()) ?u32 {
4216 if (it.last_index == 0)
4217 return null;
4218
4219 if (it.struct_type.hasReorderedFields()) {
4220 it.last_index -= 1;
4221 const order = it.struct_type.runtime_order.get(it.ip);
4222 while (order[it.last_index] == .omitted) {
4223 it.last_index -= 1;
4224 if (it.last_index == 0)
4225 return null;
4226 }
4227 return order[it.last_index].toInt();
4228 }
4229
4230 it.last_index -= 1;
4231 while (it.struct_type.fieldIsComptime(it.ip, it.last_index)) {
4232 it.last_index -= 1;
4233 if (it.last_index == 0)
4234 return null;
4235 }
4236
4237 return it.last_index;
4238 }
4239 };
4240
4241 pub fn iterateRuntimeOrderReverse(s: LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator {
4242 assert(s.layout != .@"packed");
4243 return .{
4244 .ip = ip,
4245 .last_index = s.field_types.len,
4246 .struct_type = s,
4247 };
4248 }
4249};
3584 // TODO: the non-fqn will be needed by the new dwarf structure
3585 /// The name of this opaque type.
3586 name: NullTerminatedString,
3587 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
3588 /// Otherwise, this is `.none`.
3589 name_nav: Nav.Index.Optional,
3590 namespace: NamespaceIndex,
3591};
42503592
42513593pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
42523594 const unwrapped_index = index.unwrap(ip);
42533595 const extra_list = unwrapped_index.getExtra(ip);
42543596 const extra_items = extra_list.view().items(.@"0");
42553597 const item = unwrapped_index.getItem(ip);
4256 switch (item.tag) {
3598 // Exiting this `switch` means this is a `packed struct`.
3599 const backing_mode: PackedBackingMode, const any_defaults: bool = switch (item.tag) {
3600 .type_struct_packed_auto => .{ .auto, false },
3601 .type_struct_packed_explicit => .{ .explicit, false },
3602 .type_struct_packed_auto_defaults => .{ .auto, true },
3603 .type_struct_packed_explicit_defaults => .{ .explicit, true },
42573604 .type_struct => {
4258 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name").?]);
4259 const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?]);
4260 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?]);
4261 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
4262 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "fields_len").?];
4263 const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered));
4264 var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len);
4265 const captures_len = if (flags.any_captures) c: {
4266 const len = extra_list.view().items(.@"0")[extra_index];
4267 extra_index += 1;
4268 break :c len;
4269 } else 0;
4270 const captures: CaptureValue.Slice = .{
3605 const extra = extraDataTrail(extra_list, Tag.TypeStruct, item.data);
3606 var extra_index = extra.end;
3607 const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) {
3608 .reified => captures: {
3609 extra_index += 2; // type_hash: PackedU64
3610 break :captures .empty;
3611 },
3612 .false => .empty,
3613 .true => captures: {
3614 const len = extra_items[extra_index];
3615 extra_index += 1;
3616 break :captures .{
3617 .tid = unwrapped_index.tid,
3618 .start = extra_index,
3619 .len = len,
3620 };
3621 },
3622 };
3623 extra_index += captures.len;
3624 const field_names: NullTerminatedString.Slice = .{
42713625 .tid = unwrapped_index.tid,
42723626 .start = extra_index,
4273 .len = captures_len,
3627 .len = extra.data.fields_len,
42743628 };
4275 extra_index += captures_len;
4276 if (flags.is_reified) {
4277 extra_index += 2; // type_hash: PackedU64
4278 }
3629 extra_index += field_names.len;
42793630 const field_types: Index.Slice = .{
42803631 .tid = unwrapped_index.tid,
42813632 .start = extra_index,
4282 .len = fields_len,
4283 };
4284 extra_index += fields_len;
4285 const names_map: OptionalMapIndex, const names = n: {
4286 const names_map: OptionalMapIndex = @enumFromInt(extra_list.view().items(.@"0")[extra_index]);
4287 extra_index += 1;
4288 const names: NullTerminatedString.Slice = .{
4289 .tid = unwrapped_index.tid,
4290 .start = extra_index,
4291 .len = fields_len,
4292 };
4293 extra_index += fields_len;
4294 break :n .{ names_map, names };
3633 .len = extra.data.fields_len,
42953634 };
4296 const inits: Index.Slice = if (flags.any_default_inits) i: {
4297 const inits: Index.Slice = .{
4298 .tid = unwrapped_index.tid,
4299 .start = extra_index,
4300 .len = fields_len,
4301 };
4302 extra_index += fields_len;
4303 break :i inits;
4304 } else Index.Slice.empty;
4305 const aligns: Alignment.Slice = if (flags.any_aligned_fields) a: {
4306 const a: Alignment.Slice = .{
4307 .tid = unwrapped_index.tid,
4308 .start = extra_index,
4309 .len = fields_len,
4310 };
4311 extra_index += std.math.divCeil(u32, fields_len, 4) catch unreachable;
4312 break :a a;
4313 } else Alignment.Slice.empty;
4314 const comptime_bits: LoadedStructType.ComptimeBits = if (flags.any_comptime_fields) c: {
4315 const len = std.math.divCeil(u32, fields_len, 32) catch unreachable;
4316 const c: LoadedStructType.ComptimeBits = .{
4317 .tid = unwrapped_index.tid,
4318 .start = extra_index,
4319 .len = len,
4320 };
4321 extra_index += len;
4322 break :c c;
4323 } else LoadedStructType.ComptimeBits.empty;
4324 const runtime_order: LoadedStructType.RuntimeOrder.Slice = if (!flags.is_extern) ro: {
4325 const ro: LoadedStructType.RuntimeOrder.Slice = .{
4326 .tid = unwrapped_index.tid,
4327 .start = extra_index,
4328 .len = fields_len,
4329 };
4330 extra_index += fields_len;
4331 break :ro ro;
4332 } else LoadedStructType.RuntimeOrder.Slice.empty;
4333 const offsets: LoadedStructType.Offsets = o: {
4334 const o: LoadedStructType.Offsets = .{
4335 .tid = unwrapped_index.tid,
4336 .start = extra_index,
4337 .len = fields_len,
4338 };
4339 extra_index += fields_len;
4340 break :o o;
4341 };
4342 return .{
3635 extra_index += field_types.len;
3636 const field_defaults: Index.Slice = if (extra.data.flags.any_field_defaults) .{
43433637 .tid = unwrapped_index.tid,
4344 .extra_index = item.data,
4345 .name = name,
4346 .name_nav = name_nav,
4347 .namespace = namespace,
4348 .zir_index = zir_index,
4349 .layout = if (flags.is_extern) .@"extern" else .auto,
4350 .field_names = names,
4351 .field_types = field_types,
4352 .field_inits = inits,
4353 .field_aligns = aligns,
4354 .runtime_order = runtime_order,
4355 .comptime_bits = comptime_bits,
4356 .offsets = offsets,
4357 .names_map = names_map,
4358 .captures = captures,
4359 };
4360 },
4361 .type_struct_packed, .type_struct_packed_inits => {
4362 const name: NullTerminatedString = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?]);
4363 const name_nav: Nav.Index.Optional = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?]);
4364 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
4365 const fields_len = extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "fields_len").?];
4366 const namespace: NamespaceIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?]);
4367 const names_map: MapIndex = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "names_map").?]);
4368 const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered));
4369 var extra_index = item.data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len);
4370 const has_inits = item.tag == .type_struct_packed_inits;
4371 const captures_len = if (flags.any_captures) c: {
4372 const len = extra_list.view().items(.@"0")[extra_index];
4373 extra_index += 1;
4374 break :c len;
4375 } else 0;
4376 const captures: CaptureValue.Slice = .{
3638 .start = extra_index,
3639 .len = extra.data.fields_len,
3640 } else .empty;
3641 extra_index += field_defaults.len;
3642 const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{
43773643 .tid = unwrapped_index.tid,
43783644 .start = extra_index,
4379 .len = captures_len,
4380 };
4381 extra_index += captures_len;
4382 if (flags.is_reified) {
4383 extra_index += 2; // PackedU64
4384 }
4385 const field_types: Index.Slice = .{
3645 .len = extra.data.fields_len,
3646 } else .empty;
3647 extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable;
3648 const field_is_comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) .{
43863649 .tid = unwrapped_index.tid,
43873650 .start = extra_index,
4388 .len = fields_len,
4389 };
4390 extra_index += fields_len;
4391 const field_names: NullTerminatedString.Slice = .{
3651 .len = std.math.divCeil(u32, extra.data.fields_len, 32) catch unreachable,
3652 } else .empty;
3653 extra_index += field_is_comptime_bits.len;
3654 const field_runtime_order: LoadedStructType.RuntimeOrder.Slice = if (extra.data.flags.layout == .auto) .{
43923655 .tid = unwrapped_index.tid,
43933656 .start = extra_index,
4394 .len = fields_len,
3657 .len = extra.data.fields_len,
3658 } else .empty;
3659 extra_index += field_runtime_order.len;
3660 const field_offsets: LoadedStructType.Offsets = .{
3661 .tid = unwrapped_index.tid,
3662 .start = extra_index,
3663 .len = extra.data.fields_len,
43953664 };
4396 extra_index += fields_len;
4397 const field_inits: Index.Slice = if (has_inits) inits: {
4398 const i: Index.Slice = .{
4399 .tid = unwrapped_index.tid,
4400 .start = extra_index,
4401 .len = fields_len,
4402 };
4403 extra_index += fields_len;
4404 break :inits i;
4405 } else Index.Slice.empty;
3665 extra_index += field_offsets.len;
3666
44063667 return .{
4407 .tid = unwrapped_index.tid,
4408 .extra_index = item.data,
4409 .name = name,
4410 .name_nav = name_nav,
4411 .namespace = namespace,
4412 .zir_index = zir_index,
4413 .layout = .@"packed",
3668 .zir_index = extra.data.zir_index,
3669 .captures = captures,
3670 .name = extra.data.name,
3671 .name_nav = extra.data.name_nav,
3672 .namespace = extra.data.namespace,
3673 .layout = switch (extra.data.flags.layout) {
3674 .auto => .auto,
3675 .@"extern" => .@"extern",
3676 },
3677 .packed_backing_mode = undefined,
3678 .packed_backing_int_type = undefined,
3679 .field_name_map = extra.data.field_name_map,
44143680 .field_names = field_names,
44153681 .field_types = field_types,
4416 .field_inits = field_inits,
4417 .field_aligns = Alignment.Slice.empty,
4418 .runtime_order = LoadedStructType.RuntimeOrder.Slice.empty,
4419 .comptime_bits = LoadedStructType.ComptimeBits.empty,
4420 .offsets = LoadedStructType.Offsets.empty,
4421 .names_map = names_map.toOptional(),
4422 .captures = captures,
3682 .field_defaults = field_defaults,
3683 .field_aligns = field_aligns,
3684 .field_is_comptime_bits = field_is_comptime_bits,
3685 .field_runtime_order = field_runtime_order,
3686 .field_offsets = field_offsets,
3687 .has_no_possible_value = extra.data.flags.has_no_possible_value,
3688 .has_one_possible_value = extra.data.flags.has_one_possible_value,
3689 .comptime_only = extra.data.flags.comptime_only,
3690 .size = extra.data.size,
3691 .alignment = extra.data.flags.alignment,
44233692 };
44243693 },
44253694 else => unreachable,
4426 }
4427}
4428
4429pub const LoadedEnumType = struct {
4430 // TODO: the non-fqn will be needed by the new dwarf structure
4431 /// The name of this enum type.
4432 name: NullTerminatedString,
4433 /// Represents the declarations inside this enum.
4434 namespace: NamespaceIndex,
4435 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
4436 /// Otherwise, this is `.none`.
4437 name_nav: Nav.Index.Optional,
4438 /// An integer type which is used for the numerical value of the enum.
4439 /// This field is present regardless of whether the enum has an
4440 /// explicitly provided tag type or auto-numbered.
4441 tag_ty: Index,
4442 /// Set of field names in declaration order.
4443 names: NullTerminatedString.Slice,
4444 /// Maps integer tag value to field index.
4445 /// Entries are in declaration order, same as `fields`.
4446 /// If this is empty, it means the enum tags are auto-numbered.
4447 values: Index.Slice,
4448 tag_mode: TagMode,
4449 names_map: MapIndex,
4450 /// This is guaranteed to not be `.none` if explicit values are provided.
4451 values_map: OptionalMapIndex,
4452 /// This is `none` only if this is a generated tag type.
4453 zir_index: TrackedInst.Index.Optional,
4454 captures: CaptureValue.Slice,
4455
4456 pub const TagMode = enum {
4457 /// The integer tag type was auto-numbered by zig.
4458 auto,
4459 /// The integer tag type was provided by the enum declaration, and the enum
4460 /// is exhaustive.
4461 explicit,
4462 /// The integer tag type was provided by the enum declaration, and the enum
4463 /// is non-exhaustive.
4464 nonexhaustive,
44653695 };
3696 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data);
3697 var extra_index = extra.end;
3698 const captures: CaptureValue.Slice = switch (extra.data.captures_len) {
3699 .reified => captures: {
3700 extra_index += 2; // type_hash: PackedU64
3701 break :captures .empty;
3702 },
3703 _ => .{
3704 .tid = unwrapped_index.tid,
3705 .start = extra_index,
3706 .len = @intFromEnum(extra.data.captures_len),
3707 },
3708 };
3709 extra_index += captures.len;
3710 const field_names: NullTerminatedString.Slice = .{
3711 .tid = unwrapped_index.tid,
3712 .start = extra_index,
3713 .len = extra.data.fields_len,
3714 };
3715 extra_index += field_names.len;
3716 const field_types: Index.Slice = .{
3717 .tid = unwrapped_index.tid,
3718 .start = extra_index,
3719 .len = extra.data.fields_len,
3720 };
3721 extra_index += field_types.len;
3722 const field_defaults: Index.Slice = if (any_defaults) .{
3723 .tid = unwrapped_index.tid,
3724 .start = extra_index,
3725 .len = extra.data.fields_len,
3726 } else .empty;
3727 extra_index += field_defaults.len;
3728 return .{
3729 .zir_index = extra.data.zir_index,
3730 .captures = captures,
3731 .name = extra.data.name,
3732 .name_nav = extra.data.name_nav,
3733 .namespace = extra.data.namespace,
3734 .layout = .@"packed",
3735 .packed_backing_mode = backing_mode,
3736 .packed_backing_int_type = extra.data.backing_int_type,
3737 .field_name_map = extra.data.field_name_map,
3738 .field_names = field_names,
3739 .field_types = field_types,
3740 .field_defaults = field_defaults,
3741 .field_aligns = .empty,
3742 .field_is_comptime_bits = .empty,
3743 .field_runtime_order = .empty,
3744 .field_offsets = .empty,
3745 .has_no_possible_value = undefined,
3746 .has_one_possible_value = undefined,
3747 .comptime_only = undefined,
3748 .size = undefined,
3749 .alignment = undefined,
3750 };
3751}
44663752
4467 /// Look up field index based on field name.
4468 pub fn nameIndex(self: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
4469 const map = self.names_map.get(ip);
4470 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) };
4471 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
4472 return @intCast(field_index);
4473 }
4474
4475 /// Look up field index based on tag value.
4476 /// Asserts that `values_map` is not `none`.
4477 /// This function returns `null` when `tag_val` does not have the
4478 /// integer tag type of the enum.
4479 pub fn tagValueIndex(self: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 {
4480 assert(tag_val != .none);
4481 // TODO: we should probably decide a single interface for this function, but currently
4482 // it's being called with both tag values and underlying ints. Fix this!
4483 const int_tag_val = switch (ip.indexToKey(tag_val)) {
4484 .enum_tag => |enum_tag| enum_tag.int,
4485 .int => tag_val,
4486 else => unreachable,
4487 };
4488 if (self.values_map.unwrap()) |values_map| {
4489 const map = values_map.get(ip);
4490 const adapter: Index.Adapter = .{ .indexes = self.values.get(ip) };
4491 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
4492 return @intCast(field_index);
4493 }
4494 // Auto-numbered enum. Convert `int_tag_val` to field index.
4495 const field_index = switch (ip.indexToKey(int_tag_val).int.storage) {
4496 inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null,
4497 .big_int => |x| x.toInt(u32) catch return null,
4498 .lazy_align, .lazy_size => unreachable,
4499 };
4500 return if (field_index < self.names.len) field_index else null;
4501 }
4502};
4503
4504pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
3753pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType {
45053754 const unwrapped_index = index.unwrap(ip);
45063755 const extra_list = unwrapped_index.getExtra(ip);
3756 const extra_items = extra_list.view().items(.@"0");
45073757 const item = unwrapped_index.getItem(ip);
4508 const tag_mode: LoadedEnumType.TagMode = switch (item.tag) {
4509 .type_enum_auto => {
4510 const extra = extraDataTrail(extra_list, EnumAuto, item.data);
4511 var extra_index: u32 = @intCast(extra.end);
4512 if (extra.data.zir_index == .none) {
4513 extra_index += 1; // owner_union
4514 }
4515 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4516 extra_index += 2; // type_hash: PackedU64
4517 break :c 0;
4518 } else extra.data.captures_len;
3758 // Exiting this `switch` means this is a `packed union`.
3759 const backing_mode: PackedBackingMode = switch (item.tag) {
3760 .type_union_packed_auto => .auto,
3761 .type_union_packed_explicit => .explicit,
3762 .type_union => {
3763 const extra = extraDataTrail(extra_list, Tag.TypeUnion, item.data);
3764 var extra_index = extra.end;
3765 const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) {
3766 .reified => captures: {
3767 extra_index += 2; // type_hash: PackedU64
3768 break :captures .empty;
3769 },
3770 .false => .empty,
3771 .true => captures: {
3772 const len = extra_items[extra_index];
3773 extra_index += 1;
3774 break :captures .{
3775 .tid = unwrapped_index.tid,
3776 .start = extra_index,
3777 .len = len,
3778 };
3779 },
3780 };
3781 extra_index += captures.len;
3782 const field_types: Index.Slice = .{
3783 .tid = unwrapped_index.tid,
3784 .start = extra_index,
3785 .len = extra.data.fields_len,
3786 };
3787 extra_index += field_types.len;
3788 const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{
3789 .tid = unwrapped_index.tid,
3790 .start = extra_index,
3791 .len = extra.data.fields_len,
3792 } else .empty;
3793 extra_index += std.math.divCeil(u32, field_aligns.len, 4) catch unreachable;
3794
45193795 return .{
3796 .zir_index = extra.data.zir_index,
3797 .captures = captures,
45203798 .name = extra.data.name,
45213799 .name_nav = extra.data.name_nav,
45223800 .namespace = extra.data.namespace,
4523 .tag_ty = extra.data.int_tag_type,
4524 .names = .{
4525 .tid = unwrapped_index.tid,
4526 .start = extra_index + captures_len,
4527 .len = extra.data.fields_len,
4528 },
4529 .values = Index.Slice.empty,
4530 .tag_mode = .auto,
4531 .names_map = extra.data.names_map,
4532 .values_map = .none,
4533 .zir_index = extra.data.zir_index,
4534 .captures = .{
4535 .tid = unwrapped_index.tid,
4536 .start = extra_index,
4537 .len = captures_len,
3801 .layout = switch (extra.data.flags.layout) {
3802 .auto => .auto,
3803 .@"extern" => .@"extern",
45383804 },
3805 .runtime_tag = extra.data.flags.runtime_tag,
3806 .enum_tag_type = extra.data.enum_tag_type,
3807 .packed_backing_mode = undefined,
3808 .packed_backing_int_type = undefined,
3809 .field_types = field_types,
3810 .field_aligns = field_aligns,
3811 .has_no_possible_value = extra.data.flags.has_no_possible_value,
3812 .has_one_possible_value = extra.data.flags.has_one_possible_value,
3813 .comptime_only = extra.data.flags.comptime_only,
3814 .size = extra.data.size,
3815 .padding = extra.data.padding,
3816 .alignment = extra.data.flags.alignment,
45393817 };
45403818 },
4541 .type_enum_explicit => .explicit,
4542 .type_enum_nonexhaustive => .nonexhaustive,
45433819 else => unreachable,
45443820 };
4545 const extra = extraDataTrail(extra_list, EnumExplicit, item.data);
4546 var extra_index: u32 = @intCast(extra.end);
4547 if (extra.data.zir_index == .none) {
4548 extra_index += 1; // owner_union
4549 }
4550 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32)) c: {
4551 extra_index += 2; // type_hash: PackedU64
4552 break :c 0;
4553 } else extra.data.captures_len;
4554 return .{
4555 .name = extra.data.name,
4556 .name_nav = extra.data.name_nav,
4557 .namespace = extra.data.namespace,
4558 .tag_ty = extra.data.int_tag_type,
4559 .names = .{
4560 .tid = unwrapped_index.tid,
4561 .start = extra_index + captures_len,
4562 .len = extra.data.fields_len,
4563 },
4564 .values = .{
4565 .tid = unwrapped_index.tid,
4566 .start = extra_index + captures_len + extra.data.fields_len,
4567 .len = if (extra.data.values_map != .none) extra.data.fields_len else 0,
3821 const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, item.data);
3822 var extra_index = extra.end;
3823 const captures: CaptureValue.Slice = switch (extra.data.captures_len) {
3824 .reified => captures: {
3825 extra_index += 2; // type_hash: PackedU64
3826 break :captures .empty;
45683827 },
4569 .tag_mode = tag_mode,
4570 .names_map = extra.data.names_map,
4571 .values_map = extra.data.values_map,
4572 .zir_index = extra.data.zir_index,
4573 .captures = .{
3828 _ => .{
45743829 .tid = unwrapped_index.tid,
45753830 .start = extra_index,
4576 .len = captures_len,
3831 .len = @intFromEnum(extra.data.captures_len),
45773832 },
45783833 };
4579}
4580
4581/// Note that this type doubles as the payload for `Tag.type_opaque`.
4582pub const LoadedOpaqueType = struct {
4583 /// Contains the declarations inside this opaque.
4584 namespace: NamespaceIndex,
4585 // TODO: the non-fqn will be needed by the new dwarf structure
4586 /// The name of this opaque type.
4587 name: NullTerminatedString,
4588 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after.
4589 /// Otherwise, this is `.none`.
4590 name_nav: Nav.Index.Optional,
4591 /// Index of the `opaque_decl` or `reify` instruction.
4592 zir_index: TrackedInst.Index,
4593 captures: CaptureValue.Slice,
4594};
3834 extra_index += captures.len;
3835 const field_types: Index.Slice = .{
3836 .tid = unwrapped_index.tid,
3837 .start = extra_index,
3838 .len = extra.data.fields_len,
3839 };
3840 extra_index += field_types.len;
3841 return .{
3842 .zir_index = extra.data.zir_index,
3843 .captures = captures,
3844 .name = extra.data.name,
3845 .name_nav = extra.data.name_nav,
3846 .namespace = extra.data.namespace,
3847 .layout = .@"packed",
3848 .runtime_tag = .none,
3849 .enum_tag_type = extra.data.enum_tag_type,
3850 .packed_backing_mode = backing_mode,
3851 .packed_backing_int_type = extra.data.backing_int_type,
3852 .field_types = field_types,
3853 .field_aligns = .empty,
3854 .has_no_possible_value = undefined,
3855 .has_one_possible_value = undefined,
3856 .comptime_only = undefined,
3857 .size = undefined,
3858 .padding = undefined,
3859 .alignment = undefined,
3860 };
3861}
45953862
4596pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
3863pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType {
45973864 const unwrapped_index = index.unwrap(ip);
3865 const extra_list = unwrapped_index.getExtra(ip);
3866 const extra_items = extra_list.view().items(.@"0");
45983867 const item = unwrapped_index.getItem(ip);
4599 assert(item.tag == .type_opaque);
4600 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, item.data);
4601 const captures_len = if (extra.data.captures_len == std.math.maxInt(u32))
4602 0
4603 else
4604 extra.data.captures_len;
3868 const explicit_int_tag: bool, const nonexhaustive: bool = switch (item.tag) {
3869 .type_enum_auto => .{ false, false },
3870 .type_enum_explicit => .{ true, false },
3871 .type_enum_nonexhaustive => .{ true, true },
3872 else => unreachable,
3873 };
3874 const extra = extraDataTrail(extra_list, Tag.TypeEnum, item.data);
3875 var extra_index: u32 = @intCast(extra.end);
3876 const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.captures_len) {
3877 .reified => info: {
3878 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]);
3879 extra_index += 1;
3880 extra_index += 2; // type_hash: PackedU64
3881 break :info .{ zir_index.toOptional(), .empty, .none };
3882 },
3883 .generated_union_tag => info: {
3884 const owner_union: Index = @enumFromInt(extra_items[extra_index]);
3885 extra_index += 1;
3886 break :info .{ .none, .empty, owner_union };
3887 },
3888 _ => info: {
3889 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[extra_index]);
3890 extra_index += 1;
3891 const captures: CaptureValue.Slice = .{
3892 .tid = unwrapped_index.tid,
3893 .start = extra_index,
3894 .len = @intFromEnum(extra.data.captures_len),
3895 };
3896 extra_index += captures.len;
3897 break :info .{ zir_index.toOptional(), captures, .none };
3898 },
3899 };
3900 const field_value_map: OptionalMapIndex = if (explicit_int_tag) m: {
3901 const map: MapIndex = @enumFromInt(extra_items[extra_index]);
3902 extra_index += 1;
3903 break :m map.toOptional();
3904 } else .none;
3905 const field_names: NullTerminatedString.Slice = .{
3906 .tid = unwrapped_index.tid,
3907 .start = extra_index,
3908 .len = extra.data.fields_len,
3909 };
3910 extra_index += field_names.len;
3911 const field_values: Index.Slice = if (explicit_int_tag) .{
3912 .tid = unwrapped_index.tid,
3913 .start = extra_index,
3914 .len = extra.data.fields_len,
3915 } else .empty;
3916 extra_index += field_values.len;
46053917 return .{
3918 .zir_index = zir_index,
3919 .captures = captures,
3920 .owner_union = owner_union,
46063921 .name = extra.data.name,
46073922 .name_nav = extra.data.name_nav,
46083923 .namespace = extra.data.namespace,
3924 .int_tag_type = extra.data.int_tag_type,
3925 .int_tag_is_explicit = explicit_int_tag,
3926 .nonexhaustive = nonexhaustive,
3927 .field_name_map = extra.data.field_name_map,
3928 .field_value_map = field_value_map,
3929 .field_names = field_names,
3930 .field_values = field_values,
3931 };
3932}
3933
3934pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType {
3935 const unwrapped_index = index.unwrap(ip);
3936 const item = unwrapped_index.getItem(ip);
3937 assert(item.tag == .type_opaque);
3938 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, item.data);
3939 return .{
46093940 .zir_index = extra.data.zir_index,
46103941 .captures = .{
46113942 .tid = unwrapped_index.tid,
46123943 .start = extra.end,
4613 .len = captures_len,
3944 .len = extra.data.captures_len,
46143945 },
3946 .name = extra.data.name,
3947 .name_nav = extra.data.name_nav,
3948 .namespace = extra.data.namespace,
46153949 };
46163950}
46173951
......@@ -4819,7 +4153,7 @@ pub const Index = enum(u32) {
48194153 };
48204154
48214155 /// Used for a map of `Index` values to the index within a list of `Index` values.
4822 const Adapter = struct {
4156 pub const Adapter = struct {
48234157 indexes: []const Index,
48244158
48254159 pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool {
......@@ -4891,26 +4225,6 @@ pub const Index = enum(u32) {
48914225 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
48924226 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
48934227 const DataIsIndex = struct { data: Index };
4894 const DataIsExtraIndexOfEnumExplicit = struct {
4895 const @"data.fields_len" = opaque {};
4896 data: *EnumExplicit,
4897 @"trailing.names.len": *@"data.fields_len",
4898 @"trailing.values.len": *@"data.fields_len",
4899 trailing: struct {
4900 names: []NullTerminatedString,
4901 values: []Index,
4902 },
4903 };
4904 const DataIsExtraIndexOfTypeTuple = struct {
4905 const @"data.fields_len" = opaque {};
4906 data: *TypeTuple,
4907 @"trailing.types.len": *@"data.fields_len",
4908 @"trailing.values.len": *@"data.fields_len",
4909 trailing: struct {
4910 types: []Index,
4911 values: []Index,
4912 },
4913 };
49144228
49154229 removed: void,
49164230 type_int_signed: struct { data: u32 },
......@@ -4931,21 +4245,7 @@ pub const Index = enum(u32) {
49314245 trailing: struct { names: []NullTerminatedString },
49324246 },
49334247 type_inferred_error_set: DataIsIndex,
4934 type_enum_auto: struct {
4935 const @"data.fields_len" = opaque {};
4936 data: *EnumAuto,
4937 @"trailing.names.len": *@"data.fields_len",
4938 trailing: struct { names: []NullTerminatedString },
4939 },
4940 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
4941 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
49424248 simple_type: void,
4943 type_opaque: struct { data: *Tag.TypeOpaque },
4944 type_struct: struct { data: *Tag.TypeStruct },
4945 type_struct_packed: struct { data: *Tag.TypeStructPacked },
4946 type_struct_packed_inits: struct { data: *Tag.TypeStructPacked },
4947 type_tuple: DataIsExtraIndexOfTypeTuple,
4948 type_union: struct { data: *Tag.TypeUnion },
49494249 type_function: struct {
49504250 const @"data.flags.has_comptime_bits" = opaque {};
49514251 const @"data.flags.has_noalias_bits" = opaque {};
......@@ -4956,6 +4256,29 @@ pub const Index = enum(u32) {
49564256 @"trailing.param_types.len": *@"data.params_len",
49574257 trailing: struct { comptime_bits: []u32, noalias_bits: []u32, param_types: []Index },
49584258 },
4259 type_tuple: struct {
4260 const @"data.fields_len" = opaque {};
4261 data: *TypeTuple,
4262 @"trailing.types.len": *@"data.fields_len",
4263 @"trailing.values.len": *@"data.fields_len",
4264 trailing: struct {
4265 types: []Index,
4266 values: []Index,
4267 },
4268 },
4269
4270 type_struct: struct { data: *Tag.TypeStruct },
4271 type_struct_packed_auto: struct { data: *Tag.TypeStructPacked },
4272 type_struct_packed_explicit: struct { data: *Tag.TypeStructPacked },
4273 type_struct_packed_auto_defaults: struct { data: *Tag.TypeStructPacked },
4274 type_struct_packed_explicit_defaults: struct { data: *Tag.TypeStructPacked },
4275 type_union: struct { data: *Tag.TypeUnion },
4276 type_union_packed_auto: struct { data: *Tag.TypeUnionPacked },
4277 type_union_packed_explicit: struct { data: *Tag.TypeUnionPacked },
4278 type_enum_auto: struct { data: *Tag.TypeEnum },
4279 type_enum_explicit: struct { data: *Tag.TypeEnum },
4280 type_enum_nonexhaustive: struct { data: *Tag.TypeEnum },
4281 type_opaque: struct { data: *Tag.TypeOpaque },
49594282
49604283 undef: DataIsIndex,
49614284 simple_value: void,
......@@ -4982,8 +4305,6 @@ pub const Index = enum(u32) {
49824305 int_small: struct { data: *IntSmall },
49834306 int_positive: struct { data: u32 },
49844307 int_negative: struct { data: u32 },
4985 int_lazy_align: struct { data: *IntLazy },
4986 int_lazy_size: struct { data: *IntLazy },
49874308 error_set_error: struct { data: *Key.Error },
49884309 error_union_error: struct { data: *Key.Error },
49894310 error_union_payload: struct { data: *Tag.TypeValue },
......@@ -5485,6 +4806,8 @@ pub const Tag = enum(u8) {
54854806 /// assert not this tag. `data` is unused.
54864807 removed,
54874808
4809 /// A type that can be represented with only an enum tag.
4810 simple_type,
54884811 /// An integer type.
54894812 /// data is number of bits
54904813 type_int_signed,
......@@ -5524,41 +4847,68 @@ pub const Tag = enum(u8) {
55244847 /// The inferred error set type of a function.
55254848 /// data is `Index` of a `func_decl` or `func_instance`.
55264849 type_inferred_error_set,
5527 /// An enum type with auto-numbered tag values.
5528 /// The enum is exhaustive.
5529 /// data is payload index to `EnumAuto`.
5530 type_enum_auto,
5531 /// An enum type with an explicitly provided integer tag type.
5532 /// The enum is exhaustive.
5533 /// data is payload index to `EnumExplicit`.
5534 type_enum_explicit,
5535 /// An enum type with an explicitly provided integer tag type.
5536 /// The enum is non-exhaustive.
5537 /// data is payload index to `EnumExplicit`.
5538 type_enum_nonexhaustive,
5539 /// A type that can be represented with only an enum tag.
5540 simple_type,
5541 /// An opaque type.
5542 /// data is index of Tag.TypeOpaque in extra.
5543 type_opaque,
4850 /// A function body type.
4851 /// `data` is extra index to `TypeFunction`.
4852 type_function,
4853 /// A `TupleType`.
4854 /// data is extra index of `TypeTuple`.
4855 type_tuple,
4856
55444857 /// A non-packed struct type.
5545 /// data is 0 or extra index of `TypeStruct`.
4858 /// data is extra index of `TypeStruct`.
55464859 type_struct,
5547 /// A packed struct, no fields have any init values.
4860 /// `packed struct { ... }` with no default field values.
55484861 /// data is extra index of `TypeStructPacked`.
5549 type_struct_packed,
5550 /// A packed struct, one or more fields have init values.
4862 type_struct_packed_auto,
4863 /// `packed struct(T) { ... }` with no default field values.
55514864 /// data is extra index of `TypeStructPacked`.
5552 type_struct_packed_inits,
5553 /// A `TupleType`.
5554 /// data is extra index of `TypeTuple`.
5555 type_tuple,
5556 /// A union type.
5557 /// `data` is extra index of `TypeUnion`.
4865 type_struct_packed_explicit,
4866 /// `packed struct { ... }` with one or more default field values.
4867 /// data is extra index of `TypeStructPacked`.
4868 type_struct_packed_auto_defaults,
4869 /// `packed struct(T) { ... }` with one or more default field values.
4870 /// data is extra index of `TypeStructPacked`.
4871 type_struct_packed_explicit_defaults,
4872
4873 /// A non-packed union type.
4874 /// data is extra index of `TypeUnion`.
55584875 type_union,
5559 /// A function body type.
5560 /// `data` is extra index to `TypeFunction`.
5561 type_function,
4876 /// `packed union { ... }`.
4877 /// data is extra index of `TypeUnionPacked`.
4878 type_union_packed_auto,
4879 /// `packed union(T) { ... }`.
4880 /// data is extra index of `TypeUnionPacked`.
4881 type_union_packed_explicit,
4882
4883 /// An exhaustive enum type *without* an explicit integer tag type. The tag type is inferred.
4884 ///
4885 /// Because the tag type is inferred, there are no explicit field values.
4886 ///
4887 /// May be the generated tag type for a `union(enum)`.
4888 ///
4889 /// data is extra index of `TypeEnum`.
4890 type_enum_auto,
4891 /// An exhaustive enum type *with* an explicit integer tag type.
4892 ///
4893 /// May have explicit field values.
4894 ///
4895 /// May be the generated tag type for a `union(enum(T))`.
4896 ///
4897 /// data is extra index of `TypeEnum`.
4898 type_enum_explicit,
4899 /// An non-exhaustive enum type (with an explicit integer tag type, since it is required for
4900 /// non-exhaustive enums).
4901 ///
4902 /// May have explicit field values.
4903 ///
4904 /// This is *not* a union's generated tag type, because such types are always exhaustive.
4905 ///
4906 /// data is extra index of `TypeEnum`.
4907 type_enum_nonexhaustive,
4908
4909 /// An opaque type.
4910 /// data is extra index of `TypeOpaque`.
4911 type_opaque,
55624912
55634913 /// Typed `undefined`.
55644914 /// `data` is `Index` of the type.
......@@ -5644,12 +4994,6 @@ pub const Tag = enum(u8) {
56444994 /// A negative integer value.
56454995 /// data is a limbs index to `Int`.
56464996 int_negative,
5647 /// The ABI alignment of a lazy type.
5648 /// data is extra index of `IntLazy`.
5649 int_lazy_align,
5650 /// The ABI size of a lazy type.
5651 /// data is extra index of `IntLazy`.
5652 int_lazy_size,
56534997 /// An error value.
56544998 /// data is extra index of `Key.Error`.
56554999 error_set_error,
......@@ -5747,24 +5091,77 @@ pub const Tag = enum(u8) {
57475091 const Union = Key.Union;
57485092 const TypePointer = Key.PtrType;
57495093
5750 const enum_explicit_encoding = .{
5094 const struct_packed_encoding = .{
5095 .summary = .@"{.payload.name%summary#\"}",
5096 .payload = TypeStructPacked,
5097 .trailing = struct {
5098 type_hash: ?u64,
5099 captures: ?[]CaptureValue,
5100 field_names: []NullTerminatedString,
5101 field_types: []Index,
5102 },
5103 .config = .{
5104 .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
5105 .@"trailing.captures.?" = .@"payload.captures_len != .reified",
5106 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
5107 .@"trailing.field_names.len" = .@"payload.fields_len",
5108 .@"trailing.field_types.len" = .@"payload.fields_len",
5109 },
5110 };
5111 const struct_packed_defaults_encoding = .{
5112 .summary = .@"{.payload.name%summary#\"}",
5113 .payload = TypeStructPacked,
5114 .trailing = struct {
5115 type_hash: ?u64,
5116 captures: ?[]CaptureValue,
5117 field_names: []NullTerminatedString,
5118 field_types: []Index,
5119 field_defaults: []Index,
5120 },
5121 .config = .{
5122 .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
5123 .@"trailing.captures.?" = .@"payload.captures_len != .reified",
5124 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
5125 .@"trailing.field_names.len" = .@"payload.fields_len",
5126 .@"trailing.field_types.len" = .@"payload.fields_len",
5127 .@"trailing.field_defaults.len" = .@"payload.fields_len",
5128 },
5129 };
5130 const union_packed_encoding = .{
57515131 .summary = .@"{.payload.name%summary#\"}",
5752 .payload = EnumExplicit,
5132 .payload = TypeUnionPacked,
57535133 .trailing = struct {
5754 owner_union: Index,
5134 type_hash: ?u64,
57555135 captures: ?[]CaptureValue,
5136 field_types: []Index,
5137 },
5138 .config = .{
5139 .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
5140 .@"trailing.captures.?" = .@"payload.captures_len != .reified",
5141 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
5142 .@"trailing.field_types.len" = .@"payload.fields_len",
5143 },
5144 };
5145 const enum_explicit_encoding = .{
5146 .summary = .@"{.payload.name%summary#\"}",
5147 .payload = TypeEnum,
5148 .trailing = struct {
5149 owner_union: ?Index,
5150 zir_index: ?TrackedInst.Index,
57565151 type_hash: ?u64,
5152 captures: ?[]CaptureValue,
5153 field_value_map: MapIndex,
57575154 field_names: []NullTerminatedString,
5758 tag_values: []Index,
5155 field_values: []Index,
57595156 },
57605157 .config = .{
5761 .@"trailing.owner_union.?" = .@"payload.zir_index == .none",
5762 .@"trailing.cau.?" = .@"payload.zir_index != .none",
5763 .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff",
5764 .@"trailing.captures.?.len" = .@"payload.captures_len",
5765 .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff",
5158 .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag",
5159 .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag",
5160 .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
5161 .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag",
5162 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
57665163 .@"trailing.field_names.len" = .@"payload.fields_len",
5767 .@"trailing.tag_values.len" = .@"payload.fields_len",
5164 .@"trailing.field_values.len" = .@"payload.fields_len",
57685165 },
57695166 };
57705167 const encodings = .{
......@@ -5792,153 +5189,121 @@ pub const Tag = enum(u8) {
57925189 .summary = .@"@typeInfo(@typeInfo(@TypeOf({.data%summary})).@\"fn\".return_type.?).error_union.error_set",
57935190 .data = Index,
57945191 },
5795 .type_enum_auto = .{
5796 .summary = .@"{.payload.name%summary#\"}",
5797 .payload = EnumAuto,
5192 .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType },
5193 .type_tuple = .{
5194 .summary = .@"struct {...}",
5195 .payload = TypeTuple,
57985196 .trailing = struct {
5799 owner_union: ?Index,
5800 captures: ?[]CaptureValue,
5801 type_hash: ?u64,
5802 field_names: []NullTerminatedString,
5197 field_types: []Index,
5198 field_values: []Index,
58035199 },
58045200 .config = .{
5805 .@"trailing.owner_union.?" = .@"payload.zir_index == .none",
5806 .@"trailing.cau.?" = .@"payload.zir_index != .none",
5807 .@"trailing.captures.?" = .@"payload.captures_len < 0xffffffff",
5808 .@"trailing.captures.?.len" = .@"payload.captures_len",
5809 .@"trailing.type_hash.?" = .@"payload.captures_len == 0xffffffff",
5810 .@"trailing.field_names.len" = .@"payload.fields_len",
5201 .@"trailing.field_types.len" = .@"payload.fields_len",
5202 .@"trailing.field_values.len" = .@"payload.fields_len",
58115203 },
58125204 },
5813 .type_enum_explicit = enum_explicit_encoding,
5814 .type_enum_nonexhaustive = enum_explicit_encoding,
5815 .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType },
5816 .type_opaque = .{
5817 .summary = .@"{.payload.name%summary#\"}",
5818 .payload = TypeOpaque,
5819 .trailing = struct { captures: []CaptureValue },
5820 .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" },
5205 .type_function = .{
5206 .summary = .@"fn (...) ... {.payload.return_type%summary}",
5207 .payload = TypeFunction,
5208 .trailing = struct {
5209 param_comptime_bits: ?[]u32,
5210 param_noalias_bits: ?[]u32,
5211 param_type: []Index,
5212 },
5213 .config = .{
5214 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",
5215 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
5216 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
5217 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
5218 .@"trailing.param_type.len" = .@"payload.params_len",
5219 },
58215220 },
5221
58225222 .type_struct = .{
58235223 .summary = .@"{.payload.name%summary#\"}",
58245224 .payload = TypeStruct,
58255225 .trailing = struct {
5226 type_hash: ?u64,
58265227 captures_len: ?u32,
58275228 captures: ?[]CaptureValue,
5828 type_hash: ?u64,
5829 field_types: []Index,
5830 field_names_map: OptionalMapIndex,
58315229 field_names: []NullTerminatedString,
5832 field_inits: ?[]Index,
5230 field_types: []Index,
5231 field_defaults: ?[]Index,
58335232 field_aligns: ?[]Alignment,
58345233 field_is_comptime_bits: ?[]u32,
5835 field_index: ?[]LoadedStructType.RuntimeOrder,
5836 field_offset: []u32,
5234 field_runtime_order: ?[]u32,
5235 field_offsets: []u32,
58375236 },
58385237 .config = .{
5839 .@"trailing.captures_len.?" = .@"payload.flags.any_captures",
5840 .@"trailing.captures.?" = .@"payload.flags.any_captures",
5238 .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified",
5239 .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true",
5240 .@"trailing.captures.?" = .@"payload.flags.any_captures == .true",
58415241 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5842 .@"trailing.type_hash.?" = .@"payload.flags.is_reified",
5843 .@"trailing.field_types.len" = .@"payload.fields_len",
58445242 .@"trailing.field_names.len" = .@"payload.fields_len",
5845 .@"trailing.field_inits.?" = .@"payload.flags.any_default_inits",
5846 .@"trailing.field_inits.?.len" = .@"payload.fields_len",
5847 .@"trailing.field_aligns.?" = .@"payload.flags.any_aligned_fields",
5243 .@"trailing.field_types.len" = .@"payload.fields_len",
5244 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults",
5245 .@"trailing.field_defaults.?.len" = .@"payload.fields_len",
5246 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns",
58485247 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
58495248 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields",
58505249 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32",
5851 .@"trailing.field_index.?" = .@"!payload.flags.is_extern",
5852 .@"trailing.field_index.?.len" = .@"payload.fields_len",
5853 .@"trailing.field_offset.len" = .@"payload.fields_len",
5250 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto",
5251 .@"trailing.field_runtime_order.?.len" = .@"payload.fields_len",
5252 .@"trailing.field_offsets.len" = .@"payload.fields_len",
58545253 },
58555254 },
5856 .type_struct_packed = .{
5255 .type_struct_packed_auto = struct_packed_encoding,
5256 .type_struct_packed_explicit = struct_packed_encoding,
5257 .type_struct_packed_auto_defaults = struct_packed_defaults_encoding,
5258 .type_struct_packed_explicit_defaults = struct_packed_defaults_encoding,
5259 .type_union = .{
58575260 .summary = .@"{.payload.name%summary#\"}",
5858 .payload = TypeStructPacked,
5261 .payload = TypeUnion,
58595262 .trailing = struct {
5263 type_hash: ?u64,
58605264 captures_len: ?u32,
58615265 captures: ?[]CaptureValue,
5862 type_hash: ?u64,
58635266 field_types: []Index,
5864 field_names: []NullTerminatedString,
5267 field_aligns: ?[]Alignment,
58655268 },
58665269 .config = .{
5867 .@"trailing.captures_len.?" = .@"payload.flags.any_captures",
5868 .@"trailing.captures.?" = .@"payload.flags.any_captures",
5270 .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified",
5271 .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true",
5272 .@"trailing.captures.?" = .@"payload.flags.any_captures == .true",
58695273 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5870 .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified",
58715274 .@"trailing.field_types.len" = .@"payload.fields_len",
5872 .@"trailing.field_names.len" = .@"payload.fields_len",
5275 .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns",
5276 .@"trailing.field_aligns.?.len" = .@"payload.fields_len",
58735277 },
58745278 },
5875 .type_struct_packed_inits = .{
5279 .type_union_packed_auto = union_packed_encoding,
5280 .type_union_packed_explicit = union_packed_encoding,
5281 .type_enum_auto = .{
58765282 .summary = .@"{.payload.name%summary#\"}",
5877 .payload = TypeStructPacked,
5283 .payload = TypeEnum,
58785284 .trailing = struct {
5879 captures_len: ?u32,
5880 captures: ?[]CaptureValue,
5285 owner_union: ?Index,
5286 zir_index: ?TrackedInst.Index,
58815287 type_hash: ?u64,
5882 field_types: []Index,
5288 captures: ?[]CaptureValue,
58835289 field_names: []NullTerminatedString,
5884 field_inits: []Index,
58855290 },
58865291 .config = .{
5887 .@"trailing.captures_len.?" = .@"payload.flags.any_captures",
5888 .@"trailing.captures.?" = .@"payload.flags.any_captures",
5889 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5890 .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified",
5891 .@"trailing.field_types.len" = .@"payload.fields_len",
5292 .@"trailing.owner_union.?" = .@"payload.captures_len == .generated_union_tag",
5293 .@"trailing.zir_index.?" = .@"payload.captures_len != .generated_union_tag",
5294 .@"trailing.type_hash.?" = .@"payload.captures_len == .reified",
5295 .@"trailing.captures.?" = .@"payload.captures_len != .reified and payload.captures_len != .generated_enum_tag",
5296 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.captures_len)",
58925297 .@"trailing.field_names.len" = .@"payload.fields_len",
5893 .@"trailing.field_inits.len" = .@"payload.fields_len",
5894 },
5895 },
5896 .type_tuple = .{
5897 .summary = .@"struct {...}",
5898 .payload = TypeTuple,
5899 .trailing = struct {
5900 field_types: []Index,
5901 field_values: []Index,
5902 },
5903 .config = .{
5904 .@"trailing.field_types.len" = .@"payload.fields_len",
5905 .@"trailing.field_values.len" = .@"payload.fields_len",
59065298 },
59075299 },
5908 .type_union = .{
5300 .type_enum_explicit = enum_explicit_encoding,
5301 .type_enum_nonexhaustive = enum_explicit_encoding,
5302 .type_opaque = .{
59095303 .summary = .@"{.payload.name%summary#\"}",
5910 .payload = TypeUnion,
5911 .trailing = struct {
5912 captures_len: ?u32,
5913 captures: ?[]CaptureValue,
5914 type_hash: ?u64,
5915 field_types: []Index,
5916 field_aligns: []Alignment,
5917 },
5918 .config = .{
5919 .@"trailing.captures_len.?" = .@"payload.flags.any_captures",
5920 .@"trailing.captures.?" = .@"payload.flags.any_captures",
5921 .@"trailing.captures.?.len" = .@"trailing.captures_len.?",
5922 .@"trailing.type_hash.?" = .@"payload.is_flags.is_reified",
5923 .@"trailing.field_types.len" = .@"payload.fields_len",
5924 .@"trailing.field_aligns.len" = .@"payload.fields_len",
5925 },
5926 },
5927 .type_function = .{
5928 .summary = .@"fn (...) ... {.payload.return_type%summary}",
5929 .payload = TypeFunction,
5930 .trailing = struct {
5931 param_comptime_bits: ?[]u32,
5932 param_noalias_bits: ?[]u32,
5933 param_type: []Index,
5934 },
5935 .config = .{
5936 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits",
5937 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32",
5938 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits",
5939 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32",
5940 .@"trailing.param_type.len" = .@"payload.params_len",
5941 },
5304 .payload = TypeOpaque,
5305 .trailing = struct { captures: []CaptureValue },
5306 .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" },
59425307 },
59435308
59445309 .undef = .{ .summary = .@"@as({.data%summary}, undefined)", .data = Index },
......@@ -5999,8 +5364,6 @@ pub const Tag = enum(u8) {
59995364 .int_small = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.value%value})", .payload = IntSmall },
60005365 .int_positive = .{},
60015366 .int_negative = .{},
6002 .int_lazy_align = .{ .summary = .@"@as({.payload.ty%summary}, @alignOf({.payload.lazy_ty%summary}))", .payload = IntLazy },
6003 .int_lazy_size = .{ .summary = .@"@as({.payload.ty%summary}, @sizeOf({.payload.lazy_ty%summary}))", .payload = IntLazy },
60045367 .error_set_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error },
60055368 .error_union_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error },
60065369 .error_union_payload = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.val%summary})", .payload = TypeValue },
......@@ -6166,164 +5529,242 @@ pub const Tag = enum(u8) {
61665529 pub const Flags = packed struct(u32) {
61675530 cc: PackedCallingConvention,
61685531 is_var_args: bool,
6169 is_generic: bool,
61705532 has_comptime_bits: bool,
61715533 has_noalias_bits: bool,
61725534 is_noinline: bool,
6173 _: u9 = 0,
5535 _: u10 = 0,
61745536 };
61755537 };
61765538
5539 /// At first I thought of storing the denormalized data externally, such as...
5540 ///
5541 /// * runtime field order
5542 /// * calculated field offsets
5543 /// * size and alignment of the struct
5544 ///
5545 /// ...since these can be computed based on the other data here. However,
5546 /// this data does need to be memoized, and therefore stored in memory
5547 /// while the compiler is running, in order to avoid O(N^2) logic in many
5548 /// places. Since the data can be stored compactly in the InternPool
5549 /// representation, it is better for memory usage to store denormalized data
5550 /// here, and potentially also better for performance as well. It's also simpler
5551 /// than coming up with some other scheme for the data.
5552 ///
61775553 /// Trailing:
6178 /// 0. captures_len: u32 // if `any_captures`
6179 /// 1. capture: CaptureValue // for each `captures_len`
6180 /// 2. type_hash: PackedU64 // if `is_reified`
6181 /// 3. field type: Index for each field; declaration order
6182 /// 4. field align: Alignment for each field; declaration order
6183 pub const TypeUnion = struct {
5554 /// 0. type_hash: PackedU64 // if `any_captures == .reified`
5555 /// 1. captures_len: u32 // if `any_captures == .true`
5556 /// 2. capture: CaptureValue // for each `captures_len`
5557 /// 3. field_name: NullTerminatedString // for each `fields_len`
5558 /// 4. field_type: Index // for each `fields_len`
5559 /// 5. field_default: Index // if `any_field_defaults`; for each `fields_len`
5560 /// 6. field_align: Alignment // if `any_field_aligns`; for each `fields_len`
5561 /// 7. field_is_comptime_bits: u32 // if `any_comptime_fields`; minimum `u32` for `fields_len`; LSB is field 0
5562 /// 8. field_runtime_order: RuntimeOrder // if `layout == .auto`; for each `fields_len`
5563 /// 9. field_offset: u32 // for each `fields_len`
5564 pub const TypeStruct = struct {
5565 zir_index: TrackedInst.Index,
5566
61845567 name: NullTerminatedString,
61855568 name_nav: Nav.Index.Optional,
6186 flags: Flags,
6187 /// This could be provided through the tag type, but it is more convenient
6188 /// to store it directly. This is also necessary for `dumpStatsFallible` to
6189 /// work on unresolved types.
5569 namespace: NamespaceIndex,
5570
61905571 fields_len: u32,
6191 /// Only valid after .have_layout
5572 field_name_map: MapIndex,
5573
5574 /// Size in bytes of the whole struct. Always 0 until layout resolved.
61925575 size: u32,
6193 /// Only valid after .have_layout
6194 padding: u32,
6195 namespace: NamespaceIndex,
6196 /// The enum that provides the list of field names and values.
6197 tag_ty: Index,
6198 zir_index: TrackedInst.Index,
5576
5577 flags: Flags,
61995578
62005579 pub const Flags = packed struct(u32) {
6201 any_captures: bool,
6202 runtime_tag: LoadedUnionType.RuntimeTag,
6203 /// If false, the field alignment trailing data is omitted.
6204 any_aligned_fields: bool,
6205 layout: std.builtin.Type.ContainerLayout,
6206 status: LoadedUnionType.Status,
6207 requires_comptime: RequiresComptime,
6208 assumed_runtime_bits: bool,
6209 assumed_pointer_aligned: bool,
5580 any_captures: enum(u2) { true, false, reified },
5581
5582 /// `packed` layout is represented separately by `TypeStructPacked`.
5583 layout: enum(u1) { auto, @"extern" },
5584
5585 any_comptime_fields: bool,
5586 any_field_defaults: bool,
5587 any_field_aligns: bool,
5588
5589 /// Whether the struct is an OPV type. Always `false` until layout resolved.
5590 /// The actual OPV is not cached, but caching this bit of state means we avoid
5591 /// repeatedly doing redundant checks to find that the struct is not OPV!
5592 has_one_possible_value: bool,
5593 /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn).
5594 has_no_possible_value: bool,
5595 /// Whether the struct is comptime-only. Always `false` until layout resolved.
5596 comptime_only: bool,
5597 /// Alignment of the whole struct. Always `.none` until layout resolved.
62105598 alignment: Alignment,
6211 is_reified: bool,
6212 _: u12 = 0,
5599
5600 _: u17 = 0,
62135601 };
62145602 };
62155603
62165604 /// Trailing:
6217 /// 0. captures_len: u32 // if `any_captures`
6218 /// 1. capture: CaptureValue // for each `captures_len`
6219 /// 2. type_hash: PackedU64 // if `is_reified`
6220 /// 3. type: Index for each fields_len
6221 /// 4. name: NullTerminatedString for each fields_len
6222 /// 5. init: Index for each fields_len // if tag is type_struct_packed_inits
5605 /// 0. type_hash: PackedU64 // if `captures_len == .reified`
5606 /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len`
5607 /// 2. field_name: NullTerminatedString // for each `fields_len`
5608 /// 3. field_type: Index // for each `fields_len`
5609 /// 4. field_default: Index // if item tag implies field defaults; for each `fields_len`
62235610 pub const TypeStructPacked = struct {
5611 zir_index: TrackedInst.Index,
5612 captures_len: enum(u32) {
5613 reified = std.math.maxInt(u32),
5614 _,
5615 },
5616
62245617 name: NullTerminatedString,
62255618 name_nav: Nav.Index.Optional,
6226 zir_index: TrackedInst.Index,
5619 namespace: NamespaceIndex,
5620
5621 /// The corresponding `PackedBackingMode` depends on the item's `Tag`.
5622 backing_int_type: Index,
5623
62275624 fields_len: u32,
5625 field_name_map: MapIndex,
5626 };
5627
5628 /// Field names are intentionally omitted---they are available in `enum_tag_type`.
5629 ///
5630 /// Trailing:
5631 /// 0. type_hash: PackedU64 // if `any_captures == .reified`
5632 /// 1. captures_len: u32 // if `any_captures == .true`
5633 /// 2. capture: CaptureValue // if `any_captures == .true`; for each `captures_len`
5634 /// 3. field_type: Index // for each `fields_len`
5635 /// 4. field_align: Alignment // for each `fields_len` if `any_field_aligns`
5636 pub const TypeUnion = struct {
5637 zir_index: TrackedInst.Index,
5638
5639 name: NullTerminatedString,
5640 name_nav: Nav.Index.Optional,
62285641 namespace: NamespaceIndex,
6229 backing_int_ty: Index,
6230 names_map: MapIndex,
5642 /// The enum that provides the list of field names and values.
5643 enum_tag_type: Index,
5644
5645 /// This could be provided through the tag type, but it is more convenient
5646 /// to store it directly. This is also necessary for `dumpStatsFallible` to
5647 /// work on unresolved types.
5648 /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now.
5649 fields_len: u32,
5650
5651 /// Always 0 until layout resolved.
5652 size: u32,
5653 /// Always 0 until layout resolved.
5654 padding: u32,
5655
62315656 flags: Flags,
62325657
62335658 pub const Flags = packed struct(u32) {
6234 any_captures: bool = false,
6235 /// Dependency loop detection when resolving field inits.
6236 field_inits_wip: bool = false,
6237 inits_resolved: bool = false,
6238 is_reified: bool = false,
6239 _: u28 = 0,
5659 any_captures: enum(u2) { true, false, reified },
5660
5661 /// Whether `enum_tag_type` was explicitly specified with `union(E)` syntax.
5662 ///
5663 /// For `union(enum(E))` syntax, this is `false`, but the generated enum tag type is
5664 /// considered to have an explicitly specified integer tag type.
5665 explicit_tag_type: bool,
5666
5667 /// `packed` layout is represented separately by `TypeStructPacked`.
5668 layout: enum(u1) { auto, @"extern" },
5669
5670 any_field_aligns: bool,
5671 runtime_tag: LoadedUnionType.RuntimeTag,
5672
5673 /// Whether the union is an OPV type. Always `false` until layout resolved.
5674 /// The actual OPV is not cached, but caching this bit of state means we avoid
5675 /// repeatedly doing redundant checks to find that the union is not OPV!
5676 has_one_possible_value: bool,
5677 /// Like `has_one_possible_value`, but for a "noreturn" union (where all fields are noreturn).
5678 has_no_possible_value: bool,
5679 /// Whether the union is comptime-only. Always `false` until layout resolved.
5680 comptime_only: bool,
5681 /// Alignment of the whole union. Always `.none` until layout resolved.
5682 alignment: Alignment,
5683
5684 _: u16 = 0,
62405685 };
62415686 };
62425687
6243 /// At first I thought of storing the denormalized data externally, such as...
6244 ///
6245 /// * runtime field order
6246 /// * calculated field offsets
6247 /// * size and alignment of the struct
6248 ///
6249 /// ...since these can be computed based on the other data here. However,
6250 /// this data does need to be memoized, and therefore stored in memory
6251 /// while the compiler is running, in order to avoid O(N^2) logic in many
6252 /// places. Since the data can be stored compactly in the InternPool
6253 /// representation, it is better for memory usage to store denormalized data
6254 /// here, and potentially also better for performance as well. It's also simpler
6255 /// than coming up with some other scheme for the data.
5688 /// Field names are intentionally omitted---they are available in `enum_tag_type`.
62565689 ///
62575690 /// Trailing:
6258 /// 0. captures_len: u32 // if `any_captures`
6259 /// 1. capture: CaptureValue // for each `captures_len`
6260 /// 2. type_hash: PackedU64 // if `is_reified`
6261 /// 3. type: Index for each field in declared order
6262 /// 4. if any_default_inits:
6263 /// init: Index // for each field in declared order
6264 /// 5. if any_aligned_fields:
6265 /// align: Alignment // for each field in declared order
6266 /// 6. if any_comptime_fields:
6267 /// field_is_comptime_bits: u32 // minimal number of u32s needed, LSB is field 0
6268 /// 7. if not is_extern:
6269 /// field_index: RuntimeOrder // for each field in runtime order
6270 /// 8. field_offset: u32 // for each field in declared order, undef until layout_resolved
6271 pub const TypeStruct = struct {
5691 /// 0. type_hash: PackedU64 // if `captures_len == .reified`
5692 /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len`
5693 /// 2. field_type: Index // for each `fields_len`
5694 pub const TypeUnionPacked = struct {
5695 zir_index: TrackedInst.Index,
5696 captures_len: enum(u32) {
5697 reified = std.math.maxInt(u32),
5698 _,
5699 },
5700
62725701 name: NullTerminatedString,
62735702 name_nav: Nav.Index.Optional,
6274 zir_index: TrackedInst.Index,
62755703 namespace: NamespaceIndex,
5704
5705 /// The corresponding `PackedBackingMode` depends on the item's `Tag`.
5706 backing_int_type: Index,
5707 /// Although packed unions do not semantically have a tag type, the compiler still assigns
5708 /// them a "hypothetical" tag type.
5709 enum_tag_type: Index,
5710
5711 /// This could be provided through the tag type, but it is more convenient
5712 /// to store it directly. This is also necessary for `dumpStatsFallible` to
5713 /// work on unresolved types.
5714 /// MLUGG TODO: reconsider, because we resolve the tag type eagerly now.
62765715 fields_len: u32,
6277 flags: Flags,
6278 size: u32,
5716 };
62795717
6280 pub const Flags = packed struct(u32) {
6281 any_captures: bool = false,
6282 is_extern: bool = false,
6283 known_non_opv: bool = false,
6284 requires_comptime: RequiresComptime = @enumFromInt(0),
6285 assumed_runtime_bits: bool = false,
6286 assumed_pointer_aligned: bool = false,
6287 any_comptime_fields: bool = false,
6288 any_default_inits: bool = false,
6289 any_aligned_fields: bool = false,
6290 /// `.none` until layout_resolved
6291 alignment: Alignment = @enumFromInt(0),
6292 /// Dependency loop detection when resolving struct alignment.
6293 alignment_wip: bool = false,
6294 /// Dependency loop detection when resolving field types.
6295 field_types_wip: bool = false,
6296 /// Dependency loop detection when resolving struct layout.
6297 layout_wip: bool = false,
6298 /// Indicates whether `size`, `alignment`, runtime field order, and
6299 /// field offets are populated.
6300 layout_resolved: bool = false,
6301 /// Dependency loop detection when resolving field inits.
6302 field_inits_wip: bool = false,
6303 /// Indicates whether `field_inits` has been resolved.
6304 inits_resolved: bool = false,
6305 // The types and all its fields have had their layout resolved. Even through pointer = false,
6306 // which `layout_resolved` does not ensure.
6307 fully_resolved: bool = false,
6308 is_reified: bool = false,
6309 _: u8 = 0,
6310 };
5718 /// Trailing:
5719 /// 0. owner_union: Index // if `captures_len == .generated_union_tag`
5720 /// 1. zir_index: TrackedInst.Index // if `captures_len != .generated_union_tag`
5721 /// 2. type_hash: PackedU64 // if `captures_len == .reified`
5722 /// 3. capture: CaptureValue // if `captures_len` is not a named tag; for each `captures_len`
5723 /// 4. field_value_map: MapIndex // if tag is not `.type_enum_auto`
5724 /// 5. field_name: NullTerminatedString // for each `fields_len`
5725 /// 6. field_value: Index // if tag is not `.type_enum_auto`; for each `fields_len`
5726 pub const TypeEnum = struct {
5727 captures_len: enum(u32) {
5728 reified = std.math.maxInt(u32),
5729 generated_union_tag = std.math.maxInt(u32) - 1,
5730 _,
5731 },
5732
5733 name: NullTerminatedString,
5734 name_nav: Nav.Index.Optional,
5735 namespace: NamespaceIndex,
5736
5737 /// An integer type which is used for the numerical value of the enum. Whether this was
5738 /// user-provided or inferred by the compiler depends on the tag. Either way, the field
5739 /// is populated immediately (i.e. does not require any type resolution).
5740 int_tag_type: Index,
5741
5742 fields_len: u32,
5743 field_name_map: MapIndex,
63115744 };
63125745
63135746 /// Trailing:
63145747 /// 0. capture: CaptureValue // for each `captures_len`
63155748 pub const TypeOpaque = struct {
5749 zir_index: TrackedInst.Index,
5750 captures_len: u32,
5751
63165752 name: NullTerminatedString,
63175753 name_nav: Nav.Index.Optional,
6318 /// Contains the declarations inside this opaque.
63195754 namespace: NamespaceIndex,
6320 /// The index of the `opaque_decl` instruction.
6321 zir_index: TrackedInst.Index,
6322 /// `std.math.maxInt(u32)` indicates this type is reified.
6323 captures_len: u32,
63245755 };
63255756};
63265757
5758/// Differentiates between user-provided and compiler-generated backing types for packed aggregates.
5759pub const PackedBackingMode = enum(u1) {
5760 /// The backing type was explicitly provided by the user, i.e. `packed struct(T)` or `packed union(T)`.
5761 /// Type resolution simply *validates* that type.
5762 explicit,
5763 /// No backing type was explicitly provided by the user. Type layout resolution will populate the
5764 /// backing type based on the field types; before then it is invalid (probably `.none`).
5765 auto,
5766};
5767
63275768/// State that is mutable during semantic analysis. This data is not used for
63285769/// equality or hashing, except for `inferred_error_set` which is considered
63295770/// to be part of the type of the function.
......@@ -6536,10 +5977,8 @@ pub const Alignment = enum(u6) {
65365977 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 };
65375978
65385979 pub fn get(slice: Slice, ip: *const InternPool) []Alignment {
6539 // TODO: implement @ptrCast between slices changing the length
65405980 const extra = ip.getLocalShared(slice.tid).extra.acquire();
6541 //const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]);
6542 const bytes: []u8 = std.mem.sliceAsBytes(extra.view().items(.@"0")[slice.start..]);
5981 const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]);
65435982 return @ptrCast(bytes[0..slice.len]);
65445983 }
65455984 };
......@@ -6596,55 +6035,6 @@ pub const Array = struct {
65966035 }
65976036};
65986037
6599/// Trailing:
6600/// 0. owner_union: Index // if `zir_index == .none`
6601/// 1. capture: CaptureValue // for each `captures_len`
6602/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6603/// 3. field name: NullTerminatedString for each fields_len; declaration order
6604/// 4. tag value: Index for each fields_len; declaration order
6605pub const EnumExplicit = struct {
6606 name: NullTerminatedString,
6607 name_nav: Nav.Index.Optional,
6608 /// `std.math.maxInt(u32)` indicates this type is reified.
6609 captures_len: u32,
6610 namespace: NamespaceIndex,
6611 /// An integer type which is used for the numerical value of the enum, which
6612 /// has been explicitly provided by the enum declaration.
6613 int_tag_type: Index,
6614 fields_len: u32,
6615 /// Maps field names to declaration index.
6616 names_map: MapIndex,
6617 /// Maps field values to declaration index.
6618 /// If this is `none`, it means the trailing tag values are absent because
6619 /// they are auto-numbered.
6620 values_map: OptionalMapIndex,
6621 /// `none` means this is a generated tag type.
6622 /// There will be a trailing union type for which this is a tag.
6623 zir_index: TrackedInst.Index.Optional,
6624};
6625
6626/// Trailing:
6627/// 0. owner_union: Index // if `zir_index == .none`
6628/// 1. capture: CaptureValue // for each `captures_len`
6629/// 2. type_hash: PackedU64 // if reified (`captures_len == std.math.maxInt(u32)`)
6630/// 3. field name: NullTerminatedString for each fields_len; declaration order
6631pub const EnumAuto = struct {
6632 name: NullTerminatedString,
6633 name_nav: Nav.Index.Optional,
6634 /// `std.math.maxInt(u32)` indicates this type is reified.
6635 captures_len: u32,
6636 namespace: NamespaceIndex,
6637 /// An integer type which is used for the numerical value of the enum, which
6638 /// was inferred by Zig based on the number of tags.
6639 int_tag_type: Index,
6640 fields_len: u32,
6641 /// Maps field names to declaration index.
6642 names_map: MapIndex,
6643 /// `none` means this is a generated tag type.
6644 /// There will be a trailing union type for which this is a tag.
6645 zir_index: TrackedInst.Index.Optional,
6646};
6647
66486038pub const PackedU64 = packed struct(u64) {
66496039 a: u32,
66506040 b: u32,
......@@ -6827,11 +6217,6 @@ pub const IntSmall = struct {
68276217 value: u32,
68286218};
68296219
6830pub const IntLazy = struct {
6831 ty: Index,
6832 lazy_ty: Index,
6833};
6834
68356220/// A f64 value, broken up into 2 u32 parts.
68366221pub const Float64 = struct {
68376222 piece0: u32,
......@@ -6994,7 +6379,9 @@ pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void {
69946379 ip.src_hash_deps.deinit(gpa);
69956380 ip.nav_val_deps.deinit(gpa);
69966381 ip.nav_ty_deps.deinit(gpa);
6997 ip.interned_deps.deinit(gpa);
6382 ip.func_ies_deps.deinit(gpa);
6383 ip.type_layout_deps.deinit(gpa);
6384 ip.type_inits_deps.deinit(gpa);
69986385 ip.zon_file_deps.deinit(gpa);
69996386 ip.embed_file_deps.deinit(gpa);
70006387 ip.namespace_deps.deinit(gpa);
......@@ -7130,132 +6517,138 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
71306517 .type_inferred_error_set => .{
71316518 .inferred_error_set_type = @enumFromInt(data),
71326519 },
7133
7134 .type_opaque => .{ .opaque_type = ns: {
7135 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data);
7136 if (extra.data.captures_len == std.math.maxInt(u32)) {
7137 break :ns .{ .reified = .{
7138 .zir_index = extra.data.zir_index,
7139 .type_hash = 0,
7140 } };
7141 }
7142 break :ns .{ .declared = .{
7143 .zir_index = extra.data.zir_index,
7144 .captures = .{ .owned = .{
7145 .tid = unwrapped_index.tid,
7146 .start = extra.end,
7147 .len = extra.data.captures_len,
7148 } },
7149 } };
7150 } },
6520 .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
6521 .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
71516522
71526523 .type_struct => .{ .struct_type = ns: {
71536524 const extra_list = unwrapped_index.getExtra(ip);
7154 const extra_items = extra_list.view().items(.@"0");
7155 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "zir_index").?]);
7156 const flags: Tag.TypeStruct.Flags = @bitCast(@atomicLoad(u32, &extra_items[data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?], .unordered));
7157 const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStruct).@"struct".fields.len);
7158 if (flags.is_reified) {
7159 assert(!flags.any_captures);
7160 break :ns .{ .reified = .{
7161 .zir_index = zir_index,
7162 .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(),
7163 } };
7164 }
7165 break :ns .{ .declared = .{
7166 .zir_index = zir_index,
7167 .captures = .{ .owned = if (flags.any_captures) .{
7168 .tid = unwrapped_index.tid,
7169 .start = end_extra_index + 1,
7170 .len = extra_list.view().items(.@"0")[end_extra_index],
7171 } else CaptureValue.Slice.empty },
7172 } };
6525 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data);
6526 break :ns switch (extra.data.flags.any_captures) {
6527 .reified => .{ .reified = .{
6528 .zir_index = extra.data.zir_index,
6529 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6530 } },
6531 .false => .{ .declared = .{
6532 .zir_index = extra.data.zir_index,
6533 .arg_ty = .none,
6534 .captures = .{ .owned = .empty },
6535 } },
6536 .true => .{ .declared = .{
6537 .zir_index = extra.data.zir_index,
6538 .arg_ty = .none,
6539 .captures = .{ .owned = .{
6540 .tid = unwrapped_index.tid,
6541 .start = extra.end + 1,
6542 .len = extra_list.view().items(.@"0")[extra.end],
6543 } },
6544 } },
6545 };
71736546 } },
7174
7175 .type_struct_packed, .type_struct_packed_inits => .{ .struct_type = ns: {
6547 .type_struct_packed_auto,
6548 .type_struct_packed_explicit,
6549 .type_struct_packed_auto_defaults,
6550 .type_struct_packed_explicit_defaults,
6551 => .{ .struct_type = ns: {
71766552 const extra_list = unwrapped_index.getExtra(ip);
7177 const extra_items = extra_list.view().items(.@"0");
7178 const zir_index: TrackedInst.Index = @enumFromInt(extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "zir_index").?]);
7179 const flags: Tag.TypeStructPacked.Flags = @bitCast(@atomicLoad(u32, &extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "flags").?], .unordered));
7180 const end_extra_index = data + @as(u32, @typeInfo(Tag.TypeStructPacked).@"struct".fields.len);
7181 if (flags.is_reified) {
7182 assert(!flags.any_captures);
7183 break :ns .{ .reified = .{
7184 .zir_index = zir_index,
7185 .type_hash = extraData(extra_list, PackedU64, end_extra_index).get(),
7186 } };
7187 }
7188 break :ns .{ .declared = .{
7189 .zir_index = zir_index,
7190 .captures = .{ .owned = if (flags.any_captures) .{
7191 .tid = unwrapped_index.tid,
7192 .start = end_extra_index + 1,
7193 .len = extra_items[end_extra_index],
7194 } else CaptureValue.Slice.empty },
7195 } };
6553 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);
6554 break :ns switch (extra.data.captures_len) {
6555 .reified => .{ .reified = .{
6556 .zir_index = extra.data.zir_index,
6557 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
6558 } },
6559 _ => .{ .declared = .{
6560 .zir_index = extra.data.zir_index,
6561 .arg_ty = switch (item.tag) {
6562 .type_struct_packed_auto, .type_struct_packed_auto_defaults => .none,
6563 .type_struct_packed_explicit, .type_struct_packed_explicit_defaults => extra.data.backing_int_type,
6564 else => unreachable,
6565 },
6566 .captures = .{ .owned = .{
6567 .tid = unwrapped_index.tid,
6568 .start = extra.end,
6569 .len = @intFromEnum(extra.data.captures_len),
6570 } },
6571 } },
6572 };
71966573 } },
7197 .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
71986574 .type_union => .{ .union_type = ns: {
71996575 const extra_list = unwrapped_index.getExtra(ip);
72006576 const extra = extraDataTrail(extra_list, Tag.TypeUnion, data);
7201 if (extra.data.flags.is_reified) {
7202 assert(!extra.data.flags.any_captures);
7203 break :ns .{ .reified = .{
6577 break :ns switch (extra.data.flags.any_captures) {
6578 .reified => .{ .reified = .{
72046579 .zir_index = extra.data.zir_index,
72056580 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
7206 } };
7207 }
7208 break :ns .{ .declared = .{
7209 .zir_index = extra.data.zir_index,
7210 .captures = .{ .owned = if (extra.data.flags.any_captures) .{
7211 .tid = unwrapped_index.tid,
7212 .start = extra.end + 1,
7213 .len = extra_list.view().items(.@"0")[extra.end],
7214 } else CaptureValue.Slice.empty },
7215 } };
6581 } },
6582 .false => .{ .declared = .{
6583 .zir_index = extra.data.zir_index,
6584 .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none,
6585 .captures = .{ .owned = .empty },
6586 } },
6587 .true => .{ .declared = .{
6588 .zir_index = extra.data.zir_index,
6589 .arg_ty = if (extra.data.flags.explicit_tag_type) extra.data.enum_tag_type else .none,
6590 .captures = .{ .owned = .{
6591 .tid = unwrapped_index.tid,
6592 .start = extra.end + 1,
6593 .len = extra_list.view().items(.@"0")[extra.end],
6594 } },
6595 } },
6596 };
72166597 } },
7217
7218 .type_enum_auto => .{ .enum_type = ns: {
6598 .type_union_packed_auto, .type_union_packed_explicit => .{ .union_type = ns: {
72196599 const extra_list = unwrapped_index.getExtra(ip);
7220 const extra = extraDataTrail(extra_list, EnumAuto, data);
7221 const zir_index = extra.data.zir_index.unwrap() orelse {
7222 assert(extra.data.captures_len == 0);
7223 break :ns .{ .generated_tag = .{
7224 .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]),
7225 } };
7226 };
7227 if (extra.data.captures_len == std.math.maxInt(u32)) {
7228 break :ns .{ .reified = .{
7229 .zir_index = zir_index,
6600 const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data);
6601 break :ns switch (extra.data.captures_len) {
6602 .reified => .{ .reified = .{
6603 .zir_index = extra.data.zir_index,
72306604 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
7231 } };
7232 }
7233 break :ns .{ .declared = .{
7234 .zir_index = zir_index,
7235 .captures = .{ .owned = .{
7236 .tid = unwrapped_index.tid,
7237 .start = extra.end,
7238 .len = extra.data.captures_len,
72396605 } },
7240 } };
6606 _ => .{ .declared = .{
6607 .zir_index = extra.data.zir_index,
6608 .arg_ty = switch (item.tag) {
6609 .type_union_packed_auto => .none,
6610 .type_union_packed_explicit => extra.data.backing_int_type,
6611 else => unreachable,
6612 },
6613 .captures = .{ .owned = .{
6614 .tid = unwrapped_index.tid,
6615 .start = extra.end,
6616 .len = @intFromEnum(extra.data.captures_len),
6617 } },
6618 } },
6619 };
72416620 } },
7242 .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: {
6621 .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: {
72436622 const extra_list = unwrapped_index.getExtra(ip);
7244 const extra = extraDataTrail(extra_list, EnumExplicit, data);
7245 const zir_index = extra.data.zir_index.unwrap() orelse {
7246 assert(extra.data.captures_len == 0);
7247 break :ns .{ .generated_tag = .{
7248 .union_type = @enumFromInt(extra_list.view().items(.@"0")[extra.end]),
7249 } };
6623 const extra = extraDataTrail(extra_list, Tag.TypeEnum, data);
6624 break :ns switch (extra.data.captures_len) {
6625 .reified => .{ .reified = .{
6626 .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]),
6627 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(),
6628 } },
6629 .generated_union_tag => .{ .generated_union_tag = owner_union: {
6630 break :owner_union @enumFromInt(extra_list.view().items(.@"0")[extra.end]);
6631 } },
6632 _ => .{ .declared = .{
6633 .zir_index = @enumFromInt(extra_list.view().items(.@"0")[extra.end]),
6634 .arg_ty = switch (item.tag) {
6635 .type_enum_auto => .none,
6636 .type_enum_explicit, .type_enum_nonexhaustive => extra.data.int_tag_type,
6637 else => unreachable,
6638 },
6639 .captures = .{ .owned = .{
6640 .tid = unwrapped_index.tid,
6641 .start = extra.end + 1,
6642 .len = @intFromEnum(extra.data.captures_len),
6643 } },
6644 } },
72506645 };
7251 if (extra.data.captures_len == std.math.maxInt(u32)) {
7252 break :ns .{ .reified = .{
7253 .zir_index = zir_index,
7254 .type_hash = extraData(extra_list, PackedU64, extra.end).get(),
7255 } };
7256 }
6646 } },
6647 .type_opaque => .{ .opaque_type = ns: {
6648 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data);
72576649 break :ns .{ .declared = .{
7258 .zir_index = zir_index,
6650 .zir_index = extra.data.zir_index,
6651 .arg_ty = .none,
72596652 .captures = .{ .owned = .{
72606653 .tid = unwrapped_index.tid,
72616654 .start = extra.end,
......@@ -7263,7 +6656,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
72636656 } },
72646657 } };
72656658 } },
7266 .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) },
72676659
72686660 .undef => .{ .undef = @enumFromInt(data) },
72696661 .opt_null => .{ .opt = .{
......@@ -7390,17 +6782,6 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
73906782 .storage = .{ .u64 = info.value },
73916783 } };
73926784 },
7393 .int_lazy_align, .int_lazy_size => |tag| {
7394 const info = extraData(unwrapped_index.getExtra(ip), IntLazy, data);
7395 return .{ .int = .{
7396 .ty = info.ty,
7397 .storage = switch (tag) {
7398 .int_lazy_align => .{ .lazy_align = info.lazy_ty },
7399 .int_lazy_size => .{ .lazy_size = info.lazy_ty },
7400 else => unreachable,
7401 },
7402 } };
7403 },
74046785 .float_f16 => .{ .float = .{
74056786 .ty = .f16_type,
74066787 .storage = .{ .f16 = @bitCast(@as(u16, @intCast(data))) },
......@@ -7488,7 +6869,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
74886869 },
74896870 .type_array_small,
74906871 .type_vector,
7491 .type_struct_packed,
6872 // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire.
6873 .type_struct_packed_auto,
6874 .type_struct_packed_explicit,
74926875 => .{ .aggregate = .{
74936876 .ty = ty,
74946877 .storage = .{ .elems = &.{} },
......@@ -7496,11 +6879,15 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
74966879
74976880 // There is only one possible value precisely due to the
74986881 // fact that this values slice is fully populated!
7499 .type_struct, .type_struct_packed_inits => {
6882 .type_struct,
6883 // MLUGG TODO: is this still possible? also, i hate .only_possible_value, it should die in a fire.
6884 .type_struct_packed_auto_defaults,
6885 .type_struct_packed_explicit_defaults,
6886 => {
75006887 const info = loadStructType(ip, ty);
75016888 return .{ .aggregate = .{
75026889 .ty = ty,
7503 .storage = .{ .elems = @ptrCast(info.field_inits.get(ip)) },
6890 .storage = .{ .elems = @ptrCast(info.field_defaults.get(ip)) },
75046891 } };
75056892 },
75066893
......@@ -7634,7 +7021,6 @@ fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Ke
76347021 .cc = type_function.data.flags.cc.unpack(),
76357022 .is_var_args = type_function.data.flags.is_var_args,
76367023 .is_noinline = type_function.data.flags.is_noinline,
7637 .is_generic = type_function.data.flags.is_generic,
76387024 };
76397025}
76407026
......@@ -7893,45 +7279,6 @@ fn getOrPutKeyEnsuringAdditionalCapacity(
78937279 .map_index = map_index,
78947280 } };
78957281}
7896/// Like `getOrPutKey`, but asserts that the key already exists, and prepares to replace
7897/// its shard entry with a new `Index` anyway. After finalizing this, the old index remains
7898/// valid (in that `indexToKey` and similar queries will behave as before), but it will
7899/// never be returned from a lookup (`getOrPutKey` etc).
7900/// This is used by incremental compilation when an existing container type is outdated. In
7901/// this case, the type must be recreated at a new `InternPool.Index`, but the old index must
7902/// remain valid since now-unreferenced `AnalUnit`s may retain references to it. The old index
7903/// will be cleaned up when the `Zcu` undergoes garbage collection.
7904fn putKeyReplace(
7905 ip: *InternPool,
7906 io: Io,
7907 tid: Zcu.PerThread.Id,
7908 key: Key,
7909) GetOrPutKey {
7910 const full_hash = key.hash64(ip);
7911 const hash: u32 = @truncate(full_hash >> 32);
7912 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))];
7913 shard.mutate.map.mutex.lock(io, tid);
7914 errdefer shard.mutate.map.mutex.unlock(io);
7915 const map = shard.shared.map;
7916 const map_mask = map.header().mask();
7917 var map_index = hash;
7918 while (true) : (map_index += 1) {
7919 map_index &= map_mask;
7920 const entry = &map.entries[map_index];
7921 const index = entry.value;
7922 assert(index != .none); // key not present
7923 if (entry.hash == hash and ip.indexToKey(index).eql(key, ip)) {
7924 break; // we found the entry to replace
7925 }
7926 }
7927 return .{ .new = .{
7928 .ip = ip,
7929 .tid = tid,
7930 .io = io,
7931 .shard = shard,
7932 .map_index = map_index,
7933 } };
7934}
79357282
79367283pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index {
79377284 var gop = try ip.getOrPutKey(gpa, io, tid, key);
......@@ -8249,23 +7596,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
82497596
82507597 .int => |int| b: {
82517598 assert(ip.isIntegerType(int.ty));
8252 switch (int.storage) {
8253 .u64, .i64, .big_int => {},
8254 .lazy_align, .lazy_size => |lazy_ty| {
8255 items.appendAssumeCapacity(.{
8256 .tag = switch (int.storage) {
8257 else => unreachable,
8258 .lazy_align => .int_lazy_align,
8259 .lazy_size => .int_lazy_size,
8260 },
8261 .data = try addExtra(extra, IntLazy{
8262 .ty = int.ty,
8263 .lazy_ty = lazy_ty,
8264 }),
8265 });
8266 return gop.put();
8267 },
8268 }
82697599 switch (int.ty) {
82707600 .u8_type => switch (int.storage) {
82717601 .big_int => |big_int| {
......@@ -8282,7 +7612,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
82827612 });
82837613 break :b;
82847614 },
8285 .lazy_align, .lazy_size => unreachable,
82867615 },
82877616 .u16_type => switch (int.storage) {
82887617 .big_int => |big_int| {
......@@ -8299,7 +7628,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
82997628 });
83007629 break :b;
83017630 },
8302 .lazy_align, .lazy_size => unreachable,
83037631 },
83047632 .u32_type => switch (int.storage) {
83057633 .big_int => |big_int| {
......@@ -8316,7 +7644,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
83167644 });
83177645 break :b;
83187646 },
8319 .lazy_align, .lazy_size => unreachable,
83207647 },
83217648 .i32_type => switch (int.storage) {
83227649 .big_int => |big_int| {
......@@ -8334,7 +7661,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
83347661 });
83357662 break :b;
83367663 },
8337 .lazy_align, .lazy_size => unreachable,
83387664 },
83397665 .usize_type => switch (int.storage) {
83407666 .big_int => |big_int| {
......@@ -8355,7 +7681,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
83557681 break :b;
83567682 }
83577683 },
8358 .lazy_align, .lazy_size => unreachable,
83597684 },
83607685 .comptime_int_type => switch (int.storage) {
83617686 .big_int => |big_int| {
......@@ -8390,7 +7715,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
83907715 break :b;
83917716 }
83927717 },
8393 .lazy_align, .lazy_size => unreachable,
83947718 },
83957719 else => {},
83967720 }
......@@ -8427,7 +7751,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
84277751 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
84287752 try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs);
84297753 },
8430 .lazy_align, .lazy_size => unreachable,
84317754 }
84327755 },
84337756
......@@ -8468,7 +7791,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
84687791 assert(ip.isEnumType(enum_tag.ty));
84697792 switch (ip.indexToKey(enum_tag.ty)) {
84707793 .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))),
8471 .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).tag_ty),
7794 .enum_type => assert(ip.typeOf(enum_tag.int) == ip.loadEnumType(enum_tag.ty).int_tag_type),
84727795 else => unreachable,
84737796 }
84747797 items.appendAssumeCapacity(.{
......@@ -8735,465 +8058,637 @@ pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key:
87358058 return gop.put();
87368059}
87378060
8738pub fn getUnion(
8739 ip: *InternPool,
8740 gpa: Allocator,
8741 io: Io,
8742 tid: Zcu.PerThread.Id,
8743 un: Key.Union,
8744) Allocator.Error!Index {
8745 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un });
8746 defer gop.deinit();
8747 if (gop == .existing) return gop.existing;
8748 const local = ip.getLocal(tid);
8749 const items = local.getMutableItems(gpa, io);
8750 const extra = local.getMutableExtra(gpa, io);
8751 try items.ensureUnusedCapacity(1);
8752
8753 assert(un.ty != .none);
8754 assert(un.val != .none);
8755 items.appendAssumeCapacity(.{
8756 .tag = .union_value,
8757 .data = try addExtra(extra, un),
8758 });
8759
8760 return gop.put();
8761}
8762
8763pub const UnionTypeInit = struct {
8764 flags: packed struct {
8765 runtime_tag: LoadedUnionType.RuntimeTag,
8766 any_aligned_fields: bool,
8767 layout: std.builtin.Type.ContainerLayout,
8768 status: LoadedUnionType.Status,
8769 requires_comptime: RequiresComptime,
8770 assumed_runtime_bits: bool,
8771 assumed_pointer_aligned: bool,
8772 alignment: Alignment,
8773 },
8061pub fn getStructType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct {
87748062 fields_len: u32,
8775 enum_tag_ty: Index,
8776 /// May have length 0 which leaves the values unset until later.
8777 field_types: []const Index,
8778 /// May have length 0 which leaves the values unset until later.
8779 /// The logic for `any_aligned_fields` is asserted to have been done before
8780 /// calling this function.
8781 field_aligns: []const Alignment,
8063 layout: std.builtin.Type.ContainerLayout,
8064 /// The following only applies if `layout == .@"packed"`; this field is ignored otherwise.
8065 ///
8066 /// The explicitly specified backing integer type. `.none` means the backing integer is inferred
8067 /// by the compiler. Asserts that this is an integer type.
8068 explicit_packed_backing_type: Index,
8069 any_comptime_fields: bool,
8070 any_field_defaults: bool,
8071 any_field_aligns: bool,
87828072 key: union(enum) {
87838073 declared: struct {
87848074 zir_index: TrackedInst.Index,
87858075 captures: []const CaptureValue,
87868076 },
8787 declared_owned_captures: struct {
8788 zir_index: TrackedInst.Index,
8789 captures: CaptureValue.Slice,
8790 },
87918077 reified: struct {
87928078 zir_index: TrackedInst.Index,
87938079 type_hash: u64,
87948080 },
87958081 },
8796};
8797
8798pub fn getUnionType(
8799 ip: *InternPool,
8800 gpa: Allocator,
8801 io: Io,
8802 tid: Zcu.PerThread.Id,
8803 ini: UnionTypeInit,
8804 /// If it is known that there is an existing type with this key which is outdated,
8805 /// this is passed as `true`, and the type is replaced with one at a fresh index.
8806 replace_existing: bool,
8807) Allocator.Error!WipNamespaceType.Result {
8808 const key: Key = .{ .union_type = switch (ini.key) {
8082}) Allocator.Error!WipContainerType.Result {
8083 const key: Key = .{ .struct_type = switch (ini.key) {
88098084 .declared => |d| .{ .declared = .{
88108085 .zir_index = d.zir_index,
8086 .arg_ty = switch (ini.layout) {
8087 .auto, .@"extern" => .none,
8088 .@"packed" => ini.explicit_packed_backing_type,
8089 },
88118090 .captures = .{ .external = d.captures },
88128091 } },
8813 .declared_owned_captures => |d| .{ .declared = .{
8814 .zir_index = d.zir_index,
8815 .captures = .{ .owned = d.captures },
8816 } },
88178092 .reified => |r| .{ .reified = .{
88188093 .zir_index = r.zir_index,
88198094 .type_hash = r.type_hash,
88208095 } },
88218096 } };
8822 var gop = if (replace_existing)
8823 ip.putKeyReplace(io, tid, key)
8824 else
8825 try ip.getOrPutKey(gpa, io, tid, key);
8097 var gop = try ip.getOrPutKey(gpa, io, tid, key);
88268098 defer gop.deinit();
88278099 if (gop == .existing) return .{ .existing = gop.existing };
88288100
88298101 const local = ip.getLocal(tid);
88308102 const items = local.getMutableItems(gpa, io);
8831 try items.ensureUnusedCapacity(1);
88328103 const extra = local.getMutableExtra(gpa, io);
8104 try items.ensureUnusedCapacity(1);
88338105
8834 const align_elements_len = if (ini.flags.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;
8835 const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);
8836 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len +
8837 // TODO: fmt bug
8838 // zig fmt: off
8839 switch (ini.key) {
8840 inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len,
8841 .reified => 2, // type_hash: PackedU64
8842 } +
8843 // zig fmt: on
8844 ini.fields_len + // field types
8845 align_elements_len);
8106 const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len);
8107 errdefer local.mutate.maps.len -= 1;
88468108
8847 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{
8848 .flags = .{
8849 .any_captures = switch (ini.key) {
8850 inline .declared, .declared_owned_captures => |d| d.captures.len != 0,
8851 .reified => false,
8852 },
8853 .runtime_tag = ini.flags.runtime_tag,
8854 .any_aligned_fields = ini.flags.any_aligned_fields,
8855 .layout = ini.flags.layout,
8856 .status = ini.flags.status,
8857 .requires_comptime = ini.flags.requires_comptime,
8858 .assumed_runtime_bits = ini.flags.assumed_runtime_bits,
8859 .assumed_pointer_aligned = ini.flags.assumed_pointer_aligned,
8860 .alignment = ini.flags.alignment,
8861 .is_reified = switch (ini.key) {
8862 .declared, .declared_owned_captures => false,
8863 .reified => true,
8864 },
8109 const zir_index, const type_hash_captures_extra_len = switch (ini.key) {
8110 .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") },
8111 .reified => |r| .{ r.zir_index, 2 },
8112 };
8113
8114 const is_extern = switch (ini.layout) {
8115 .auto => false,
8116 .@"extern" => true,
8117 .@"packed" => {
8118 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len +
8119 type_hash_captures_extra_len +
8120 ini.fields_len + // field_name
8121 ini.fields_len + // field_type
8122 (if (ini.any_field_defaults) ini.fields_len else 0)); // field_default
8123
8124 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
8125 .zir_index = zir_index,
8126 .captures_len = switch (ini.key) {
8127 .declared => |d| @enumFromInt(d.captures.len),
8128 .reified => .reified,
8129 },
8130 .name = undefined, // set by `finish`
8131 .name_nav = undefined, // set by `finish`
8132 .namespace = undefined, // set by `finish`
8133 .backing_int_type = ini.explicit_packed_backing_type,
8134 .fields_len = ini.fields_len,
8135 .field_name_map = field_name_map,
8136 });
8137 switch (ini.key) {
8138 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
8139 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
8140 }
8141 const field_names_start = extra.mutate.len;
8142 extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name
8143 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type
8144 if (ini.any_field_defaults) {
8145 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default
8146 }
8147 items.appendAssumeCapacity(.{
8148 .tag = switch (ini.explicit_packed_backing_type) {
8149 .none => if (ini.any_field_defaults) .type_struct_packed_auto_defaults else .type_struct_packed_auto,
8150 else => if (ini.any_field_defaults) .type_struct_packed_explicit_defaults else .type_struct_packed_explicit,
8151 },
8152 .data = extra_index,
8153 });
8154 return .{ .wip = .{
8155 .index = gop.put(),
8156 .tid = tid,
8157 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
8158 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?,
8159 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
8160 .tag_type_index = null,
8161 .fields_len = ini.fields_len,
8162 .field_name_map = field_name_map,
8163 .field_names_start = field_names_start,
8164 .field_comptime_bits_start = null,
8165 } };
88658166 },
8866 .fields_len = ini.fields_len,
8867 .size = std.math.maxInt(u32),
8868 .padding = std.math.maxInt(u32),
8167 };
8168
8169 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len +
8170 type_hash_captures_extra_len +
8171 ini.fields_len + // field_name
8172 ini.fields_len + // field_type
8173 (if (ini.any_field_defaults) ini.fields_len else 0) + // field_default
8174 (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0) + // field_align
8175 (if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0) + // field_is_comptime_bits
8176 (if (!is_extern) ini.fields_len else 0) + // field_runtime_order
8177 ini.fields_len); // field_offset
8178
8179 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
8180 .zir_index = zir_index,
88698181 .name = undefined, // set by `finish`
88708182 .name_nav = undefined, // set by `finish`
88718183 .namespace = undefined, // set by `finish`
8872 .tag_ty = ini.enum_tag_ty,
8873 .zir_index = switch (ini.key) {
8874 inline else => |x| x.zir_index,
8184 .fields_len = ini.fields_len,
8185 .field_name_map = field_name_map,
8186 .size = 0,
8187 .flags = .{
8188 .any_captures = switch (ini.key) {
8189 .declared => |d| if (d.captures.len != 0) .true else .false,
8190 .reified => .reified,
8191 },
8192 .layout = if (is_extern) .@"extern" else .auto,
8193 .any_comptime_fields = ini.any_comptime_fields,
8194 .any_field_defaults = ini.any_field_defaults,
8195 .any_field_aligns = ini.any_field_aligns,
8196 .has_one_possible_value = false,
8197 .has_no_possible_value = false,
8198 .comptime_only = false,
8199 .alignment = .none,
88758200 },
88768201 });
8877
8878 items.appendAssumeCapacity(.{
8879 .tag = .type_union,
8880 .data = extra_index,
8881 });
8882
88838202 switch (ini.key) {
88848203 .declared => |d| if (d.captures.len != 0) {
88858204 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
88868205 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)});
88878206 },
8888 .declared_owned_captures => |d| if (d.captures.len != 0) {
8889 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
8890 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))});
8891 },
88928207 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
88938208 }
8894
8895 // field types
8896 if (ini.field_types.len > 0) {
8897 assert(ini.field_types.len == ini.fields_len);
8898 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.field_types)});
8899 } else {
8900 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
8209 const field_names_start = extra.mutate.len;
8210 extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name
8211 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type
8212 if (ini.any_field_defaults) {
8213 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_default
89018214 }
8902
8903 // field alignments
8904 if (ini.flags.any_aligned_fields) {
8905 extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len);
8906 if (ini.field_aligns.len > 0) {
8907 assert(ini.field_aligns.len == ini.fields_len);
8908 @memcpy((Alignment.Slice{
8909 .tid = tid,
8910 .start = @intCast(extra.mutate.len - align_elements_len),
8911 .len = @intCast(ini.field_aligns.len),
8912 }).get(ip), ini.field_aligns);
8913 }
8914 } else {
8915 assert(ini.field_aligns.len == 0);
8215 if (ini.any_field_aligns) {
8216 extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align
89168217 }
8917
8218 const field_comptime_bits_start: ?u32 = if (ini.any_comptime_fields) start: {
8219 const start = extra.mutate.len;
8220 extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 31) / 32); // field_is_comptime_bits
8221 break :start start;
8222 } else null;
8223 if (!is_extern) {
8224 extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len); // field_runtime_order
8225 }
8226 extra.appendNTimesAssumeCapacity(.{0}, ini.fields_len); // field_offset
8227 items.appendAssumeCapacity(.{
8228 .tag = .type_struct,
8229 .data = extra_index,
8230 });
89188231 return .{ .wip = .{
8919 .tid = tid,
89208232 .index = gop.put(),
8921 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
8922 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?,
8923 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
8233 .tid = tid,
8234 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
8235 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?,
8236 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
8237 .tag_type_index = null,
8238 .fields_len = ini.fields_len,
8239 .field_name_map = field_name_map,
8240 .field_names_start = field_names_start,
8241 .field_comptime_bits_start = field_comptime_bits_start,
89248242 } };
89258243}
89268244
8927pub const WipNamespaceType = struct {
8928 tid: Zcu.PerThread.Id,
8929 index: Index,
8930 type_name_extra_index: u32,
8931 namespace_extra_index: u32,
8932 name_nav_extra_index: u32,
8933
8934 pub fn setName(
8935 wip: WipNamespaceType,
8936 ip: *InternPool,
8937 type_name: NullTerminatedString,
8938 /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
8939 /// This is also `.none` if we use `.parent` because we are the root struct type for a file.
8940 name_nav: Nav.Index.Optional,
8941 ) void {
8942 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8943 const extra_items = extra.view().items(.@"0");
8944 extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
8945 extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
8946 }
8947
8948 pub fn finish(
8949 wip: WipNamespaceType,
8950 ip: *InternPool,
8951 namespace: NamespaceIndex,
8952 ) Index {
8953 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8954 const extra_items = extra.view().items(.@"0");
8955
8956 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
8957
8958 return wip.index;
8959 }
8960
8961 pub fn cancel(wip: WipNamespaceType, ip: *InternPool, tid: Zcu.PerThread.Id) void {
8962 ip.remove(tid, wip.index);
8963 }
8964
8965 pub const Result = union(enum) {
8966 wip: WipNamespaceType,
8967 existing: Index,
8968 };
8969};
8970
8971pub const StructTypeInit = struct {
8972 layout: std.builtin.Type.ContainerLayout,
8245pub fn getUnionType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct {
89738246 fields_len: u32,
8974 known_non_opv: bool,
8975 requires_comptime: RequiresComptime,
8976 any_comptime_fields: bool,
8977 any_default_inits: bool,
8978 inits_resolved: bool,
8979 any_aligned_fields: bool,
8247 layout: std.builtin.Type.ContainerLayout,
8248 /// The explicitly specified backing integer type for a `packed union`.
8249 /// `.none` means the backing integer is inferred by the compiler. If set,
8250 /// must be an integer type. If the union is not packed, must be `.none`.
8251 explicit_packed_backing_type: Index,
8252 runtime_tag: LoadedUnionType.RuntimeTag,
8253 /// `true` for `union(T)`, but `false` for anything else, including `union(enum(T))`.
8254 have_explicit_enum_tag: bool,
8255 any_field_aligns: bool,
89808256 key: union(enum) {
89818257 declared: struct {
89828258 zir_index: TrackedInst.Index,
89838259 captures: []const CaptureValue,
8984 },
8985 declared_owned_captures: struct {
8986 zir_index: TrackedInst.Index,
8987 captures: CaptureValue.Slice,
8260 /// This is the `T` in one of the following:
8261 /// * `union(T)` (enum tag type)
8262 /// * `union(enum(T))` (int tag type)
8263 /// * `packed union(T)` (int backing type)
8264 /// Or `.none` otherwise.
8265 arg_ty: InternPool.Index,
89888266 },
89898267 reified: struct {
89908268 zir_index: TrackedInst.Index,
89918269 type_hash: u64,
89928270 },
89938271 },
8994};
8995
8996pub fn getStructType(
8997 ip: *InternPool,
8998 gpa: Allocator,
8999 io: Io,
9000 tid: Zcu.PerThread.Id,
9001 ini: StructTypeInit,
9002 /// If it is known that there is an existing type with this key which is outdated,
9003 /// this is passed as `true`, and the type is replaced with one at a fresh index.
9004 replace_existing: bool,
9005) Allocator.Error!WipNamespaceType.Result {
9006 const key: Key = .{ .struct_type = switch (ini.key) {
8272}) Allocator.Error!WipContainerType.Result {
8273 if (ini.explicit_packed_backing_type != .none) {
8274 assert(ip.zigTypeTag(ini.explicit_packed_backing_type) == .int);
8275 if (ini.key == .declared) assert(ini.key.declared.arg_ty == ini.explicit_packed_backing_type);
8276 }
8277 const key: Key = .{ .union_type = switch (ini.key) {
90078278 .declared => |d| .{ .declared = .{
90088279 .zir_index = d.zir_index,
8280 .arg_ty = d.arg_ty,
90098281 .captures = .{ .external = d.captures },
90108282 } },
9011 .declared_owned_captures => |d| .{ .declared = .{
9012 .zir_index = d.zir_index,
9013 .captures = .{ .owned = d.captures },
9014 } },
90158283 .reified => |r| .{ .reified = .{
90168284 .zir_index = r.zir_index,
90178285 .type_hash = r.type_hash,
90188286 } },
90198287 } };
9020 var gop = if (replace_existing)
9021 ip.putKeyReplace(io, tid, key)
9022 else
9023 try ip.getOrPutKey(gpa, io, tid, key);
8288 var gop = try ip.getOrPutKey(gpa, io, tid, key);
90248289 defer gop.deinit();
90258290 if (gop == .existing) return .{ .existing = gop.existing };
90268291
90278292 const local = ip.getLocal(tid);
90288293 const items = local.getMutableItems(gpa, io);
90298294 const extra = local.getMutableExtra(gpa, io);
8295 try items.ensureUnusedCapacity(1);
90308296
9031 const names_map = try ip.addMap(gpa, io, tid, ini.fields_len);
9032 errdefer local.mutate.maps.len -= 1;
9033
9034 const zir_index = switch (ini.key) {
9035 inline else => |x| x.zir_index,
8297 const zir_index, const type_hash_captures_extra_len = switch (ini.key) {
8298 .declared => |d| .{ d.zir_index, d.captures.len + @intFromBool(ini.layout != .@"packed") },
8299 .reified => |r| .{ r.zir_index, 2 },
90368300 };
90378301
90388302 const is_extern = switch (ini.layout) {
90398303 .auto => false,
90408304 .@"extern" => true,
90418305 .@"packed" => {
9042 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStructPacked).@"struct".fields.len +
9043 // TODO: fmt bug
9044 // zig fmt: off
9045 switch (ini.key) {
9046 inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len,
9047 .reified => 2, // type_hash: PackedU64
9048 } +
9049 // zig fmt: on
9050 ini.fields_len + // types
9051 ini.fields_len + // names
9052 ini.fields_len); // inits
9053 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStructPacked{
8306 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnionPacked).@"struct".fields.len +
8307 type_hash_captures_extra_len +
8308 ini.fields_len); // field_type
8309
8310 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnionPacked{
8311 .zir_index = zir_index,
8312 .captures_len = switch (ini.key) {
8313 .declared => |d| @enumFromInt(d.captures.len),
8314 .reified => .reified,
8315 },
90548316 .name = undefined, // set by `finish`
90558317 .name_nav = undefined, // set by `finish`
9056 .zir_index = zir_index,
9057 .fields_len = ini.fields_len,
90588318 .namespace = undefined, // set by `finish`
9059 .backing_int_ty = .none,
9060 .names_map = names_map,
9061 .flags = .{
9062 .any_captures = switch (ini.key) {
9063 inline .declared, .declared_owned_captures => |d| d.captures.len != 0,
9064 .reified => false,
9065 },
9066 .field_inits_wip = false,
9067 .inits_resolved = ini.inits_resolved,
9068 .is_reified = switch (ini.key) {
9069 .declared, .declared_owned_captures => false,
9070 .reified => true,
9071 },
9072 },
9073 });
9074 try items.append(.{
9075 .tag = if (ini.any_default_inits) .type_struct_packed_inits else .type_struct_packed,
9076 .data = extra_index,
8319 .backing_int_type = ini.explicit_packed_backing_type,
8320 .enum_tag_type = .none, // set by `setTagType`
8321 .fields_len = ini.fields_len,
90778322 });
90788323 switch (ini.key) {
9079 .declared => |d| if (d.captures.len != 0) {
9080 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
9081 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)});
9082 },
9083 .declared_owned_captures => |d| if (d.captures.len != 0) {
9084 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
9085 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))});
8324 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
8325 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
8326 }
8327 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type
8328 items.appendAssumeCapacity(.{
8329 .tag = switch (ini.explicit_packed_backing_type) {
8330 .none => .type_union_packed_auto,
8331 else => .type_union_packed_explicit,
90868332 },
9087 .reified => |r| {
9088 _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash));
8333 .data = extra_index,
8334 });
8335 return .{
8336 .wip = .{
8337 .index = gop.put(),
8338 .tid = tid,
8339 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name").?,
8340 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "name_nav").?,
8341 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "namespace").?,
8342 .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnionPacked, "enum_tag_type").?,
8343 .fields_len = 0, // the fields come from the enum, so nothing to set
8344 .field_name_map = undefined,
8345 .field_names_start = undefined,
8346 .field_comptime_bits_start = undefined,
90898347 },
9090 }
9091 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
9092 extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len);
9093 if (ini.any_default_inits) {
9094 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
9095 }
9096 return .{ .wip = .{
9097 .tid = tid,
9098 .index = gop.put(),
9099 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name").?,
9100 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "name_nav").?,
9101 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStructPacked, "namespace").?,
9102 } };
8348 };
91038349 },
91048350 };
91058351
9106 const align_elements_len = if (ini.any_aligned_fields) (ini.fields_len + 3) / 4 else 0;
9107 const align_element: u32 = @bitCast([1]u8{@intFromEnum(Alignment.none)} ** 4);
9108 const comptime_elements_len = if (ini.any_comptime_fields) (ini.fields_len + 31) / 32 else 0;
8352 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeUnion).@"struct".fields.len +
8353 type_hash_captures_extra_len +
8354 ini.fields_len + // field_type
8355 (if (ini.any_field_aligns) (ini.fields_len + 3) / 4 else 0)); // field_align
91098356
9110 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeStruct).@"struct".fields.len +
9111 // TODO: fmt bug
9112 // zig fmt: off
9113 switch (ini.key) {
9114 inline .declared, .declared_owned_captures => |d| @intFromBool(d.captures.len != 0) + d.captures.len,
9115 .reified => 2, // type_hash: PackedU64
9116 } +
9117 // zig fmt: on
9118 (ini.fields_len * 5) + // types, names, inits, runtime order, offsets
9119 align_elements_len + comptime_elements_len +
9120 1); // names_map
9121 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeStruct{
8357 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeUnion{
8358 .zir_index = zir_index,
91228359 .name = undefined, // set by `finish`
91238360 .name_nav = undefined, // set by `finish`
9124 .zir_index = zir_index,
91258361 .namespace = undefined, // set by `finish`
8362 .enum_tag_type = .none, // set by `setTagType`
91268363 .fields_len = ini.fields_len,
9127 .size = std.math.maxInt(u32),
8364 .size = 0,
8365 .padding = 0,
91288366 .flags = .{
91298367 .any_captures = switch (ini.key) {
9130 inline .declared, .declared_owned_captures => |d| d.captures.len != 0,
9131 .reified => false,
8368 .declared => |d| if (d.captures.len != 0) .true else .false,
8369 .reified => .reified,
91328370 },
9133 .is_extern = is_extern,
9134 .known_non_opv = ini.known_non_opv,
9135 .requires_comptime = ini.requires_comptime,
9136 .assumed_runtime_bits = false,
9137 .assumed_pointer_aligned = false,
9138 .any_comptime_fields = ini.any_comptime_fields,
9139 .any_default_inits = ini.any_default_inits,
9140 .any_aligned_fields = ini.any_aligned_fields,
8371 .explicit_tag_type = ini.have_explicit_enum_tag,
8372 .layout = if (is_extern) .@"extern" else .auto,
8373 .any_field_aligns = ini.any_field_aligns,
8374 .runtime_tag = ini.runtime_tag,
8375 .has_one_possible_value = false,
8376 .has_no_possible_value = false,
8377 .comptime_only = false,
91418378 .alignment = .none,
9142 .alignment_wip = false,
9143 .field_types_wip = false,
9144 .layout_wip = false,
9145 .layout_resolved = false,
9146 .field_inits_wip = false,
9147 .inits_resolved = ini.inits_resolved,
9148 .fully_resolved = false,
9149 .is_reified = switch (ini.key) {
9150 .declared, .declared_owned_captures => false,
9151 .reified => true,
9152 },
91538379 },
91548380 });
9155 try items.append(.{
9156 .tag = .type_struct,
9157 .data = extra_index,
9158 });
91598381 switch (ini.key) {
91608382 .declared => |d| if (d.captures.len != 0) {
91618383 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
91628384 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)});
91638385 },
9164 .declared_owned_captures => |d| if (d.captures.len != 0) {
9165 extra.appendAssumeCapacity(.{@intCast(d.captures.len)});
9166 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))});
9167 },
9168 .reified => |r| {
9169 _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash));
9170 },
9171 }
9172 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
9173 extra.appendAssumeCapacity(.{@intFromEnum(names_map)});
9174 extra.appendNTimesAssumeCapacity(.{@intFromEnum(OptionalNullTerminatedString.none)}, ini.fields_len);
9175 if (ini.any_default_inits) {
9176 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len);
8386 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
91778387 }
9178 if (ini.any_aligned_fields) {
9179 extra.appendNTimesAssumeCapacity(.{align_element}, align_elements_len);
8388 extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_type
8389 if (ini.any_field_aligns) {
8390 extra.appendNTimesAssumeCapacity(.{0}, (ini.fields_len + 3) / 4); // field_align
91808391 }
9181 if (ini.any_comptime_fields) {
9182 extra.appendNTimesAssumeCapacity(.{0}, comptime_elements_len);
9183 }
9184 if (ini.layout == .auto) {
9185 extra.appendNTimesAssumeCapacity(.{@intFromEnum(LoadedStructType.RuntimeOrder.unresolved)}, ini.fields_len);
8392 items.appendAssumeCapacity(.{
8393 .tag = .type_union,
8394 .data = extra_index,
8395 });
8396 return .{
8397 .wip = .{
8398 .index = gop.put(),
8399 .tid = tid,
8400 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name").?,
8401 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "name_nav").?,
8402 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "namespace").?,
8403 .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeUnion, "enum_tag_type").?,
8404 .fields_len = 0, // the fields come from the enum, so nothing to set
8405 .field_name_map = undefined,
8406 .field_names_start = undefined,
8407 .field_comptime_bits_start = undefined,
8408 },
8409 };
8410}
8411
8412pub fn getEnumType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct {
8413 fields_len: u32,
8414 /// For `enum(T)` or `union(enum(T))`, this is `T`. Asserts `T` is an integer type.
8415 /// Otherwise, `.none`.
8416 explicit_int_tag_type: Index,
8417 nonexhaustive: bool,
8418 key: union(enum) {
8419 declared: struct {
8420 zir_index: TrackedInst.Index,
8421 captures: []const CaptureValue,
8422 },
8423 reified: struct {
8424 zir_index: TrackedInst.Index,
8425 type_hash: u64,
8426 },
8427 generated_union_tag: Index,
8428 },
8429}) Allocator.Error!WipContainerType.Result {
8430 const key: Key = .{ .enum_type = switch (ini.key) {
8431 .declared => |d| .{ .declared = .{
8432 .zir_index = d.zir_index,
8433 .arg_ty = ini.explicit_int_tag_type,
8434 .captures = .{ .external = d.captures },
8435 } },
8436 .reified => |r| .{ .reified = .{
8437 .zir_index = r.zir_index,
8438 .type_hash = r.type_hash,
8439 } },
8440 .generated_union_tag => |u| .{ .generated_union_tag = u },
8441 } };
8442 var gop = try ip.getOrPutKey(gpa, io, tid, key);
8443 defer gop.deinit();
8444 if (gop == .existing) return .{ .existing = gop.existing };
8445
8446 const local = ip.getLocal(tid);
8447 const items = local.getMutableItems(gpa, io);
8448 const extra = local.getMutableExtra(gpa, io);
8449 try items.ensureUnusedCapacity(1);
8450
8451 const tag: Tag, const have_values: bool = if (ini.nonexhaustive)
8452 .{ .type_enum_nonexhaustive, true }
8453 else if (ini.explicit_int_tag_type != .none)
8454 .{ .type_enum_explicit, true }
8455 else
8456 .{ .type_enum_auto, false };
8457
8458 const field_name_map = try ip.addMap(gpa, io, tid, ini.fields_len);
8459 errdefer local.mutate.maps.len -= 1;
8460
8461 const field_value_map = if (have_values) try ip.addMap(gpa, io, tid, ini.fields_len) else undefined;
8462 errdefer local.mutate.maps.len -= @intFromBool(have_values);
8463
8464 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeEnum).@"struct".fields.len +
8465 switch (ini.key) {
8466 .declared => |d| 1 + d.captures.len, // `zir_index` and `capture`
8467 .reified => 3, // `zir_index` and `type_hash`
8468 .generated_union_tag => 1, // owner_union
8469 } +
8470 @intFromBool(have_values) + // field_value_map
8471 ini.fields_len + // field_name
8472 (if (have_values) ini.fields_len else 0)); // field_value
8473
8474 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeEnum{
8475 .captures_len = switch (ini.key) {
8476 .declared => |d| @enumFromInt(d.captures.len),
8477 .reified => .reified,
8478 .generated_union_tag => .generated_union_tag,
8479 },
8480 .name = undefined, // set by `finish`
8481 .name_nav = undefined, // set by `finish`
8482 .namespace = undefined, // set by `finish`
8483 .int_tag_type = ini.explicit_int_tag_type,
8484 .fields_len = ini.fields_len,
8485 .field_name_map = field_name_map,
8486 });
8487 switch (ini.key) {
8488 .declared => |d| {
8489 extra.appendAssumeCapacity(.{@intFromEnum(d.zir_index)}); // zir_index
8490 extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}); // capture
8491 },
8492 .reified => |r| {
8493 extra.appendAssumeCapacity(.{@intFromEnum(r.zir_index)}); // zir_index
8494 _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)); // type_hash
8495 },
8496 .generated_union_tag => |owner_union| {
8497 extra.appendAssumeCapacity(.{@intFromEnum(owner_union)}); // owner_union
8498 },
91868499 }
9187 extra.appendNTimesAssumeCapacity(.{std.math.maxInt(u32)}, ini.fields_len);
8500 if (have_values) extra.appendAssumeCapacity(.{@intFromEnum(field_value_map)});
8501 const field_names_start = extra.mutate.len;
8502 extra.appendNTimesAssumeCapacity(.{@intFromEnum(NullTerminatedString.empty)}, ini.fields_len); // field_name
8503 if (have_values) extra.appendNTimesAssumeCapacity(.{@intFromEnum(Index.none)}, ini.fields_len); // field_value
8504 items.appendAssumeCapacity(.{
8505 .tag = tag,
8506 .data = extra_index,
8507 });
91888508 return .{ .wip = .{
8509 .index = gop.put(),
91898510 .tid = tid,
8511 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name").?,
8512 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "name_nav").?,
8513 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "namespace").?,
8514 .tag_type_index = extra_index + std.meta.fieldIndex(Tag.TypeEnum, "int_tag_type").?,
8515 .fields_len = ini.fields_len,
8516 .field_name_map = field_name_map,
8517 .field_names_start = field_names_start,
8518 .field_comptime_bits_start = null,
8519 } };
8520}
8521
8522pub fn getOpaqueType(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, ini: struct {
8523 zir_index: TrackedInst.Index,
8524 captures: []const CaptureValue,
8525}) Allocator.Error!WipContainerType.Result {
8526 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{
8527 .zir_index = ini.zir_index,
8528 .captures = .{ .external = ini.captures },
8529 .arg_ty = .none,
8530 } } });
8531 defer gop.deinit();
8532 if (gop == .existing) return .{ .existing = gop.existing };
8533
8534 const local = ip.getLocal(tid);
8535 const items = local.getMutableItems(gpa, io);
8536 const extra = local.getMutableExtra(gpa, io);
8537 try items.ensureUnusedCapacity(1);
8538
8539 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
8540 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
8541 .zir_index = ini.zir_index,
8542 .captures_len = @intCast(ini.captures.len),
8543 .name = undefined, // set by `finish`
8544 .name_nav = undefined, // set by `finish`
8545 .namespace = undefined, // set by `finish`
8546 });
8547 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
8548 items.appendAssumeCapacity(.{
8549 .tag = .type_opaque,
8550 .data = extra_index,
8551 });
8552 return .{ .wip = .{
91908553 .index = gop.put(),
9191 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name").?,
9192 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "name_nav").?,
9193 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeStruct, "namespace").?,
8554 .tid = tid,
8555 .type_name_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
8556 .name_nav_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?,
8557 .namespace_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
8558 .tag_type_index = null,
8559 .fields_len = 0,
8560 .field_name_map = undefined,
8561 .field_names_start = undefined,
8562 .field_comptime_bits_start = undefined,
91948563 } };
91958564}
91968565
8566pub const WipContainerType = struct {
8567 index: Index,
8568 tid: Zcu.PerThread.Id,
8569 type_name_index: u32,
8570 name_nav_index: u32,
8571 namespace_index: u32,
8572
8573 tag_type_index: ?u32,
8574
8575 fields_len: u32,
8576 field_name_map: MapIndex,
8577 field_names_start: u32,
8578 field_comptime_bits_start: ?u32,
8579
8580 pub fn setName(
8581 wip: WipContainerType,
8582 ip: *InternPool,
8583 type_name: NullTerminatedString,
8584 /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
8585 /// This is also `.none` if we use `.parent` because we are the root struct type for a file.
8586 name_nav: Nav.Index.Optional,
8587 ) void {
8588 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8589 const extra_items = extra.view().items(.@"0");
8590 extra_items[wip.type_name_index] = @intFromEnum(type_name);
8591 extra_items[wip.name_nav_index] = @intFromEnum(name_nav);
8592 }
8593
8594 pub fn setTagType(
8595 wip: WipContainerType,
8596 ip: *InternPool,
8597 tag_ty: Index,
8598 ) void {
8599 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8600 const extra_items = extra.view().items(.@"0");
8601 const i = wip.tag_type_index.?;
8602 const old_val: InternPool.Index = @enumFromInt(extra_items[i]);
8603 assert(old_val == .none);
8604 assert(tag_ty != .none);
8605 extra_items[i] = @intFromEnum(tag_ty);
8606 }
8607
8608 /// Returns the already-existing field with the same name, if any.
8609 pub fn nextField(
8610 wip: WipContainerType,
8611 ip: *InternPool,
8612 name: NullTerminatedString,
8613 marked_comptime: bool,
8614 ) ?u32 {
8615 assert(wip.fields_len > 0);
8616 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8617 const extra_items = extra.view().items(.@"0");
8618 const map = wip.field_name_map.get(ip);
8619 const field_idx = map.count();
8620 assert(field_idx < wip.fields_len);
8621 const names: []NullTerminatedString = @ptrCast(extra_items[wip.field_names_start..][0..wip.fields_len]);
8622 const adapter: NullTerminatedString.Adapter = .{ .strings = names[0..field_idx] };
8623 const gop = map.getOrPutAssumeCapacityAdapted(name, adapter);
8624 if (gop.found_existing) return @intCast(gop.index);
8625 names[field_idx] = name;
8626 if (wip.field_comptime_bits_start) |start_idx| {
8627 if (marked_comptime) {
8628 extra_items[start_idx + field_idx / 32] |= @as(u32, 1) << @intCast(field_idx % 32);
8629 }
8630 } else {
8631 assert(!marked_comptime);
8632 }
8633 return null;
8634 }
8635
8636 pub fn finish(
8637 wip: WipContainerType,
8638 ip: *InternPool,
8639 namespace: NamespaceIndex,
8640 ) Index {
8641 const extra = ip.getLocalShared(wip.tid).extra.acquire();
8642 const extra_items = extra.view().items(.@"0");
8643
8644 extra_items[wip.namespace_index] = @intFromEnum(namespace);
8645
8646 if (wip.fields_len > 0) {
8647 assert(wip.field_name_map.get(ip).count() == wip.fields_len);
8648 }
8649 if (wip.tag_type_index) |i| {
8650 const tag_ty: Index = @enumFromInt(extra_items[i]);
8651 assert(tag_ty != .none);
8652 }
8653
8654 return wip.index;
8655 }
8656
8657 pub fn cancel(wip: WipContainerType, ip: *InternPool, tid: Zcu.PerThread.Id) void {
8658 ip.remove(tid, wip.index);
8659 }
8660
8661 pub const Result = union(enum) {
8662 wip: WipContainerType,
8663 existing: Index,
8664 };
8665};
8666
8667pub fn getUnion(
8668 ip: *InternPool,
8669 gpa: Allocator,
8670 io: Io,
8671 tid: Zcu.PerThread.Id,
8672 un: Key.Union,
8673) Allocator.Error!Index {
8674 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .un = un });
8675 defer gop.deinit();
8676 if (gop == .existing) return gop.existing;
8677 const local = ip.getLocal(tid);
8678 const items = local.getMutableItems(gpa, io);
8679 const extra = local.getMutableExtra(gpa, io);
8680 try items.ensureUnusedCapacity(1);
8681
8682 assert(un.ty != .none);
8683 assert(un.val != .none);
8684 items.appendAssumeCapacity(.{
8685 .tag = .union_value,
8686 .data = try addExtra(extra, un),
8687 });
8688
8689 return gop.put();
8690}
8691
91978692pub const TupleTypeInit = struct {
91988693 types: []const Index,
91998694 /// These elements may be `none`, indicating runtime-known.
......@@ -9252,10 +8747,7 @@ pub const GetFuncTypeKey = struct {
92528747 /// `null` means generic.
92538748 cc: ?std.builtin.CallingConvention = .auto,
92548749 is_var_args: bool = false,
9255 is_generic: bool = false,
92568750 is_noinline: bool = false,
9257 section_is_generic: bool = false,
9258 addrspace_is_generic: bool = false,
92598751};
92608752
92618753pub fn getFuncType(
......@@ -9293,7 +8785,6 @@ pub fn getFuncType(
92938785 .is_var_args = key.is_var_args,
92948786 .has_comptime_bits = key.comptime_bits != 0,
92958787 .has_noalias_bits = key.noalias_bits != 0,
9296 .is_generic = key.is_generic,
92978788 .is_noinline = key.is_noinline,
92988789 },
92998790 });
......@@ -9480,7 +8971,6 @@ pub const GetFuncDeclIesKey = struct {
94808971 /// null means generic.
94818972 cc: ?std.builtin.CallingConvention,
94828973 is_var_args: bool,
9483 is_generic: bool,
94848974 is_noinline: bool,
94858975 zir_body_inst: TrackedInst.Index,
94868976 lbrace_line: u32,
......@@ -9564,7 +9054,6 @@ pub fn getFuncDeclIes(
95649054 .is_var_args = key.is_var_args,
95659055 .has_comptime_bits = key.comptime_bits != 0,
95669056 .has_noalias_bits = key.noalias_bits != 0,
9567 .is_generic = key.is_generic,
95689057 .is_noinline = key.is_noinline,
95699058 },
95709059 });
......@@ -9864,7 +9353,6 @@ fn getFuncInstanceIes(
98649353 .is_var_args = false,
98659354 .has_comptime_bits = false,
98669355 .has_noalias_bits = arg.noalias_bits != 0,
9867 .is_generic = false,
98689356 .is_noinline = arg.is_noinline,
98699357 },
98709358 });
......@@ -9876,538 +9364,100 @@ fn getFuncInstanceIes(
98769364 .tag = &.{
98779365 .func_instance,
98789366 .type_error_union,
9879 .type_inferred_error_set,
9880 .type_function,
9881 },
9882 .data = &.{
9883 func_extra_index,
9884 addExtraAssumeCapacity(extra, Tag.ErrorUnionType{
9885 .error_set_type = error_set_type,
9886 .payload_type = arg.bare_return_type,
9887 }),
9888 @intFromEnum(func_index),
9889 func_type_extra_index,
9890 },
9891 });
9892 errdefer {
9893 items.mutate.len -= 4;
9894 extra.mutate.len = prev_extra_len;
9895 }
9896
9897 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9898 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),
9899 }, 3);
9900 defer func_gop.deinit();
9901 if (func_gop == .existing) {
9902 // Hot path: undo the additions to our two arrays.
9903 items.mutate.len -= 4;
9904 extra.mutate.len = prev_extra_len;
9905 return func_gop.existing;
9906 }
9907 func_gop.putTentative(func_index);
9908 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{
9909 .error_set_type = error_set_type,
9910 .payload_type = arg.bare_return_type,
9911 } }, 2);
9912 defer error_union_type_gop.deinit();
9913 error_union_type_gop.putTentative(error_union_type);
9914 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9915 .inferred_error_set_type = func_index,
9916 }, 1);
9917 defer error_set_type_gop.deinit();
9918 error_set_type_gop.putTentative(error_set_type);
9919 var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{
9920 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
9921 });
9922 defer func_ty_gop.deinit();
9923 func_ty_gop.putTentative(func_ty);
9924 try finishFuncInstance(
9925 ip,
9926 gpa,
9927 io,
9928 tid,
9929 extra,
9930 generic_owner,
9931 func_index,
9932 func_extra_index,
9933 );
9934
9935 func_gop.putFinal(func_index);
9936 error_union_type_gop.putFinal(error_union_type);
9937 error_set_type_gop.putFinal(error_set_type);
9938 func_ty_gop.putFinal(func_ty);
9939 return func_index;
9940}
9941
9942fn finishFuncInstance(
9943 ip: *InternPool,
9944 gpa: Allocator,
9945 io: Io,
9946 tid: Zcu.PerThread.Id,
9947 extra: Local.Extra.Mutable,
9948 generic_owner: Index,
9949 func_index: Index,
9950 func_extra_index: u32,
9951) Allocator.Error!void {
9952 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);
9953 const fn_namespace = fn_owner_nav.analysis.?.namespace;
9954
9955 // TODO: improve this name
9956 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{
9957 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9958 }, .no_embedded_nulls);
9959 const nav_index = try ip.createNav(gpa, io, tid, .{
9960 .name = nav_name,
9961 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name),
9962 .val = func_index,
9963 .is_const = fn_owner_nav.status.fully_resolved.is_const,
9964 .alignment = fn_owner_nav.status.fully_resolved.alignment,
9965 .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection",
9966 .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace",
9967 });
9968
9969 // Populate the owner_nav field which was left undefined until now.
9970 extra.view().items(.@"0")[
9971 func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_nav").?
9972 ] = @intFromEnum(nav_index);
9973}
9974
9975pub const EnumTypeInit = struct {
9976 has_values: bool,
9977 tag_mode: LoadedEnumType.TagMode,
9978 fields_len: u32,
9979 key: union(enum) {
9980 declared: struct {
9981 zir_index: TrackedInst.Index,
9982 captures: []const CaptureValue,
9983 },
9984 declared_owned_captures: struct {
9985 zir_index: TrackedInst.Index,
9986 captures: CaptureValue.Slice,
9987 },
9988 reified: struct {
9989 zir_index: TrackedInst.Index,
9990 type_hash: u64,
9991 },
9992 },
9993};
9994
9995pub const WipEnumType = struct {
9996 tid: Zcu.PerThread.Id,
9997 index: Index,
9998 tag_ty_index: u32,
9999 type_name_extra_index: u32,
10000 namespace_extra_index: u32,
10001 name_nav_extra_index: u32,
10002 names_map: MapIndex,
10003 names_start: u32,
10004 values_map: OptionalMapIndex,
10005 values_start: u32,
10006
10007 pub fn setName(
10008 wip: WipEnumType,
10009 ip: *InternPool,
10010 type_name: NullTerminatedString,
10011 /// This should be the `Nav` we are named after if we use the `.parent` name strategy; `.none` otherwise.
10012 name_nav: Nav.Index.Optional,
10013 ) void {
10014 const extra = ip.getLocalShared(wip.tid).extra.acquire();
10015 const extra_items = extra.view().items(.@"0");
10016 extra_items[wip.type_name_extra_index] = @intFromEnum(type_name);
10017 extra_items[wip.name_nav_extra_index] = @intFromEnum(name_nav);
10018 }
10019
10020 pub fn prepare(
10021 wip: WipEnumType,
10022 ip: *InternPool,
10023 namespace: NamespaceIndex,
10024 ) void {
10025 const extra = ip.getLocalShared(wip.tid).extra.acquire();
10026 const extra_items = extra.view().items(.@"0");
10027
10028 extra_items[wip.namespace_extra_index] = @intFromEnum(namespace);
10029 }
10030
10031 pub fn setTagTy(wip: WipEnumType, ip: *InternPool, tag_ty: Index) void {
10032 assert(ip.isIntegerType(tag_ty));
10033 const extra = ip.getLocalShared(wip.tid).extra.acquire();
10034 extra.view().items(.@"0")[wip.tag_ty_index] = @intFromEnum(tag_ty);
10035 }
10036
10037 pub const FieldConflict = struct {
10038 kind: enum { name, value },
10039 prev_field_idx: u32,
10040 };
10041
10042 /// Returns the already-existing field with the same name or value, if any.
10043 /// If the enum is automatially numbered, `value` must be `.none`.
10044 /// Otherwise, the type of `value` must be the integer tag type of the enum.
10045 pub fn nextField(wip: WipEnumType, ip: *InternPool, name: NullTerminatedString, value: Index) ?FieldConflict {
10046 const unwrapped_index = wip.index.unwrap(ip);
10047 const extra_list = ip.getLocalShared(unwrapped_index.tid).extra.acquire();
10048 const extra_items = extra_list.view().items(.@"0");
10049 if (ip.addFieldName(extra_list, wip.names_map, wip.names_start, name)) |conflict| {
10050 return .{ .kind = .name, .prev_field_idx = conflict };
10051 }
10052 if (value == .none) {
10053 assert(wip.values_map == .none);
10054 return null;
10055 }
10056 assert(ip.typeOf(value) == @as(Index, @enumFromInt(extra_items[wip.tag_ty_index])));
10057 const map = wip.values_map.unwrap().?.get(ip);
10058 const field_index = map.count();
10059 const indexes = extra_items[wip.values_start..][0..field_index];
10060 const adapter: Index.Adapter = .{ .indexes = @ptrCast(indexes) };
10061 const gop = map.getOrPutAssumeCapacityAdapted(value, adapter);
10062 if (gop.found_existing) {
10063 return .{ .kind = .value, .prev_field_idx = @intCast(gop.index) };
10064 }
10065 extra_items[wip.values_start + field_index] = @intFromEnum(value);
10066 return null;
10067 }
10068
10069 pub fn cancel(wip: WipEnumType, ip: *InternPool, tid: Zcu.PerThread.Id) void {
10070 ip.remove(tid, wip.index);
10071 }
10072
10073 pub const Result = union(enum) {
10074 wip: WipEnumType,
10075 existing: Index,
10076 };
10077};
10078
10079pub fn getEnumType(
10080 ip: *InternPool,
10081 gpa: Allocator,
10082 io: Io,
10083 tid: Zcu.PerThread.Id,
10084 ini: EnumTypeInit,
10085 /// If it is known that there is an existing type with this key which is outdated,
10086 /// this is passed as `true`, and the type is replaced with one at a fresh index.
10087 replace_existing: bool,
10088) Allocator.Error!WipEnumType.Result {
10089 const key: Key = .{ .enum_type = switch (ini.key) {
10090 .declared => |d| .{ .declared = .{
10091 .zir_index = d.zir_index,
10092 .captures = .{ .external = d.captures },
10093 } },
10094 .declared_owned_captures => |d| .{ .declared = .{
10095 .zir_index = d.zir_index,
10096 .captures = .{ .owned = d.captures },
10097 } },
10098 .reified => |r| .{ .reified = .{
10099 .zir_index = r.zir_index,
10100 .type_hash = r.type_hash,
10101 } },
10102 } };
10103 var gop = if (replace_existing)
10104 ip.putKeyReplace(io, tid, key)
10105 else
10106 try ip.getOrPutKey(gpa, io, tid, key);
10107 defer gop.deinit();
10108 if (gop == .existing) return .{ .existing = gop.existing };
10109
10110 const local = ip.getLocal(tid);
10111 const items = local.getMutableItems(gpa, io);
10112 try items.ensureUnusedCapacity(1);
10113 const extra = local.getMutableExtra(gpa, io);
10114
10115 const names_map = try ip.addMap(gpa, io, tid, ini.fields_len);
10116 errdefer local.mutate.maps.len -= 1;
10117
10118 switch (ini.tag_mode) {
10119 .auto => {
10120 assert(!ini.has_values);
10121 try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len +
10122 // TODO: fmt bug
10123 // zig fmt: off
10124 switch (ini.key) {
10125 inline .declared, .declared_owned_captures => |d| d.captures.len,
10126 .reified => 2, // type_hash: PackedU64
10127 } +
10128 // zig fmt: on
10129 ini.fields_len); // field types
10130
10131 const extra_index = addExtraAssumeCapacity(extra, EnumAuto{
10132 .name = undefined, // set by `prepare`
10133 .name_nav = undefined, // set by `prepare`
10134 .captures_len = switch (ini.key) {
10135 inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
10136 .reified => std.math.maxInt(u32),
10137 },
10138 .namespace = undefined, // set by `prepare`
10139 .int_tag_type = .none, // set by `prepare`
10140 .fields_len = ini.fields_len,
10141 .names_map = names_map,
10142 .zir_index = switch (ini.key) {
10143 inline else => |x| x.zir_index,
10144 }.toOptional(),
10145 });
10146 items.appendAssumeCapacity(.{
10147 .tag = .type_enum_auto,
10148 .data = extra_index,
10149 });
10150 switch (ini.key) {
10151 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
10152 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
10153 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
10154 }
10155 const names_start = extra.mutate.len;
10156 _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len);
10157 return .{ .wip = .{
10158 .tid = tid,
10159 .index = gop.put(),
10160 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
10161 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name").?,
10162 .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "name_nav").?,
10163 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumAuto, "namespace").?,
10164 .names_map = names_map,
10165 .names_start = @intCast(names_start),
10166 .values_map = .none,
10167 .values_start = undefined,
10168 } };
10169 },
10170 .explicit, .nonexhaustive => {
10171 const values_map: OptionalMapIndex = if (!ini.has_values) .none else m: {
10172 const values_map = try ip.addMap(gpa, io, tid, ini.fields_len);
10173 break :m values_map.toOptional();
10174 };
10175 errdefer if (ini.has_values) {
10176 local.mutate.maps.len -= 1;
10177 };
10178
10179 try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len +
10180 // TODO: fmt bug
10181 // zig fmt: off
10182 switch (ini.key) {
10183 inline .declared, .declared_owned_captures => |d| d.captures.len,
10184 .reified => 2, // type_hash: PackedU64
10185 } +
10186 // zig fmt: on
10187 ini.fields_len + // field types
10188 ini.fields_len * @intFromBool(ini.has_values)); // field values
10189
10190 const extra_index = addExtraAssumeCapacity(extra, EnumExplicit{
10191 .name = undefined, // set by `prepare`
10192 .name_nav = undefined, // set by `prepare`
10193 .captures_len = switch (ini.key) {
10194 inline .declared, .declared_owned_captures => |d| @intCast(d.captures.len),
10195 .reified => std.math.maxInt(u32),
10196 },
10197 .namespace = undefined, // set by `prepare`
10198 .int_tag_type = .none, // set by `prepare`
10199 .fields_len = ini.fields_len,
10200 .names_map = names_map,
10201 .values_map = values_map,
10202 .zir_index = switch (ini.key) {
10203 inline else => |x| x.zir_index,
10204 }.toOptional(),
10205 });
10206 items.appendAssumeCapacity(.{
10207 .tag = switch (ini.tag_mode) {
10208 .auto => unreachable,
10209 .explicit => .type_enum_explicit,
10210 .nonexhaustive => .type_enum_nonexhaustive,
10211 },
10212 .data = extra_index,
10213 });
10214 switch (ini.key) {
10215 .declared => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures)}),
10216 .declared_owned_captures => |d| extra.appendSliceAssumeCapacity(.{@ptrCast(d.captures.get(ip))}),
10217 .reified => |r| _ = addExtraAssumeCapacity(extra, PackedU64.init(r.type_hash)),
10218 }
10219 const names_start = extra.mutate.len;
10220 _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len);
10221 const values_start = extra.mutate.len;
10222 if (ini.has_values) {
10223 _ = extra.addManyAsSliceAssumeCapacity(ini.fields_len);
10224 }
10225 return .{ .wip = .{
10226 .tid = tid,
10227 .index = gop.put(),
10228 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
10229 .type_name_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name").?,
10230 .name_nav_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "name_nav").?,
10231 .namespace_extra_index = extra_index + std.meta.fieldIndex(EnumExplicit, "namespace").?,
10232 .names_map = names_map,
10233 .names_start = @intCast(names_start),
10234 .values_map = values_map,
10235 .values_start = @intCast(values_start),
10236 } };
10237 },
10238 }
10239}
10240
10241const GeneratedTagEnumTypeInit = struct {
10242 name: NullTerminatedString,
10243 owner_union_ty: Index,
10244 tag_ty: Index,
10245 names: []const NullTerminatedString,
10246 values: []const Index,
10247 tag_mode: LoadedEnumType.TagMode,
10248 parent_namespace: NamespaceIndex,
10249};
10250
10251/// Creates an enum type which was automatically-generated as the tag type of a
10252/// `union` with no explicit tag type. Since this is only called once per union
10253/// type, it asserts that no matching type yet exists.
10254pub fn getGeneratedTagEnumType(
10255 ip: *InternPool,
10256 gpa: Allocator,
10257 io: Io,
10258 tid: Zcu.PerThread.Id,
10259 ini: GeneratedTagEnumTypeInit,
10260) Allocator.Error!Index {
10261 assert(ip.isUnion(ini.owner_union_ty));
10262 assert(ip.isIntegerType(ini.tag_ty));
10263 for (ini.values) |val| assert(ip.typeOf(val) == ini.tag_ty);
10264
10265 const local = ip.getLocal(tid);
10266 const items = local.getMutableItems(gpa, io);
10267 try items.ensureUnusedCapacity(1);
10268 const extra = local.getMutableExtra(gpa, io);
10269
10270 const names_map = try ip.addMap(gpa, io, tid, ini.names.len);
10271 errdefer local.mutate.maps.len -= 1;
10272 ip.addStringsToMap(names_map, ini.names);
10273
10274 const fields_len: u32 = @intCast(ini.names.len);
10275
10276 // Predict the index the enum will live at so we can construct the namespace before releasing the shard's mutex.
10277 const enum_index = Index.Unwrapped.wrap(.{
10278 .tid = tid,
10279 .index = items.mutate.len,
10280 }, ip);
10281 const parent_namespace = ip.namespacePtr(ini.parent_namespace);
10282 const namespace = try ip.createNamespace(gpa, io, tid, .{
10283 .parent = ini.parent_namespace.toOptional(),
10284 .owner_type = enum_index,
10285 .file_scope = parent_namespace.file_scope,
10286 .generation = parent_namespace.generation,
10287 });
10288 errdefer ip.destroyNamespace(tid, namespace);
10289
10290 const prev_extra_len = extra.mutate.len;
10291 switch (ini.tag_mode) {
10292 .auto => {
10293 try extra.ensureUnusedCapacity(@typeInfo(EnumAuto).@"struct".fields.len +
10294 1 + // owner_union
10295 fields_len); // field names
10296 items.appendAssumeCapacity(.{
10297 .tag = .type_enum_auto,
10298 .data = addExtraAssumeCapacity(extra, EnumAuto{
10299 .name = ini.name,
10300 .name_nav = .none,
10301 .captures_len = 0,
10302 .namespace = namespace,
10303 .int_tag_type = ini.tag_ty,
10304 .fields_len = fields_len,
10305 .names_map = names_map,
10306 .zir_index = .none,
10307 }),
10308 });
10309 extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)});
10310 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)});
10311 },
10312 .explicit, .nonexhaustive => {
10313 try extra.ensureUnusedCapacity(@typeInfo(EnumExplicit).@"struct".fields.len +
10314 1 + // owner_union
10315 fields_len + // field names
10316 ini.values.len); // field values
10317
10318 const values_map: OptionalMapIndex = if (ini.values.len != 0) m: {
10319 const map = try ip.addMap(gpa, io, tid, ini.values.len);
10320 ip.addIndexesToMap(map, ini.values);
10321 break :m map.toOptional();
10322 } else .none;
10323 // We don't clean up the values map on error!
10324 errdefer @compileError("error path leaks values_map");
10325
10326 items.appendAssumeCapacity(.{
10327 .tag = switch (ini.tag_mode) {
10328 .explicit => .type_enum_explicit,
10329 .nonexhaustive => .type_enum_nonexhaustive,
10330 .auto => unreachable,
10331 },
10332 .data = addExtraAssumeCapacity(extra, EnumExplicit{
10333 .name = ini.name,
10334 .name_nav = .none,
10335 .captures_len = 0,
10336 .namespace = namespace,
10337 .int_tag_type = ini.tag_ty,
10338 .fields_len = fields_len,
10339 .names_map = names_map,
10340 .values_map = values_map,
10341 .zir_index = .none,
10342 }),
10343 });
10344 extra.appendAssumeCapacity(.{@intFromEnum(ini.owner_union_ty)});
10345 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.names)});
10346 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.values)});
9367 .type_inferred_error_set,
9368 .type_function,
103479369 },
10348 }
10349 errdefer extra.mutate.len = prev_extra_len;
10350 errdefer switch (ini.tag_mode) {
10351 .auto => {},
10352 .explicit, .nonexhaustive => if (ini.values.len != 0) {
10353 local.mutate.maps.len -= 1;
9370 .data = &.{
9371 func_extra_index,
9372 addExtraAssumeCapacity(extra, Tag.ErrorUnionType{
9373 .error_set_type = error_set_type,
9374 .payload_type = arg.bare_return_type,
9375 }),
9376 @intFromEnum(func_index),
9377 func_type_extra_index,
103549378 },
10355 };
9379 });
9380 errdefer {
9381 items.mutate.len -= 4;
9382 extra.mutate.len = prev_extra_len;
9383 }
103569384
10357 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .enum_type = .{
10358 .generated_tag = .{ .union_type = ini.owner_union_ty },
10359 } });
10360 defer gop.deinit();
10361 assert(gop.put() == enum_index);
10362 return enum_index;
10363}
9385 var func_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9386 .func = ip.extraFuncInstance(tid, extra.list.*, func_extra_index),
9387 }, 3);
9388 defer func_gop.deinit();
9389 if (func_gop == .existing) {
9390 // Hot path: undo the additions to our two arrays.
9391 items.mutate.len -= 4;
9392 extra.mutate.len = prev_extra_len;
9393 return func_gop.existing;
9394 }
9395 func_gop.putTentative(func_index);
9396 var error_union_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{ .error_union_type = .{
9397 .error_set_type = error_set_type,
9398 .payload_type = arg.bare_return_type,
9399 } }, 2);
9400 defer error_union_type_gop.deinit();
9401 error_union_type_gop.putTentative(error_union_type);
9402 var error_set_type_gop = try ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, .{
9403 .inferred_error_set_type = func_index,
9404 }, 1);
9405 defer error_set_type_gop.deinit();
9406 error_set_type_gop.putTentative(error_set_type);
9407 var func_ty_gop = try ip.getOrPutKey(gpa, io, tid, .{
9408 .func_type = extraFuncType(tid, extra.list.*, func_type_extra_index),
9409 });
9410 defer func_ty_gop.deinit();
9411 func_ty_gop.putTentative(func_ty);
9412 try finishFuncInstance(
9413 ip,
9414 gpa,
9415 io,
9416 tid,
9417 extra,
9418 generic_owner,
9419 func_index,
9420 func_extra_index,
9421 );
103649422
10365pub const OpaqueTypeInit = struct {
10366 zir_index: TrackedInst.Index,
10367 captures: []const CaptureValue,
10368};
9423 func_gop.putFinal(func_index);
9424 error_union_type_gop.putFinal(error_union_type);
9425 error_set_type_gop.putFinal(error_set_type);
9426 func_ty_gop.putFinal(func_ty);
9427 return func_index;
9428}
103699429
10370pub fn getOpaqueType(
9430fn finishFuncInstance(
103719431 ip: *InternPool,
103729432 gpa: Allocator,
103739433 io: Io,
103749434 tid: Zcu.PerThread.Id,
10375 ini: OpaqueTypeInit,
10376) Allocator.Error!WipNamespaceType.Result {
10377 var gop = try ip.getOrPutKey(gpa, io, tid, .{ .opaque_type = .{ .declared = .{
10378 .zir_index = ini.zir_index,
10379 .captures = .{ .external = ini.captures },
10380 } } });
10381 defer gop.deinit();
10382 if (gop == .existing) return .{ .existing = gop.existing };
10383
10384 const local = ip.getLocal(tid);
10385 const items = local.getMutableItems(gpa, io);
10386 const extra = local.getMutableExtra(gpa, io);
10387 try items.ensureUnusedCapacity(1);
9435 extra: Local.Extra.Mutable,
9436 generic_owner: Index,
9437 func_index: Index,
9438 func_extra_index: u32,
9439) Allocator.Error!void {
9440 const fn_owner_nav = ip.getNav(ip.funcDeclInfo(generic_owner).owner_nav);
9441 const fn_namespace = fn_owner_nav.analysis.?.namespace;
103889442
10389 try extra.ensureUnusedCapacity(@typeInfo(Tag.TypeOpaque).@"struct".fields.len + ini.captures.len);
10390 const extra_index = addExtraAssumeCapacity(extra, Tag.TypeOpaque{
10391 .name = undefined, // set by `finish`
10392 .name_nav = undefined, // set by `finish`
10393 .namespace = undefined, // set by `finish`
10394 .zir_index = ini.zir_index,
10395 .captures_len = @intCast(ini.captures.len),
10396 });
10397 items.appendAssumeCapacity(.{
10398 .tag = .type_opaque,
10399 .data = extra_index,
9443 // TODO: improve this name
9444 const nav_name = try ip.getOrPutStringFmt(gpa, io, tid, "{f}__anon_{d}", .{
9445 fn_owner_nav.name.fmt(ip), @intFromEnum(func_index),
9446 }, .no_embedded_nulls);
9447 const nav_index = try ip.createNav(gpa, io, tid, .{
9448 .name = nav_name,
9449 .fqn = try ip.namespacePtr(fn_namespace).internFullyQualifiedName(ip, gpa, io, tid, nav_name),
9450 .val = func_index,
9451 .is_const = fn_owner_nav.status.fully_resolved.is_const,
9452 .alignment = fn_owner_nav.status.fully_resolved.alignment,
9453 .@"linksection" = fn_owner_nav.status.fully_resolved.@"linksection",
9454 .@"addrspace" = fn_owner_nav.status.fully_resolved.@"addrspace",
104009455 });
10401 extra.appendSliceAssumeCapacity(.{@ptrCast(ini.captures)});
10402 return .{
10403 .wip = .{
10404 .tid = tid,
10405 .index = gop.put(),
10406 .type_name_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name").?,
10407 .name_nav_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "name_nav").?,
10408 .namespace_extra_index = extra_index + std.meta.fieldIndex(Tag.TypeOpaque, "namespace").?,
10409 },
10410 };
9456
9457 // Populate the owner_nav field which was left undefined until now.
9458 extra.view().items(.@"0")[
9459 func_extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_nav").?
9460 ] = @intFromEnum(nav_index);
104119461}
104129462
104139463pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
......@@ -10534,6 +9584,9 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
105349584 TrackedInst.Index,
105359585 TrackedInst.Index.Optional,
105369586 ComptimeAllocIndex,
9587 @FieldType(Tag.TypeStructPacked, "captures_len"),
9588 @FieldType(Tag.TypeUnionPacked, "captures_len"),
9589 @FieldType(Tag.TypeEnum, "captures_len"),
105379590 => @intFromEnum(@field(item, field.name)),
105389591
105399592 u32,
......@@ -10545,7 +9598,6 @@ fn addExtraAssumeCapacity(extra: Local.Extra.Mutable, item: anytype) u32 {
105459598 Tag.TypePointer.PackedOffset,
105469599 Tag.TypeUnion.Flags,
105479600 Tag.TypeStruct.Flags,
10548 Tag.TypeStructPacked.Flags,
105499601 => @bitCast(@field(item, field.name)),
105509602
105519603 else => @compileError("bad field type: " ++ @typeName(field.type)),
......@@ -10597,6 +9649,9 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
105979649 TrackedInst.Index,
105989650 TrackedInst.Index.Optional,
105999651 ComptimeAllocIndex,
9652 @FieldType(Tag.TypeStructPacked, "captures_len"),
9653 @FieldType(Tag.TypeUnionPacked, "captures_len"),
9654 @FieldType(Tag.TypeEnum, "captures_len"),
106009655 => @enumFromInt(extra_item),
106019656
106029657 u32,
......@@ -10607,7 +9662,6 @@ fn extraDataTrail(extra: Local.Extra, comptime T: type, index: u32) struct { dat
106079662 Tag.TypePointer.PackedOffset,
106089663 Tag.TypeUnion.Flags,
106099664 Tag.TypeStruct.Flags,
10610 Tag.TypeStructPacked.Flags,
106119665 FuncAnalysis,
106129666 => @bitCast(extra_item),
106139667
......@@ -10786,7 +9840,7 @@ pub fn getCoerced(
107869840 .int => |int| switch (ip.indexToKey(new_ty)) {
107879841 .enum_type => return ip.get(gpa, io, tid, .{ .enum_tag = .{
107889842 .ty = new_ty,
10789 .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).tag_ty),
9843 .int = try ip.getCoerced(gpa, io, tid, val, ip.loadEnumType(new_ty).int_tag_type),
107909844 } }),
107919845 .ptr_type => switch (int.storage) {
107929846 inline .u64, .i64 => |int_val| return ip.get(gpa, io, tid, .{ .ptr = .{
......@@ -10795,7 +9849,6 @@ pub fn getCoerced(
107959849 .byte_offset = @intCast(int_val),
107969850 } }),
107979851 .big_int => unreachable, // must be a usize
10798 .lazy_align, .lazy_size => {},
107999852 },
108009853 else => if (ip.isIntegerType(new_ty))
108019854 return ip.getCoercedInts(gpa, io, tid, int, new_ty),
......@@ -10825,11 +9878,11 @@ pub fn getCoerced(
108259878 const index = enum_type.nameIndex(ip, enum_literal).?;
108269879 return ip.get(gpa, io, tid, .{ .enum_tag = .{
108279880 .ty = new_ty,
10828 .int = if (enum_type.values.len != 0)
10829 enum_type.values.get(ip)[index]
9881 .int = if (enum_type.field_values.len != 0)
9882 enum_type.field_values.get(ip)[index]
108309883 else
108319884 try ip.get(gpa, io, tid, .{ .int = .{
10832 .ty = enum_type.tag_ty,
9885 .ty = enum_type.int_tag_type,
108339886 .storage = .{ .u64 = index },
108349887 } }),
108359888 } });
......@@ -11266,98 +10319,137 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1126610319 break :b @sizeOf(Tag.ErrorSet) + (@sizeOf(u32) * info.names_len);
1126710320 },
1126810321 .type_inferred_error_set => 0,
11269 .type_enum_explicit, .type_enum_nonexhaustive => b: {
11270 const info = extraData(extra_list, EnumExplicit, data);
11271 var ints = @typeInfo(EnumExplicit).@"struct".fields.len;
11272 if (info.zir_index == .none) ints += 1;
11273 ints += if (info.captures_len != std.math.maxInt(u32))
11274 info.captures_len
11275 else
11276 @typeInfo(PackedU64).@"struct".fields.len;
11277 ints += info.fields_len;
11278 if (info.values_map != .none) ints += info.fields_len;
11279 break :b @sizeOf(u32) * ints;
11280 },
11281 .type_enum_auto => b: {
11282 const info = extraData(extra_list, EnumAuto, data);
11283 const ints = @typeInfo(EnumAuto).@"struct".fields.len + info.captures_len + info.fields_len;
11284 break :b @sizeOf(u32) * ints;
10322 .type_tuple => b: {
10323 const info = extraData(extra_list, TypeTuple, data);
10324 break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len);
1128510325 },
11286 .type_opaque => b: {
11287 const info = extraData(extra_list, Tag.TypeOpaque, data);
11288 const ints = @typeInfo(Tag.TypeOpaque).@"struct".fields.len + info.captures_len;
11289 break :b @sizeOf(u32) * ints;
10326 .type_function => b: {
10327 const info = extraData(extra_list, Tag.TypeFunction, data);
10328 break :b @sizeOf(Tag.TypeFunction) +
10329 (@sizeOf(Index) * info.params_len) +
10330 (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
10331 (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
1129010332 },
10333
1129110334 .type_struct => b: {
10335 var n: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len;
1129210336 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data);
11293 const info = extra.data;
11294 var ints: usize = @typeInfo(Tag.TypeStruct).@"struct".fields.len;
11295 if (info.flags.any_captures) {
11296 const captures_len = extra_items[extra.end];
11297 ints += 1 + captures_len;
10337 switch (extra.data.flags.any_captures) {
10338 .reified => n += 2, // type_hash: PackedU64
10339 .true => {
10340 n += 1; // captures_len: u32
10341 n += extra_items[extra.end]; // capture: CaptureValue
10342 },
10343 .false => {},
10344 }
10345 n += extra.data.fields_len; // field_name: NullTerminatedString
10346 n += extra.data.fields_len; // field_type: Index
10347 if (extra.data.flags.any_field_defaults) {
10348 n += extra.data.fields_len; // field_default: Index
10349 }
10350 if (extra.data.flags.any_field_aligns) {
10351 n += (extra.data.fields_len + 3) / 4; // field_align: Alignment
10352 }
10353 if (extra.data.flags.any_comptime_fields) {
10354 n += (extra.data.fields_len + 31) / 32; // field_is_comptime_bits: u32
1129810355 }
11299 ints += info.fields_len; // types
11300 ints += 1; // names_map
11301 ints += info.fields_len; // names
11302 if (info.flags.any_default_inits)
11303 ints += info.fields_len; // inits
11304 if (info.flags.any_aligned_fields)
11305 ints += (info.fields_len + 3) / 4; // aligns
11306 if (info.flags.any_comptime_fields)
11307 ints += (info.fields_len + 31) / 32; // comptime bits
11308 if (!info.flags.is_extern)
11309 ints += info.fields_len; // runtime order
11310 ints += info.fields_len; // offsets
11311 break :b @sizeOf(u32) * ints;
10356 if (extra.data.flags.layout == .auto) {
10357 n += extra.data.fields_len; // field_runtime_order: RuntimeOrder
10358 }
10359 n += extra.data.fields_len; // field_offset: u32
10360 break :b n * @sizeOf(u32);
1131210361 },
11313 .type_struct_packed => b: {
10362 .type_struct_packed_auto, .type_struct_packed_explicit => b: {
10363 var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len;
1131410364 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);
11315 const captures_len = if (extra.data.flags.any_captures)
11316 extra_items[extra.end]
11317 else
11318 0;
11319 break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len +
11320 @intFromBool(extra.data.flags.any_captures) + captures_len +
11321 extra.data.fields_len * 2);
10365 switch (extra.data.captures_len) {
10366 .reified => n += 2, // type_hash: PackedU64
10367 _ => |len| n += @intFromEnum(len), // capture: CaptureValue
10368 }
10369 n += extra.data.fields_len; // field_name: NullTerminatedString
10370 n += extra.data.fields_len; // field_type: Index
10371 break :b n * @sizeOf(u32);
1132210372 },
11323 .type_struct_packed_inits => b: {
10373 .type_struct_packed_auto_defaults, .type_struct_packed_explicit_defaults => b: {
10374 var n: usize = @typeInfo(Tag.TypeStructPacked).@"struct".fields.len;
1132410375 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data);
11325 const captures_len = if (extra.data.flags.any_captures)
11326 extra_items[extra.end]
11327 else
11328 0;
11329 break :b @sizeOf(u32) * (@typeInfo(Tag.TypeStructPacked).@"struct".fields.len +
11330 @intFromBool(extra.data.flags.any_captures) + captures_len +
11331 extra.data.fields_len * 3);
11332 },
11333 .type_tuple => b: {
11334 const info = extraData(extra_list, TypeTuple, data);
11335 break :b @sizeOf(TypeTuple) + (@sizeOf(u32) * 2 * info.fields_len);
10376 switch (extra.data.captures_len) {
10377 .reified => n += 2, // type_hash: PackedU64
10378 _ => |len| n += @intFromEnum(len), // capture: CaptureValue
10379 }
10380 n += extra.data.fields_len; // field_name: NullTerminatedString
10381 n += extra.data.fields_len; // field_type: Index
10382 n += extra.data.fields_len; // field_default: Index
10383 break :b n * @sizeOf(u32);
1133610384 },
11337
1133810385 .type_union => b: {
10386 var n: usize = @typeInfo(Tag.TypeUnion).@"struct".fields.len;
1133910387 const extra = extraDataTrail(extra_list, Tag.TypeUnion, data);
11340 const captures_len = if (extra.data.flags.any_captures)
11341 extra_items[extra.end]
11342 else
11343 0;
11344 const per_field = @sizeOf(u32); // field type
11345 // 1 byte per field for alignment, rounded up to the nearest 4 bytes
11346 const alignments = if (extra.data.flags.any_aligned_fields)
11347 ((extra.data.fields_len + 3) / 4) * 4
11348 else
11349 0;
11350 break :b @sizeOf(Tag.TypeUnion) +
11351 4 * (@intFromBool(extra.data.flags.any_captures) + captures_len) +
11352 (extra.data.fields_len * per_field) + alignments;
10388 switch (extra.data.flags.any_captures) {
10389 .reified => n += 2, // type_hash: PackedU64
10390 .true => {
10391 n += 1; // captures_len: u32
10392 n += extra_items[extra.end]; // capture: CaptureValue
10393 },
10394 .false => {},
10395 }
10396 n += extra.data.fields_len; // field_type: Index
10397 if (extra.data.flags.any_field_aligns) {
10398 n += (extra.data.fields_len + 3) / 4; // field_align: Alignment
10399 }
10400 break :b n * @sizeOf(u32);
1135310401 },
11354
11355 .type_function => b: {
11356 const info = extraData(extra_list, Tag.TypeFunction, data);
11357 break :b @sizeOf(Tag.TypeFunction) +
11358 (@sizeOf(Index) * info.params_len) +
11359 (@as(u32, 4) * @intFromBool(info.flags.has_comptime_bits)) +
11360 (@as(u32, 4) * @intFromBool(info.flags.has_noalias_bits));
10402 .type_union_packed_auto, .type_union_packed_explicit => b: {
10403 var n: usize = @typeInfo(Tag.TypeUnionPacked).@"struct".fields.len;
10404 const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data);
10405 switch (extra.data.captures_len) {
10406 .reified => n += 2, // type_hash: PackedU64
10407 _ => |len| n += @intFromEnum(len), // capture: CaptureValue
10408 }
10409 n += extra.data.fields_len; // field_type: Index
10410 break :b n * @sizeOf(u32);
10411 },
10412 .type_enum_auto => b: {
10413 var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len;
10414 const extra = extraData(extra_list, Tag.TypeEnum, data);
10415 switch (extra.captures_len) {
10416 .generated_union_tag => n += 1, // owner_union: Index
10417 .reified => {
10418 n += 1; // zir_index: TrackedInst.Index,
10419 n += 2; // type_hash: PackedU64
10420 },
10421 _ => |len| {
10422 n += 1; // zir_index: TrackedInst.Index,
10423 n += @intFromEnum(len); // capture: CaptureValue
10424 },
10425 }
10426 n += extra.fields_len; // field_name: NullTerminatedString
10427 break :b n * @sizeOf(u32);
10428 },
10429 .type_enum_explicit, .type_enum_nonexhaustive => b: {
10430 var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len;
10431 const extra = extraData(extra_list, Tag.TypeEnum, data);
10432 switch (extra.captures_len) {
10433 .generated_union_tag => n += 1, // owner_union: Index
10434 .reified => {
10435 n += 1; // zir_index: TrackedInst.Index,
10436 n += 2; // type_hash: PackedU64
10437 },
10438 _ => |len| {
10439 n += 1; // zir_index: TrackedInst.Index,
10440 n += @intFromEnum(len); // capture: CaptureValue
10441 },
10442 }
10443 n += 1; // field_value_map: MapIndex
10444 n += extra.fields_len; // field_name: NullTerminatedString
10445 n += extra.fields_len; // field_value: Index
10446 break :b n * @sizeOf(u32);
10447 },
10448 .type_opaque => b: {
10449 var n: usize = @typeInfo(Tag.TypeEnum).@"struct".fields.len;
10450 const extra = extraData(extra_list, Tag.TypeOpaque, data);
10451 n += extra.captures_len; // capture: CaptureValue
10452 break :b n * @sizeOf(u32);
1136110453 },
1136210454
1136310455 .undef => 0,
......@@ -11393,8 +10485,6 @@ fn dumpStatsFallible(ip: *const InternPool, w: *Io.Writer, arena: Allocator) !vo
1139310485 break :b @sizeOf(Int) + int.limbs_len * @sizeOf(Limb);
1139410486 },
1139510487
11396 .int_lazy_align, .int_lazy_size => @sizeOf(IntLazy),
11397
1139810488 .error_set_error, .error_union_error => @sizeOf(Key.Error),
1139910489 .error_union_payload => @sizeOf(Tag.TypeValue),
1140010490 .enum_literal => 0,
......@@ -11484,16 +10574,20 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
1148410574 .type_anyerror_union,
1148510575 .type_error_set,
1148610576 .type_inferred_error_set,
10577 .type_tuple,
10578 .type_function,
10579 .type_struct,
10580 .type_struct_packed_auto,
10581 .type_struct_packed_explicit,
10582 .type_struct_packed_auto_defaults,
10583 .type_struct_packed_explicit_defaults,
10584 .type_union,
10585 .type_union_packed_auto,
10586 .type_union_packed_explicit,
10587 .type_enum_auto,
1148710588 .type_enum_explicit,
1148810589 .type_enum_nonexhaustive,
11489 .type_enum_auto,
1149010590 .type_opaque,
11491 .type_struct,
11492 .type_struct_packed,
11493 .type_struct_packed_inits,
11494 .type_tuple,
11495 .type_union,
11496 .type_function,
1149710591 .undef,
1149810592 .ptr_nav,
1149910593 .ptr_comptime_alloc,
......@@ -11517,8 +10611,6 @@ fn dumpAllFallible(ip: *const InternPool, w: *Io.Writer) anyerror!void {
1151710611 .int_small,
1151810612 .int_positive,
1151910613 .int_negative,
11520 .int_lazy_align,
11521 .int_lazy_size,
1152210614 .error_set_error,
1152310615 .error_union_error,
1152410616 .error_union_payload,
......@@ -12245,16 +11337,20 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
1224511337 .type_anyerror_union,
1224611338 .type_error_set,
1224711339 .type_inferred_error_set,
11340 .type_tuple,
11341 .type_function,
11342 .type_struct,
11343 .type_struct_packed_auto,
11344 .type_struct_packed_explicit,
11345 .type_struct_packed_auto_defaults,
11346 .type_struct_packed_explicit_defaults,
11347 .type_union,
11348 .type_union_packed_auto,
11349 .type_union_packed_explicit,
1224811350 .type_enum_auto,
1224911351 .type_enum_explicit,
1225011352 .type_enum_nonexhaustive,
1225111353 .type_opaque,
12252 .type_struct,
12253 .type_struct_packed,
12254 .type_struct_packed_inits,
12255 .type_tuple,
12256 .type_union,
12257 .type_function,
1225811354 => .type_type,
1225911355
1226011356 .undef,
......@@ -12278,8 +11374,6 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
1227811374 .opt_payload,
1227911375 .error_union_payload,
1228011376 .int_small,
12281 .int_lazy_align,
12282 .int_lazy_size,
1228311377 .error_set_error,
1228411378 .error_union_error,
1228511379 .enum_tag,
......@@ -12613,22 +11707,26 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
1261311707 .type_inferred_error_set,
1261411708 => .error_set,
1261511709
12616 .type_enum_auto,
12617 .type_enum_explicit,
12618 .type_enum_nonexhaustive,
12619 => .@"enum",
12620
1262111710 .simple_type => unreachable, // handled via Index tag above
1262211711
12623 .type_opaque => .@"opaque",
11712 .type_tuple => .@"struct",
1262411713
1262511714 .type_struct,
12626 .type_struct_packed,
12627 .type_struct_packed_inits,
12628 .type_tuple,
11715 .type_struct_packed_auto,
11716 .type_struct_packed_explicit,
11717 .type_struct_packed_auto_defaults,
11718 .type_struct_packed_explicit_defaults,
1262911719 => .@"struct",
12630
12631 .type_union => .@"union",
11720 .type_union,
11721 .type_union_packed_auto,
11722 .type_union_packed_explicit,
11723 => .@"union",
11724 .type_enum_auto,
11725 .type_enum_explicit,
11726 .type_enum_nonexhaustive,
11727 => .@"enum",
11728 .type_opaque,
11729 => .@"opaque",
1263211730
1263311731 .type_function => .@"fn",
1263411732
......@@ -12658,8 +11756,6 @@ pub fn zigTypeTag(ip: *const InternPool, index: Index) std.builtin.TypeId {
1265811756 .int_small,
1265911757 .int_positive,
1266011758 .int_negative,
12661 .int_lazy_align,
12662 .int_lazy_size,
1266311759 .error_set_error,
1266411760 .error_union_error,
1266511761 .error_union_payload,
......@@ -13169,3 +12265,113 @@ const PackedCallingConvention = packed struct(u18) {
1316912265 };
1317012266 }
1317112267};
12268
12269/// Asserts that `struct_type` is a non-packed struct type.
12270/// As well as calling this function, the caller must also populate these arrays:
12271/// * `field_types`
12272/// * `field_aligns`
12273/// * `field_runtime_order`
12274/// * `field_offsets`
12275pub fn resolveStructLayout(
12276 ip: *InternPool,
12277 io: Io,
12278 struct_type: Index,
12279 size: u32,
12280 alignment: Alignment,
12281 has_no_possible_value: bool,
12282 has_one_possible_value: bool,
12283 comptime_only: bool,
12284) void {
12285 const unwrapped_index = struct_type.unwrap(ip);
12286
12287 const local = ip.getLocal(unwrapped_index.tid);
12288 local.mutate.extra.mutex.lockUncancelable(io);
12289 defer local.mutate.extra.mutex.unlock(io);
12290
12291 const extra_items = local.shared.extra.view().items(.@"0");
12292 const item = unwrapped_index.getItem(ip);
12293 assert(item.tag == .type_struct);
12294
12295 extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "size").?] = size;
12296 const flags: *Tag.TypeStruct.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeStruct, "flags").?]);
12297 flags.has_no_possible_value = has_no_possible_value;
12298 flags.has_one_possible_value = has_one_possible_value;
12299 flags.comptime_only = comptime_only;
12300 flags.alignment = alignment;
12301}
12302
12303/// Asserts that `union_type` is a non-packed union type.
12304/// As well as calling this function, the caller must also populate these arrays:
12305/// * `field_types`
12306/// * `field_aligns`
12307pub fn resolveUnionLayout(
12308 ip: *InternPool,
12309 io: Io,
12310 union_type: Index,
12311 size: u32,
12312 padding: u32,
12313 alignment: Alignment,
12314 has_no_possible_value: bool,
12315 has_one_possible_value: bool,
12316 comptime_only: bool,
12317) void {
12318 const unwrapped_index = union_type.unwrap(ip);
12319
12320 const local = ip.getLocal(unwrapped_index.tid);
12321 local.mutate.extra.mutex.lockUncancelable(io);
12322 defer local.mutate.extra.mutex.unlock(io);
12323
12324 const extra_items = local.shared.extra.view().items(.@"0");
12325 const item = unwrapped_index.getItem(ip);
12326 assert(item.tag == .type_union);
12327
12328 extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "size").?] = size;
12329 extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "padding").?] = padding;
12330 const flags: *Tag.TypeUnion.Flags = @ptrCast(&extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnion, "flags").?]);
12331 flags.has_no_possible_value = has_no_possible_value;
12332 flags.has_one_possible_value = has_one_possible_value;
12333 flags.comptime_only = comptime_only;
12334 flags.alignment = alignment;
12335}
12336
12337/// Asserts that `struct_type` is a packed struct type.
12338pub fn resolvePackedStructBackingInt(ip: *InternPool, io: Io, struct_type: Index, backing_int_type: Index) void {
12339 const unwrapped_index = struct_type.unwrap(ip);
12340
12341 const local = ip.getLocal(unwrapped_index.tid);
12342 local.mutate.extra.mutex.lockUncancelable(io);
12343 defer local.mutate.extra.mutex.unlock(io);
12344
12345 const extra_items = local.shared.extra.view().items(.@"0");
12346 const item = unwrapped_index.getItem(ip);
12347 switch (item.tag) {
12348 .type_struct_packed_auto,
12349 .type_struct_packed_explicit,
12350 .type_struct_packed_auto_defaults,
12351 .type_struct_packed_explicit_defaults,
12352 => {},
12353 else => unreachable,
12354 }
12355
12356 extra_items[item.data + std.meta.fieldIndex(Tag.TypeStructPacked, "backing_int_type").?] = @intFromEnum(backing_int_type);
12357}
12358
12359/// Asserts that `union_type` is a packed union type.
12360pub fn resolvePackedUnionBackingInt(ip: *InternPool, io: Io, union_type: Index, backing_int_type: Index) void {
12361 const unwrapped_index = union_type.unwrap(ip);
12362
12363 const local = ip.getLocal(unwrapped_index.tid);
12364 local.mutate.extra.mutex.lockUncancelable(io);
12365 defer local.mutate.extra.mutex.unlock(io);
12366
12367 const extra_items = local.shared.extra.view().items(.@"0");
12368 const item = unwrapped_index.getItem(ip);
12369 switch (item.tag) {
12370 .type_union_packed_auto,
12371 .type_union_packed_explicit,
12372 => {},
12373 else => unreachable,
12374 }
12375
12376 extra_items[item.data + std.meta.fieldIndex(Tag.TypeUnionPacked, "backing_int_type").?] = @intFromEnum(backing_int_type);
12377}
src/Sema.zig+2201-4328
......@@ -173,13 +173,17 @@ const ComptimeAlloc = struct {
173173 runtime_index: RuntimeIndex,
174174};
175175
176/// Asserts that `ty` is not an OPV type.
176177/// `src` may be `null` if `is_const` will be set.
177178fn newComptimeAlloc(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type, alignment: Alignment) !ComptimeAllocIndex {
178179 const pt = sema.pt;
179 const init_val = try sema.typeHasOnePossibleValue(ty) orelse try pt.undefValue(ty);
180
181 // Explicit guard because this call mutates the InternPool so cannot be optimized out.
182 if (std.debug.runtime_safety) assert(ty.onePossibleValue(pt) catch @panic("") == null);
183
180184 const idx = sema.comptime_allocs.items.len;
181185 try sema.comptime_allocs.append(sema.gpa, .{
182 .val = .{ .interned = init_val.toIntern() },
186 .val = .{ .interned = (try pt.undefValue(ty)).toIntern() },
183187 .is_const = false,
184188 .src = src,
185189 .alignment = alignment,
......@@ -1382,10 +1386,10 @@ fn analyzeBodyInner(
13821386 const extended = datas[@intFromEnum(inst)].extended;
13831387 break :ext switch (extended.opcode) {
13841388 // zig fmt: off
1385 .struct_decl => try sema.zirStructDecl( block, extended, inst),
1386 .enum_decl => try sema.zirEnumDecl( block, extended, inst),
1387 .union_decl => try sema.zirUnionDecl( block, extended, inst),
1388 .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst),
1389 .struct_decl => try sema.zirStructDecl( block, inst),
1390 .enum_decl => try sema.zirEnumDecl( block, inst),
1391 .union_decl => try sema.zirUnionDecl( block, inst),
1392 .opaque_decl => try sema.zirOpaqueDecl( block, inst),
13891393 .tuple_decl => try sema.zirTupleDecl( block, extended),
13901394 .this => try sema.zirThis( block, extended),
13911395 .ret_addr => try sema.zirRetAddr( block, extended),
......@@ -1993,6 +1997,24 @@ fn analyzeBodyInner(
19931997 assert(sema.isNoReturn(block.instructions.items[block.instructions.items.len - 1].toRef()));
19941998 break;
19951999 }
2000 // <MLUGG TODO REMOVE THIS BLOCK, SILLY OPV CHECK>
2001 if (air_inst.toIndex()) |air_inst_index| {
2002 switch (sema.air_instructions.items(.tag)[@intFromEnum(air_inst_index)]) {
2003 .inferred_alloc, .inferred_alloc_comptime => {},
2004 else => {
2005 assert(sema.typeOf(air_inst).onePossibleValue(pt) catch @panic("") == null);
2006 sema.typeOf(air_inst).assertHasLayout(zcu);
2007 },
2008 }
2009 } else {
2010 switch (tags[@intFromEnum(inst)]) {
2011 // MLUGG TODO: do we actually *want* this exception? we could arguably simplify things without it
2012 // e.g. analyzeNavVal could stop doing ensureLayoutResolved in most cases (`extern` is an exception) and instead do `assertHasLayout`
2013 .func, .func_inferred, .func_fancy => {}, // exception: we're in a func decl, layout will get resolved in a bit by `analyzeNavVal`
2014 else => sema.typeOf(air_inst).assertHasLayout(zcu),
2015 }
2016 }
2017 // </MLUGG TODO REMOVE THIS BLOCK, SILLY OPV CHECK>
19962018 map.putAssumeCapacity(inst, air_inst);
19972019 i += 1;
19982020 }
......@@ -2190,7 +2212,7 @@ fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoi
21902212 }
21912213}
21922214
2193fn analyzeAsType(
2215pub fn analyzeAsType(
21942216 sema: *Sema,
21952217 block: *Block,
21962218 src: LazySrcLoc,
......@@ -2227,7 +2249,6 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
22272249
22282250 // var st: StackTrace = undefined;
22292251 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
2230 try stack_trace_ty.resolveFields(pt);
22312252 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
22322253
22332254 // st.instruction_addresses = &addrs;
......@@ -2247,14 +2268,11 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
22472268}
22482269
22492270/// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value.
2250fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2271/// TODO MLUGG: remove the error union return!
2272fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) error{}!?Value {
22512273 const zcu = sema.pt.zcu;
22522274 assert(inst != .none);
22532275
2254 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
2255 return opv;
2256 }
2257
22582276 if (inst.toInterned()) |ip_index| {
22592277 const val: Value = .fromInterned(ip_index);
22602278 assert(val.getVariable(zcu) == null);
......@@ -2267,12 +2285,18 @@ fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
22672285 .inferred_alloc_comptime => unreachable, // assertion failure
22682286 else => {},
22692287 }
2288 // Assert that the type is not OPV -- if it was, the value would have been comptime-known.
2289 // Explicit guard because this could add to the InternPool so cannot be optimized away.
2290 if (std.debug.runtime_safety) {
2291 const opv = sema.typeOf(inst).onePossibleValue(sema.pt) catch @panic("oom in assert");
2292 assert(opv == null);
2293 }
22702294 return null;
22712295 }
22722296}
22732297
22742298/// Like `resolveValue`, but emits an error if the value is not comptime-known.
2275fn resolveConstValue(
2299pub fn resolveConstValue(
22762300 sema: *Sema,
22772301 block: *Block,
22782302 src: LazySrcLoc,
......@@ -2301,7 +2325,7 @@ fn resolveDefinedValue(
23012325}
23022326
23032327/// Like `resolveValue`, but emits an error if the value is not comptime-known or is undefined.
2304fn resolveConstDefinedValue(
2328pub fn resolveConstDefinedValue(
23052329 sema: *Sema,
23062330 block: *Block,
23072331 src: LazySrcLoc,
......@@ -2315,11 +2339,6 @@ fn resolveConstDefinedValue(
23152339 return val;
23162340}
23172341
2318/// Like `resolveValue`, but recursively resolves lazy values before returning.
2319fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value {
2320 return try sema.resolveLazyValue((try sema.resolveValue(inst)) orelse return null);
2321}
2322
23232342/// Value Tag may be `undef` or `variable`.
23242343pub fn resolveFinalDeclValue(
23252344 sema: *Sema,
......@@ -2439,13 +2458,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non
24392458
24402459fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
24412460 const pt = sema.pt;
2461 const zcu = pt.zcu;
24422462 const msg = msg: {
24432463 const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{
24442464 ty.fmt(pt),
24452465 });
24462466 errdefer msg.destroy(sema.gpa);
2447 if (ty.isSlice(pt.zcu)) {
2448 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.elemType2(pt.zcu).fmt(pt)});
2467 if (ty.isSlice(zcu)) {
2468 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.childType(zcu).fmt(pt)});
24492469 }
24502470 break :msg msg;
24512471 };
......@@ -2644,7 +2664,7 @@ pub fn fail(
26442664 src: LazySrcLoc,
26452665 comptime format: []const u8,
26462666 args: anytype,
2647) CompileError {
2667) SemaError {
26482668 const err_msg = try sema.errMsg(src, format, args);
26492669 inline for (args) |arg| {
26502670 if (@TypeOf(arg) == Type.Formatter) {
......@@ -2798,27 +2818,26 @@ fn analyzeAsInt(
27982818) !u64 {
27992819 const coerced = try sema.coerce(block, dest_ty, air_ref, src);
28002820 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);
2801 return try val.toUnsignedIntSema(sema.pt);
2821 return val.toUnsignedInt(sema.pt.zcu);
28022822}
28032823
28042824fn analyzeValueAsCallconv(
28052825 sema: *Sema,
28062826 block: *Block,
28072827 src: LazySrcLoc,
2808 unresolved_val: Value,
2828 val: Value,
28092829) !std.builtin.CallingConvention {
2810 return interpretBuiltinType(sema, block, src, unresolved_val, std.builtin.CallingConvention);
2830 return interpretBuiltinType(sema, block, src, val, std.builtin.CallingConvention);
28112831}
28122832
28132833fn interpretBuiltinType(
28142834 sema: *Sema,
28152835 block: *Block,
28162836 src: LazySrcLoc,
2817 unresolved_val: Value,
2837 val: Value,
28182838 comptime T: type,
28192839) !T {
2820 const resolved_val = try sema.resolveLazyValue(unresolved_val);
2821 return resolved_val.interpret(T, sema.pt) catch |err| switch (err) {
2840 return val.interpret(T, sema.pt) catch |err| switch (err) {
28222841 error.OutOfMemory => |e| return e,
28232842 error.UndefinedValue => return sema.failWithUseOfUndef(block, src, null),
28242843 error.TypeMismatch => @panic("std.builtin is corrupt"),
......@@ -2913,7 +2932,13 @@ fn validateTupleFieldType(
29132932
29142933/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
29152934/// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`.
2916fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue {
2935fn getCaptures(
2936 sema: *Sema,
2937 block: *Block,
2938 type_src: LazySrcLoc,
2939 zir_captures: []const Zir.Inst.Capture,
2940 zir_capture_names: []const Zir.NullTerminatedString,
2941) ![]InternPool.CaptureValue {
29172942 const pt = sema.pt;
29182943 const zcu = pt.zcu;
29192944 const comp = zcu.comp;
......@@ -2924,41 +2949,38 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
29242949 const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type);
29252950 const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu);
29262951
2927 const captures = try sema.arena.alloc(InternPool.CaptureValue, captures_len);
2952 const captures = try sema.arena.alloc(InternPool.CaptureValue, zir_captures.len);
29282953
2929 for (sema.code.extra[extra_index..][0..captures_len], sema.code.extra[extra_index + captures_len ..][0..captures_len], captures) |raw, raw_name, *capture| {
2930 const zir_capture: Zir.Inst.Capture = @bitCast(raw);
2931 const zir_name: Zir.NullTerminatedString = @enumFromInt(raw_name);
2954 for (zir_captures, zir_capture_names, captures) |zir_capture, zir_name, *capture| {
29322955 const zir_name_slice = sema.code.nullTerminatedString(zir_name);
29332956 capture.* = switch (zir_capture.unwrap()) {
29342957 .nested => |parent_idx| parent_captures.get(ip)[parent_idx],
2935 .instruction_load => |ptr_inst| InternPool.CaptureValue.wrap(capture: {
2958 .instruction_load => |ptr_inst| capture: {
29362959 const ptr_ref = try sema.resolveInst(ptr_inst.toRef());
29372960 const ptr_val = try sema.resolveValue(ptr_ref) orelse {
2938 break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() };
2961 break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() });
29392962 };
29402963 // TODO: better source location
2941 const unresolved_loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse {
2942 break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() };
2964 const loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse {
2965 break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() });
29432966 };
2944 const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val);
29452967 if (loaded_val.canMutateComptimeVarState(zcu)) {
29462968 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls);
29472969 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val);
29482970 }
2949 break :capture .{ .@"comptime" = loaded_val.toIntern() };
2950 }),
2951 .instruction => |inst| InternPool.CaptureValue.wrap(capture: {
2971 break :capture .wrap(.{ .@"comptime" = loaded_val.toIntern() });
2972 },
2973 .instruction => |inst| capture: {
29522974 const air_ref = try sema.resolveInst(inst.toRef());
2953 if (try sema.resolveValueResolveLazy(air_ref)) |val| {
2975 if (try sema.resolveValue(air_ref)) |val| {
29542976 if (val.canMutateComptimeVarState(zcu)) {
29552977 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls);
29562978 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val);
29572979 }
2958 break :capture .{ .@"comptime" = val.toIntern() };
2980 break :capture .wrap(.{ .@"comptime" = val.toIntern() });
29592981 }
2960 break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() };
2961 }),
2982 break :capture .wrap(.{ .runtime = sema.typeOf(air_ref).toIntern() });
2983 },
29622984 .decl_val => |str| capture: {
29632985 const decl_name = try ip.getOrPutString(
29642986 gpa,
......@@ -2968,7 +2990,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
29682990 .no_embedded_nulls,
29692991 );
29702992 const nav = try sema.lookupIdentifier(block, decl_name);
2971 break :capture InternPool.CaptureValue.wrap(.{ .nav_val = nav });
2993 break :capture .wrap(.{ .nav_val = nav });
29722994 },
29732995 .decl_ref => |str| capture: {
29742996 const decl_name = try ip.getOrPutString(
......@@ -2987,621 +3009,6 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
29873009 return captures;
29883010}
29893011
2990fn zirStructDecl(
2991 sema: *Sema,
2992 block: *Block,
2993 extended: Zir.Inst.Extended.InstData,
2994 inst: Zir.Inst.Index,
2995) CompileError!Air.Inst.Ref {
2996 const pt = sema.pt;
2997 const zcu = pt.zcu;
2998 const comp = zcu.comp;
2999 const gpa = comp.gpa;
3000 const io = comp.io;
3001 const ip = &zcu.intern_pool;
3002
3003 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
3004 const extra = sema.code.extraData(Zir.Inst.StructDecl, extended.operand);
3005
3006 const tracked_inst = try block.trackZir(inst);
3007 const src: LazySrcLoc = .{
3008 .base_node_inst = tracked_inst,
3009 .offset = LazySrcLoc.Offset.nodeOffset(.zero),
3010 };
3011
3012 var extra_index = extra.end;
3013
3014 const captures_len = if (small.has_captures_len) blk: {
3015 const captures_len = sema.code.extra[extra_index];
3016 extra_index += 1;
3017 break :blk captures_len;
3018 } else 0;
3019 const fields_len = if (small.has_fields_len) blk: {
3020 const fields_len = sema.code.extra[extra_index];
3021 extra_index += 1;
3022 break :blk fields_len;
3023 } else 0;
3024 const decls_len = if (small.has_decls_len) blk: {
3025 const decls_len = sema.code.extra[extra_index];
3026 extra_index += 1;
3027 break :blk decls_len;
3028 } else 0;
3029
3030 const captures = try sema.getCaptures(block, src, extra_index, captures_len);
3031 extra_index += captures_len * 2;
3032
3033 if (small.has_backing_int) {
3034 const backing_int_body_len = sema.code.extra[extra_index];
3035 extra_index += 1; // backing_int_body_len
3036 if (backing_int_body_len == 0) {
3037 extra_index += 1; // backing_int_ref
3038 } else {
3039 extra_index += backing_int_body_len; // backing_int_body_inst
3040 }
3041 }
3042
3043 const struct_init: InternPool.StructTypeInit = .{
3044 .layout = small.layout,
3045 .fields_len = fields_len,
3046 .known_non_opv = small.known_non_opv,
3047 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
3048 .any_comptime_fields = small.any_comptime_fields,
3049 .any_default_inits = small.any_default_inits,
3050 .inits_resolved = false,
3051 .any_aligned_fields = small.any_aligned_fields,
3052 .key = .{ .declared = .{
3053 .zir_index = tracked_inst,
3054 .captures = captures,
3055 } },
3056 };
3057 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, struct_init, false)) {
3058 .existing => |ty| {
3059 const new_ty = try pt.ensureTypeUpToDate(ty);
3060
3061 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3062 // up on e.g. changed comptime decls.
3063 try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu));
3064
3065 try sema.declareDependency(.{ .interned = new_ty });
3066 try sema.addTypeReferenceEntry(src, new_ty);
3067 return Air.internedToRef(new_ty);
3068 },
3069 .wip => |wip| wip,
3070 };
3071 errdefer wip_ty.cancel(ip, pt.tid);
3072
3073 const type_name = try sema.createTypeName(
3074 block,
3075 small.name_strategy,
3076 "struct",
3077 inst,
3078 wip_ty.index,
3079 );
3080 wip_ty.setName(ip, type_name.name, type_name.nav);
3081
3082 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
3083 .parent = block.namespace.toOptional(),
3084 .owner_type = wip_ty.index,
3085 .file_scope = block.getFileScopeIndex(zcu),
3086 .generation = zcu.generation,
3087 });
3088 errdefer pt.destroyNamespace(new_namespace_index);
3089
3090 if (pt.zcu.comp.config.incremental) {
3091 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst });
3092 }
3093
3094 const decls = sema.code.bodySlice(extra_index, decls_len);
3095 try pt.scanNamespace(new_namespace_index, decls);
3096
3097 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
3098 codegen_type: {
3099 if (zcu.comp.config.use_llvm) break :codegen_type;
3100 if (block.ownerModule().strip) break :codegen_type;
3101 // This job depends on any resolve_type_fully jobs queued up before it.
3102 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3103 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3104 }
3105 try sema.declareDependency(.{ .interned = wip_ty.index });
3106 try sema.addTypeReferenceEntry(src, wip_ty.index);
3107 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
3108 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3109}
3110
3111pub fn createTypeName(
3112 sema: *Sema,
3113 block: *Block,
3114 name_strategy: Zir.Inst.NameStrategy,
3115 anon_prefix: []const u8,
3116 inst: ?Zir.Inst.Index,
3117 /// This is used purely to give the type a unique name in the `anon` case.
3118 type_index: InternPool.Index,
3119) CompileError!struct {
3120 name: InternPool.NullTerminatedString,
3121 nav: InternPool.Nav.Index.Optional,
3122} {
3123 const pt = sema.pt;
3124 const zcu = pt.zcu;
3125 const comp = zcu.comp;
3126 const gpa = comp.gpa;
3127 const io = comp.io;
3128 const ip = &zcu.intern_pool;
3129
3130 switch (name_strategy) {
3131 .anon => {}, // handled after switch
3132 .parent => return .{
3133 .name = block.type_name_ctx,
3134 .nav = sema.owner.unwrap().nav_val.toOptional(),
3135 },
3136 .func => func_strat: {
3137 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
3138 const zir_tags = sema.code.instructions.items(.tag);
3139
3140 var aw: std.Io.Writer.Allocating = .init(gpa);
3141 defer aw.deinit();
3142 const w = &aw.writer;
3143 w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory;
3144
3145 var arg_i: usize = 0;
3146 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
3147 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {
3148 const arg = sema.inst_map.get(zir_inst).?;
3149 // If this is being called in a generic function then analyzeCall will
3150 // have already resolved the args and this will work.
3151 // If not then this is a struct type being returned from a non-generic
3152 // function and the name doesn't matter since it will later
3153 // result in a compile error.
3154 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat
3155
3156 if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory;
3157
3158 // Limiting the depth here helps avoid type names getting too long, which
3159 // in turn helps to avoid unreasonably long symbol names for namespaced
3160 // symbols. Such names should ideally be human-readable, and additionally,
3161 // some tooling may not support very long symbol names.
3162 w.print("{f}", .{Value.fmtValueSemaFull(.{
3163 .val = arg_val,
3164 .pt = pt,
3165 .opt_sema = sema,
3166 .depth = 1,
3167 })}) catch return error.OutOfMemory;
3168
3169 arg_i += 1;
3170 continue;
3171 },
3172 else => continue,
3173 };
3174
3175 w.writeByte(')') catch return error.OutOfMemory;
3176 return .{
3177 .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls),
3178 .nav = .none,
3179 };
3180 },
3181 .dbg_var => {
3182 // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions.
3183 const ref = inst.?.toRef();
3184 const zir_tags = sema.code.instructions.items(.tag);
3185 const zir_data = sema.code.instructions.items(.data);
3186 for (@intFromEnum(inst.?)..zir_tags.len) |i| switch (zir_tags[i]) {
3187 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
3188 return .{
3189 .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{
3190 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
3191 }, .no_embedded_nulls),
3192 .nav = .none,
3193 };
3194 },
3195 else => {},
3196 };
3197 // fall through to anon strat
3198 },
3199 }
3200
3201 // anon strat handling
3202
3203 // It would be neat to have "struct:line:column" but this name has
3204 // to survive incremental updates, where it may have been shifted down
3205 // or up to a different line, but unchanged, and thus not unnecessarily
3206 // semantically analyzed.
3207 // TODO: that would be possible, by detecting line number changes and renaming
3208 // types appropriately. However, `@typeName` becomes a problem then. If we remove
3209 // that builtin from the language, we can consider this.
3210
3211 return .{
3212 .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}__{s}_{d}", .{
3213 block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(type_index),
3214 }, .no_embedded_nulls),
3215 .nav = .none,
3216 };
3217}
3218
3219fn zirEnumDecl(
3220 sema: *Sema,
3221 block: *Block,
3222 extended: Zir.Inst.Extended.InstData,
3223 inst: Zir.Inst.Index,
3224) CompileError!Air.Inst.Ref {
3225 const tracy = trace(@src());
3226 defer tracy.end();
3227
3228 const pt = sema.pt;
3229 const zcu = pt.zcu;
3230 const comp = zcu.comp;
3231 const gpa = comp.gpa;
3232 const io = comp.io;
3233 const ip = &zcu.intern_pool;
3234
3235 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
3236 const extra = sema.code.extraData(Zir.Inst.EnumDecl, extended.operand);
3237 var extra_index: usize = extra.end;
3238
3239 const tracked_inst = try block.trackZir(inst);
3240 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3241
3242 const tag_type_ref = if (small.has_tag_type) blk: {
3243 const tag_type_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
3244 extra_index += 1;
3245 break :blk tag_type_ref;
3246 } else .none;
3247
3248 const captures_len = if (small.has_captures_len) blk: {
3249 const captures_len = sema.code.extra[extra_index];
3250 extra_index += 1;
3251 break :blk captures_len;
3252 } else 0;
3253
3254 const body_len = if (small.has_body_len) blk: {
3255 const body_len = sema.code.extra[extra_index];
3256 extra_index += 1;
3257 break :blk body_len;
3258 } else 0;
3259
3260 const fields_len = if (small.has_fields_len) blk: {
3261 const fields_len = sema.code.extra[extra_index];
3262 extra_index += 1;
3263 break :blk fields_len;
3264 } else 0;
3265
3266 const decls_len = if (small.has_decls_len) blk: {
3267 const decls_len = sema.code.extra[extra_index];
3268 extra_index += 1;
3269 break :blk decls_len;
3270 } else 0;
3271
3272 const captures = try sema.getCaptures(block, src, extra_index, captures_len);
3273 extra_index += captures_len * 2;
3274
3275 const decls = sema.code.bodySlice(extra_index, decls_len);
3276 extra_index += decls_len;
3277
3278 const body = sema.code.bodySlice(extra_index, body_len);
3279 extra_index += body.len;
3280
3281 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
3282 const body_end = extra_index;
3283 extra_index += bit_bags_count;
3284
3285 const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| {
3286 if (bag != 0) break true;
3287 } else false;
3288
3289 const enum_init: InternPool.EnumTypeInit = .{
3290 .has_values = any_values,
3291 .tag_mode = if (small.nonexhaustive)
3292 .nonexhaustive
3293 else if (tag_type_ref == .none)
3294 .auto
3295 else
3296 .explicit,
3297 .fields_len = fields_len,
3298 .key = .{ .declared = .{
3299 .zir_index = tracked_inst,
3300 .captures = captures,
3301 } },
3302 };
3303 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, enum_init, false)) {
3304 .existing => |ty| {
3305 const new_ty = try pt.ensureTypeUpToDate(ty);
3306
3307 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3308 // up on e.g. changed comptime decls.
3309 try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu));
3310
3311 try sema.declareDependency(.{ .interned = new_ty });
3312 try sema.addTypeReferenceEntry(src, new_ty);
3313
3314 // Since this is an enum, it has to be resolved immediately.
3315 // `ensureTypeUpToDate` has resolved the new type if necessary.
3316 // We just need to check for resolution failures.
3317 const ty_unit: AnalUnit = .wrap(.{ .type = new_ty });
3318 if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) {
3319 return error.AnalysisFail;
3320 }
3321
3322 return Air.internedToRef(new_ty);
3323 },
3324 .wip => |wip| wip,
3325 };
3326
3327 // Once this is `true`, we will not delete the decl or type even upon failure, since we
3328 // have finished constructing the type and are in the process of analyzing it.
3329 var done = false;
3330
3331 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
3332
3333 const type_name = try sema.createTypeName(
3334 block,
3335 small.name_strategy,
3336 "enum",
3337 inst,
3338 wip_ty.index,
3339 );
3340 wip_ty.setName(ip, type_name.name, type_name.nav);
3341
3342 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
3343 .parent = block.namespace.toOptional(),
3344 .owner_type = wip_ty.index,
3345 .file_scope = block.getFileScopeIndex(zcu),
3346 .generation = zcu.generation,
3347 });
3348 errdefer if (!done) pt.destroyNamespace(new_namespace_index);
3349
3350 try pt.scanNamespace(new_namespace_index, decls);
3351
3352 try sema.declareDependency(.{ .interned = wip_ty.index });
3353 try sema.addTypeReferenceEntry(src, wip_ty.index);
3354
3355 // We've finished the initial construction of this type, and are about to perform analysis.
3356 // Set the namespace appropriately, and don't destroy anything on failure.
3357 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
3358 wip_ty.prepare(ip, new_namespace_index);
3359 done = true;
3360
3361 {
3362 const tracked_unit = zcu.trackUnitSema(type_name.name.toSlice(ip), null);
3363 defer tracked_unit.end(zcu);
3364 try Sema.resolveDeclaredEnum(
3365 pt,
3366 wip_ty,
3367 inst,
3368 tracked_inst,
3369 new_namespace_index,
3370 type_name.name,
3371 small,
3372 body,
3373 tag_type_ref,
3374 any_values,
3375 fields_len,
3376 sema.code,
3377 body_end,
3378 );
3379 }
3380
3381 codegen_type: {
3382 if (zcu.comp.config.use_llvm) break :codegen_type;
3383 if (block.ownerModule().strip) break :codegen_type;
3384 // This job depends on any resolve_type_fully jobs queued up before it.
3385 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3386 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3387 }
3388 return Air.internedToRef(wip_ty.index);
3389}
3390
3391fn zirUnionDecl(
3392 sema: *Sema,
3393 block: *Block,
3394 extended: Zir.Inst.Extended.InstData,
3395 inst: Zir.Inst.Index,
3396) CompileError!Air.Inst.Ref {
3397 const tracy = trace(@src());
3398 defer tracy.end();
3399
3400 const pt = sema.pt;
3401 const zcu = pt.zcu;
3402 const comp = zcu.comp;
3403 const gpa = comp.gpa;
3404 const io = comp.io;
3405 const ip = &zcu.intern_pool;
3406
3407 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
3408 const extra = sema.code.extraData(Zir.Inst.UnionDecl, extended.operand);
3409 var extra_index: usize = extra.end;
3410
3411 const tracked_inst = try block.trackZir(inst);
3412 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3413
3414 extra_index += @intFromBool(small.has_tag_type);
3415 const captures_len = if (small.has_captures_len) blk: {
3416 const captures_len = sema.code.extra[extra_index];
3417 extra_index += 1;
3418 break :blk captures_len;
3419 } else 0;
3420 extra_index += @intFromBool(small.has_body_len);
3421 const fields_len = if (small.has_fields_len) blk: {
3422 const fields_len = sema.code.extra[extra_index];
3423 extra_index += 1;
3424 break :blk fields_len;
3425 } else 0;
3426
3427 const decls_len = if (small.has_decls_len) blk: {
3428 const decls_len = sema.code.extra[extra_index];
3429 extra_index += 1;
3430 break :blk decls_len;
3431 } else 0;
3432
3433 const captures = try sema.getCaptures(block, src, extra_index, captures_len);
3434 extra_index += captures_len * 2;
3435
3436 const union_init: InternPool.UnionTypeInit = .{
3437 .flags = .{
3438 .layout = small.layout,
3439 .status = .none,
3440 .runtime_tag = if (small.has_tag_type or small.auto_enum_tag)
3441 .tagged
3442 else if (small.layout != .auto)
3443 .none
3444 else switch (block.wantSafeTypes()) {
3445 true => .safety,
3446 false => .none,
3447 },
3448 .any_aligned_fields = small.any_aligned_fields,
3449 .requires_comptime = .unknown,
3450 .assumed_runtime_bits = false,
3451 .assumed_pointer_aligned = false,
3452 .alignment = .none,
3453 },
3454 .fields_len = fields_len,
3455 .enum_tag_ty = .none, // set later
3456 .field_types = &.{}, // set later
3457 .field_aligns = &.{}, // set later
3458 .key = .{ .declared = .{
3459 .zir_index = tracked_inst,
3460 .captures = captures,
3461 } },
3462 };
3463 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, union_init, false)) {
3464 .existing => |ty| {
3465 const new_ty = try pt.ensureTypeUpToDate(ty);
3466
3467 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3468 // up on e.g. changed comptime decls.
3469 try pt.ensureNamespaceUpToDate(Type.fromInterned(new_ty).getNamespaceIndex(zcu));
3470
3471 try sema.declareDependency(.{ .interned = new_ty });
3472 try sema.addTypeReferenceEntry(src, new_ty);
3473 return Air.internedToRef(new_ty);
3474 },
3475 .wip => |wip| wip,
3476 };
3477 errdefer wip_ty.cancel(ip, pt.tid);
3478
3479 const type_name = try sema.createTypeName(
3480 block,
3481 small.name_strategy,
3482 "union",
3483 inst,
3484 wip_ty.index,
3485 );
3486 wip_ty.setName(ip, type_name.name, type_name.nav);
3487
3488 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
3489 .parent = block.namespace.toOptional(),
3490 .owner_type = wip_ty.index,
3491 .file_scope = block.getFileScopeIndex(zcu),
3492 .generation = zcu.generation,
3493 });
3494 errdefer pt.destroyNamespace(new_namespace_index);
3495
3496 if (pt.zcu.comp.config.incremental) {
3497 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst });
3498 }
3499
3500 const decls = sema.code.bodySlice(extra_index, decls_len);
3501 try pt.scanNamespace(new_namespace_index, decls);
3502
3503 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
3504 codegen_type: {
3505 if (zcu.comp.config.use_llvm) break :codegen_type;
3506 if (block.ownerModule().strip) break :codegen_type;
3507 // This job depends on any resolve_type_fully jobs queued up before it.
3508 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3509 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3510 }
3511 try sema.declareDependency(.{ .interned = wip_ty.index });
3512 try sema.addTypeReferenceEntry(src, wip_ty.index);
3513 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
3514 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3515}
3516
3517fn zirOpaqueDecl(
3518 sema: *Sema,
3519 block: *Block,
3520 extended: Zir.Inst.Extended.InstData,
3521 inst: Zir.Inst.Index,
3522) CompileError!Air.Inst.Ref {
3523 const tracy = trace(@src());
3524 defer tracy.end();
3525
3526 const pt = sema.pt;
3527 const zcu = pt.zcu;
3528 const comp = zcu.comp;
3529 const gpa = comp.gpa;
3530 const io = comp.io;
3531 const ip = &zcu.intern_pool;
3532
3533 const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small);
3534 const extra = sema.code.extraData(Zir.Inst.OpaqueDecl, extended.operand);
3535 var extra_index: usize = extra.end;
3536
3537 const tracked_inst = try block.trackZir(inst);
3538 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
3539
3540 const captures_len = if (small.has_captures_len) blk: {
3541 const captures_len = sema.code.extra[extra_index];
3542 extra_index += 1;
3543 break :blk captures_len;
3544 } else 0;
3545
3546 const decls_len = if (small.has_decls_len) blk: {
3547 const decls_len = sema.code.extra[extra_index];
3548 extra_index += 1;
3549 break :blk decls_len;
3550 } else 0;
3551
3552 const captures = try sema.getCaptures(block, src, extra_index, captures_len);
3553 extra_index += captures_len * 2;
3554
3555 const opaque_init: InternPool.OpaqueTypeInit = .{
3556 .zir_index = tracked_inst,
3557 .captures = captures,
3558 };
3559 const wip_ty = switch (try ip.getOpaqueType(gpa, io, pt.tid, opaque_init)) {
3560 .existing => |ty| {
3561 // Make sure we update the namespace if the declaration is re-analyzed, to pick
3562 // up on e.g. changed comptime decls.
3563 try pt.ensureNamespaceUpToDate(Type.fromInterned(ty).getNamespaceIndex(zcu));
3564
3565 try sema.declareDependency(.{ .interned = ty });
3566 try sema.addTypeReferenceEntry(src, ty);
3567 return Air.internedToRef(ty);
3568 },
3569 .wip => |wip| wip,
3570 };
3571 errdefer wip_ty.cancel(ip, pt.tid);
3572
3573 const type_name = try sema.createTypeName(
3574 block,
3575 small.name_strategy,
3576 "opaque",
3577 inst,
3578 wip_ty.index,
3579 );
3580 wip_ty.setName(ip, type_name.name, type_name.nav);
3581
3582 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
3583 .parent = block.namespace.toOptional(),
3584 .owner_type = wip_ty.index,
3585 .file_scope = block.getFileScopeIndex(zcu),
3586 .generation = zcu.generation,
3587 });
3588 errdefer pt.destroyNamespace(new_namespace_index);
3589
3590 const decls = sema.code.bodySlice(extra_index, decls_len);
3591 try pt.scanNamespace(new_namespace_index, decls);
3592
3593 codegen_type: {
3594 if (zcu.comp.config.use_llvm) break :codegen_type;
3595 if (block.ownerModule().strip) break :codegen_type;
3596 // This job depends on any resolve_type_fully jobs queued up before it.
3597 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
3598 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
3599 }
3600 try sema.addTypeReferenceEntry(src, wip_ty.index);
3601 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
3602 return Air.internedToRef(wip_ty.finish(ip, new_namespace_index));
3603}
3604
36053012fn zirErrorSetDecl(
36063013 sema: *Sema,
36073014 inst: Zir.Inst.Index,
......@@ -3640,16 +3047,16 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
36403047 defer tracy.end();
36413048
36423049 const pt = sema.pt;
3050 const zcu = pt.zcu;
36433051
36443052 const src = block.nodeOffset(sema.code.instructions.items(.data)[@intFromEnum(inst)].node);
36453053
3646 if (block.isComptime() or try sema.fn_ret_ty.comptimeOnlySema(pt)) {
3647 try sema.fn_ret_ty.resolveFields(pt);
3054 if (block.isComptime() or sema.fn_ret_ty.comptimeOnly(zcu)) {
36483055 return sema.analyzeComptimeAlloc(block, src, sema.fn_ret_ty, .none);
36493056 }
36503057
3651 const target = pt.zcu.getTarget();
3652 const ptr_type = try pt.ptrTypeSema(.{
3058 const target = zcu.getTarget();
3059 const ptr_type = try pt.ptrType(.{
36533060 .child = sema.fn_ret_ty.toIntern(),
36543061 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
36553062 });
......@@ -3826,6 +3233,7 @@ fn zirAllocExtended(
38263233 extended: Zir.Inst.Extended.InstData,
38273234) CompileError!Air.Inst.Ref {
38283235 const pt = sema.pt;
3236 const zcu = pt.zcu;
38293237 const gpa = sema.gpa;
38303238 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
38313239 const var_src = block.nodeOffset(extra.data.src_node);
......@@ -3847,37 +3255,20 @@ fn zirAllocExtended(
38473255 break :blk try sema.resolveAlign(block, align_src, align_ref);
38483256 } else .none;
38493257
3850 if (block.isComptime() or small.is_comptime) {
3851 if (small.has_type) {
3258 if (small.has_type) {
3259 try sema.ensureLayoutResolved(var_ty);
3260 if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) {
38523261 return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment);
3853 } else {
3854 try sema.air_instructions.append(gpa, .{
3855 .tag = .inferred_alloc_comptime,
3856 .data = .{ .inferred_alloc_comptime = .{
3857 .alignment = alignment,
3858 .is_const = small.is_const,
3859 .ptr = undefined,
3860 } },
3861 });
3862 return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef();
38633262 }
3864 }
3865
3866 if (small.has_type and try var_ty.comptimeOnlySema(pt)) {
3867 return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment);
3868 }
3869
3870 if (small.has_type) {
38713263 if (!small.is_const) {
38723264 try sema.validateVarType(block, ty_src, var_ty, false);
38733265 }
38743266 const target = pt.zcu.getTarget();
3875 try var_ty.resolveLayout(pt);
3876 if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
3267 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) {
38773268 const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node });
38783269 return sema.fail(block, store_src, "local variable in naked function", .{});
38793270 }
3880 const ptr_type = try sema.pt.ptrTypeSema(.{
3271 const ptr_type = try pt.ptrType(.{
38813272 .child = var_ty.toIntern(),
38823273 .flags = .{
38833274 .alignment = alignment,
......@@ -3893,6 +3284,19 @@ fn zirAllocExtended(
38933284 return ptr;
38943285 }
38953286
3287 if (block.isComptime() or small.is_comptime) {
3288 const iac_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
3289 try sema.air_instructions.append(gpa, .{
3290 .tag = .inferred_alloc_comptime,
3291 .data = .{ .inferred_alloc_comptime = .{
3292 .alignment = alignment,
3293 .is_const = small.is_const,
3294 .ptr = undefined,
3295 } },
3296 });
3297 return iac_index.toRef();
3298 }
3299
38963300 const result_index = try block.addInstAsIndex(.{
38973301 .tag = .inferred_alloc,
38983302 .data = .{ .inferred_alloc = .{
......@@ -3916,6 +3320,7 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
39163320 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
39173321 const var_src = block.nodeOffset(inst_data.src_node);
39183322 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
3323 try sema.ensureLayoutResolved(var_ty);
39193324 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
39203325}
39213326
......@@ -3978,7 +3383,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
39783383 return sema.makePtrConst(block, Air.internedToRef(ptr_val));
39793384 }
39803385
3981 if (try elem_ty.comptimeOnlySema(pt)) {
3386 if (elem_ty.comptimeOnly(zcu)) {
39823387 // The value was initialized through RLS, so we didn't detect the runtime condition earlier.
39833388 // TODO: source location of runtime control flow
39843389 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
......@@ -4001,20 +3406,23 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
40013406 const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc);
40023407 const ptr_info = alloc_ty.ptrInfo(zcu);
40033408 const elem_ty: Type = .fromInterned(ptr_info.child);
3409 elem_ty.assertHasLayout(zcu);
40043410
40053411 const alloc_inst = alloc.toIndex() orelse return null;
40063412 const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null;
40073413 const stores = comptime_info.value.stores.items(.inst);
40083414
3415 // If the elem type is OPV, no need to faff about with `stores`; just use the OPV.
3416 if (try elem_ty.onePossibleValue(pt)) |opv| {
3417 return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, opv.toIntern(), null, alloc_inst, comptime_info.value);
3418 }
3419
3420 // Since the elem type isn't OPV, there should have been at least one store.
3421 assert(stores.len > 0);
3422
40093423 // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known.
40103424 // We will resolve and return its value.
40113425
4012 // We expect to have emitted at least one store, unless the elem type is OPV.
4013 if (stores.len == 0) {
4014 const val = (try sema.typeHasOnePossibleValue(elem_ty)).?.toIntern();
4015 return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value);
4016 }
4017
40183426 // In general, we want to create a comptime alloc of the correct type and
40193427 // apply the stores to that alloc in order. However, before going to all
40203428 // that effort, let's optimize for the common case of a single store.
......@@ -4118,7 +3526,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
41183526 const idx_val = (try sema.resolveValue(data.rhs)).?;
41193527 break :blk .{
41203528 data.lhs,
4121 .{ .elem = try idx_val.toUnsignedIntSema(pt) },
3529 .{ .elem = idx_val.toUnsignedInt(zcu) },
41223530 };
41233531 },
41243532 .bitcast => .{
......@@ -4150,7 +3558,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
41503558 // If the payload is OPV, we must use that value instead of undef.
41513559 const opt_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu);
41523560 const payload_ty = opt_ty.optionalChild(zcu);
4153 const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty);
3561 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty);
41543562 const opt_val = try pt.intern(.{ .opt = .{
41553563 .ty = opt_ty.toIntern(),
41563564 .val = payload_val.toIntern(),
......@@ -4163,7 +3571,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
41633571 // If the payload is OPV, we must use that value instead of undef.
41643572 const eu_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu);
41653573 const payload_ty = eu_ty.errorUnionPayload(zcu);
4166 const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty);
3574 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty);
41673575 const eu_val = try pt.intern(.{ .error_union = .{
41683576 .ty = eu_ty.toIntern(),
41693577 .val = .{ .payload = payload_val.toIntern() },
......@@ -4178,7 +3586,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
41783586 // The payload value will be stored later, so undef is a sufficent payload for now.
41793587 const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]);
41803588 const payload_val = try pt.undefValue(payload_ty);
4181 const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), idx);
3589 const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), idx);
41823590 const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val);
41833591 try sema.storePtrVal(block, .unneeded, .fromInterned(decl_parent_ptr), store_val, maybe_union_ty);
41843592 }
......@@ -4207,7 +3615,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
42073615 const tag_val: Value = .fromInterned(store_inst.data.bin_op.rhs.toInterned().?);
42083616 const union_ty = union_ptr_val.typeOf(zcu).childType(zcu);
42093617 const field_ty = union_ty.unionFieldType(tag_val, zcu).?;
4210 if (try sema.typeHasOnePossibleValue(field_ty)) |payload_val| {
3618 if (try field_ty.onePossibleValue(pt)) |payload_val| {
42113619 const new_union_val = try pt.unionValue(union_ty, tag_val, payload_val);
42123620 try sema.storePtrVal(block, .unneeded, union_ptr_val, new_union_val, union_ty);
42133621 }
......@@ -4289,7 +3697,7 @@ fn finishResolveComptimeKnownAllocPtr(
42893697fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type {
42903698 var ptr_info = ptr_ty.ptrInfo(sema.pt.zcu);
42913699 ptr_info.flags.is_const = true;
4292 return sema.pt.ptrTypeSema(ptr_info);
3700 return sema.pt.ptrType(ptr_info);
42933701}
42943702
42953703fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {
......@@ -4326,21 +3734,23 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
43263734 defer tracy.end();
43273735
43283736 const pt = sema.pt;
3737 const zcu = pt.zcu;
43293738
43303739 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
43313740 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
43323741 const var_src = block.nodeOffset(inst_data.src_node);
43333742
43343743 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
4335 if (block.isComptime() or try var_ty.comptimeOnlySema(pt)) {
3744 try sema.ensureLayoutResolved(var_ty);
3745 if (block.isComptime() or var_ty.comptimeOnly(zcu)) {
43363746 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
43373747 }
4338 if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
3748 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) {
43393749 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
43403750 return sema.fail(block, mut_src, "local variable in naked function", .{});
43413751 }
4342 const target = pt.zcu.getTarget();
4343 const ptr_type = try pt.ptrTypeSema(.{
3752 const target = zcu.getTarget();
3753 const ptr_type = try pt.ptrType(.{
43443754 .child = var_ty.toIntern(),
43453755 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
43463756 });
......@@ -4356,21 +3766,24 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
43563766 defer tracy.end();
43573767
43583768 const pt = sema.pt;
3769 const zcu = pt.zcu;
43593770
43603771 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
43613772 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
43623773 const var_src = block.nodeOffset(inst_data.src_node);
3774
43633775 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
3776 try sema.ensureLayoutResolved(var_ty);
43643777 if (block.isComptime()) {
43653778 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
43663779 }
4367 if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
3780 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) {
43683781 const store_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
43693782 return sema.fail(block, store_src, "local variable in naked function", .{});
43703783 }
43713784 try sema.validateVarType(block, ty_src, var_ty, false);
4372 const target = pt.zcu.getTarget();
4373 const ptr_type = try pt.ptrTypeSema(.{
3785 const target = zcu.getTarget();
3786 const ptr_type = try pt.ptrType(.{
43743787 .child = var_ty.toIntern(),
43753788 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
43763789 });
......@@ -4430,8 +3843,9 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
44303843
44313844 switch (sema.air_instructions.items(.tag)[@intFromEnum(ptr_inst)]) {
44323845 .inferred_alloc_comptime => {
4433 // The work was already done for us by `Sema.storeToInferredAllocComptime`.
4434 // All we need to do is return the pointer.
3846 // The work was already done for us by `Sema.storeToInferredAllocComptime`. Also, since
3847 // we had a value of the exact correct type to store, the result type's layout must be
3848 // already resolved. So all we need to do here is return the pointer.
44353849 const iac = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc_comptime;
44363850 const resolved_ptr = iac.ptr;
44373851
......@@ -4450,7 +3864,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
44503864 };
44513865 if (zcu.intern_pool.isFuncBody(val)) {
44523866 const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val));
4453 if (try ty.fnHasRuntimeBitsSema(pt)) {
3867 if (ty.fnHasRuntimeBits(zcu)) {
44543868 const orig_fn_index = zcu.intern_pool.unwrapCoercedFunc(val);
44553869 try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index }));
44563870 try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index);
......@@ -4469,8 +3883,10 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
44693883 peer_val.* = bin_op.rhs;
44703884 }
44713885 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none);
3886 // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too.
3887 final_elem_ty.assertHasLayout(zcu);
44723888
4473 const final_ptr_ty = try pt.ptrTypeSema(.{
3889 const final_ptr_ty = try pt.ptrType(.{
44743890 .child = final_elem_ty.toIntern(),
44753891 .flags = .{
44763892 .alignment = ia1.alignment,
......@@ -4484,21 +3900,16 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
44843900 const const_ptr_ty = try sema.makePtrTyConst(final_ptr_ty);
44853901 const new_const_ptr = try pt.getCoerced(Value.fromInterned(ptr_val), const_ptr_ty);
44863902
4487 // Unless the block is comptime, `alloc_inferred` always produces
4488 // a runtime constant. The final inferred type needs to be
4489 // fully resolved so it can be lowered in codegen.
4490 try final_elem_ty.resolveFully(pt);
4491
44923903 return Air.internedToRef(new_const_ptr.toIntern());
44933904 }
44943905
4495 if (try final_elem_ty.comptimeOnlySema(pt)) {
3906 if (final_elem_ty.comptimeOnly(zcu)) {
44963907 // The alloc wasn't comptime-known per the above logic, so the
44973908 // type cannot be comptime-only.
44983909 // TODO: source location of runtime control flow
44993910 return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)});
45003911 }
4501 if (sema.func_is_naked and try final_elem_ty.hasRuntimeBitsSema(pt)) {
3912 if (sema.func_is_naked and final_elem_ty.hasRuntimeBits(zcu)) {
45023913 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
45033914 return sema.fail(block, mut_src, "local variable in naked function", .{});
45043915 }
......@@ -4812,7 +4223,7 @@ fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: boo
48124223 if (is_ref) {
48134224 var ptr_info = operand_ty.ptrInfo(zcu);
48144225 ptr_info.child = eu_ty.toIntern();
4815 const eu_ptr_ty = try pt.ptrTypeSema(ptr_info);
4226 const eu_ptr_ty = try pt.ptrType(ptr_info);
48164227 return Air.internedToRef(eu_ptr_ty.toIntern());
48174228 } else {
48184229 return Air.internedToRef(eu_ty.toIntern());
......@@ -4935,7 +4346,6 @@ fn validateArrayInitTy(
49354346 return;
49364347 },
49374348 .@"struct" => if (ty.isTuple(zcu)) {
4938 try ty.resolveFields(pt);
49394349 const array_len = ty.arrayLen(zcu);
49404350 if (init_count > array_len) {
49414351 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
......@@ -5097,12 +4507,16 @@ fn validateStructInit(
50974507 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
50984508
50994509 for (found_fields, 0..) |explicit, i_usize| {
5100 if (explicit) continue;
51014510 const i: u32 = @intCast(i_usize);
51024511
5103 try struct_ty.resolveStructFieldInits(pt);
5104 const default_val = struct_ty.structFieldDefaultValue(i, zcu);
5105 if (default_val.toIntern() == .unreachable_value) {
4512 if (explicit) continue;
4513 if (struct_ty.structFieldIsComptime(i, zcu)) continue;
4514
4515 if (!struct_ty.isTuple(zcu)) {
4516 try sema.ensureFieldInitsResolved(struct_ty);
4517 }
4518
4519 const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse {
51064520 const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse {
51074521 const template = "missing tuple field with index {d}";
51084522 if (root_msg) |msg| {
......@@ -5120,7 +4534,7 @@ fn validateStructInit(
51204534 root_msg = try sema.errMsg(init_src, template, args);
51214535 }
51224536 continue;
5123 }
4537 };
51244538
51254539 const field_src = init_src; // TODO better source location
51264540 const default_field_ptr = if (struct_ty.isTuple(zcu))
......@@ -5166,11 +4580,9 @@ fn zirValidatePtrArrayInit(
51664580 var root_msg: ?*Zcu.ErrorMsg = null;
51674581 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
51684582
5169 try array_ty.resolveStructFieldInits(pt);
51704583 var i = instrs.len;
51714584 while (i < array_len) : (i += 1) {
5172 const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern();
5173 if (default_val == .unreachable_value) {
4585 if (array_ty.structFieldDefaultValue(i, zcu) == null) {
51744586 const template = "missing tuple field with index {d}";
51754587 if (root_msg) |msg| {
51764588 try sema.errNote(init_src, msg, template, .{i});
......@@ -5224,17 +4636,19 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
52244636 .slice => return sema.fail(block, src, "index syntax required for slice type '{f}'", .{operand_ty.fmt(pt)}),
52254637 }
52264638
5227 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(zcu))) != null) {
4639 const elem_ty = operand_ty.childType(zcu);
4640 try sema.ensureLayoutResolved(elem_ty);
4641
4642 if (try elem_ty.onePossibleValue(pt) != null) {
52284643 // No need to validate the actual pointer value, we don't need it!
52294644 return;
52304645 }
52314646
5232 const elem_ty = operand_ty.elemType2(zcu);
52334647 if (try sema.resolveValue(operand)) |val| {
52344648 if (val.isUndef(zcu)) {
52354649 return sema.fail(block, src, "cannot dereference undefined value", .{});
52364650 }
5237 } else if (try elem_ty.comptimeOnlySema(pt)) {
4651 } else if (elem_ty.comptimeOnly(zcu)) {
52384652 const msg = msg: {
52394653 const msg = try sema.errMsg(
52404654 src,
......@@ -5373,7 +4787,7 @@ fn failWithBadUnionFieldAccess(
53734787 return sema.failWithOwnedErrorMsg(block, msg);
53744788}
53754789
5376fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void {
4790pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !void {
53774791 const zcu = sema.pt.zcu;
53784792 const src_loc = decl_ty.srcLocOrNull(zcu) orelse return;
53794793 const category = switch (decl_ty.zigTypeTag(zcu)) {
......@@ -5443,14 +4857,16 @@ fn storeToInferredAllocComptime(
54434857 const operand_val = try sema.resolveValue(operand) orelse {
54444858 return sema.failWithNeededComptime(block, src, .{ .simple = .stored_to_comptime_var });
54454859 };
5446 const alloc_ty = try pt.ptrTypeSema(.{
4860 const alloc_ty = try pt.ptrType(.{
54474861 .child = operand_ty.toIntern(),
54484862 .flags = .{
54494863 .alignment = iac.alignment,
54504864 .is_const = iac.is_const,
54514865 },
54524866 });
5453 if (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)) {
4867 if (try operand_ty.onePossibleValue(pt) != null or
4868 (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)))
4869 {
54544870 iac.ptr = try pt.intern(.{ .ptr = .{
54554871 .ty = alloc_ty.toIntern(),
54564872 .base_addr = .{ .uav = .{
......@@ -5624,7 +5040,7 @@ fn zirCompileLog(
56245040
56255041 const arg = try sema.resolveInst(arg_ref);
56265042 const arg_ty = sema.typeOf(arg);
5627 if (try sema.resolveValueResolveLazy(arg)) |val| {
5043 if (try sema.resolveValue(arg)) |val| {
56285044 writer.print("@as({f}, {f})", .{
56295045 arg_ty.fmt(pt), val.fmtValueSema(pt, sema),
56305046 }) catch return error.OutOfMemory;
......@@ -5928,10 +5344,9 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
59285344 return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
59295345
59305346 try pt.ensureFileAnalyzed(new_file_index);
5931 const ty = zcu.fileRootType(new_file_index);
5932 try sema.declareDependency(.{ .interned = ty });
5347 const ty: Type = .fromInterned(zcu.fileRootType(new_file_index));
59335348 try sema.addTypeReferenceEntry(src, ty);
5934 return Air.internedToRef(ty);
5349 return .fromType(ty);
59355350}
59365351
59375352fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -6177,10 +5592,11 @@ fn resolveAnalyzedBlock(
61775592 // to emit a jump instruction to after the block when it encounters the break.
61785593 try parent_block.instructions.append(gpa, merges.block_inst);
61795594 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items });
5595 resolved_ty.assertHasLayout(zcu);
61805596 // TODO add note "missing else causes void value"
61815597
61825598 const type_src = src; // TODO: better source location
6183 if (try resolved_ty.comptimeOnlySema(pt)) {
5599 if (resolved_ty.comptimeOnly(zcu)) {
61845600 const msg = msg: {
61855601 const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)});
61865602 errdefer msg.destroy(sema.gpa);
......@@ -6274,10 +5690,7 @@ fn resolveAnalyzedBlock(
62745690 });
62755691 }
62765692
6277 if (try sema.typeHasOnePossibleValue(resolved_ty)) |block_only_value| {
6278 return Air.internedToRef(block_only_value.toIntern());
6279 }
6280
5693 if (try resolved_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
62815694 return merges.block_inst.toRef();
62825695}
62835696
......@@ -6413,7 +5826,8 @@ fn zirDisableInstrumentation(sema: *Sema) CompileError!void {
64135826 .@"comptime",
64145827 .nav_val,
64155828 .nav_ty,
6416 .type,
5829 .type_layout,
5830 .type_inits,
64175831 .memoized_state,
64185832 => return, // does nothing outside a function
64195833 };
......@@ -6431,7 +5845,8 @@ fn zirDisableIntrinsics(sema: *Sema) CompileError!void {
64315845 .@"comptime",
64325846 .nav_val,
64335847 .nav_ty,
6434 .type,
5848 .type_layout,
5849 .type_inits,
64355850 .memoized_state,
64365851 => return, // does nothing outside a function
64375852 };
......@@ -6589,8 +6004,8 @@ fn addDbgVar(
65896004 .dbg_var_val, .dbg_arg_inline => operand_ty,
65906005 else => unreachable,
65916006 };
6592 if (try val_ty.comptimeOnlySema(pt)) return;
6593 if (!(try val_ty.hasRuntimeBitsSema(pt))) return;
6007 if (val_ty.comptimeOnly(zcu)) return;
6008 if (!val_ty.hasRuntimeBits(zcu)) return;
65946009 if (try sema.resolveValue(operand)) |operand_val| {
65956010 if (operand_val.canMutateComptimeVarState(zcu)) return;
65966011 }
......@@ -6759,7 +6174,6 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
67596174 if (!block.ownerModule().error_tracing) return .none;
67606175
67616176 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
6762 try stack_trace_ty.resolveFields(pt);
67636177 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
67646178 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
67656179 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
......@@ -6803,7 +6217,6 @@ fn popErrorReturnTrace(
68036217 // the result is comptime-known to be a non-error. Either way, pop unconditionally.
68046218
68056219 const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
6806 try stack_trace_ty.resolveFields(pt);
68076220 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
68086221 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
68096222 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
......@@ -6829,7 +6242,6 @@ fn popErrorReturnTrace(
68296242
68306243 // If non-error, then pop the error return trace by restoring the index.
68316244 const stack_trace_ty = try sema.getBuiltinType(src, .StackTrace);
6832 try stack_trace_ty.resolveFields(pt);
68336245 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
68346246 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
68356247 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
......@@ -6969,7 +6381,6 @@ fn zirCall(
69696381 // need to clean-up our own trace if we were passed to a non-error-handling expression.
69706382 if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) {
69716383 const stack_trace_ty = try sema.getBuiltinType(call_src, .StackTrace);
6972 try stack_trace_ty.resolveFields(pt);
69736384 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls);
69746385 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
69756386
......@@ -7318,6 +6729,8 @@ fn analyzeCall(
73186729 } else func_src;
73196730
73206731 const func_ty_info = zcu.typeToFunc(func_ty).?;
6732 // MLUGG TODO: this isn't quite the check i want. this includes inline functions, which aren't *generic*...
6733 const func_is_generic = !func_ty.fnHasRuntimeBits(zcu);
73216734 if (!callConvIsCallable(func_ty_info.cc)) {
73226735 return sema.failWithOwnedErrorMsg(block, msg: {
73236736 const msg = try sema.errMsg(
......@@ -7353,7 +6766,7 @@ fn analyzeCall(
73536766 else => unreachable,
73546767 } else .{ null, false };
73556768
7356 if (func_ty_info.is_generic and func_val == null) {
6769 if (func_is_generic and func_val == null) {
73576770 return sema.failWithNeededComptime(block, func_src, .{ .simple = .generic_call_target });
73586771 }
73596772
......@@ -7369,19 +6782,18 @@ fn analyzeCall(
73696782 .src = call_src,
73706783 .r = .{ .simple = .comptime_call_modifier },
73716784 } };
7372 } else if (!inline_requested and try Type.fromInterned(func_ty_info.return_type).comptimeOnlySema(pt)) {
7373 block.comptime_reason = .{
7374 .reason = .{
6785 } else if (!inline_requested) {
6786 const ret_ty: Type = .fromInterned(func_ty_info.return_type);
6787 if (ret_ty.comptimeOnly(zcu)) {
6788 block.comptime_reason = .{ .reason = .{
73756789 .src = call_src,
7376 .r = .{
7377 .comptime_only_ret_ty = .{
7378 .ty = .fromInterned(func_ty_info.return_type),
7379 .is_generic_inst = false,
7380 .ret_ty_src = func_ret_ty_src,
7381 },
7382 },
7383 },
7384 };
6790 .r = .{ .comptime_only_ret_ty = .{
6791 .ty = .fromInterned(func_ty_info.return_type),
6792 .is_generic_inst = false,
6793 .ret_ty_src = func_ret_ty_src,
6794 } },
6795 } };
6796 }
73856797 }
73866798 }
73876799
......@@ -7403,13 +6815,13 @@ fn analyzeCall(
74036815 // This is the `inst_map` used when evaluating generic parameters and return types.
74046816 var generic_inst_map: InstMap = .{};
74056817 defer generic_inst_map.deinit(gpa);
7406 if (func_ty_info.is_generic) {
6818 if (func_is_generic) {
74076819 try generic_inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body);
74086820 }
74096821
74106822 // This exists so that `generic_block` below can include a "called from here" note back to this
74116823 // call site when analyzing generic parameter/return types.
7412 var generic_inlining: Block.Inlining = if (func_ty_info.is_generic) .{
6824 var generic_inlining: Block.Inlining = if (func_is_generic) .{
74136825 .call_block = block,
74146826 .call_src = call_src,
74156827 .func = func_val.?.toIntern(),
......@@ -7422,7 +6834,7 @@ fn analyzeCall(
74226834 // This is the block in which we evaluate generic function components: that is, generic parameter
74236835 // types and the generic return type. This must not be used if the function is not generic.
74246836 // `comptime_reason` is set as needed.
7425 var generic_block: Block = if (func_ty_info.is_generic) .{
6837 var generic_block: Block = if (func_is_generic) .{
74266838 .parent = null,
74276839 .sema = sema,
74286840 .namespace = fn_nav.analysis.?.namespace,
......@@ -7431,9 +6843,9 @@ fn analyzeCall(
74316843 .src_base_inst = fn_nav.analysis.?.zir_index,
74326844 .type_name_ctx = fn_nav.fqn,
74336845 } else undefined;
7434 defer if (func_ty_info.is_generic) generic_block.instructions.deinit(gpa);
6846 defer if (func_is_generic) generic_block.instructions.deinit(gpa);
74356847
7436 if (func_ty_info.is_generic) {
6848 if (func_is_generic) {
74376849 // We certainly depend on the generic owner's signature!
74386850 try sema.declareDependency(.{ .src_hash = fn_tracked_inst });
74396851 }
......@@ -7445,7 +6857,7 @@ fn analyzeCall(
74456857 if (raw != .generic_poison_type) break :ty .fromInterned(raw);
74466858
74476859 // We must discover the generic parameter type.
7448 assert(func_ty_info.is_generic);
6860 assert(func_is_generic);
74496861 const param_inst_idx = fn_zir_info.param_body[arg_idx];
74506862 const param_inst = fn_zir.instructions.get(@intFromEnum(param_inst_idx));
74516863 switch (param_inst.tag) {
......@@ -7494,11 +6906,11 @@ fn analyzeCall(
74946906 return arg.*; // terminate analysis here
74956907 }
74966908
7497 if (func_ty_info.is_generic) {
6909 if (func_is_generic) {
74986910 // We need to put the argument into `generic_inst_map` so that other parameters can refer to it.
74996911 const param_inst_idx = fn_zir_info.param_body[arg_idx];
75006912 const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false;
7501 const param_is_comptime = declared_comptime or try arg_ty.comptimeOnlySema(pt);
6913 const param_is_comptime = declared_comptime or arg_ty.comptimeOnly(zcu);
75026914 // We allow comptime-known arguments to propagate to generic types not only for comptime
75036915 // parameters, but if the call is known to be inline.
75046916 if (param_is_comptime or early_known_inline) {
......@@ -7516,6 +6928,10 @@ fn analyzeCall(
75166928 );
75176929 }
75186930 generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, arg.*);
6931 } else if (try arg_ty.onePossibleValue(pt)) |opv| {
6932 // The argument is comptime-known, even though this is a generic instantiation (as
6933 // opposed to an inline call), because the parameter type is OPV.
6934 generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, .fromValue(opv));
75196935 } else {
75206936 // We need a dummy instruction with this type. It doesn't actually need to be in any block,
75216937 // since it will never be referenced at runtime!
......@@ -7532,7 +6948,7 @@ fn analyzeCall(
75326948 // calls (where it should be the IES of the instantiation). However, it's how we print this
75336949 // in error messages.
75346950 const resolved_ret_ty: Type = ret_ty: {
7535 if (!func_ty_info.is_generic) break :ret_ty .fromInterned(func_ty_info.return_type);
6951 if (!func_is_generic) break :ret_ty .fromInterned(func_ty_info.return_type);
75366952
75376953 const maybe_poison_bare = if (fn_zir_info.inferred_error_set) maybe_poison: {
75386954 break :maybe_poison ip.errorUnionPayload(func_ty_info.return_type);
......@@ -7542,7 +6958,7 @@ fn analyzeCall(
75426958
75436959 // Evaluate the generic return type. As with generic parameters, we switch out `sema.code` and `sema.inst_map`.
75446960
7545 assert(func_ty_info.is_generic);
6961 assert(func_is_generic);
75466962
75476963 const old_code = sema.code;
75486964 const old_inst_map = sema.inst_map;
......@@ -7584,10 +7000,11 @@ fn analyzeCall(
75847000
75857001 break :ret_ty full_ty;
75867002 };
7003 try sema.ensureLayoutResolved(resolved_ret_ty);
75877004
75887005 // If we've discovered after evaluating arguments that a generic function instantiation is
75897006 // comptime-only, then we can mark the block as comptime *now*.
7590 if (!inline_requested and !block.isComptime() and try resolved_ret_ty.comptimeOnlySema(pt)) {
7007 if (!inline_requested and !block.isComptime() and resolved_ret_ty.comptimeOnly(zcu)) {
75917008 block.comptime_reason = .{
75927009 .reason = .{
75937010 .src = call_src,
......@@ -7618,7 +7035,7 @@ fn analyzeCall(
76187035 });
76197036 if (func_ty_info.cc == .auto) {
76207037 switch (sema.owner.unwrap()) {
7621 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
7038 .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {},
76227039 .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true),
76237040 }
76247041 }
......@@ -7626,7 +7043,7 @@ fn analyzeCall(
76267043 try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg);
76277044 }
76287045 const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: {
7629 if (!func_ty_info.is_generic) break :func .{ callee, args };
7046 if (!func_is_generic) break :func .{ callee, args };
76307047
76317048 // Instantiate the generic function!
76327049
......@@ -7648,7 +7065,7 @@ fn analyzeCall(
76487065 break :c true;
76497066 }
76507067 }
7651 break :c try arg_ty.comptimeOnlySema(pt);
7068 break :c arg_ty.comptimeOnly(zcu);
76527069 };
76537070 const is_noalias = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsNoalias(i) else false;
76547071
......@@ -7680,6 +7097,7 @@ fn analyzeCall(
76807097 .generic_owner = func_val.?.toIntern(),
76817098 .comptime_args = comptime_args,
76827099 });
7100 try sema.ensureLayoutResolved(.fromInterned(ip.typeOf(func_instance)));
76837101 if (zcu.comp.debugIncremental()) {
76847102 const nav = ip.indexToKey(func_instance).func.owner_nav;
76857103 const gop = try zcu.incremental_debug_state.navs.getOrPut(gpa, nav);
......@@ -7753,12 +7171,12 @@ fn analyzeCall(
77537171 return .unreachable_value;
77547172 }
77557173
7756 const result: Air.Inst.Ref = if (try sema.typeHasOnePossibleValue(sema.typeOf(maybe_opv))) |opv|
7757 .fromValue(opv)
7758 else
7759 maybe_opv;
7760
7761 return result;
7174 try sema.ensureLayoutResolved(sema.typeOf(maybe_opv));
7175 if (try sema.typeOf(maybe_opv).onePossibleValue(pt)) |opv| {
7176 return .fromValue(opv);
7177 } else {
7178 return maybe_opv;
7179 }
77627180 }
77637181
77647182 // This is an inline call. The function must be comptime-known. We will analyze its body directly using this `Sema`.
......@@ -7824,6 +7242,11 @@ fn analyzeCall(
78247242 }
78257243 }
78267244
7245 // We're about to do an inline call; if the return type expression was generic, the return type
7246 // may not be resolved yet. It's correct to resolve it because the function is going to return a
7247 // value of this type.
7248 try sema.ensureLayoutResolved(resolved_ret_ty);
7249
78277250 // For an inline call, we depend on the source code of the whole function definition.
78287251 try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index });
78297252
......@@ -8000,6 +7423,10 @@ fn analyzeCall(
80007423 break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope);
80017424 };
80027425
7426 if (sema.typeOf(result_raw).isNoReturn(zcu)) {
7427 return .unreachable_value;
7428 }
7429
80037430 const maybe_opv: Air.Inst.Ref = if (try sema.resolveValue(result_raw)) |result_val| r: {
80047431 const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern());
80057432 break :r Air.internedToRef(val_resolved);
......@@ -8080,16 +7507,16 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
80807507 const zcu = pt.zcu;
80817508 const bin = sema.code.instructions.items(.data)[@intFromEnum(inst)].bin;
80827509 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type;
7510 try sema.ensureLayoutResolved(maybe_wrapped_indexable_ty);
80837511 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu);
8084 try indexable_ty.resolveFields(pt);
80857512 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction
8086 if (indexable_ty.zigTypeTag(zcu) == .@"struct") {
8087 const elem_type = indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu);
8088 return Air.internedToRef(elem_type.toIntern());
8089 } else {
8090 const elem_type = indexable_ty.elemType2(zcu);
8091 return Air.internedToRef(elem_type.toIntern());
8092 }
7513 const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) {
7514 .@"struct" => indexable_ty.fieldType(@intFromEnum(bin.rhs), zcu),
7515 .array, .vector => indexable_ty.childType(zcu),
7516 .pointer => indexable_ty.indexablePtrElem(zcu),
7517 else => unreachable,
7518 };
7519 return .fromType(elem_ty);
80937520}
80947521
80957522fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -8355,7 +7782,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
83557782 const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src);
83567783
83577784 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8358 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));
7785 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(zcu));
83597786 if (int > len: {
83607787 const mutate = &ip.global_error_set.mutate;
83617788 mutate.map.mutex.lockUncancelable(io);
......@@ -8539,7 +7966,6 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
85397966 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) {
85407967 .@"enum" => operand,
85417968 .@"union" => blk: {
8542 try operand_ty.resolveFields(pt);
85437969 const tag_ty = operand_ty.unionTagType(zcu) orelse {
85447970 return sema.fail(
85457971 block,
......@@ -8568,17 +7994,9 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
85687994 });
85697995 }
85707996
8571 if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {
8572 return Air.internedToRef((try pt.getCoerced(opv, int_tag_ty)).toIntern());
8573 }
8574
85757997 if (try sema.resolveValue(enum_tag)) |enum_tag_val| {
8576 if (enum_tag_val.isUndef(zcu)) {
8577 return pt.undefRef(int_tag_ty);
8578 }
8579
8580 const val = try enum_tag_val.intFromEnum(enum_tag_ty, pt);
8581 return Air.internedToRef(val.toIntern());
7998 if (enum_tag_val.isUndef(zcu)) return pt.undefRef(int_tag_ty);
7999 return .fromValue(enum_tag_val.intFromEnum(zcu));
85828000 }
85838001
85848002 try sema.requireRuntimeBlock(block, src, operand_src);
......@@ -8626,19 +8044,15 @@ fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
86268044 return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_enum });
86278045 }
86288046
8629 if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| {
8047 if (try dest_ty.onePossibleValue(pt)) |opv| {
86308048 if (block.wantSafety()) {
86318049 // The operand is runtime-known but the result is comptime-known. In
86328050 // this case we still need a safety check.
8633 const expect_int_val = switch (zcu.intern_pool.indexToKey(opv.toIntern())) {
8634 .enum_tag => |enum_tag| enum_tag.int,
8635 else => unreachable,
8636 };
8637 const expect_int_coerced = try pt.getCoerced(.fromInterned(expect_int_val), operand_ty);
8638 const ok = try block.addBinOp(.cmp_eq, operand, Air.internedToRef(expect_int_coerced.toIntern()));
8051 const expect_int = try pt.getCoerced(opv.intFromEnum(zcu), operand_ty);
8052 const ok = try block.addBinOp(.cmp_eq, operand, .fromValue(expect_int));
86398053 try sema.addSafetyCheck(block, src, ok, .invalid_enum_value);
86408054 }
8641 return Air.internedToRef(opv.toIntern());
8055 return .fromValue(opv);
86428056 }
86438057
86448058 try sema.requireRuntimeBlock(block, src, operand_src);
......@@ -8666,6 +8080,7 @@ fn zirOptionalPayloadPtr(
86668080 return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false);
86678081}
86688082
8083/// MLUGG TODO: pre-resolved child?
86698084fn analyzeOptionalPayloadPtr(
86708085 sema: *Sema,
86718086 block: *Block,
......@@ -8685,7 +8100,8 @@ fn analyzeOptionalPayloadPtr(
86858100 }
86868101
86878102 const child_type = opt_type.optionalChild(zcu);
8688 const child_pointer = try pt.ptrTypeSema(.{
8103 try sema.ensureLayoutResolved(child_type);
8104 const child_pointer = try pt.ptrType(.{
86898105 .child = child_type.toIntern(),
86908106 .flags = .{
86918107 .is_const = optional_ptr_ty.isConstPtr(zcu),
......@@ -8698,7 +8114,7 @@ fn analyzeOptionalPayloadPtr(
86988114 if (sema.isComptimeMutablePtr(ptr_val)) {
86998115 // Set the optional to non-null at comptime.
87008116 // If the payload is OPV, we must use that value instead of undef.
8701 const payload_val = try sema.typeHasOnePossibleValue(child_type) orelse try pt.undefValue(child_type);
8117 const payload_val = try child_type.onePossibleValue(pt) orelse try pt.undefValue(child_type);
87028118 const opt_val = try pt.intern(.{ .opt = .{
87038119 .ty = opt_type.toIntern(),
87048120 .val = payload_val.toIntern(),
......@@ -8759,7 +8175,7 @@ fn zirOptionalPayload(
87598175 // TODO https://github.com/ziglang/zig/issues/6597
87608176 if (true) break :t operand_ty;
87618177 const ptr_info = operand_ty.ptrInfo(zcu);
8762 break :t try pt.ptrTypeSema(.{
8178 break :t try pt.ptrType(.{
87638179 .child = ptr_info.child,
87648180 .flags = .{
87658181 .alignment = ptr_info.flags.alignment,
......@@ -8784,11 +8200,14 @@ fn zirOptionalPayload(
87848200 return .unreachable_value;
87858201 }
87868202
8787 try sema.requireRuntimeBlock(block, src, null);
87888203 if (safety_check and block.wantSafety()) {
87898204 const is_non_null = try block.addUnOp(.is_non_null, operand);
87908205 try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null);
87918206 }
8207
8208 // If the payload is OPV, we need the safety check but have a comptime-known result.
8209 if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
8210
87928211 return block.addTyOp(.optional_payload, result_ty, operand);
87938212}
87948213
......@@ -8844,8 +8263,8 @@ fn analyzeErrUnionPayload(
88448263 try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err);
88458264 }
88468265
8847 if (try sema.typeHasOnePossibleValue(payload_ty)) |payload_only_value| {
8848 return Air.internedToRef(payload_only_value.toIntern());
8266 if (try payload_ty.onePossibleValue(pt)) |payload_opv| {
8267 return .fromValue(payload_opv);
88498268 }
88508269
88518270 return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand);
......@@ -8867,6 +8286,7 @@ fn zirErrUnionPayloadPtr(
88678286 return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
88688287}
88698288
8289/// MLUGG TODO LAYOUT: already-resolved child?
88708290fn analyzeErrUnionPayloadPtr(
88718291 sema: *Sema,
88728292 block: *Block,
......@@ -8888,7 +8308,8 @@ fn analyzeErrUnionPayloadPtr(
88888308
88898309 const err_union_ty = operand_ty.childType(zcu);
88908310 const payload_ty = err_union_ty.errorUnionPayload(zcu);
8891 const operand_pointer_ty = try pt.ptrTypeSema(.{
8311 try sema.ensureLayoutResolved(payload_ty);
8312 const operand_pointer_ty = try pt.ptrType(.{
88928313 .child = payload_ty.toIntern(),
88938314 .flags = .{
88948315 .is_const = operand_ty.isConstPtr(zcu),
......@@ -8901,7 +8322,7 @@ fn analyzeErrUnionPayloadPtr(
89018322 if (sema.isComptimeMutablePtr(ptr_val)) {
89028323 // Set the error union to non-error at comptime.
89038324 // If the payload is OPV, we must use that value instead of undef.
8904 const payload_val = try sema.typeHasOnePossibleValue(payload_ty) orelse try pt.undefValue(payload_ty);
8325 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty);
89058326 const eu_val = try pt.intern(.{ .error_union = .{
89068327 .ty = err_union_ty.toIntern(),
89078328 .val = .{ .payload = payload_val.toIntern() },
......@@ -9571,10 +8992,6 @@ fn funcCommon(
95718992
95728993 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset });
95738994 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset });
9574 const func_src = block.nodeOffset(src_node_offset);
9575
9576 const ret_ty_requires_comptime = try bare_return_type.comptimeOnlySema(pt);
9577 var is_generic = bare_return_type.isGenericPoison() or ret_ty_requires_comptime;
95788995
95798996 var comptime_bits: u32 = 0;
95808997 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| {
......@@ -9587,11 +9004,7 @@ fn funcCommon(
95879004 .fn_proto_node_offset = src_node_offset,
95889005 .param_index = @intCast(i),
95899006 } });
9590 const param_ty_comptime = try param_ty.comptimeOnlySema(pt);
95919007 const param_ty_generic = param_ty.isGenericPoison();
9592 if (param_is_comptime or param_ty_comptime or param_ty_generic) {
9593 is_generic = true;
9594 }
95959008 if (param_is_comptime) {
95969009 comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error
95979010 }
......@@ -9609,24 +9022,6 @@ fn funcCommon(
96099022 param_src,
96109023 cc,
96119024 );
9612 if (param_ty_comptime and !param_is_comptime and has_body and !block.isComptime()) {
9613 const msg = msg: {
9614 const msg = try sema.errMsg(param_src, "parameter of type '{f}' must be declared comptime", .{
9615 param_ty.fmt(pt),
9616 });
9617 errdefer msg.destroy(sema.gpa);
9618
9619 try sema.explainWhyTypeIsComptime(msg, param_src, param_ty);
9620
9621 try sema.addDeclaredHereNote(msg, param_ty);
9622 break :msg msg;
9623 };
9624 return sema.failWithOwnedErrorMsg(block, msg);
9625 }
9626 }
9627
9628 if (var_args and is_generic) {
9629 return sema.fail(block, func_src, "generic function cannot be variadic", .{});
96309025 }
96319026
96329027 try sema.checkReturnTypeAndCallConvCommon(
......@@ -9643,46 +9038,6 @@ fn funcCommon(
96439038 is_noinline,
96449039 );
96459040
9646 // If the return type is comptime-only but not dependent on parameters then
9647 // all parameter types also need to be comptime.
9648 if (has_body and ret_ty_requires_comptime and !block.isComptime()) comptime_check: {
9649 for (block.params.items(.is_comptime)) |is_comptime| {
9650 if (!is_comptime) break;
9651 } else break :comptime_check;
9652 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else "";
9653 const msg = try sema.errMsg(
9654 ret_ty_src,
9655 "function with comptime-only return type '{s}{f}' requires all parameters to be comptime",
9656 .{ ies_ret_ty_prefix, bare_return_type.fmt(pt) },
9657 );
9658 errdefer msg.destroy(sema.gpa);
9659 try sema.explainWhyTypeIsComptime(msg, ret_ty_src, bare_return_type);
9660
9661 const tags = sema.code.instructions.items(.tag);
9662 const data = sema.code.instructions.items(.data);
9663 const param_body = sema.code.getParamBody(func_inst);
9664 for (
9665 block.params.items(.is_comptime),
9666 block.params.items(.name),
9667 param_body[0..block.params.len],
9668 ) |is_comptime, name_nts, param_index| {
9669 if (!is_comptime) {
9670 const param_src = block.tokenOffset(switch (tags[@intFromEnum(param_index)]) {
9671 .param => data[@intFromEnum(param_index)].pl_tok.src_tok,
9672 .param_anytype => data[@intFromEnum(param_index)].str_tok.src_tok,
9673 else => unreachable,
9674 });
9675 const name = sema.code.nullTerminatedString(name_nts);
9676 if (name.len != 0) {
9677 try sema.errNote(param_src, msg, "param '{s}' is required to be comptime", .{name});
9678 } else {
9679 try sema.errNote(param_src, msg, "param is required to be comptime", .{});
9680 }
9681 }
9682 }
9683 return sema.failWithOwnedErrorMsg(block, msg);
9684 }
9685
96869041 const param_types = block.params.items(.ty);
96879042
96889043 if (inferred_error_set) {
......@@ -9696,7 +9051,6 @@ fn funcCommon(
96969051 .bare_return_type = bare_return_type.toIntern(),
96979052 .cc = cc,
96989053 .is_var_args = var_args,
9699 .is_generic = is_generic,
97009054 .is_noinline = is_noinline,
97019055
97029056 .zir_body_inst = try block.trackZir(func_inst),
......@@ -9714,7 +9068,6 @@ fn funcCommon(
97149068 .return_type = bare_return_type.toIntern(),
97159069 .cc = cc,
97169070 .is_var_args = var_args,
9717 .is_generic = is_generic,
97189071 .is_noinline = is_noinline,
97199072 });
97209073
......@@ -9845,16 +9198,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
98459198 if (!ptr_ty.isPtrAtRuntime(zcu)) {
98469199 return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)});
98479200 }
9848 const pointee_ty = ptr_ty.childType(zcu);
9849 if (try ptr_ty.comptimeOnlySema(pt)) {
9850 const msg = msg: {
9851 const msg = try sema.errMsg(ptr_src, "comptime-only type '{f}' has no pointer address", .{pointee_ty.fmt(pt)});
9852 errdefer msg.destroy(sema.gpa);
9853 try sema.explainWhyTypeIsComptime(msg, ptr_src, pointee_ty);
9854 break :msg msg;
9855 };
9856 return sema.failWithOwnedErrorMsg(block, msg);
9857 }
9201
98589202 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined;
98599203 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize;
98609204
......@@ -9863,7 +9207,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
98639207 if (operand_val.isUndef(zcu)) {
98649208 return .undef_usize;
98659209 }
9866 const addr = try operand_val.getUnsignedIntSema(pt) orelse {
9210 const addr = operand_val.getUnsignedInt(zcu) orelse {
98679211 // Wasn't an integer pointer. This is a runtime operation.
98689212 break :ct;
98699213 };
......@@ -9879,7 +9223,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
98799223 new_elem.* = .undef_usize;
98809224 continue;
98819225 }
9882 const addr = try ptr_val.getUnsignedIntSema(pt) orelse {
9226 const addr = ptr_val.getUnsignedInt(zcu) orelse {
98839227 // A vector element wasn't an integer pointer. This is a runtime operation.
98849228 break :ct;
98859229 };
......@@ -10044,7 +9388,7 @@ fn intCast(
100449388 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src);
100459389 const is_vector = dest_ty.zigTypeTag(zcu) == .vector;
100469390
10047 if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| {
9391 if (try dest_ty.onePossibleValue(pt)) |opv| {
100489392 // requirement: intCast(u0, input) iff input == 0
100499393 if (block.wantSafety()) {
100509394 try sema.requireRuntimeBlock(block, src, operand_src);
......@@ -10382,6 +9726,8 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
103829726 };
103839727 return sema.failWithOwnedErrorMsg(block, msg);
103849728 }
9729 try sema.checkIndexable(block, src, indexable_ty);
9730 try sema.ensureLayoutResolved(indexable_ty.childType(zcu));
103859731 return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false);
103869732}
103879733
......@@ -10764,7 +10110,8 @@ fn analyzeSwitchBlock(
1076410110 .{ raw_operand, .none };
1076510111
1076610112 const operand_ty = sema.typeOf(val);
10767 const maybe_operand_opv = try sema.typeHasOnePossibleValue(operand_ty);
10113 operand_ty.assertHasLayout(zcu);
10114 const maybe_operand_opv = try operand_ty.onePossibleValue(pt);
1076810115 const init_cond: Air.Inst.Ref, const item_ty: Type = switch (operand_ty.zigTypeTag(zcu)) {
1076910116 .@"union" => tag: {
1077010117 const tag_ty = operand_ty.unionTagType(zcu).?;
......@@ -10776,6 +10123,7 @@ fn analyzeSwitchBlock(
1077610123 operand_ty,
1077710124 },
1077810125 };
10126 item_ty.assertHasLayout(zcu);
1077910127
1078010128 if (zir_switch.has_continue and !block.isComptime()) {
1078110129 const operand_alloc: Air.Inst.Ref = if (zir_switch.any_maybe_runtime_capture and
......@@ -10881,7 +10229,7 @@ fn analyzeSwitchBlock(
1088110229 unreachable;
1088210230 }
1088310231
10884 if (try sema.typeHasOnePossibleValue(item_ty)) |item_opv| {
10232 if (try item_ty.onePossibleValue(pt)) |item_opv| {
1088510233 // We simplify conditions with OPV to either a `loop` or a `block` since
1088610234 // we cannot switch on a value which doesn't exist at runtime.
1088710235 assert(operand == .loop); // `simple` should have already been comptime-resolved above!
......@@ -11249,8 +10597,8 @@ fn finishSwitchBr(
1124910597 var item = sema.resolveConstDefinedValue(block, .unneeded, range_ref[0], undefined) catch unreachable;
1125010598 const item_last = sema.resolveConstDefinedValue(block, .unneeded, range_ref[1], undefined) catch unreachable;
1125110599
11252 if (try item.getUnsignedIntSema(pt)) |first_int| {
11253 if (try item_last.getUnsignedIntSema(pt)) |last_int| {
10600 if (item.getUnsignedInt(zcu)) |first_int| {
10601 if (item_last.getUnsignedInt(zcu)) |last_int| {
1125410602 if (std.math.cast(u32, last_int - first_int)) |range_len| {
1125510603 try branch_hints.ensureUnusedCapacity(gpa, range_len);
1125610604 }
......@@ -11259,7 +10607,6 @@ fn finishSwitchBr(
1125910607
1126010608 var prev_result_overflowed = false;
1126110609 while (item.compareScalar(.lte, item_last, operand_ty, zcu)) : ({
11262 // Previous validation has resolved any possible lazy values.
1126310610 const int_val: Value, const int_ty: Type = switch (operand_ty.zigTypeTag(zcu)) {
1126410611 .int => .{ item, operand_ty },
1126510612 .@"enum" => b: {
......@@ -11896,72 +11243,68 @@ fn validateSwitchBlock(
1189611243 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{tag_capture_inst});
1189711244 }
1189811245
11899 const operand_ty: Type, const item_ty: Type = check_operand: {
11900 const operand_ty = operand_ty: {
11901 const raw_operand_ty = sema.typeOf(raw_operand);
11902 if (operand_is_ref) {
11903 try sema.checkPtrType(block, operand_src, raw_operand_ty, false);
11904 break :operand_ty raw_operand_ty.childType(zcu);
11905 }
11906 break :operand_ty raw_operand_ty;
11907 };
11908
11909 const item_ty: Type = item_ty: {
11910 switch (operand_ty.zigTypeTag(zcu)) {
11911 .@"enum",
11912 .error_set,
11913 .int,
11914 .comptime_int,
11915 .type,
11916 .enum_literal,
11917 .@"fn",
11918 .bool,
11919 .void,
11920 => break :item_ty operand_ty,
11246 const operand_ty = operand_ty: {
11247 const raw_operand_ty = sema.typeOf(raw_operand);
11248 if (operand_is_ref) {
11249 try sema.checkPtrType(block, operand_src, raw_operand_ty, false);
11250 break :operand_ty raw_operand_ty.childType(zcu);
11251 }
11252 break :operand_ty raw_operand_ty;
11253 };
11254 try sema.ensureLayoutResolved(operand_ty);
1192111255
11922 .@"union" => {
11923 try operand_ty.resolveFields(pt);
11924 const enum_ty = operand_ty.unionTagType(zcu) orelse {
11925 return sema.failWithOwnedErrorMsg(block, msg: {
11926 const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{});
11927 errdefer msg.destroy(sema.gpa);
11928 if (operand_ty.srcLocOrNull(zcu)) |union_src| {
11929 try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{});
11930 }
11931 break :msg msg;
11932 });
11933 };
11934 break :item_ty enum_ty;
11935 },
11256 const item_ty: Type = item_ty: {
11257 switch (operand_ty.zigTypeTag(zcu)) {
11258 .@"enum",
11259 .error_set,
11260 .int,
11261 .comptime_int,
11262 .type,
11263 .enum_literal,
11264 .@"fn",
11265 .bool,
11266 .void,
11267 => break :item_ty operand_ty,
1193611268
11937 .pointer => {
11938 if (!operand_ty.isSlice(zcu)) {
11939 break :item_ty operand_ty;
11940 }
11941 },
11269 .@"union" => {
11270 const enum_ty = operand_ty.unionTagType(zcu) orelse {
11271 return sema.failWithOwnedErrorMsg(block, msg: {
11272 const msg = try sema.errMsg(operand_src, "switch on union with no attached enum", .{});
11273 errdefer msg.destroy(sema.gpa);
11274 if (operand_ty.srcLocOrNull(zcu)) |union_src| {
11275 try sema.errNote(union_src, msg, "consider 'union(enum)' here", .{});
11276 }
11277 break :msg msg;
11278 });
11279 };
11280 break :item_ty enum_ty;
11281 },
1194211282
11943 else => {},
11944 }
11945 return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
11946 };
11283 .pointer => {
11284 if (!operand_ty.isSlice(zcu)) {
11285 break :item_ty operand_ty;
11286 }
11287 },
1194711288
11948 if (zir_switch.has_continue and !block.isComptime()) {
11949 if (try operand_ty.comptimeOnlySema(pt)) {
11950 // Even if the operand is comptime-known, this `switch` is runtime.
11951 return sema.failWithOwnedErrorMsg(block, msg: {
11952 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)});
11953 errdefer msg.destroy(gpa);
11954 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
11955 try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty);
11956 break :msg msg;
11957 });
11958 }
11959 try sema.validateRuntimeValue(block, operand_src, raw_operand);
11289 else => {},
1196011290 }
11961
11962 break :check_operand .{ operand_ty, item_ty };
11291 return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)});
1196311292 };
1196411293
11294 if (zir_switch.has_continue and !block.isComptime()) {
11295 if (operand_ty.comptimeOnly(zcu)) {
11296 // Even if the operand is comptime-known, this `switch` is runtime.
11297 return sema.failWithOwnedErrorMsg(block, msg: {
11298 const msg = try sema.errMsg(operand_src, "operand of switch loop has comptime-only type '{f}'", .{operand_ty.fmt(pt)});
11299 errdefer msg.destroy(gpa);
11300 try sema.errNote(operand_src, msg, "switch loops are evaluated at runtime outside of comptime scopes", .{});
11301 try sema.explainWhyTypeIsComptime(msg, operand_src, operand_ty);
11302 break :msg msg;
11303 });
11304 }
11305 try sema.validateRuntimeValue(block, operand_src, raw_operand);
11306 }
11307
1196511308 const has_else = zir_switch.else_case != null;
1196611309 const has_under = zir_switch.has_under;
1196711310
......@@ -12305,7 +11648,7 @@ fn resolveSwitchBlock(
1230511648 child_block: *Block,
1230611649 operand: SwitchOperand,
1230711650 raw_operand_ty: Type,
12308 maybe_lazy_cond_val: Value,
11651 cond_val: Value,
1230911652 merges: *Block.Merges,
1231011653 switch_inst: Zir.Inst.Index,
1231111654 zir_switch: *const Zir.UnwrappedSwitchBlock,
......@@ -12325,9 +11668,6 @@ fn resolveSwitchBlock(
1232511668 const err_set = item_ty.zigTypeTag(zcu) == .error_set;
1232611669
1232711670 const cond_ref = operand.simple.cond;
12328 // We have to resolve lazy values to ensure that comparisons with switch
12329 // prong items don't produce false negatives.
12330 const cond_val = try sema.resolveLazyValue(maybe_lazy_cond_val);
1233111671
1233211672 const case_vals = validated_switch.case_vals;
1233311673 var case_val_idx: usize = 0;
......@@ -12617,14 +11957,12 @@ fn wantSwitchProngBodyAnalysis(
1261711957) bool {
1261811958 const zcu = sema.pt.zcu;
1261911959 if (union_originally) {
12620 const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable;
12621 const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable;
11960 const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable;
1262211961 const field_ty = operand_ty.unionFieldType(item_val, zcu).?;
1262311962 if (field_ty.isNoReturn(zcu)) return false;
1262411963 }
1262511964 if (err_set and prong_is_comptime_unreach) {
12626 const unresolved_item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable;
12627 const item_val = sema.resolveLazyValue(unresolved_item_val) catch unreachable;
11965 const item_val = sema.resolveConstDefinedValue(block, .unneeded, item_ref, undefined) catch unreachable;
1262811966 const err_name = item_val.getErrorName(zcu).unwrap().?;
1262911967 if (!Type.errorSetHasFieldIp(&zcu.intern_pool, operand_ty.toIntern(), err_name)) return false;
1263011968 }
......@@ -12807,7 +12145,7 @@ fn analyzeSwitchPayloadCapture(
1280712145 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
1280812146 if (capture_by_ref) {
1280912147 const operand_ptr_info = sema.typeOf(operand_ptr).ptrInfo(zcu);
12810 const ptr_field_ty = try pt.ptrTypeSema(.{
12148 const ptr_field_ty = try pt.ptrType(.{
1281112149 .child = field_ty.toIntern(),
1281212150 .flags = .{
1281312151 .is_const = operand_ptr_info.flags.is_const,
......@@ -12821,6 +12159,7 @@ fn analyzeSwitchPayloadCapture(
1282112159 const tag_and_val = ip.indexToKey(union_val.toIntern()).un;
1282212160 return .fromIntern(tag_and_val.val);
1282312161 }
12162 if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
1282412163 return case_block.addStructFieldVal(operand_val, field_index, field_ty);
1282512164 }
1282612165 } else if (capture_by_ref) {
......@@ -12914,13 +12253,27 @@ fn analyzeSwitchPayloadCapture(
1291412253 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len);
1291512254 for (field_indices, dummy_captures) |field_idx, *dummy| {
1291612255 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
12917 const field_ptr_ty = try pt.ptrTypeSema(.{
12256 const field_ptr_ty = try pt.ptrType(.{
1291812257 .child = field_ty.toIntern(),
1291912258 .flags = .{
1292012259 .is_const = operand_ptr_info.flags.is_const,
1292112260 .is_volatile = operand_ptr_info.flags.is_volatile,
1292212261 .address_space = operand_ptr_info.flags.address_space,
12923 .alignment = union_obj.fieldAlign(ip, field_idx),
12262 // TODO MLUGG: double-check this. and, um, EVERYWHERE we do ptr alignment...
12263 .alignment = a: {
12264 if (operand_ty.explicitFieldAlignment(field_idx, zcu) == .none and
12265 operand_ptr_info.flags.alignment == .none)
12266 {
12267 break :a .none;
12268 }
12269
12270 const union_align = switch (operand_ptr_info.flags.alignment) {
12271 .none => operand_ty.abiAlignment(zcu),
12272 else => |a| a,
12273 };
12274 const field_align = operand_ty.resolvedFieldAlignment(field_idx, zcu);
12275 break :a .minStrict(union_align, field_align);
12276 },
1292412277 },
1292512278 });
1292612279 dummy.* = try pt.undefRef(field_ptr_ty);
......@@ -12963,6 +12316,8 @@ fn analyzeSwitchPayloadCapture(
1296312316 return case_block.addStructFieldPtr(operand_ptr, first_field_index, capture_ptr_ty);
1296412317 }
1296512318
12319 if (try capture_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
12320
1296612321 if (try sema.resolveDefinedValue(case_block, operand_src, operand_val)) |operand_val_val| {
1296712322 if (operand_val_val.isUndef(zcu)) return pt.undefRef(capture_ty);
1296812323 const union_val = ip.indexToKey(operand_val_val.toIntern()).un;
......@@ -13119,7 +12474,7 @@ fn analyzeSwitchPayloadCapture(
1311912474 try sema.air_instructions.append(sema.gpa, .{
1312012475 .tag = .get_union_tag,
1312112476 .data = .{ .ty_op = .{
13122 .ty = .fromIntern(union_obj.enum_tag_ty),
12477 .ty = .fromIntern(union_obj.enum_tag_type),
1312312478 .operand = operand_val,
1312412479 } },
1312512480 });
......@@ -13261,17 +12616,8 @@ fn resolveSwitchItem(
1326112616 }
1326212617 break :item_ref try sema.coerce(block, item_ty, uncoerced, item_src);
1326312618 };
13264 const maybe_lazy = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item });
13265
13266 // We have to resolve lazy values here to avoid false negatives when detecting
13267 // duplicate items and comparing items to a comptime-known switch operand.
13268
13269 const val = try sema.resolveLazyValue(maybe_lazy);
13270 const ref: Air.Inst.Ref = if (val.toIntern() == maybe_lazy.toIntern())
13271 item_ref
13272 else
13273 .fromValue(val);
13274 return .{ .{ .ref = ref, .val = val }, end };
12619 const val = try sema.resolveConstDefinedValue(block, item_src, item_ref, .{ .simple = .switch_item });
12620 return .{ .{ .ref = item_ref, .val = val }, end };
1327512621}
1327612622
1327712623fn validateSwitchItemOrRange(
......@@ -13488,7 +12834,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1348812834 const name_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1348912835 const ty = try sema.resolveType(block, ty_src, extra.lhs);
1349012836 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{ .simple = .field_name });
13491 try ty.resolveFields(pt);
12837 try sema.ensureLayoutResolved(ty);
1349212838 const ip = &zcu.intern_pool;
1349312839
1349412840 const has_field = hf: {
......@@ -13510,7 +12856,8 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1351012856 },
1351112857 .union_type => {
1351212858 const union_type = ip.loadUnionType(ty.toIntern());
13513 break :hf union_type.loadTagType(ip).nameIndex(ip, field_name) != null;
12859 const enum_type = ip.loadEnumType(union_type.enum_tag_type);
12860 break :hf enum_type.nameIndex(ip, field_name) != null;
1351412861 },
1351512862 .enum_type => {
1351612863 break :hf ip.loadEnumType(ty.toIntern()).nameIndex(ip, field_name) != null;
......@@ -13569,10 +12916,9 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1356912916 switch (file.getMode()) {
1357012917 .zig => {
1357112918 try pt.ensureFileAnalyzed(file_index);
13572 const ty = zcu.fileRootType(file_index);
13573 try sema.declareDependency(.{ .interned = ty });
12919 const ty: Type = .fromInterned(zcu.fileRootType(file_index));
1357412920 try sema.addTypeReferenceEntry(operand_src, ty);
13575 return Air.internedToRef(ty);
12921 return .fromType(ty);
1357612922 },
1357712923 .zon => {
1357812924 const res_ty: InternPool.Index = b: {
......@@ -13692,8 +13038,8 @@ fn zirShl(
1369213038 // we already know `scalar_rhs_ty` is valid for `.shl` -- we only need to validate for `.shl_sat`.
1369313039 if (air_tag == .shl_sat) _ = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);
1369413040
13695 const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs);
13696 const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs);
13041 const maybe_lhs_val = try sema.resolveValue(lhs);
13042 const maybe_rhs_val = try sema.resolveValue(rhs);
1369713043
1369813044 const runtime_src = rs: {
1369913045 if (maybe_rhs_val) |rhs_val| {
......@@ -13713,11 +13059,11 @@ fn zirShl(
1371313059 const bits = scalar_ty.intInfo(zcu).bits;
1371413060 switch (rhs_ty.zigTypeTag(zcu)) {
1371513061 .int, .comptime_int => {
13716 switch (try rhs_val.orderAgainstZeroSema(pt)) {
13062 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
1371713063 .gt => {
1371813064 if (air_tag != .shl_sat) {
1371913065 var rhs_space: Value.BigIntSpace = undefined;
13720 const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt);
13066 const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu);
1372113067 if (rhs_bigint.orderAgainstScalar(bits) != .lt) {
1372213068 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null);
1372313069 }
......@@ -13736,11 +13082,11 @@ fn zirShl(
1373613082 .shl, .shl_exact => return sema.failWithUseOfUndef(block, rhs_src, elem_idx),
1373713083 else => unreachable,
1373813084 };
13739 switch (try rhs_elem.orderAgainstZeroSema(pt)) {
13085 switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) {
1374013086 .gt => {
1374113087 if (air_tag != .shl_sat) {
1374213088 var rhs_elem_space: Value.BigIntSpace = undefined;
13743 const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt);
13089 const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu);
1374413090 if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) {
1374513091 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx);
1374613092 }
......@@ -13769,7 +13115,7 @@ fn zirShl(
1376913115 .shl, .shl_exact => try sema.checkAllScalarsDefined(block, lhs_src, lhs_val),
1377013116 else => unreachable,
1377113117 }
13772 if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs;
13118 if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs;
1377313119 }
1377413120 }
1377513121 break :rs rhs_src;
......@@ -13785,13 +13131,13 @@ fn zirShl(
1378513131 const rt_rhs_scalar_ty = try pt.smallestUnsignedInt(bit_count);
1378613132 if (!rhs_ty.isVector(zcu)) break :rt_rhs try pt.intValue(
1378713133 rt_rhs_scalar_ty,
13788 @min(try rhs_val.getUnsignedIntSema(pt) orelse bit_count, bit_count),
13134 @min(rhs_val.getUnsignedInt(zcu) orelse bit_count, bit_count),
1378913135 );
1379013136 const rhs_len = rhs_ty.vectorLen(zcu);
1379113137 const rhs_elems = try sema.arena.alloc(InternPool.Index, rhs_len);
1379213138 for (rhs_elems, 0..) |*rhs_elem, i| rhs_elem.* = (try pt.intValue(
1379313139 rt_rhs_scalar_ty,
13794 @min(try (try rhs_val.elemValue(pt, i)).getUnsignedIntSema(pt) orelse bit_count, bit_count),
13140 @min((try rhs_val.elemValue(pt, i)).getUnsignedInt(zcu) orelse bit_count, bit_count),
1379513141 )).toIntern();
1379613142 break :rt_rhs try pt.aggregateValue(try pt.vectorType(.{
1379713143 .len = rhs_len,
......@@ -13875,8 +13221,8 @@ fn zirShr(
1387513221 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1387613222 const scalar_ty = lhs_ty.scalarType(zcu);
1387713223
13878 const maybe_lhs_val = try sema.resolveValueResolveLazy(lhs);
13879 const maybe_rhs_val = try sema.resolveValueResolveLazy(rhs);
13224 const maybe_lhs_val = try sema.resolveValue(lhs);
13225 const maybe_rhs_val = try sema.resolveValue(rhs);
1388013226
1388113227 const runtime_src = rs: {
1388213228 if (maybe_rhs_val) |rhs_val| {
......@@ -13893,10 +13239,10 @@ fn zirShr(
1389313239 const bits = scalar_ty.intInfo(zcu).bits;
1389413240 switch (rhs_ty.zigTypeTag(zcu)) {
1389513241 .int, .comptime_int => {
13896 switch (try rhs_val.orderAgainstZeroSema(pt)) {
13242 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
1389713243 .gt => {
1389813244 var rhs_space: Value.BigIntSpace = undefined;
13899 const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt);
13245 const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu);
1390013246 if (rhs_bigint.orderAgainstScalar(bits) != .lt) {
1390113247 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null);
1390213248 }
......@@ -13912,10 +13258,10 @@ fn zirShr(
1391213258 if (rhs_elem.isUndef(zcu)) {
1391313259 return sema.failWithUseOfUndef(block, rhs_src, elem_idx);
1391413260 }
13915 switch (try rhs_elem.orderAgainstZeroSema(pt)) {
13261 switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) {
1391613262 .gt => {
1391713263 var rhs_elem_space: Value.BigIntSpace = undefined;
13918 const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt);
13264 const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu);
1391913265 if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) {
1392013266 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx);
1392113267 }
......@@ -13936,7 +13282,7 @@ fn zirShr(
1393613282 }
1393713283 if (maybe_lhs_val) |lhs_val| {
1393813284 try sema.checkAllScalarsDefined(block, lhs_src, lhs_val);
13939 if (try lhs_val.compareAllWithZeroSema(.eq, pt)) return lhs;
13285 if (lhs_val.compareAllWithZero(.eq, zcu)) return lhs;
1394013286 }
1394113287 }
1394213288 break :rs rhs_src;
......@@ -14011,8 +13357,8 @@ fn zirBitwise(
1401113357 const runtime_src = runtime: {
1401213358 // TODO: ask the linker what kind of relocations are available, and
1401313359 // in some cases emit a Value that means "this decl's address AND'd with this operand".
14014 if (try sema.resolveValueResolveLazy(casted_lhs)) |lhs_val| {
14015 if (try sema.resolveValueResolveLazy(casted_rhs)) |rhs_val| {
13360 if (try sema.resolveValue(casted_lhs)) |lhs_val| {
13361 if (try sema.resolveValue(casted_rhs)) |rhs_val| {
1401613362 const result_val = switch (air_tag) {
1401713363 // zig fmt: off
1401813364 .bit_and => try arith.bitwiseBin(sema, resolved_type, lhs_val, rhs_val, .@"and"),
......@@ -14106,13 +13452,13 @@ fn analyzeTupleCat(
1410613452 var i: u32 = 0;
1410713453 while (i < lhs_len) : (i += 1) {
1410813454 types[i] = lhs_ty.fieldType(i, zcu).toIntern();
14109 const default_val = lhs_ty.structFieldDefaultValue(i, zcu);
14110 values[i] = default_val.toIntern();
1411113455 const operand_src = block.src(.{ .array_cat_lhs = .{
1411213456 .array_cat_offset = src_node,
1411313457 .elem_index = i,
1411413458 } });
14115 if (default_val.toIntern() == .unreachable_value) {
13459 if (lhs_ty.structFieldDefaultValue(i, zcu)) |default_val| {
13460 values[i] = default_val.toIntern();
13461 } else {
1411613462 runtime_src = operand_src;
1411713463 values[i] = .none;
1411813464 }
......@@ -14120,13 +13466,13 @@ fn analyzeTupleCat(
1412013466 i = 0;
1412113467 while (i < rhs_len) : (i += 1) {
1412213468 types[i + lhs_len] = rhs_ty.fieldType(i, zcu).toIntern();
14123 const default_val = rhs_ty.structFieldDefaultValue(i, zcu);
14124 values[i + lhs_len] = default_val.toIntern();
1412513469 const operand_src = block.src(.{ .array_cat_rhs = .{
1412613470 .array_cat_offset = src_node,
1412713471 .elem_index = i,
1412813472 } });
14129 if (default_val.toIntern() == .unreachable_value) {
13473 if (rhs_ty.structFieldDefaultValue(i, zcu)) |default_val| {
13474 values[i + lhs_len] = default_val.toIntern();
13475 } else {
1413013476 runtime_src = operand_src;
1413113477 values[i + lhs_len] = .none;
1413213478 }
......@@ -14290,8 +13636,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1429013636 var elem_i: u32 = 0;
1429113637 while (elem_i < lhs_len) : (elem_i += 1) {
1429213638 const lhs_elem_i = elem_i;
14293 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else Value.@"unreachable";
14294 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(pt, lhs_elem_i) else elem_default_val;
13639 const elem_default_val: ?Value = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, zcu) else null;
13640 const elem_val = elem_default_val orelse try lhs_sub_val.elemValue(pt, lhs_elem_i);
1429513641 const elem_val_inst = Air.internedToRef(elem_val.toIntern());
1429613642 const operand_src = block.src(.{ .array_cat_lhs = .{
1429713643 .array_cat_offset = inst_data.src_node,
......@@ -14303,8 +13649,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1430313649 }
1430413650 while (elem_i < result_len) : (elem_i += 1) {
1430513651 const rhs_elem_i = elem_i - lhs_len;
14306 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else Value.@"unreachable";
14307 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(pt, rhs_elem_i) else elem_default_val;
13652 const elem_default_val: ?Value = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, zcu) else null;
13653 const elem_val = elem_default_val orelse try rhs_sub_val.elemValue(pt, rhs_elem_i);
1430813654 const elem_val_inst = Air.internedToRef(elem_val.toIntern());
1430913655 const operand_src = block.src(.{ .array_cat_rhs = .{
1431013656 .array_cat_offset = inst_data.src_node,
......@@ -14324,18 +13670,18 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1432413670 try sema.requireRuntimeBlock(block, src, runtime_src);
1432513671
1432613672 if (ptr_addrspace) |ptr_as| {
14327 const constant_alloc_ty = try pt.ptrTypeSema(.{
13673 const constant_alloc_ty = try pt.ptrType(.{
1432813674 .child = result_ty.toIntern(),
1432913675 .flags = .{
1433013676 .address_space = ptr_as,
1433113677 .is_const = true,
1433213678 },
1433313679 });
14334 const alloc_ty = try pt.ptrTypeSema(.{
13680 const alloc_ty = try pt.ptrType(.{
1433513681 .child = result_ty.toIntern(),
1433613682 .flags = .{ .address_space = ptr_as },
1433713683 });
14338 const elem_ptr_ty = try pt.ptrTypeSema(.{
13684 const elem_ptr_ty = try pt.ptrType(.{
1433913685 .child = resolved_elem_ty.toIntern(),
1434013686 .flags = .{ .address_space = ptr_as },
1434113687 });
......@@ -14347,7 +13693,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1434713693 if (lhs_ty.zigTypeTag(zcu) == .pointer and
1434813694 rhs_ty.zigTypeTag(zcu) == .pointer)
1434913695 {
14350 const slice_ty = try pt.ptrTypeSema(.{
13696 const slice_ty = try pt.ptrType(.{
1435113697 .child = resolved_elem_ty.toIntern(),
1435213698 .flags = .{
1435313699 .size = .slice,
......@@ -14486,7 +13832,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
1448613832 .none => null,
1448713833 else => Value.fromInterned(ptr_info.sentinel),
1448813834 },
14489 .len = try val.sliceLen(pt),
13835 .len = val.sliceLen(zcu),
1449013836 };
1449113837 },
1449213838 .one => {
......@@ -14500,8 +13846,20 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
1450013846 .@"struct" => {
1450113847 if (operand_ty.isTuple(zcu) and peer_ty.isIndexable(zcu)) {
1450213848 assert(!peer_ty.isTuple(zcu));
13849 const peer_elem_ty = switch (peer_ty.zigTypeTag(zcu)) {
13850 .pointer => switch (peer_ty.ptrSize(zcu)) {
13851 .one => switch (peer_ty.childType(zcu).zigTypeTag(zcu)) {
13852 .array, .vector => peer_ty.childType(zcu).childType(zcu),
13853 .@"struct" => return null,
13854 else => unreachable,
13855 },
13856 .many, .c, .slice => peer_ty.childType(zcu),
13857 },
13858 .vector, .array => peer_ty.childType(zcu),
13859 else => unreachable,
13860 };
1450313861 return .{
14504 .elem_type = peer_ty.elemType2(zcu),
13862 .elem_type = peer_elem_ty,
1450513863 .sentinel = null,
1450613864 .len = operand_ty.arrayLen(zcu),
1450713865 };
......@@ -14543,12 +13901,13 @@ fn analyzeTupleMul(
1454313901 var runtime_src: ?LazySrcLoc = null;
1454413902 for (0..tuple_len) |i| {
1454513903 types[i] = operand_ty.fieldType(i, zcu).toIntern();
14546 values[i] = operand_ty.structFieldDefaultValue(i, zcu).toIntern();
1454713904 const operand_src = block.src(.{ .array_cat_lhs = .{
1454813905 .array_cat_offset = src_node,
1454913906 .elem_index = @intCast(i),
1455013907 } });
14551 if (values[i] == .unreachable_value) {
13908 if (operand_ty.structFieldDefaultValue(i, zcu)) |default_val| {
13909 values[i] = default_val.toIntern();
13910 } else {
1455213911 runtime_src = operand_src;
1455313912 values[i] = .none; // TODO don't treat unreachable_value as special
1455413913 }
......@@ -14714,7 +14073,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1471414073 }
1471514074
1471614075 if (ptr_addrspace) |ptr_as| {
14717 const alloc_ty = try pt.ptrTypeSema(.{
14076 const alloc_ty = try pt.ptrType(.{
1471814077 .child = result_ty.toIntern(),
1471914078 .flags = .{
1472014079 .address_space = ptr_as,
......@@ -14722,7 +14081,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1472214081 },
1472314082 });
1472414083 const alloc = try block.addTy(.alloc, alloc_ty);
14725 const elem_ptr_ty = try pt.ptrTypeSema(.{
14084 const elem_ptr_ty = try pt.ptrType(.{
1472614085 .child = lhs_info.elem_type.toIntern(),
1472714086 .flags = .{ .address_space = ptr_as },
1472814087 });
......@@ -14859,8 +14218,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1485914218
1486014219 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div);
1486114220
14862 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
14863 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14221 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14222 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1486414223
1486514224 if ((lhs_ty.zigTypeTag(zcu) == .comptime_float and rhs_ty.zigTypeTag(zcu) == .comptime_int) or
1486614225 (lhs_ty.zigTypeTag(zcu) == .comptime_int and rhs_ty.zigTypeTag(zcu) == .comptime_float))
......@@ -14968,8 +14327,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1496814327
1496914328 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact);
1497014329
14971 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
14972 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14330 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14331 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1497314332
1497414333 // Because `@divExact` can trigger Illegal Behavior, undefined operands trigger Illegal Behavior.
1497514334
......@@ -15064,8 +14423,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1506414423
1506514424 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor);
1506614425
15067 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15068 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14426 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14427 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1506914428
1507014429 const allow_div_zero = !is_int and
1507114430 resolved_type.toIntern() != .comptime_float_type and
......@@ -15129,8 +14488,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1512914488
1513014489 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc);
1513114490
15132 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15133 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14491 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14492 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1513414493
1513514494 const allow_div_zero = !is_int and
1513614495 resolved_type.toIntern() != .comptime_float_type and
......@@ -15341,8 +14700,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1534114700
1534214701 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem);
1534314702
15344 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15345 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14703 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14704 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1534614705
1534714706 const lhs_maybe_negative = a: {
1534814707 if (lhs_scalar_ty.isUnsignedInt(zcu)) break :a false;
......@@ -15440,8 +14799,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1544014799
1544114800 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod);
1544214801
15443 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15444 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14802 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14803 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1544514804
1544614805 const allow_div_zero = !is_int and
1544714806 resolved_type.toIntern() != .comptime_float_type and
......@@ -15504,8 +14863,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1550414863
1550514864 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem);
1550614865
15507 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15508 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
14866 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
14867 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1550914868
1551014869 const allow_div_zero = !is_int and
1551114870 resolved_type.toIntern() != .comptime_float_type and
......@@ -15601,12 +14960,12 @@ fn zirOverflowArithmetic(
1560114960 // to the result, even if it is undefined..
1560214961 // Otherwise, if either of the argument is undefined, undefined is returned.
1560314962 if (maybe_lhs_val) |lhs_val| {
15604 if (!lhs_val.isUndef(zcu) and (try lhs_val.compareAllWithZeroSema(.eq, pt))) {
14963 if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) {
1560514964 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs };
1560614965 }
1560714966 }
1560814967 if (maybe_rhs_val) |rhs_val| {
15609 if (!rhs_val.isUndef(zcu) and (try rhs_val.compareAllWithZeroSema(.eq, pt))) {
14968 if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) {
1561014969 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
1561114970 }
1561214971 }
......@@ -15627,7 +14986,7 @@ fn zirOverflowArithmetic(
1562714986 if (maybe_rhs_val) |rhs_val| {
1562814987 if (rhs_val.isUndef(zcu)) {
1562914988 break :result .{ .overflow_bit = .undef, .wrapped = .undef };
15630 } else if (try rhs_val.compareAllWithZeroSema(.eq, pt)) {
14989 } else if (rhs_val.compareAllWithZero(.eq, zcu)) {
1563114990 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
1563214991 } else if (maybe_lhs_val) |lhs_val| {
1563314992 if (lhs_val.isUndef(zcu)) {
......@@ -15642,12 +15001,12 @@ fn zirOverflowArithmetic(
1564215001 .mul_with_overflow => {
1564315002 // If either of the arguments is zero, the result is zero and no overflow occured.
1564415003 if (maybe_lhs_val) |lhs_val| {
15645 if (!lhs_val.isUndef(zcu) and try lhs_val.compareAllWithZeroSema(.eq, pt)) {
15004 if (!lhs_val.isUndef(zcu) and lhs_val.compareAllWithZero(.eq, zcu)) {
1564615005 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
1564715006 }
1564815007 }
1564915008 if (maybe_rhs_val) |rhs_val| {
15650 if (!rhs_val.isUndef(zcu) and try rhs_val.compareAllWithZeroSema(.eq, pt)) {
15009 if (!rhs_val.isUndef(zcu) and rhs_val.compareAllWithZero(.eq, zcu)) {
1565115010 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = rhs };
1565215011 }
1565315012 }
......@@ -15694,10 +15053,10 @@ fn zirOverflowArithmetic(
1569415053 const bits = scalar_ty.intInfo(zcu).bits;
1569515054 switch (rhs_ty.zigTypeTag(zcu)) {
1569615055 .int, .comptime_int => {
15697 switch (try rhs_val.orderAgainstZeroSema(pt)) {
15056 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
1569815057 .gt => {
1569915058 var rhs_space: Value.BigIntSpace = undefined;
15700 const rhs_bigint = try rhs_val.toBigIntSema(&rhs_space, pt);
15059 const rhs_bigint = rhs_val.toBigInt(&rhs_space, zcu);
1570115060 if (rhs_bigint.orderAgainstScalar(bits) != .lt) {
1570215061 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_val, rhs_src, null);
1570315062 }
......@@ -15711,10 +15070,10 @@ fn zirOverflowArithmetic(
1571115070 for (0..rhs_ty.vectorLen(zcu)) |elem_idx| {
1571215071 const rhs_elem = try rhs_val.elemValue(pt, elem_idx);
1571315072 if (rhs_elem.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, elem_idx);
15714 switch (try rhs_elem.orderAgainstZeroSema(pt)) {
15073 switch (Value.order(rhs_elem, .zero_comptime_int, zcu)) {
1571515074 .gt => {
1571615075 var rhs_elem_space: Value.BigIntSpace = undefined;
15717 const rhs_elem_bigint = try rhs_elem.toBigIntSema(&rhs_elem_space, pt);
15076 const rhs_elem_bigint = rhs_elem.toBigInt(&rhs_elem_space, zcu);
1571815077 if (rhs_elem_bigint.orderAgainstScalar(bits) != .lt) {
1571915078 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs_elem, rhs_src, elem_idx);
1572015079 }
......@@ -15728,7 +15087,7 @@ fn zirOverflowArithmetic(
1572815087 },
1572915088 else => unreachable,
1573015089 }
15731 if (try rhs_val.compareAllWithZeroSema(.eq, pt)) {
15090 if (rhs_val.compareAllWithZero(.eq, zcu)) {
1573215091 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
1573315092 }
1573415093 } else {
......@@ -15737,7 +15096,7 @@ fn zirOverflowArithmetic(
1573715096 }
1573815097 if (maybe_lhs_val) |lhs_val| {
1573915098 try sema.checkAllScalarsDefined(block, lhs_src, lhs_val);
15740 if (try lhs_val.compareAllWithZeroSema(.eq, pt)) {
15099 if (lhs_val.compareAllWithZero(.eq, zcu)) {
1574115100 break :result .{ .overflow_bit = try sema.splat(overflow_ty, .zero_u1), .inst = lhs };
1574215101 }
1574315102 }
......@@ -15817,16 +15176,16 @@ fn analyzeArithmetic(
1581715176 if (zir_tag != .sub) {
1581815177 return sema.failWithInvalidPtrArithmetic(block, src, "pointer-pointer", "subtraction");
1581915178 }
15820 if (!lhs_ty.elemType2(zcu).eql(rhs_ty.elemType2(zcu), zcu)) {
15179 if (!lhs_ty.childType(zcu).eql(rhs_ty.childType(zcu), zcu)) {
1582115180 return sema.fail(block, src, "incompatible pointer arithmetic operands '{f}' and '{f}'", .{
1582215181 lhs_ty.fmt(pt), rhs_ty.fmt(pt),
1582315182 });
1582415183 }
1582515184
15826 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
15185 const elem_size = lhs_ty.childType(zcu).abiSize(zcu);
1582715186 if (elem_size == 0) {
15828 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
15829 lhs_ty.elemType2(zcu).fmt(pt),
15187 return sema.fail(block, src, "pointer subtraction requires element type '{f}' to have runtime bits", .{
15188 lhs_ty.childType(zcu).fmt(pt),
1583015189 });
1583115190 }
1583215191
......@@ -15875,11 +15234,7 @@ fn analyzeArithmetic(
1587515234 else => return sema.failWithInvalidPtrArithmetic(block, src, "pointer-integer", "addition and subtraction"),
1587615235 };
1587715236
15878 if (!try lhs_ty.elemType2(zcu).hasRuntimeBitsSema(pt)) {
15879 return sema.fail(block, src, "pointer arithmetic requires element type '{f}' to have runtime bits", .{
15880 lhs_ty.elemType2(zcu).fmt(pt),
15881 });
15882 }
15237 try sema.ensureLayoutResolved(lhs_ty.childType(zcu));
1588315238 return sema.analyzePtrArithmetic(block, src, lhs, rhs, air_tag, lhs_src, rhs_src);
1588415239 },
1588515240 }
......@@ -15915,8 +15270,8 @@ fn analyzeArithmetic(
1591515270 else => unreachable,
1591615271 };
1591715272
15918 const maybe_lhs_val = try sema.resolveValueResolveLazy(casted_lhs);
15919 const maybe_rhs_val = try sema.resolveValueResolveLazy(casted_rhs);
15273 const maybe_lhs_val = try sema.resolveValue(casted_lhs);
15274 const maybe_rhs_val = try sema.resolveValue(casted_rhs);
1592015275
1592115276 if (maybe_lhs_val) |lhs_val| {
1592215277 if (maybe_rhs_val) |rhs_val| {
......@@ -15972,6 +15327,7 @@ fn analyzeArithmetic(
1597215327 return block.addBinOp(air_tag, casted_lhs, casted_rhs);
1597315328}
1597415329
15330/// Asserts that the layout of the pointer child type is already resolved.
1597515331fn analyzePtrArithmetic(
1597615332 sema: *Sema,
1597715333 block: *Block,
......@@ -15993,7 +15349,10 @@ fn analyzePtrArithmetic(
1599315349 const ptr_info = ptr_ty.ptrInfo(zcu);
1599415350 assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c);
1599515351
15996 if ((try sema.typeHasOnePossibleValue(.fromInterned(ptr_info.child))) != null) {
15352 const elem_ty: Type = .fromInterned(ptr_info.child);
15353 elem_ty.assertHasLayout(zcu);
15354
15355 if (elem_ty.abiSize(zcu) == 0) {
1599715356 // Offset will be multiplied by zero, so result is the same as the base pointer.
1599815357 return ptr;
1599915358 }
......@@ -16007,9 +15366,9 @@ fn analyzePtrArithmetic(
1600715366 }
1600815367 // If the addend is not a comptime-known value we can still count on
1600915368 // it being a multiple of the type size.
16010 const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt);
15369 const elem_size = elem_ty.abiSize(zcu);
1601115370 const addend = if (opt_off_val) |off_val| a: {
16012 const off_int = try sema.usizeCast(block, offset_src, try off_val.toUnsignedIntSema(pt));
15371 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(zcu));
1601315372 break :a elem_size * off_int;
1601415373 } else elem_size;
1601515374
......@@ -16022,7 +15381,7 @@ fn analyzePtrArithmetic(
1602215381 ));
1602315382 assert(new_align != .none);
1602415383
16025 break :t try pt.ptrTypeSema(.{
15384 break :t try pt.ptrType(.{
1602615385 .child = ptr_info.child,
1602715386 .sentinel = ptr_info.sentinel,
1602815387 .flags = .{
......@@ -16041,10 +15400,10 @@ fn analyzePtrArithmetic(
1604115400 if (opt_off_val) |offset_val| {
1604215401 if (ptr_val.isUndef(zcu)) return pt.undefRef(new_ptr_ty);
1604315402
16044 const offset_int = try sema.usizeCast(block, offset_src, try offset_val.toUnsignedIntSema(pt));
15403 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(zcu));
1604515404 if (offset_int == 0) return ptr;
1604615405 if (air_tag == .ptr_sub) {
16047 const elem_size = try Type.fromInterned(ptr_info.child).abiSizeSema(pt);
15406 const elem_size = elem_ty.abiSize(zcu);
1604815407 const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty);
1604915408 return Air.internedToRef(new_ptr_val.toIntern());
1605015409 } else {
......@@ -16248,6 +15607,7 @@ fn zirAsm(
1624815607 buffer[input.c.len + 1 + input.n.len] = 0;
1624915608 sema.air_extra.items.len += (input.c.len + input.n.len + (2 + 3)) / 4;
1625015609 }
15610 if (try expr_ty.toType().onePossibleValue(pt)) |opv| return .fromValue(opv);
1625115611 return asm_air;
1625215612}
1625315613
......@@ -16343,7 +15703,6 @@ fn analyzeCmpUnionTag(
1634315703 const pt = sema.pt;
1634415704 const zcu = pt.zcu;
1634515705 const union_ty = sema.typeOf(un);
16346 try union_ty.resolveFields(pt);
1634715706 const union_tag_ty = union_ty.unionTagType(zcu) orelse {
1634815707 const msg = msg: {
1634915708 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
......@@ -16534,10 +15893,11 @@ fn runtimeBoolCmp(
1653415893
1653515894fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1653615895 const pt = sema.pt;
15896 const zcu = pt.zcu;
1653715897 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
1653815898 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
1653915899 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
16540 switch (ty.zigTypeTag(pt.zcu)) {
15900 switch (ty.zigTypeTag(zcu)) {
1654115901 .@"fn",
1654215902 .noreturn,
1654315903 .undefined,
......@@ -16568,8 +15928,8 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1656815928 .@"anyframe",
1656915929 => {},
1657015930 }
16571 const val = try ty.abiSizeLazy(pt);
16572 return Air.internedToRef(val.toIntern());
15931 try sema.ensureLayoutResolved(ty);
15932 return .fromValue(try pt.intValue(.comptime_int, ty.abiSize(zcu)));
1657315933}
1657415934
1657515935fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -16609,8 +15969,8 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1660915969 .@"anyframe",
1661015970 => {},
1661115971 }
16612 const bit_size = try operand_ty.bitSizeSema(pt);
16613 return pt.intRef(.comptime_int, bit_size);
15972 try sema.ensureLayoutResolved(operand_ty);
15973 return .fromValue(try pt.intValue(.comptime_int, operand_ty.bitSize(zcu)));
1661415974}
1661515975
1661615976fn zirThis(
......@@ -16619,34 +15979,16 @@ fn zirThis(
1661915979 extended: Zir.Inst.Extended.InstData,
1662015980) CompileError!Air.Inst.Ref {
1662115981 _ = extended;
16622 const pt = sema.pt;
16623 const zcu = pt.zcu;
16624 const namespace = pt.zcu.namespacePtr(block.namespace);
15982 const zcu = sema.pt.zcu;
15983 const namespace = zcu.namespacePtr(block.namespace);
1662515984
16626 switch (pt.zcu.intern_pool.indexToKey(namespace.owner_type)) {
16627 .opaque_type => {
16628 // Opaque types are never outdated since they don't undergo type resolution, so nothing to do!
16629 return Air.internedToRef(namespace.owner_type);
16630 },
16631 .struct_type, .union_type => {
16632 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
16633 try sema.declareDependency(.{ .interned = new_ty });
16634 return Air.internedToRef(new_ty);
16635 },
16636 .enum_type => {
16637 const new_ty = try pt.ensureTypeUpToDate(namespace.owner_type);
16638 try sema.declareDependency(.{ .interned = new_ty });
16639 // Since this is an enum, it has to be resolved immediately.
16640 // `ensureTypeUpToDate` has resolved the new type if necessary.
16641 // We just need to check for resolution failures.
16642 const ty_unit: AnalUnit = .wrap(.{ .type = new_ty });
16643 if (zcu.failed_analysis.contains(ty_unit) or zcu.transitive_failed_analysis.contains(ty_unit)) {
16644 return error.AnalysisFail;
16645 }
16646 return Air.internedToRef(new_ty);
16647 },
15985 switch (zcu.intern_pool.indexToKey(namespace.owner_type)) {
15986 .opaque_type, .struct_type, .union_type => {},
15987 // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol
15988 .enum_type => try sema.ensureFieldInitsResolved(.fromInterned(namespace.owner_type)),
1664815989 else => unreachable,
1664915990 }
15991 return .fromIntern(namespace.owner_type);
1665015992}
1665115993
1665215994fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
......@@ -16739,7 +16081,7 @@ fn zirRetAddr(
1673916081 _ = sema;
1674016082 _ = extended;
1674116083 if (block.isComptime()) {
16742 // TODO: we could give a meaningful lazy value here. #14938
16084 // TODO: we could give a meaningful value here. #14938
1674316085 return .zero_usize;
1674416086 } else {
1674516087 return block.addNoOp(.ret_addr);
......@@ -16886,6 +16228,8 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1688616228 try sema.declareDependency(.{ .namespace = type_decl_inst });
1688716229 }
1688816230
16231 try sema.ensureLayoutResolved(ty);
16232
1688916233 switch (ty.zigTypeTag(zcu)) {
1689016234 .type,
1689116235 .void,
......@@ -16934,7 +16278,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1693416278 .child = param_info_ty.toIntern(),
1693516279 });
1693616280 const new_decl_val = (try pt.aggregateValue(new_decl_ty, param_vals)).toIntern();
16937 const slice_ty = (try pt.ptrTypeSema(.{
16281 const slice_ty = (try pt.ptrType(.{
1693816282 .child = param_info_ty.toIntern(),
1693916283 .flags = .{
1694016284 .size = .slice,
......@@ -16976,11 +16320,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1697616320 error.OutOfMemory => |e| return e,
1697716321 };
1697816322
16323 // MLUGG TODO
16324 const func_is_generic = false;
16325
1697916326 const field_values: [5]InternPool.Index = .{
1698016327 // calling_convention: CallingConvention,
1698116328 callconv_val.toIntern(),
1698216329 // is_generic: bool,
16983 Value.makeBool(func_ty_info.is_generic).toIntern(),
16330 Value.makeBool(func_is_generic).toIntern(),
1698416331 // is_var_args: bool,
1698516332 Value.makeBool(func_ty_info.is_var_args).toIntern(),
1698616333 // return_type: ?type,
......@@ -17015,7 +16362,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1701516362
1701616363 const field_vals = .{
1701716364 // bits: u16,
17018 (try pt.intValue(.u16, ty.bitSize(zcu))).toIntern(),
16365 (try pt.intValue(.u16, ty.floatBits(zcu.getTarget()))).toIntern(),
1701916366 };
1702016367 return Air.internedToRef((try pt.internUnion(.{
1702116368 .ty = type_info_ty.toIntern(),
......@@ -17025,10 +16372,13 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1702516372 },
1702616373 .pointer => {
1702716374 const info = ty.ptrInfo(zcu);
17028 const alignment = if (info.flags.alignment.toByteUnits()) |alignment|
17029 try pt.intValue(.comptime_int, alignment)
17030 else
17031 try Type.fromInterned(info.child).lazyAbiAlignment(pt);
16375 const alignment_val = try pt.intValue(.comptime_int, bytes: {
16376 if (info.flags.alignment.toByteUnits()) |b| break :bytes b;
16377 const elem_ty: Type = .fromInterned(info.child);
16378 // MLUGG TODO: this resolution is sus, but i doubt i'll solve it in this branch
16379 try sema.ensureLayoutResolved(elem_ty);
16380 break :bytes elem_ty.abiAlignment(zcu).toByteUnits().?;
16381 });
1703216382
1703316383 const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace);
1703416384 const pointer_ty = try sema.getBuiltinType(src, .@"Type.Pointer");
......@@ -17042,7 +16392,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1704216392 // is_volatile: bool,
1704316393 Value.makeBool(info.flags.is_volatile).toIntern(),
1704416394 // alignment: comptime_int,
17045 alignment.toIntern(),
16395 alignment_val.toIntern(),
1704616396 // address_space: AddressSpace
1704716397 (try pt.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(),
1704816398 // child: type,
......@@ -17159,7 +16509,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1715916509 };
1716016510
1716116511 // Build our ?[]const Error value
17162 const slice_errors_ty = try pt.ptrTypeSema(.{
16512 const slice_errors_ty = try pt.ptrType(.{
1716316513 .child = error_field_ty.toIntern(),
1716416514 .flags = .{
1716516515 .size = .slice,
......@@ -17215,19 +16565,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1721516565 })));
1721616566 },
1721716567 .@"enum" => {
17218 const is_exhaustive = Value.makeBool(ip.loadEnumType(ty.toIntern()).tag_mode != .nonexhaustive);
16568 const enum_obj = ip.loadEnumType(ty.toIntern());
16569 const is_exhaustive: Value = .makeBool(!enum_obj.nonexhaustive);
1721916570
1722016571 const enum_field_ty = try sema.getBuiltinType(src, .@"Type.EnumField");
1722116572
17222 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.loadEnumType(ty.toIntern()).names.len);
16573 const enum_field_vals = try sema.arena.alloc(InternPool.Index, enum_obj.field_names.len);
1722316574 for (enum_field_vals, 0..) |*field_val, tag_index| {
17224 const enum_type = ip.loadEnumType(ty.toIntern());
17225 const value_val = if (enum_type.values.len > 0)
16575 const value_val = if (enum_obj.field_values.len > 0)
1722616576 try ip.getCoercedInts(
1722716577 gpa,
1722816578 io,
1722916579 pt.tid,
17230 ip.indexToKey(enum_type.values.get(ip)[tag_index]).int,
16580 ip.indexToKey(enum_obj.field_values.get(ip)[tag_index]).int,
1723116581 .comptime_int_type,
1723216582 )
1723316583 else
......@@ -17235,7 +16585,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1723516585
1723616586 // TODO: write something like getCoercedInts to avoid needing to dupe
1723716587 const name_val = v: {
17238 const tag_name = enum_type.names.get(ip)[tag_index];
16588 const tag_name = enum_obj.field_names.get(ip)[tag_index];
1723916589 const tag_name_len = tag_name.length(ip);
1724016590 const new_decl_ty = try pt.arrayType(.{
1724116591 .len = tag_name_len,
......@@ -17275,7 +16625,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1727516625 .child = enum_field_ty.toIntern(),
1727616626 });
1727716627 const new_decl_val = (try pt.aggregateValue(fields_array_ty, enum_field_vals)).toIntern();
17278 const slice_ty = (try pt.ptrTypeSema(.{
16628 const slice_ty = (try pt.ptrType(.{
1727916629 .child = enum_field_ty.toIntern(),
1728016630 .flags = .{
1728116631 .size = .slice,
......@@ -17303,7 +16653,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1730316653
1730416654 const field_values = .{
1730516655 // tag_type: type,
17306 ip.loadEnumType(ty.toIntern()).tag_ty,
16656 ip.loadEnumType(ty.toIntern()).int_tag_type,
1730716657 // fields: []const EnumField,
1730816658 fields_val,
1730916659 // decls: []const Declaration,
......@@ -17321,17 +16671,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1732116671 const type_union_ty = try sema.getBuiltinType(src, .@"Type.Union");
1732216672 const union_field_ty = try sema.getBuiltinType(src, .@"Type.UnionField");
1732316673
17324 try ty.resolveLayout(pt); // Getting alignment requires type layout
17325 const union_obj = zcu.typeToUnion(ty).?;
17326 const tag_type = union_obj.loadTagType(ip);
17327 const layout = union_obj.flagsUnordered(ip).layout;
16674 const union_obj = ip.loadUnionType(ty.toIntern());
16675 const enum_obj = ip.loadEnumType(union_obj.enum_tag_type);
16676 const layout = union_obj.layout;
1732816677
17329 const union_field_vals = try gpa.alloc(InternPool.Index, tag_type.names.len);
16678 const union_field_vals = try gpa.alloc(InternPool.Index, enum_obj.field_names.len);
1733016679 defer gpa.free(union_field_vals);
1733116680
1733216681 for (union_field_vals, 0..) |*field_val, field_index| {
1733316682 const name_val = v: {
17334 const field_name = tag_type.names.get(ip)[field_index];
16683 const field_name = enum_obj.field_names.get(ip)[field_index];
1733516684 const field_name_len = field_name.length(ip);
1733616685 const new_decl_ty = try pt.arrayType(.{
1733716686 .len = field_name_len,
......@@ -17357,7 +16706,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1735716706 };
1735816707
1735916708 const alignment = switch (layout) {
17360 .auto, .@"extern" => try ty.fieldAlignmentSema(field_index, pt),
16709 .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu),
1736116710 .@"packed" => .none,
1736216711 };
1736316712
......@@ -17379,7 +16728,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1737916728 .child = union_field_ty.toIntern(),
1738016729 });
1738116730 const new_decl_val = (try pt.aggregateValue(array_fields_ty, union_field_vals)).toIntern();
17382 const slice_ty = (try pt.ptrTypeSema(.{
16731 const slice_ty = (try pt.ptrType(.{
1738316732 .child = union_field_ty.toIntern(),
1738416733 .flags = .{
1738516734 .size = .slice,
......@@ -17431,8 +16780,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1743116780 const type_struct_ty = try sema.getBuiltinType(src, .@"Type.Struct");
1743216781 const struct_field_ty = try sema.getBuiltinType(src, .@"Type.StructField");
1743316782
17434 try ty.resolveLayout(pt); // Getting alignment requires type layout
17435
1743616783 var struct_field_vals: []InternPool.Index = &.{};
1743716784 defer gpa.free(struct_field_vals);
1743816785 fv: {
......@@ -17468,8 +16815,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1746816815 } });
1746916816 };
1747016817
17471 try Type.fromInterned(field_ty).resolveLayout(pt);
17472
1747316818 const is_comptime = field_val != .none;
1747416819 const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null;
1747516820 const default_val_ptr = try sema.optRefValue(opt_default_val);
......@@ -17492,16 +16837,17 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1749216837 .struct_type => ip.loadStructType(ty.toIntern()),
1749316838 else => unreachable,
1749416839 };
16840 try sema.ensureFieldInitsResolved(ty); // can't do this sooner, since it's not allowed on tuples
1749516841 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
1749616842
17497 try ty.resolveStructFieldInits(pt);
17498
1749916843 for (struct_field_vals, 0..) |*field_val, field_index| {
17500 const field_name = struct_type.fieldName(ip, field_index);
16844 const field_name = struct_type.field_names.get(ip)[field_index];
1750116845 const field_name_len = field_name.length(ip);
1750216846 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
17503 const field_init = struct_type.fieldInit(ip, field_index);
17504 const field_is_comptime = struct_type.fieldIsComptime(ip, field_index);
16847 const field_default: InternPool.Index = if (struct_type.field_defaults.len > 0) d: {
16848 break :d struct_type.field_defaults.get(ip)[field_index];
16849 } else .none;
16850 const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index);
1750516851 const name_val = v: {
1750616852 const new_decl_ty = try pt.arrayType(.{
1750716853 .len = field_name_len,
......@@ -17526,15 +16872,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1752616872 } });
1752716873 };
1752816874
17529 const opt_default_val = if (field_init == .none) null else Value.fromInterned(field_init);
16875 const opt_default_val: ?Value = if (field_default == .none) null else .fromInterned(field_default);
1753016876 const default_val_ptr = try sema.optRefValue(opt_default_val);
1753116877 const alignment = switch (struct_type.layout) {
16878 .auto, .@"extern" => ty.resolvedFieldAlignment(field_index, zcu),
1753216879 .@"packed" => .none,
17533 else => try field_ty.structFieldAlignmentSema(
17534 struct_type.fieldAlign(ip, field_index),
17535 struct_type.layout,
17536 pt,
17537 ),
1753816880 };
1753916881
1754016882 const struct_field_fields = .{
......@@ -17559,7 +16901,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1755916901 .child = struct_field_ty.toIntern(),
1756016902 });
1756116903 const new_decl_val = (try pt.aggregateValue(array_fields_ty, struct_field_vals)).toIntern();
17562 const slice_ty = (try pt.ptrTypeSema(.{
16904 const slice_ty = (try pt.ptrType(.{
1756316905 .child = struct_field_ty.toIntern(),
1756416906 .flags = .{
1756516907 .size = .slice,
......@@ -17585,9 +16927,9 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1758516927
1758616928 const backing_integer_val = try pt.intern(.{ .opt = .{
1758716929 .ty = (try pt.optionalType(.type_type)).toIntern(),
17588 .val = if (zcu.typeToPackedStruct(ty)) |packed_struct| val: {
17589 assert(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)).isInt(zcu));
17590 break :val packed_struct.backingIntTypeUnordered(ip);
16930 .val = if (zcu.typeToPackedStruct(ty)) |struct_obj| val: {
16931 assert(Type.fromInterned(struct_obj.packed_backing_int_type).isInt(zcu));
16932 break :val struct_obj.packed_backing_int_type;
1759116933 } else .none,
1759216934 } });
1759316935
......@@ -17616,7 +16958,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1761616958 .@"opaque" => {
1761716959 const type_opaque_ty = try sema.getBuiltinType(src, .@"Type.Opaque");
1761816960
17619 try ty.resolveFields(pt);
1762016961 const decls_val = try sema.typeInfoDecls(src, ty.getNamespace(zcu));
1762116962
1762216963 const field_values = .{
......@@ -17658,7 +16999,7 @@ fn typeInfoDecls(
1765816999 .child = declaration_ty.toIntern(),
1765917000 });
1766017001 const new_decl_val = (try pt.aggregateValue(array_decl_ty, decl_vals.items)).toIntern();
17661 const slice_ty = (try pt.ptrTypeSema(.{
17002 const slice_ty = (try pt.ptrType(.{
1766217003 .child = declaration_ty.toIntern(),
1766317004 .flags = .{
1766417005 .size = .slice,
......@@ -17783,22 +17124,12 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
1778317124 const zcu = pt.zcu;
1778417125 switch (operand.zigTypeTag(zcu)) {
1778517126 .comptime_int => return .comptime_int,
17786 .int => {
17787 const bits = operand.bitSize(zcu);
17788 const count = if (bits == 0)
17789 0
17790 else blk: {
17791 var count: u16 = 0;
17792 var s = bits - 1;
17793 while (s != 0) : (s >>= 1) {
17794 count += 1;
17795 }
17796 break :blk count;
17797 };
17798 return pt.intType(.unsigned, count);
17799 },
17127 .int => return pt.intType(.unsigned, switch (operand.intInfo(zcu).bits) {
17128 0 => 0,
17129 else => |b| std.math.log2_int_ceil(u16, b),
17130 }),
1780017131 .vector => {
17801 const elem_ty = operand.elemType2(zcu);
17132 const elem_ty = operand.childType(zcu);
1780217133 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);
1780317134 return pt.vectorType(.{
1780417135 .len = operand.vectorLen(zcu),
......@@ -18082,13 +17413,15 @@ fn zirIsNonNullPtr(
1808217413 const src = block.nodeOffset(inst_data.src_node);
1808317414 const ptr = try sema.resolveInst(inst_data.operand);
1808417415 const ptr_ty = sema.typeOf(ptr);
18085 try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(zcu));
17416 assert(ptr_ty.zigTypeTag(zcu) == .pointer);
17417 const nullable_ty = ptr_ty.childType(zcu);
17418 try sema.checkNullableType(block, src, nullable_ty);
1808617419 if (try sema.resolveValue(ptr)) |ptr_val| {
18087 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |loaded_val| {
18088 return sema.analyzeIsNull(block, Air.internedToRef(loaded_val.toIntern()), true);
17420 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |nullable_val| {
17421 return sema.analyzeIsNull(block, .fromValue(nullable_val), true);
1808917422 }
1809017423 }
18091 if (ptr_ty.childType(zcu).isNullFromType(zcu)) |is_null| {
17424 if (nullable_ty.isNullFromType(zcu)) |is_null| {
1809217425 return if (is_null) .bool_false else .bool_true;
1809317426 }
1809417427 return block.addUnOp(.is_non_null_ptr, ptr);
......@@ -18125,7 +17458,10 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1812517458 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
1812617459 const src = block.nodeOffset(inst_data.src_node);
1812717460 const ptr = try sema.resolveInst(inst_data.operand);
18128 try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(zcu));
17461 const ptr_ty = sema.typeOf(ptr);
17462 assert(ptr_ty.zigTypeTag(zcu) == .pointer);
17463 const error_ty = ptr_ty.childType(zcu);
17464 try sema.checkErrorType(block, src, error_ty);
1812917465 const loaded = try sema.analyzeLoad(block, src, ptr, src);
1813017466 return sema.analyzeIsNonErr(block, src, loaded);
1813117467}
......@@ -18294,6 +17630,11 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1829417630 } },
1829517631 });
1829617632 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(sub_block.instructions.items));
17633
17634 // The payload type might still be OPV, in which case `try_inst` is just there for the runtime
17635 // control flow and we should return a comptime-known result.
17636 if (try err_union_ty.errorUnionPayload(zcu).onePossibleValue(pt)) |opv| return .fromValue(opv);
17637
1829717638 return try_inst;
1829817639}
1829917640
......@@ -18347,7 +17688,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1834717688
1834817689 const operand_ty = sema.typeOf(operand);
1834917690 const ptr_info = operand_ty.ptrInfo(zcu);
18350 const res_ty = try pt.ptrTypeSema(.{
17691 const res_ty = try pt.ptrType(.{
1835117692 .child = err_union_ty.errorUnionPayload(zcu).toIntern(),
1835217693 .flags = .{
1835317694 .is_const = ptr_info.flags.is_const,
......@@ -18512,7 +17853,7 @@ fn zirRetImplicit(
1851217853
1851317854 const operand = try sema.resolveInst(inst_data.operand);
1851417855 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = .zero });
18515 const base_tag = sema.fn_ret_ty.baseZigTypeTag(zcu);
17856 const base_tag = sema.fn_ret_ty.optEuBaseType(zcu).zigTypeTag(zcu);
1851617857 if (base_tag == .noreturn) {
1851717858 const msg = msg: {
1851817859 const msg = try sema.errMsg(ret_ty_src, "function declared '{f}' implicitly returns", .{
......@@ -18809,8 +18150,6 @@ fn analyzeRet(
1880918150 return sema.failWithOwnedErrorMsg(block, msg);
1881018151 }
1881118152
18812 try sema.fn_ret_ty.resolveLayout(pt);
18813
1881418153 try sema.validateRuntimeValue(block, operand_src, operand);
1881518154
1881618155 const air_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret;
......@@ -18889,16 +18228,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1888918228 extra_i += 1;
1889018229 const coerced = try sema.coerce(block, align_ty, try sema.resolveInst(ref), align_src);
1889118230 const val = try sema.resolveConstDefinedValue(block, align_src, coerced, .{ .simple = .@"align" });
18892 // Check if this happens to be the lazy alignment of our element type, in
18893 // which case we can make this 0 without resolving it.
18894 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
18895 .int => |int| switch (int.storage) {
18896 .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.toIntern()) break :blk .none,
18897 else => {},
18898 },
18899 else => {},
18900 }
18901 const align_bytes = (try val.getUnsignedIntSema(pt)).?;
18231 const align_bytes = val.toUnsignedInt(zcu);
1890218232 break :blk try sema.validateAlign(block, align_src, align_bytes);
1890318233 } else .none;
1890418234
......@@ -18928,7 +18258,8 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1892818258 elem_ty.fmt(pt), bit_offset, bit_offset - host_size * 8, host_size,
1892918259 });
1893018260 }
18931 const elem_bit_size = try elem_ty.bitSizeSema(pt);
18261 try sema.ensureLayoutResolved(elem_ty);
18262 const elem_bit_size = elem_ty.bitSize(zcu);
1893218263 if (elem_bit_size > host_size * 8 - bit_offset) {
1893318264 return sema.fail(block, bitoffset_src, "packed type '{f}' at bit offset {d} ends {d} bits after the end of a {d} byte host integer", .{
1893418265 elem_ty.fmt(pt), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
......@@ -18957,16 +18288,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1895718288 }
1895818289 }
1895918290
18960 if (host_size != 0 and !try sema.validatePackedType(elem_ty)) {
18291 if (host_size != 0 and !elem_ty.packable(zcu)) {
1896118292 return sema.failWithOwnedErrorMsg(block, msg: {
1896218293 const msg = try sema.errMsg(elem_ty_src, "bit-pointer cannot refer to value of type '{f}'", .{elem_ty.fmt(pt)});
1896318294 errdefer msg.destroy(sema.gpa);
18964 try sema.explainWhyTypeIsNotPacked(msg, elem_ty_src, elem_ty);
18295 try sema.explainWhyTypeIsNotPackable(msg, elem_ty_src, elem_ty);
1896518296 break :msg msg;
1896618297 });
1896718298 }
1896818299
18969 const ty = try pt.ptrTypeSema(.{
18300 const ty = try pt.ptrType(.{
1897018301 .child = elem_ty.toIntern(),
1897118302 .sentinel = sentinel,
1897218303 .flags = .{
......@@ -18996,6 +18327,8 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1899618327 const pt = sema.pt;
1899718328 const zcu = pt.zcu;
1899818329
18330 try sema.ensureLayoutResolved(obj_ty);
18331
1899918332 switch (obj_ty.zigTypeTag(zcu)) {
1900018333 .@"struct" => return sema.structInitEmpty(block, obj_ty, src, src),
1900118334 .array, .vector => return sema.arrayInitEmpty(block, src, obj_ty),
......@@ -19058,6 +18391,9 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
1905818391 .child = ptr_ty.childType(zcu).toIntern(),
1905918392 });
1906018393 } else ty_operand;
18394
18395 try sema.ensureLayoutResolved(init_ty);
18396
1906118397 const obj_ty = init_ty.optEuBaseType(zcu);
1906218398
1906318399 const empty_ref = switch (obj_ty.zigTypeTag(zcu)) {
......@@ -19076,6 +18412,7 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
1907618412 }
1907718413}
1907818414
18415/// Asserts that the layout of `struct_ty` is already resolved.
1907918416fn structInitEmpty(
1908018417 sema: *Sema,
1908118418 block: *Block,
......@@ -19087,7 +18424,7 @@ fn structInitEmpty(
1908718424 const zcu = pt.zcu;
1908818425 const gpa = sema.gpa;
1908918426 // This logic must be synchronized with that in `zirStructInit`.
19090 try struct_ty.resolveFields(pt);
18427 struct_ty.assertHasLayout(zcu);
1909118428
1909218429 // The init values to use for the struct instance.
1909318430 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(zcu));
......@@ -19202,8 +18539,8 @@ fn zirStructInit(
1920218539 // The type wasn't actually known, so treat this as an anon struct init.
1920318540 return sema.structInitAnon(block, src, inst, .typed_init, extra.data, extra.end, is_ref);
1920418541 };
18542 try sema.ensureLayoutResolved(result_ty);
1920518543 const resolved_ty = result_ty.optEuBaseType(zcu);
19206 try resolved_ty.resolveLayout(pt);
1920718544
1920818545 if (resolved_ty.zigTypeTag(zcu) == .@"struct") {
1920918546 // This logic must be synchronized with that in `zirStructInitEmpty`.
......@@ -19226,7 +18563,6 @@ fn zirStructInit(
1922618563 var field_i: u32 = 0;
1922718564 var extra_index = extra.end;
1922818565
19229 const is_packed = resolved_ty.containerLayout(zcu) == .@"packed";
1923018566 while (field_i < extra.data.fields_len) : (field_i += 1) {
1923118567 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
1923218568 extra_index = item.end;
......@@ -19251,16 +18587,16 @@ fn zirStructInit(
1925118587 const uncoerced_init = try sema.resolveInst(item.data.init);
1925218588 const field_ty = resolved_ty.fieldType(field_index, zcu);
1925318589 field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src);
19254 if (!is_packed) {
19255 try resolved_ty.resolveStructFieldInits(pt);
19256 if (try resolved_ty.structFieldValueComptime(pt, field_index)) |default_value| {
19257 const init_val = (try sema.resolveValue(field_inits[field_index])) orelse {
19258 return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field });
19259 };
19260
19261 if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) {
19262 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
19263 }
18590 if (resolved_ty.structFieldIsComptime(field_index, zcu)) {
18591 if (!resolved_ty.isTuple(zcu)) {
18592 try sema.ensureFieldInitsResolved(resolved_ty);
18593 }
18594 const default_value = (try resolved_ty.structFieldValueComptime(pt, field_index)).?;
18595 const init_val = (try sema.resolveValue(field_inits[field_index])) orelse {
18596 return sema.failWithNeededComptime(block, field_src, .{ .simple = .stored_to_comptime_field });
18597 };
18598 if (!init_val.eql(default_value, resolved_ty.fieldType(field_index, zcu), zcu)) {
18599 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
1926418600 }
1926518601 }
1926618602 }
......@@ -19315,7 +18651,7 @@ fn zirStructInit(
1931518651 return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
1931618652 }
1931718653
19318 if (try resolved_ty.comptimeOnlySema(pt)) {
18654 if (resolved_ty.comptimeOnly(zcu)) {
1931918655 return sema.failWithNeededComptime(block, field_src, .{ .comptime_only = .{
1932018656 .ty = resolved_ty,
1932118657 .msg = .union_init,
......@@ -19326,7 +18662,7 @@ fn zirStructInit(
1932618662
1932718663 if (is_ref) {
1932818664 const target = zcu.getTarget();
19329 const alloc_ty = try pt.ptrTypeSema(.{
18665 const alloc_ty = try pt.ptrType(.{
1933018666 .child = result_ty.toIntern(),
1933118667 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1933218668 });
......@@ -19334,9 +18670,8 @@ fn zirStructInit(
1933418670 const base_ptr = try sema.optEuBasePtrInit(block, alloc, src);
1933518671 const field_ptr = try sema.unionFieldPtr(block, field_src, base_ptr, field_name, field_src, resolved_ty, true);
1933618672 try sema.storePtr(block, src, field_ptr, init_inst);
19337 if ((try sema.typeHasOnePossibleValue(tag_ty)) == null) {
19338 const new_tag = Air.internedToRef(tag_val.toIntern());
19339 _ = try block.addBinOp(.set_union_tag, base_ptr, new_tag);
18673 if (try tag_ty.onePossibleValue(pt) == null) {
18674 _ = try block.addBinOp(.set_union_tag, base_ptr, .fromValue(tag_val));
1934018675 }
1934118676 return sema.makePtrConst(block, alloc);
1934218677 }
......@@ -19409,20 +18744,24 @@ fn finishStructInit(
1940918744 continue;
1941018745 }
1941118746
19412 try struct_ty.resolveStructFieldInits(pt);
18747 try sema.ensureFieldInitsResolved(struct_ty);
1941318748
19414 const field_init = struct_type.fieldInit(ip, i);
19415 if (field_init == .none) {
19416 const field_name = struct_type.field_names.get(ip)[i];
19417 const template = "missing struct field: {f}";
19418 const args = .{field_name.fmt(ip)};
19419 if (root_msg) |msg| {
19420 try sema.errNote(init_src, msg, template, args);
19421 } else {
19422 root_msg = try sema.errMsg(init_src, template, args);
19423 }
18749 const field_default: InternPool.Index = d: {
18750 if (struct_type.field_defaults.len == 0) break :d .none;
18751 break :d struct_type.field_defaults.get(ip)[i];
18752 };
18753 if (field_default != .none) {
18754 field_inits[i] = .fromIntern(field_default);
18755 continue;
18756 }
18757
18758 const field_name = struct_type.field_names.get(ip)[i];
18759 const template = "missing struct field: {f}";
18760 const args = .{field_name.fmt(ip)};
18761 if (root_msg) |msg| {
18762 try sema.errNote(init_src, msg, template, args);
1942418763 } else {
19425 field_inits[i] = Air.internedToRef(field_init);
18764 root_msg = try sema.errMsg(init_src, template, args);
1942618765 }
1942718766 }
1942818767 },
......@@ -19453,7 +18792,7 @@ fn finishStructInit(
1945318792 return sema.addConstantMaybeRef(final_val.toIntern(), is_ref);
1945418793 };
1945518794
19456 if (try struct_ty.comptimeOnlySema(pt)) {
18795 if (struct_ty.comptimeOnly(zcu)) {
1945718796 return sema.failWithNeededComptime(block, block.src(.{ .init_elem = .{
1945818797 .init_node_offset = init_src.offset.node_offset.x,
1945918798 .elem_index = @intCast(runtime_index),
......@@ -19468,9 +18807,8 @@ fn finishStructInit(
1946818807 }
1946918808
1947018809 if (is_ref) {
19471 try struct_ty.resolveLayout(pt);
1947218810 const target = zcu.getTarget();
19473 const alloc_ty = try pt.ptrTypeSema(.{
18811 const alloc_ty = try pt.ptrType(.{
1947418812 .child = result_ty.toIntern(),
1947518813 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1947618814 });
......@@ -19489,7 +18827,6 @@ fn finishStructInit(
1948918827 .init_node_offset = init_src.offset.node_offset.x,
1949018828 .elem_index = @intCast(runtime_index),
1949118829 } }));
19492 try struct_ty.resolveStructFieldInits(pt);
1949318830 const struct_val = try block.addAggregateInit(struct_ty, field_inits);
1949418831 return sema.coerce(block, result_ty, struct_val, init_src);
1949518832}
......@@ -19585,12 +18922,11 @@ fn structInitAnon(
1958518922 break :rs runtime_index;
1958618923 };
1958718924
19588 // We treat anonymous struct types as reified types, because there are similarities:
19589 // * They use a form of structural equivalence, which we can easily model using a custom hash
19590 // * They do not have captures
19591 // * They immediately have their fields resolved
19592 // In general, other code should treat anon struct types and reified struct types identically,
19593 // so there's no point having a separate `InternPool.NamespaceType` field for them.
18925 // We treat anonymous struct types as reified types, because there are similarities: they have
18926 // no captures, and instead use a form of structural equivalence which we can easy represent by
18927 // hashing the field names/types/values. They also perform layout resolution immediately. These
18928 // similarities mean that other code should actually treat anon struct types and reified struct
18929 // types identically anyway, so sharing the representation makes everything simpler.
1959418930 const type_hash: u64 = hash: {
1959518931 var hasher = std.hash.Wyhash.init(0);
1959618932 hasher.update(std.mem.sliceAsBytes(types));
......@@ -19599,36 +18935,36 @@ fn structInitAnon(
1959918935 break :hash hasher.final();
1960018936 };
1960118937 const tracked_inst = try block.trackZir(inst);
19602 const struct_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
19603 .layout = .auto,
18938 const struct_ty: Type = switch (try ip.getStructType(gpa, io, pt.tid, .{
1960418939 .fields_len = extra_data.fields_len,
19605 .known_non_opv = false,
19606 .requires_comptime = .unknown,
18940 .layout = .auto,
18941 .explicit_packed_backing_type = .none,
1960718942 .any_comptime_fields = any_values,
19608 .any_default_inits = any_values,
19609 .inits_resolved = true,
19610 .any_aligned_fields = false,
18943 .any_field_defaults = any_values,
18944 .any_field_aligns = false,
1961118945 .key = .{ .reified = .{
1961218946 .zir_index = tracked_inst,
1961318947 .type_hash = type_hash,
1961418948 } },
19615 }, false)) {
18949 })) {
1961618950 .wip => |wip| ty: {
1961718951 errdefer wip.cancel(ip, pt.tid);
19618 const type_name = try sema.createTypeName(block, .anon, "struct", inst, wip.index);
19619 wip.setName(ip, type_name.name, type_name.nav);
18952 // MLUGG TODO obvs this sux
18953 const anon_prefix = (try sema.createTypeName(block, .anon, "struct", inst)).anon_prefix;
18954 wip.setName(ip, try ip.getOrPutStringFmt(gpa, io, pt.tid, "{s}_{d}", .{ anon_prefix, @intFromEnum(wip.index) }, .no_embedded_nulls), .none);
1962018955
1962118956 const struct_type = ip.loadStructType(wip.index);
1962218957
19623 for (names, values, 0..) |name, init_val, field_idx| {
19624 assert(struct_type.addFieldName(ip, name) == null);
19625 if (init_val != .none) struct_type.setFieldComptime(ip, field_idx);
18958 for (names, values) |name, init_val| {
18959 assert(wip.nextField(ip, name, init_val != .none) == null); // AstGen validated no duplicates for us
1962618960 }
1962718961
18962 // Populating these means the type is already resolved; we don't need to add it to `zcu.outdated` or anything.
18963 // That's important because type resolution relies on types being declared.
1962818964 @memcpy(struct_type.field_types.get(ip), types);
19629 if (any_values) {
19630 @memcpy(struct_type.field_inits.get(ip), values);
19631 }
18965 @memcpy(struct_type.field_defaults.get(ip), if (any_values) values else @as([]const InternPool.Index, &.{}));
18966
18967 try type_resolution.finishStructLayout(sema, block, src, wip.index, &struct_type);
1963218968
1963318969 const new_namespace_index = try pt.createNamespace(.{
1963418970 .parent = block.namespace.toOptional(),
......@@ -19636,7 +18972,6 @@ fn structInitAnon(
1963618972 .file_scope = block.getFileScopeIndex(zcu),
1963718973 .generation = zcu.generation,
1963818974 });
19639 try zcu.comp.queueJob(.{ .resolve_type_fully = wip.index });
1964018975 codegen_type: {
1964118976 if (zcu.comp.config.use_llvm) break :codegen_type;
1964218977 if (block.ownerModule().strip) break :codegen_type;
......@@ -19644,22 +18979,21 @@ fn structInitAnon(
1964418979 try zcu.comp.queueJob(.{ .link_type = wip.index });
1964518980 }
1964618981 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
19647 break :ty wip.finish(ip, new_namespace_index);
18982 break :ty .fromInterned(wip.finish(ip, new_namespace_index));
1964818983 },
19649 .existing => |ty| ty,
18984 .existing => |ty| .fromInterned(ty),
1965018985 };
19651 try sema.declareDependency(.{ .interned = struct_ty });
1965218986 try sema.addTypeReferenceEntry(src, struct_ty);
1965318987
1965418988 _ = opt_runtime_index orelse {
19655 const struct_val = try pt.aggregateValue(.fromInterned(struct_ty), values);
18989 const struct_val = try pt.aggregateValue(struct_ty, values);
1965618990 return sema.addConstantMaybeRef(struct_val.toIntern(), is_ref);
1965718991 };
1965818992
1965918993 if (is_ref) {
1966018994 const target = zcu.getTarget();
19661 const alloc_ty = try pt.ptrTypeSema(.{
19662 .child = struct_ty,
18995 const alloc_ty = try pt.ptrType(.{
18996 .child = struct_ty.toIntern(),
1966318997 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1966418998 });
1966518999 const alloc = try block.addTy(.alloc, alloc_ty);
......@@ -19672,7 +19006,7 @@ fn structInitAnon(
1967219006 };
1967319007 extra_index = item.end;
1967419008
19675 const field_ptr_ty = try pt.ptrTypeSema(.{
19009 const field_ptr_ty = try pt.ptrType(.{
1967619010 .child = field_ty,
1967719011 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1967819012 });
......@@ -19697,7 +19031,7 @@ fn structInitAnon(
1969719031 element_refs[i] = try sema.resolveInst(item.data.init);
1969819032 }
1969919033
19700 return block.addAggregateInit(.fromInterned(struct_ty), element_refs);
19034 return block.addAggregateInit(struct_ty, element_refs);
1970119035}
1970219036
1970319037fn zirArrayInit(
......@@ -19737,17 +19071,16 @@ fn zirArrayInit(
1973719071 } });
1973819072 // Less inits than needed.
1973919073 if (i + 2 > args.len) if (is_tuple) {
19740 const default_val = array_ty.structFieldDefaultValue(i, zcu).toIntern();
19741 if (default_val == .unreachable_value) {
19074 const default_val = array_ty.structFieldDefaultValue(i, zcu) orelse {
1974219075 const template = "missing tuple field with index {d}";
1974319076 if (root_msg) |msg| {
1974419077 try sema.errNote(src, msg, template, .{i});
1974519078 } else {
1974619079 root_msg = try sema.errMsg(src, template, .{i});
1974719080 }
19748 } else {
19749 dest.* = Air.internedToRef(default_val);
19750 }
19081 continue;
19082 };
19083 dest.* = .fromValue(default_val);
1975119084 continue;
1975219085 } else {
1975319086 dest.* = Air.internedToRef(sentinel_val.?.toIntern());
......@@ -19759,11 +19092,9 @@ fn zirArrayInit(
1975919092 const elem_ty = if (is_tuple)
1976019093 array_ty.fieldType(i, zcu)
1976119094 else
19762 array_ty.elemType2(zcu);
19095 array_ty.childType(zcu);
1976319096 dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src);
1976419097 if (is_tuple) {
19765 if (array_ty.structFieldIsComptime(i, zcu))
19766 try array_ty.resolveStructFieldInits(pt);
1976719098 if (try array_ty.structFieldValueComptime(pt, i)) |field_val| {
1976819099 const init_val = try sema.resolveConstValue(block, elem_src, dest.*, .{ .simple = .stored_to_comptime_field });
1976919100 if (!field_val.eql(init_val, elem_ty, zcu)) {
......@@ -19798,7 +19129,7 @@ fn zirArrayInit(
1979819129
1979919130 if (is_ref) {
1980019131 const target = zcu.getTarget();
19801 const alloc_ty = try pt.ptrTypeSema(.{
19132 const alloc_ty = try pt.ptrType(.{
1980219133 .child = result_ty.toIntern(),
1980319134 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1980419135 });
......@@ -19807,7 +19138,7 @@ fn zirArrayInit(
1980719138
1980819139 if (is_tuple) {
1980919140 for (resolved_args, 0..) |arg, i| {
19810 const elem_ptr_ty = try pt.ptrTypeSema(.{
19141 const elem_ptr_ty = try pt.ptrType(.{
1981119142 .child = array_ty.fieldType(i, zcu).toIntern(),
1981219143 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1981319144 });
......@@ -19820,8 +19151,8 @@ fn zirArrayInit(
1982019151 return sema.makePtrConst(block, alloc);
1982119152 }
1982219153
19823 const elem_ptr_ty = try pt.ptrTypeSema(.{
19824 .child = array_ty.elemType2(zcu).toIntern(),
19154 const elem_ptr_ty = try pt.ptrType(.{
19155 .child = array_ty.childType(zcu).toIntern(),
1982519156 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1982619157 });
1982719158 const elem_ptr_ty_ref = Air.internedToRef(elem_ptr_ty.toIntern());
......@@ -19932,14 +19263,14 @@ fn arrayInitAnon(
1993219263
1993319264 if (is_ref) {
1993419265 const target = sema.pt.zcu.getTarget();
19935 const alloc_ty = try pt.ptrTypeSema(.{
19266 const alloc_ty = try pt.ptrType(.{
1993619267 .child = tuple_ty.toIntern(),
1993719268 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1993819269 });
1993919270 const alloc = try block.addTy(.alloc, alloc_ty);
1994019271 for (operands, 0..) |operand, i_usize| {
1994119272 const i: u32 = @intCast(i_usize);
19942 const field_ptr_ty = try pt.ptrTypeSema(.{
19273 const field_ptr_ty = try pt.ptrType(.{
1994319274 .child = types[i],
1994419275 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
1994519276 });
......@@ -19971,6 +19302,7 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
1997119302 const field_src = block.builtinCallArgSrc(inst_data.src_node, 1);
1997219303 const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type);
1997319304 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, .{ .simple = .field_name });
19305 try sema.ensureLayoutResolved(aggregate_ty);
1997419306 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
1997519307}
1997619308
......@@ -19990,9 +19322,11 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
1999019322 const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(zcu);
1999119323 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
1999219324 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_field_name, .no_embedded_nulls);
19325 try sema.ensureLayoutResolved(aggregate_ty);
1999319326 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
1999419327}
1999519328
19329/// Asserts that the layout of `aggregate_ty` is resolved.
1999619330fn fieldType(
1999719331 sema: *Sema,
1999819332 block: *Block,
......@@ -20006,7 +19340,6 @@ fn fieldType(
2000619340 const ip = &zcu.intern_pool;
2000719341 var cur_ty = aggregate_ty;
2000819342 while (true) {
20009 try cur_ty.resolveFields(pt);
2001019343 switch (cur_ty.zigTypeTag(zcu)) {
2001119344 .@"struct" => switch (ip.indexToKey(cur_ty.toIntern())) {
2001219345 .tuple_type => |tuple| {
......@@ -20024,10 +19357,11 @@ fn fieldType(
2002419357 },
2002519358 .@"union" => {
2002619359 const union_obj = zcu.typeToUnion(cur_ty).?;
20027 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
19360 const enum_obj = ip.loadEnumType(union_obj.enum_tag_type);
19361 const field_index = enum_obj.nameIndex(ip, field_name) orelse
2002819362 return sema.failWithBadUnionFieldAccess(block, cur_ty, union_obj, field_src, field_name);
2002919363 const field_ty = union_obj.field_types.get(ip)[field_index];
20030 return Air.internedToRef(field_ty);
19364 return .fromIntern(field_ty);
2003119365 },
2003219366 .optional => {
2003319367 // Struct/array init through optional requires the child type to not be a pointer.
......@@ -20056,7 +19390,6 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
2005619390 const zcu = pt.zcu;
2005719391 const ip = &zcu.intern_pool;
2005819392 const stack_trace_ty = try sema.getBuiltinType(block.nodeOffset(.zero), .StackTrace);
20059 try stack_trace_ty.resolveFields(pt);
2006019393 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
2006119394 const opt_ptr_stack_trace_ty = try pt.optionalType(ptr_stack_trace_ty.toIntern());
2006219395
......@@ -20064,7 +19397,7 @@ fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
2006419397 .func => |func| if (ip.funcAnalysisUnordered(func).has_error_trace and block.ownerModule().error_tracing) {
2006519398 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
2006619399 },
20067 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
19400 .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {},
2006819401 }
2006919402 return Air.internedToRef(try pt.intern(.{ .opt = .{
2007019403 .ty = opt_ptr_stack_trace_ty.toIntern(),
......@@ -20083,15 +19416,16 @@ fn zirFrame(
2008319416}
2008419417
2008519418fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20086 const zcu = sema.pt.zcu;
19419 const pt = sema.pt;
19420 const zcu = pt.zcu;
2008719421 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
2008819422 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0);
2008919423 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
2009019424 if (ty.isNoReturn(zcu)) {
2009119425 return sema.fail(block, operand_src, "no align available for type '{f}'", .{ty.fmt(sema.pt)});
2009219426 }
20093 const val = try ty.lazyAbiAlignment(sema.pt);
20094 return Air.internedToRef(val.toIntern());
19427 try sema.ensureLayoutResolved(ty);
19428 return .fromValue(try pt.intValue(.comptime_int, ty.abiAlignment(zcu).toByteUnits().?));
2009519429}
2009619430
2009719431fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -20249,7 +19583,6 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2024919583 const pt = sema.pt;
2025019584 const zcu = pt.zcu;
2025119585 const ip = &zcu.intern_pool;
20252 try operand_ty.resolveLayout(pt);
2025319586 const enum_ty = switch (operand_ty.zigTypeTag(zcu)) {
2025419587 .enum_literal => {
2025519588 const val = (try sema.resolveDefinedValue(block, operand_src, operand)).?;
......@@ -20332,7 +19665,7 @@ fn zirReifySliceArgTy(
2033219665 // zig fmt: on
2033319666 };
2033419667
20335 const operand_ty = try pt.ptrTypeSema(.{
19668 const operand_ty = try pt.ptrType(.{
2033619669 .child = in_scalar_ty.toIntern(),
2033719670 .flags = .{ .size = .slice, .is_const = true },
2033819671 });
......@@ -20342,7 +19675,7 @@ fn zirReifySliceArgTy(
2034219675 const operand_val = try sema.resolveConstDefinedValue(block, src, operand_coerced, .{ .simple = comptime_reason });
2034319676 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
2034419677 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null);
20345 const len = try len_val.toUnsignedIntSema(pt);
19678 const len = len_val.toUnsignedInt(zcu);
2034619679
2034719680 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
2034819681 .len = len,
......@@ -20370,7 +19703,7 @@ fn zirReifyEnumValueSliceTy(
2037019703 const operand_val = try sema.resolveConstDefinedValue(block, field_names_src, operand_coerced, .{ .simple = .enum_field_names });
2037119704 const len_val: Value = .fromInterned(zcu.intern_pool.indexToKey(operand_val.toIntern()).slice.len);
2037219705 if (len_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, field_names_src, null);
20373 const len = try len_val.toUnsignedIntSema(pt);
19706 const len = len_val.toUnsignedInt(zcu);
2037419707
2037519708 return .fromType(try pt.singleConstPtrType(try pt.arrayType(.{
2037619709 .len = len,
......@@ -20422,6 +19755,7 @@ fn zirReifyTuple(
2042219755 if (field_ty_val.isUndef(zcu)) {
2042319756 return sema.failWithUseOfUndef(block, operand_src, null);
2042419757 }
19758 try sema.validateTupleFieldType(block, field_ty_val.toType(), operand_src);
2042519759 field_ty.* = field_ty_val.toIntern();
2042619760 }
2042719761
......@@ -20516,7 +19850,7 @@ fn zirReifyPointer(
2051619850 }
2051719851 }
2051819852
20519 return .fromType(try pt.ptrTypeSema(.{
19853 return .fromType(try pt.ptrType(.{
2052019854 .child = elem_ty.toIntern(),
2052119855 .sentinel = if (opt_sentinel) |s| s.toIntern() else .none,
2052219856 .flags = .{
......@@ -20571,6 +19905,7 @@ fn zirReifyFn(
2057119905 const param_attrs_arr = try sema.derefSliceAsArray(block, param_attrs_src, param_attrs_slice, .{ .simple = .fn_param_attrs });
2057219906
2057319907 const ret_ty = try sema.resolveType(block, ret_ty_src, extra.ret_ty);
19908 try sema.ensureLayoutResolved(ret_ty);
2057419909
2057519910 const fn_attrs_uncoerced = try sema.resolveInst(extra.fn_attrs);
2057619911 const fn_attrs_coerced = try sema.coerce(block, fn_attrs_ty, fn_attrs_uncoerced, fn_attrs_src);
......@@ -20595,7 +19930,8 @@ fn zirReifyFn(
2059519930 param_types_src,
2059619931 fn_attrs.@"callconv",
2059719932 );
20598 if (try param_ty.comptimeOnlySema(pt)) {
19933 try sema.ensureLayoutResolved(param_ty);
19934 if (param_ty.comptimeOnly(zcu)) {
2059919935 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only parameter type '{f}'", .{param_ty.fmt(pt)});
2060019936 }
2060119937 if (param_attrs.@"noalias") {
......@@ -20621,7 +19957,7 @@ fn zirReifyFn(
2062119957 false,
2062219958 false,
2062319959 );
20624 if (try ret_ty.comptimeOnlySema(pt)) {
19960 if (ret_ty.comptimeOnly(zcu)) {
2062519961 return sema.fail(block, param_attrs_src, "cannot reify function type with comptime-only return type '{f}'", .{ret_ty.fmt(pt)});
2062619962 }
2062719963
......@@ -20632,7 +19968,6 @@ fn zirReifyFn(
2063219968 .return_type = ret_ty.toIntern(),
2063319969 .cc = fn_attrs.@"callconv",
2063419970 .is_var_args = fn_attrs.varargs,
20635 .is_generic = false,
2063619971 .is_noinline = false,
2063719972 }));
2063819973}
......@@ -20791,8 +20126,7 @@ fn zirReifyStruct(
2079120126 field_attrs_src,
2079220127 .{ .simple = .struct_field_default_value },
2079320128 );
20794 // Resolve the value so that lazy values do not create distinct types.
20795 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
20129 break :d deref_val.toIntern();
2079620130 };
2079720131
2079820132 std.hash.autoHash(&hasher, .{
......@@ -20823,36 +20157,31 @@ fn zirReifyStruct(
2082320157 }
2082420158
2082520159 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
20826 .layout = layout,
2082720160 .fields_len = @intCast(fields_len),
20828 .known_non_opv = false,
20829 .requires_comptime = .unknown,
20161 .layout = layout,
20162 .explicit_packed_backing_type = if (backing_int_ty) |t| t.toIntern() else .none,
2083020163 .any_comptime_fields = any_comptime_fields,
20831 .any_default_inits = any_default_inits,
20832 .any_aligned_fields = any_aligned_fields,
20833 .inits_resolved = true,
20164 .any_field_defaults = any_default_inits,
20165 .any_field_aligns = any_aligned_fields,
2083420166 .key = .{ .reified = .{
2083520167 .zir_index = tracked_inst,
2083620168 .type_hash = hasher.final(),
2083720169 } },
20838 }, false)) {
20170 })) {
2083920171 .wip => |wip| wip,
2084020172 .existing => |ty| {
20841 try sema.declareDependency(.{ .interned = ty });
20842 try sema.addTypeReferenceEntry(src, ty);
20843 return Air.internedToRef(ty);
20173 try sema.addTypeReferenceEntry(src, .fromInterned(ty));
20174 return .fromIntern(ty);
2084420175 },
2084520176 };
2084620177 errdefer wip_ty.cancel(ip, pt.tid);
2084720178
20848 const type_name = try sema.createTypeName(
20179 _ = try (try sema.createTypeName(
2084920180 block,
2085020181 name_strategy,
2085120182 "struct",
2085220183 inst,
20853 wip_ty.index,
20854 );
20855 wip_ty.setName(ip, type_name.name, type_name.nav);
20184 )).apply(&wip_ty, pt);
2085620185
2085720186 const wip_struct_type = ip.loadStructType(wip_ty.index);
2085820187
......@@ -20860,15 +20189,9 @@ fn zirReifyStruct(
2086020189 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2086120190 const field_attrs_val = try field_attrs_arr.elemValue(pt, field_idx);
2086220191
20863 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
20864
2086520192 // Don't pass a reason; first loop acts as a check that this is valid.
2086620193 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
20867 if (wip_struct_type.addFieldName(ip, field_name)) |prev_index| {
20868 _ = prev_index; // TODO: better source location
20869 return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
20870 }
20871
20194 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
2087220195 const field_attr_comptime = try field_attrs_val.fieldValue(pt, std.meta.fieldIndex(
2087320196 std.builtin.Type.StructField.Attributes,
2087420197 "comptime",
......@@ -20882,14 +20205,9 @@ fn zirReifyStruct(
2088220205 "default_value_ptr",
2088320206 ).?);
2088420207
20885 if (field_attr_align.optionalValue(zcu)) |field_align_val| {
20886 assert(layout != .@"packed");
20887 const bytes = try field_align_val.toUnsignedIntSema(pt);
20888 const a = try sema.validateAlign(block, field_attrs_src, bytes);
20889 wip_struct_type.field_aligns.get(ip)[field_idx] = a;
20890 } else if (any_aligned_fields) {
20891 assert(layout != .@"packed");
20892 wip_struct_type.field_aligns.get(ip)[field_idx] = .none;
20208 if (wip_ty.nextField(ip, field_name, field_attr_comptime.toBool())) |prev_index| {
20209 _ = prev_index; // TODO: better source location
20210 return sema.fail(block, field_names_src, "duplicate struct field name {f}", .{field_name.fmt(ip)});
2089320211 }
2089420212
2089520213 const field_default: InternPool.Index = d: {
......@@ -20902,20 +20220,11 @@ fn zirReifyStruct(
2090220220 if (deref_val.canMutateComptimeVarState(zcu)) {
2090320221 return sema.failWithContainsReferenceToComptimeVar(block, field_attrs_src, field_name, "field default value", deref_val);
2090420222 }
20905 break :d (try sema.resolveLazyValue(deref_val)).toIntern();
20223 break :d deref_val.toIntern();
2090620224 };
2090720225
20908 if (field_attr_comptime.toBool()) {
20909 assert(layout == .auto);
20910 if (field_default == .none) {
20911 return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{});
20912 }
20913 wip_struct_type.setFieldComptime(ip, field_idx);
20914 }
20915
20916 wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern();
20917 if (field_default != .none) {
20918 wip_struct_type.field_inits.get(ip)[field_idx] = field_default;
20226 if (field_attr_comptime.toBool() and field_default == .none) {
20227 return sema.fail(block, field_attrs_src, "comptime field without default initialization value", .{});
2091920228 }
2092020229
2092120230 switch (field_ty.zigTypeTag(zcu)) {
......@@ -20945,32 +20254,55 @@ fn zirReifyStruct(
2094520254 break :msg msg;
2094620255 });
2094720256 },
20948 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
20257 .@"packed" => if (!field_ty.packable(zcu)) {
2094920258 return sema.failWithOwnedErrorMsg(block, msg: {
2095020259 const msg = try sema.errMsg(field_types_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2095120260 errdefer msg.destroy(gpa);
20952 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
20261 try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty);
2095320262 try sema.addDeclaredHereNote(msg, field_ty);
2095420263 break :msg msg;
2095520264 });
2095620265 },
2095720266 }
20267
20268 wip_struct_type.field_types.get(ip)[field_idx] = field_ty.toIntern();
20269 if (field_default != .none) {
20270 wip_struct_type.field_defaults.get(ip)[field_idx] = field_default;
20271 }
20272
20273 if (field_attr_align.optionalValue(zcu)) |field_align_val| {
20274 assert(layout != .@"packed");
20275 const bytes = field_align_val.toUnsignedInt(zcu);
20276 const a = try sema.validateAlign(block, field_attrs_src, bytes);
20277 wip_struct_type.field_aligns.get(ip)[field_idx] = a;
20278 } else if (any_aligned_fields) {
20279 assert(layout != .@"packed");
20280 wip_struct_type.field_aligns.get(ip)[field_idx] = .none;
20281 }
2095820282 }
2095920283
2096020284 if (layout == .@"packed") {
20961 var fields_bit_sum: u64 = 0;
20962 for (0..wip_struct_type.field_types.len) |field_idx| {
20285 var field_bits: u64 = 0;
20286 for (0..fields_len) |field_idx| {
2096320287 const field_ty: Type = .fromInterned(wip_struct_type.field_types.get(ip)[field_idx]);
20964 try field_ty.resolveLayout(pt);
20965 fields_bit_sum += field_ty.bitSize(zcu);
20966 }
20967 if (backing_int_ty) |ty| {
20968 try sema.checkBackingIntType(block, src, ty, fields_bit_sum);
20969 wip_struct_type.setBackingIntType(ip, io, ty.toIntern());
20970 } else {
20971 const ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
20972 wip_struct_type.setBackingIntType(ip, io, ty.toIntern());
20288 try sema.ensureLayoutResolved(field_ty);
20289 field_bits += field_ty.bitSize(zcu);
2097320290 }
20291 try type_resolution.resolvePackedStructBackingInt(
20292 sema,
20293 block,
20294 field_bits,
20295 .fromInterned(wip_ty.index),
20296 &wip_struct_type,
20297 );
20298 } else {
20299 try type_resolution.finishStructLayout(
20300 sema,
20301 block,
20302 src,
20303 wip_ty.index,
20304 &wip_struct_type,
20305 );
2097420306 }
2097520307
2097620308 const new_namespace_index = try pt.createNamespace(.{
......@@ -20980,16 +20312,13 @@ fn zirReifyStruct(
2098020312 .generation = zcu.generation,
2098120313 });
2098220314
20983 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
2098420315 codegen_type: {
2098520316 if (zcu.comp.config.use_llvm) break :codegen_type;
2098620317 if (block.ownerModule().strip) break :codegen_type;
20987 // This job depends on any resolve_type_fully jobs queued up before it.
2098820318 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2098920319 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2099020320 }
20991 try sema.declareDependency(.{ .interned = wip_ty.index });
20992 try sema.addTypeReferenceEntry(src, wip_ty.index);
20321 try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index));
2099320322 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
2099420323 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
2099520324}
......@@ -21134,62 +20463,52 @@ fn zirReifyUnion(
2113420463 }
2113520464
2113620465 // Some basic validation to avoid a bogus `getUnionType` call...
21137 const explicit_tag_ty: ?Type = if (arg_ty_val.optionalValue(zcu)) |arg_ty| ty: {
20466 const explicit_tag_ty: ?Type, const explicit_packed_backing_type: ?Type = ty: {
20467 const arg_ty = arg_ty_val.optionalValue(zcu) orelse break :ty .{ null, null };
2113820468 switch (layout) {
21139 .@"extern", .@"packed" => return sema.fail(block, arg_ty_src, "{t} union does not support enum tag type", .{layout}),
21140 .auto => {},
20469 .@"extern" => return sema.fail(block, arg_ty_src, "extern union does not support enum tag type", .{}),
20470 .@"packed" => break :ty .{ null, arg_ty.toType() },
20471 .auto => break :ty .{ arg_ty.toType(), null },
2114120472 }
21142 break :ty arg_ty.toType();
21143 } else null;
20473 };
2114420474 if (any_aligned_fields and layout == .@"packed") {
2114520475 return sema.fail(block, field_attrs_src, "packed union fields cannot be aligned", .{});
2114620476 }
2114720477
2114820478 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{
21149 .flags = .{
21150 .layout = layout,
21151 .status = .none,
21152 .runtime_tag = rt: {
21153 if (explicit_tag_ty != null) break :rt .tagged;
21154 if (layout == .auto and block.wantSafeTypes()) break :rt .safety;
21155 break :rt .none;
21156 },
21157 .any_aligned_fields = any_aligned_fields,
21158 .requires_comptime = .unknown,
21159 .assumed_runtime_bits = false,
21160 .assumed_pointer_aligned = false,
21161 .alignment = .none,
21162 },
2116320479 .fields_len = @intCast(fields_len),
21164 .enum_tag_ty = .none, // set later because not yet validated
21165 .field_types = &.{}, // set later
21166 .field_aligns = &.{}, // set later
20480 .layout = layout,
20481 .explicit_packed_backing_type = if (explicit_packed_backing_type) |t| t.toIntern() else .none,
20482 .runtime_tag = rt: {
20483 if (explicit_tag_ty != null) break :rt .tagged;
20484 if (layout == .auto and block.wantSafeTypes()) break :rt .safety;
20485 break :rt .none;
20486 },
20487 .have_explicit_enum_tag = explicit_tag_ty != null,
20488 .any_field_aligns = any_aligned_fields,
2116720489 .key = .{ .reified = .{
2116820490 .zir_index = tracked_inst,
2116920491 .type_hash = hasher.final(),
2117020492 } },
21171 }, false)) {
20493 })) {
2117220494 .wip => |wip| wip,
2117320495 .existing => |ty| {
21174 try sema.declareDependency(.{ .interned = ty });
21175 try sema.addTypeReferenceEntry(src, ty);
21176 return Air.internedToRef(ty);
20496 try sema.addTypeReferenceEntry(src, .fromInterned(ty));
20497 return .fromIntern(ty);
2117720498 },
2117820499 };
2117920500 errdefer wip_ty.cancel(ip, pt.tid);
2118020501
21181 const type_name = try sema.createTypeName(
20502 const type_name = try (try sema.createTypeName(
2118220503 block,
2118320504 name_strategy,
2118420505 "union",
2118520506 inst,
21186 wip_ty.index,
21187 );
21188 wip_ty.setName(ip, type_name.name, type_name.nav);
20507 )).apply(&wip_ty, pt);
2118920508
2119020509 const loaded_union = ip.loadUnionType(wip_ty.index);
2119120510
21192 const enum_tag_ty, const has_explicit_tag = if (explicit_tag_ty) |enum_tag_ty| tag: {
20511 const generated_tag_ty: InternPool.Index = if (explicit_tag_ty) |enum_tag_ty| generated_tag: {
2119320512 if (enum_tag_ty.zigTypeTag(zcu) != .@"enum") {
2119420513 return sema.fail(block, arg_ty_src, "tag type must be an enum type", .{});
2119520514 }
......@@ -21227,26 +20546,67 @@ fn zirReifyUnion(
2122720546 try sema.addDeclaredHereNote(msg, enum_tag_ty);
2122820547 break :msg msg;
2122920548 });
21230 break :tag .{ enum_tag_ty.toIntern(), true };
21231 } else tag: {
21232 // We must track field names and set up the tag type ourselves.
21233 var field_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .empty;
21234 try field_names.ensureTotalCapacity(sema.arena, fields_len);
20549 wip_ty.setTagType(ip, enum_tag_ty.toIntern());
20550 break :generated_tag .none;
20551 } else generated_tag: {
20552 // Generate the union's hypothetical tag type.
20553 const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
20554 .fields_len = @intCast(fields_len),
20555 .explicit_int_tag_type = .none,
20556 .nonexhaustive = false,
20557 .key = .{ .generated_union_tag = wip_ty.index },
20558 })) {
20559 .existing => unreachable, // enum type is keyed on this union type which we're only just creating
20560 .wip => |wip_tag_ty| wip_tag_ty,
20561 };
20562 errdefer wip_tag_ty.cancel(ip, pt.tid);
2123520563
20564 // Set its name based on the union's name
20565 _ = wip_tag_ty.setName(ip, try ip.getOrPutStringFmt(
20566 gpa,
20567 io,
20568 pt.tid,
20569 "@typeInfo({f}).@\"union\".tag_type.?",
20570 .{type_name.fmt(ip)},
20571 .no_embedded_nulls,
20572 ), .none);
20573
20574 // Populate its fields (and report any duplicates)
2123620575 for (0..fields_len) |field_idx| {
2123720576 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2123820577 // Don't pass a reason; first loop acts as a check that this is valid.
2123920578 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
21240 const gop = field_names.getOrPutAssumeCapacity(field_name);
21241 if (gop.found_existing) {
21242 // TODO: better source location
21243 return sema.fail(block, field_names_src, "duplicate union field {f}", .{field_name.fmt(ip)});
21244 }
20579 if (wip_tag_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: {
20580 const msg = try sema.errMsg(src, "duplicate union field '{f}' at index '{d}", .{ field_name.fmt(ip), field_idx });
20581 errdefer msg.destroy(gpa);
20582 try sema.errNote(src, msg, "previous field at index '{d}'", .{prev_field_idx});
20583 break :msg msg;
20584 });
2124520585 }
21246 const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), wip_ty.index, type_name.name);
21247 break :tag .{ enum_tag_ty, false };
20586
20587 // Populate the enum tag type's *integer* tag type
20588 wip_tag_ty.setTagType(ip, int_tag_ty: {
20589 // Infer the int tag type from the field count
20590 const bits = Type.smallestUnsignedBits(fields_len -| 1);
20591 break :int_tag_ty (try pt.intType(.unsigned, bits)).toIntern();
20592 });
20593
20594 // Lastly, it needs a dummy namespace
20595 const enum_tag_type_namespace = try pt.createNamespace(.{
20596 .parent = block.namespace.toOptional(),
20597 .owner_type = wip_tag_ty.index,
20598 .file_scope = block.getFileScopeIndex(zcu),
20599 .generation = zcu.generation,
20600 });
20601 errdefer pt.destroyNamespace(enum_tag_type_namespace);
20602
20603 wip_ty.setTagType(ip, wip_tag_ty.index);
20604
20605 break :generated_tag wip_tag_ty.finish(ip, enum_tag_type_namespace);
2124820606 };
21249 errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
20607 // If we fail to create the union type, we must delete the generated enum tag type, since it
20608 // would hold a reference to the deleted union.
20609 errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty);
2125020610
2125120611 for (0..fields_len) |field_idx| {
2125220612 const field_ty = (try field_types_arr.elemValue(pt, field_idx)).toType();
......@@ -21279,12 +20639,12 @@ fn zirReifyUnion(
2127920639 break :msg msg;
2128020640 });
2128120641 },
21282 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
20642 .@"packed" => if (!field_ty.packable(zcu)) {
2128320643 return sema.failWithOwnedErrorMsg(block, msg: {
2128420644 const msg = try sema.errMsg(field_types_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
2128520645 errdefer msg.destroy(gpa);
2128620646
21287 try sema.explainWhyTypeIsNotPacked(msg, field_types_src, field_ty);
20647 try sema.explainWhyTypeIsNotPackable(msg, field_types_src, field_ty);
2128820648
2128920649 try sema.addDeclaredHereNote(msg, field_ty);
2129020650 break :msg msg;
......@@ -21303,8 +20663,24 @@ fn zirReifyUnion(
2130320663 }
2130420664 }
2130520665
21306 loaded_union.setTagType(ip, io, enum_tag_ty);
21307 loaded_union.setStatus(ip, io, .have_field_types);
20666 if (layout == .@"packed") {
20667 try type_resolution.resolvePackedUnionBackingInt(
20668 sema,
20669 block,
20670 .fromInterned(wip_ty.index),
20671 &loaded_union,
20672 true,
20673 );
20674 } else {
20675 try type_resolution.finishUnionLayout(
20676 sema,
20677 block,
20678 src,
20679 wip_ty.index,
20680 &loaded_union,
20681 explicit_tag_ty orelse .fromInterned(generated_tag_ty),
20682 );
20683 }
2130820684
2130920685 const new_namespace_index = try pt.createNamespace(.{
2131020686 .parent = block.namespace.toOptional(),
......@@ -21313,17 +20689,16 @@ fn zirReifyUnion(
2131320689 .generation = zcu.generation,
2131420690 });
2131520691
21316 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
2131720692 codegen_type: {
2131820693 if (zcu.comp.config.use_llvm) break :codegen_type;
2131920694 if (block.ownerModule().strip) break :codegen_type;
21320 // This job depends on any resolve_type_fully jobs queued up before it.
2132120695 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2132220696 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2132320697 }
21324 try sema.declareDependency(.{ .interned = wip_ty.index });
21325 try sema.addTypeReferenceEntry(src, wip_ty.index);
21326 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
20698 try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index));
20699 if (zcu.comp.debugIncremental()) {
20700 try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
20701 }
2132720702 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
2132820703}
2132920704
......@@ -21436,86 +20811,84 @@ fn zirReifyEnum(
2143620811 }
2143720812
2143820813 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
21439 .has_values = true,
21440 .tag_mode = if (nonexhaustive) .nonexhaustive else .explicit,
2144120814 .fields_len = @intCast(fields_len),
20815 .explicit_int_tag_type = tag_ty.toIntern(),
20816 .nonexhaustive = nonexhaustive,
2144220817 .key = .{ .reified = .{
2144320818 .zir_index = tracked_inst,
2144420819 .type_hash = hasher.final(),
2144520820 } },
21446 }, false)) {
20821 })) {
2144720822 .wip => |wip| wip,
2144820823 .existing => |ty| {
21449 try sema.declareDependency(.{ .interned = ty });
21450 try sema.addTypeReferenceEntry(src, ty);
20824 try sema.addTypeReferenceEntry(src, .fromInterned(ty));
2145120825 return .fromIntern(ty);
2145220826 },
2145320827 };
21454 var done = false;
21455 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
20828 errdefer wip_ty.cancel(ip, pt.tid);
2145620829
21457 const type_name = try sema.createTypeName(
20830 _ = try (try sema.createTypeName(
2145820831 block,
2145920832 name_strategy,
2146020833 "enum",
2146120834 inst,
21462 wip_ty.index,
21463 );
21464 wip_ty.setName(ip, type_name.name, type_name.nav);
21465
21466 const new_namespace_index = try pt.createNamespace(.{
21467 .parent = block.namespace.toOptional(),
21468 .owner_type = wip_ty.index,
21469 .file_scope = block.getFileScopeIndex(zcu),
21470 .generation = zcu.generation,
21471 });
21472
21473 try sema.declareDependency(.{ .interned = wip_ty.index });
21474 try sema.addTypeReferenceEntry(src, wip_ty.index);
21475 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
21476 wip_ty.prepare(ip, new_namespace_index);
21477 wip_ty.setTagTy(ip, tag_ty.toIntern());
21478 done = true;
20835 )).apply(&wip_ty, pt);
2147920836
2148020837 for (0..fields_len) |field_idx| {
2148120838 const field_name_val = try field_names_arr.elemValue(pt, field_idx);
2148220839 // Don't pass a reason; first loop acts as a check that this is valid.
2148320840 const field_name = try sema.sliceToIpString(block, field_names_src, field_name_val, undefined);
20841 if (wip_ty.nextField(ip, field_name, false)) |prev_field_idx| return sema.failWithOwnedErrorMsg(block, msg: {
20842 const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}' at index '{d}'", .{ field_name.fmt(ip), field_idx });
20843 errdefer msg.destroy(gpa);
20844 try sema.errNote(field_names_src, msg, "previous field at index '{d}'", .{prev_field_idx});
20845 break :msg msg;
20846 });
20847 }
2148420848
20849 const enum_obj = ip.loadEnumType(wip_ty.index);
20850 const field_value_map = enum_obj.field_value_map.unwrap().?;
20851 for (0..fields_len) |field_idx| {
2148520852 const field_val = try field_values_arr.elemValue(pt, field_idx);
21486
21487 if (wip_ty.nextField(ip, field_name, field_val.toIntern())) |conflict| {
21488 return sema.failWithOwnedErrorMsg(block, switch (conflict.kind) {
21489 .name => msg: {
21490 const msg = try sema.errMsg(field_names_src, "duplicate enum field '{f}'", .{field_name.fmt(ip)});
21491 errdefer msg.destroy(gpa);
21492 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21493 try sema.errNote(field_names_src, msg, "other field here", .{});
21494 break :msg msg;
21495 },
21496 .value => msg: {
21497 const msg = try sema.errMsg(field_values_src, "enum tag value {f} already taken", .{field_val.fmtValueSema(pt, sema)});
21498 errdefer msg.destroy(gpa);
21499 _ = conflict.prev_field_idx; // TODO: this note is incorrect
21500 try sema.errNote(field_values_src, msg, "other enum tag value here", .{});
21501 break :msg msg;
21502 },
20853 const field_values = enum_obj.field_values.get(ip);
20854 field_values[field_idx] = field_val.toIntern();
20855 const adapter: InternPool.Index.Adapter = .{ .indexes = field_values[0..field_idx] };
20856 const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val.toIntern(), adapter);
20857 if (gop.found_existing) return sema.failWithOwnedErrorMsg(block, msg: {
20858 const field_names = enum_obj.field_names.get(ip);
20859 const this_field_name = field_names[field_idx];
20860 const prev_field_name = field_names[gop.index];
20861 const msg = try sema.errMsg(field_names_src, "duplicate enum tag value '{f}' in field '{f}'", .{
20862 field_val.fmtValueSema(pt, sema),
20863 this_field_name.fmt(ip),
2150320864 });
21504 }
20865 errdefer msg.destroy(gpa);
20866 try sema.errNote(field_names_src, msg, "previous usage in field '{f}'", .{prev_field_name.fmt(ip)});
20867 break :msg msg;
20868 });
2150520869 }
2150620870
2150720871 if (nonexhaustive and fields_len > 1 and std.math.log2_int(u64, fields_len) == tag_ty.bitSize(zcu)) {
2150820872 return sema.fail(block, src, "non-exhaustive enum specified every value", .{});
2150920873 }
2151020874
20875 const new_namespace_index = try pt.createNamespace(.{
20876 .parent = block.namespace.toOptional(),
20877 .owner_type = wip_ty.index,
20878 .file_scope = block.getFileScopeIndex(zcu),
20879 .generation = zcu.generation,
20880 });
20881
2151120882 codegen_type: {
2151220883 if (zcu.comp.config.use_llvm) break :codegen_type;
2151320884 if (block.ownerModule().strip) break :codegen_type;
21514 // This job depends on any resolve_type_fully jobs queued up before it.
2151520885 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
2151620886 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
2151720887 }
21518 return Air.internedToRef(wip_ty.index);
20888
20889 try sema.addTypeReferenceEntry(src, .fromInterned(wip_ty.index));
20890 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
20891 return .fromIntern(wip_ty.finish(ip, new_namespace_index));
2151920892}
2152020893
2152120894fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
......@@ -21573,7 +20946,8 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2157320946 const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand);
2157420947
2157520948 try sema.requireRuntimeBlock(block, src, null);
21576 return block.addUnOp(.c_va_end, va_list_ref);
20949 _ = try block.addUnOp(.c_va_end, va_list_ref);
20950 return .void_value;
2157720951}
2157820952
2157920953fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
......@@ -21683,8 +21057,20 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
2168321057 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);
2168421058
2168521059 if (try sema.resolveValue(operand)) |operand_val| {
21686 const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, pt, .sema);
21687 return Air.internedToRef(result_val.toIntern());
21060 if (operand_val.isUndef(zcu)) return .fromValue(try pt.undefValue(dest_ty));
21061 if (dest_ty.zigTypeTag(zcu) != .vector) {
21062 return .fromValue(try pt.floatValue(dest_ty, operand_val.toFloat(f128, zcu)));
21063 }
21064 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_ty.vectorLen(zcu));
21065 for (dest_elems, 0..) |*out_elem, elem_idx| {
21066 const orig_elem = try operand_val.elemValue(pt, elem_idx);
21067 const casted_elem = if (orig_elem.isUndef(zcu))
21068 try pt.undefValue(dest_scalar_ty)
21069 else
21070 try pt.floatValue(dest_scalar_ty, orig_elem.toFloat(f128, zcu));
21071 out_elem.* = casted_elem.toIntern();
21072 }
21073 return .fromValue(try pt.aggregateValue(dest_ty, dest_elems));
2168821074 } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_float) {
2168921075 return sema.failWithNeededComptime(block, operand_src, .{ .simple = .casted_to_comptime_float });
2169021076 }
......@@ -21719,8 +21105,11 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2171921105 const ptr_ty = dest_ty.scalarType(zcu);
2172021106 try sema.checkPtrType(block, src, ptr_ty, true);
2172121107
21722 const elem_ty = ptr_ty.elemType2(zcu);
21723 const ptr_align = try ptr_ty.ptrAlignmentSema(pt);
21108 const elem_ty = ptr_ty.nullablePtrElem(zcu);
21109
21110 // We'll need to validate the pointer alignment.
21111 try sema.ensureLayoutResolved(elem_ty);
21112 const ptr_align = ptr_ty.ptrAlignment(zcu);
2172421113
2172521114 if (ptr_ty.isSlice(zcu)) {
2172621115 const msg = msg: {
......@@ -21746,18 +21135,9 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2174621135 }
2174721136 return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern());
2174821137 }
21749 if (try ptr_ty.comptimeOnlySema(pt)) {
21750 return sema.failWithOwnedErrorMsg(block, msg: {
21751 const msg = try sema.errMsg(src, "pointer to comptime-only type '{f}' must be comptime-known, but operand is runtime-known", .{ptr_ty.fmt(pt)});
21752 errdefer msg.destroy(sema.gpa);
21753
21754 try sema.explainWhyTypeIsComptime(msg, src, ptr_ty);
21755 break :msg msg;
21756 });
21757 }
2175821138 try sema.requireRuntimeBlock(block, src, operand_src);
2175921139 try sema.checkLogicalPtrOperation(block, src, ptr_ty);
21760 if (block.wantSafety() and (try elem_ty.hasRuntimeBitsSema(pt) or elem_ty.zigTypeTag(zcu) == .@"fn")) {
21140 if (block.wantSafety()) {
2176121141 if (!ptr_ty.isAllowzeroPtr(zcu)) {
2176221142 const is_non_zero = if (is_vector) all_non_zero: {
2176321143 const zero_usize = Air.internedToRef((try sema.splat(operand_ty, .zero_usize)).toIntern());
......@@ -21804,7 +21184,7 @@ fn ptrFromIntVal(
2180421184 }
2180521185 return sema.failWithUseOfUndef(block, operand_src, vec_idx);
2180621186 }
21807 const addr = try operand_val.toUnsignedIntSema(pt);
21187 const addr = operand_val.toUnsignedInt(zcu);
2180821188 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)
2180921189 return sema.fail(block, operand_src, "pointer type '{f}' does not allow address zero", .{ptr_ty.fmt(pt)});
2181021190 if (addr != 0 and ptr_align != .none) {
......@@ -22043,8 +21423,8 @@ fn ptrCastFull(
2204321423 const src_info = operand_ty.ptrInfo(zcu);
2204421424 const dest_info = dest_ty.ptrInfo(zcu);
2204521425
22046 try Type.fromInterned(src_info.child).resolveLayout(pt);
22047 try Type.fromInterned(dest_info.child).resolveLayout(pt);
21426 try sema.ensureLayoutResolved(.fromInterned(src_info.child));
21427 try sema.ensureLayoutResolved(.fromInterned(dest_info.child));
2204821428
2204921429 const DestSliceLen = union(enum) {
2205021430 undef,
......@@ -22079,9 +21459,9 @@ fn ptrCastFull(
2207921459 .pointer => operand_val,
2208021460 else => unreachable,
2208121461 };
22082 const slice_len_resolved = try sema.resolveLazyValue(.fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern())));
22083 if (slice_len_resolved.isUndef(zcu)) break :len .undef;
22084 break :src .{ .fromInterned(src_info.child), slice_len_resolved.toUnsignedInt(zcu) };
21462 const slice_len: Value = .fromInterned(zcu.intern_pool.sliceLen(slice_val.toIntern()));
21463 if (slice_len.isUndef(zcu)) break :len .undef;
21464 break :src .{ .fromInterned(src_info.child), slice_len.toUnsignedInt(zcu) };
2208521465 },
2208621466 .many, .c => {
2208721467 return sema.fail(block, src, "cannot infer length of slice from {s}", .{pointerSizeString(src_info.flags.size)});
......@@ -22395,7 +21775,7 @@ fn ptrCastFull(
2239521775 };
2239621776
2239721777 if (dest_align.compare(.gt, src_align)) {
22398 if (try ptr_val.getUnsignedIntSema(pt)) |addr| {
21778 if (ptr_val.getUnsignedInt(zcu)) |addr| {
2239921779 const masked_addr = if (Type.fromInterned(dest_info.child).fnPtrMaskOrNull(zcu)) |mask|
2240021780 addr & mask
2240121781 else
......@@ -22464,7 +21844,7 @@ fn ptrCastFull(
2246421844 // Now, do an addrspace cast if necessary!
2246521845 if (!flags.addrspace_cast) break :ptr pre_addrspace_cast;
2246621846
22467 const intermediate_ptr_ty = try pt.ptrTypeSema(info: {
21847 const intermediate_ptr_ty = try pt.ptrType(info: {
2246821848 var info = src_info;
2246921849 info.flags.address_space = dest_info.flags.address_space;
2247021850 break :info info;
......@@ -22638,7 +22018,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
2263822018 if (flags.volatile_cast) ptr_info.flags.is_volatile = false;
2263922019
2264022020 const dest_ty = blk: {
22641 const dest_ty = try pt.ptrTypeSema(ptr_info);
22021 const dest_ty = try pt.ptrType(ptr_info);
2264222022 if (operand_ty.zigTypeTag(zcu) == .optional) {
2264322023 break :blk try pt.optionalType(dest_ty.toIntern());
2264422024 }
......@@ -22678,48 +22058,24 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2267822058 return sema.coerce(block, dest_ty, operand, operand_src);
2267922059 }
2268022060
22681 const dest_info = dest_scalar_ty.intInfo(zcu);
22061 if (try dest_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2268222062
22683 if (try sema.typeHasOnePossibleValue(dest_ty)) |val| {
22684 return Air.internedToRef(val.toIntern());
22685 }
22063 const dest_info = dest_scalar_ty.intInfo(zcu);
2268622064
2268722065 if (operand_scalar_ty.zigTypeTag(zcu) != .comptime_int) {
2268822066 const operand_info = operand_ty.intInfo(zcu);
22689 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
22690 return Air.internedToRef(val.toIntern());
22691 }
2269222067
2269322068 if (operand_info.signedness != dest_info.signedness) {
2269422069 return sema.fail(block, operand_src, "expected {s} integer type, found '{f}'", .{
2269522070 @tagName(dest_info.signedness), operand_ty.fmt(pt),
2269622071 });
2269722072 }
22698 switch (std.math.order(dest_info.bits, operand_info.bits)) {
22699 .gt => {
22700 const msg = msg: {
22701 const msg = try sema.errMsg(
22702 src,
22703 "destination type '{f}' has more bits than source type '{f}'",
22704 .{ dest_ty.fmt(pt), operand_ty.fmt(pt) },
22705 );
22706 errdefer msg.destroy(sema.gpa);
22707 try sema.errNote(src, msg, "destination type has {d} bits", .{
22708 dest_info.bits,
22709 });
22710 try sema.errNote(operand_src, msg, "operand type has {d} bits", .{
22711 operand_info.bits,
22712 });
22713 break :msg msg;
22714 };
22715 return sema.failWithOwnedErrorMsg(block, msg);
22716 },
22717 .eq => return operand,
22718 .lt => {},
22073 if (dest_info.bits >= operand_info.bits) {
22074 return sema.coerce(block, dest_ty, operand, operand_src);
2271922075 }
2272022076 }
2272122077
22722 if (try sema.resolveValueResolveLazy(operand)) |val| {
22078 if (try sema.resolveValue(operand)) |val| {
2272322079 const result_val = try arith.truncate(sema, val, operand_ty, dest_ty, dest_info.signedness, dest_info.bits);
2272422080 return Air.internedToRef(result_val.toIntern());
2272522081 }
......@@ -22745,10 +22101,6 @@ fn zirBitCount(
2274522101 _ = try sema.checkIntOrVector(block, operand, operand_src);
2274622102 const bits = operand_ty.intInfo(zcu).bits;
2274722103
22748 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
22749 return Air.internedToRef(val.toIntern());
22750 }
22751
2275222104 const result_scalar_ty = try pt.smallestUnsignedInt(bits);
2275322105 switch (operand_ty.zigTypeTag(zcu)) {
2275422106 .vector => {
......@@ -22774,7 +22126,7 @@ fn zirBitCount(
2277422126 }
2277522127 },
2277622128 .int => {
22777 if (try sema.resolveValueResolveLazy(operand)) |val| {
22129 if (try sema.resolveValue(operand)) |val| {
2277822130 if (val.isUndef(zcu)) return pt.undefRef(result_scalar_ty);
2277922131 return pt.intRef(result_scalar_ty, comptimeOp(val, operand_ty, zcu));
2278022132 } else {
......@@ -22803,9 +22155,6 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2280322155 .{ scalar_ty.fmt(pt), bits },
2280422156 );
2280522157 }
22806 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
22807 return .fromValue(val);
22808 }
2280922158 if (try sema.resolveValue(operand)) |operand_val| {
2281022159 return .fromValue(try arith.byteSwap(sema, operand_val, operand_ty));
2281122160 }
......@@ -22819,9 +22168,6 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2281922168 const operand_ty = sema.typeOf(operand);
2282022169 _ = try sema.checkIntOrVector(block, operand, operand_src);
2282122170
22822 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
22823 return .fromValue(val);
22824 }
2282522171 if (try sema.resolveValue(operand)) |operand_val| {
2282622172 return .fromValue(try arith.bitReverse(sema, operand_val, operand_ty));
2282722173 }
......@@ -22849,10 +22195,11 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2284922195 const ty = try sema.resolveType(block, ty_src, extra.lhs);
2285022196 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.rhs, .{ .simple = .field_name });
2285122197
22198 try sema.ensureLayoutResolved(ty);
22199
2285222200 const pt = sema.pt;
2285322201 const zcu = pt.zcu;
2285422202 const ip = &zcu.intern_pool;
22855 try ty.resolveLayout(pt);
2285622203 switch (ty.zigTypeTag(zcu)) {
2285722204 .@"struct" => {},
2285822205 else => return sema.fail(block, ty_src, "expected struct type, found '{f}'", .{ty.fmt(pt)}),
......@@ -23126,7 +22473,7 @@ fn checkAtomicPtrOperand(
2312622473 const ptr_data = switch (ptr_ty.zigTypeTag(zcu)) {
2312722474 .pointer => ptr_ty.ptrInfo(zcu),
2312822475 else => {
23129 const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data);
22476 const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data);
2313022477 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2313122478 unreachable;
2313222479 },
......@@ -23136,7 +22483,7 @@ fn checkAtomicPtrOperand(
2313622483 wanted_ptr_data.flags.is_allowzero = ptr_data.flags.is_allowzero;
2313722484 wanted_ptr_data.flags.is_volatile = ptr_data.flags.is_volatile;
2313822485
23139 const wanted_ptr_ty = try pt.ptrTypeSema(wanted_ptr_data);
22486 const wanted_ptr_ty = try pt.ptrType(wanted_ptr_data);
2314022487 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2314122488
2314222489 return casted_ptr;
......@@ -23470,11 +22817,8 @@ fn zirCmpxchg(
2347022817 const result_ty = try pt.optionalType(elem_ty.toIntern());
2347122818
2347222819 // special case zero bit types
23473 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {
23474 return Air.internedToRef((try pt.intern(.{ .opt = .{
23475 .ty = result_ty.toIntern(),
23476 .val = .none,
23477 } })));
22820 if (try elem_ty.onePossibleValue(pt) != null) {
22821 return .fromValue(try pt.nullValue(result_ty));
2347822822 }
2347922823
2348022824 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
......@@ -23537,11 +22881,7 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2353722881
2353822882 const len = try sema.usizeCast(block, src, dest_ty.arrayLen(zcu));
2353922883
23540 if (try sema.typeHasOnePossibleValue(dest_ty)) |val| {
23541 return Air.internedToRef(val.toIntern());
23542 }
23543
23544 // We also need this case because `[0:s]T` is not OPV.
22884 // If the length is 0, the result is comptime-known even if the operand isn't.
2354522885 if (len == 0) return .fromValue(try pt.aggregateValue(dest_ty, &.{}));
2354622886
2354722887 const maybe_sentinel = dest_ty.sentinel(zcu);
......@@ -23733,7 +23073,7 @@ fn analyzeShuffle(
2373323073 continue;
2373423074 }
2373523075 // Safe because mask elements are `i32` and we already checked for undef:
23736 const raw = (try sema.resolveLazyValue(mask_val)).toSignedInt(zcu);
23076 const raw = mask_val.toSignedInt(zcu);
2373723077 if (raw >= 0) {
2373823078 const idx: u32 = @intCast(raw);
2373923079 a_used = true;
......@@ -23938,6 +23278,8 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2393823278 const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, true);
2393923279 const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering, .{ .simple = .atomic_order });
2394023280
23281 try sema.ensureLayoutResolved(elem_ty);
23282
2394123283 switch (order) {
2394223284 .release, .acq_rel => {
2394323285 return sema.fail(
......@@ -23950,9 +23292,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2395023292 else => {},
2395123293 }
2395223294
23953 if (try sema.typeHasOnePossibleValue(elem_ty)) |val| {
23954 return Air.internedToRef(val.toIntern());
23955 }
23295 if (try elem_ty.onePossibleValue(sema.pt)) |opv| return .fromValue(opv);
2395623296
2395723297 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
2395823298 if (try sema.pointerDeref(block, ptr_src, ptr_val, sema.typeOf(ptr))) |elem_val| {
......@@ -24009,9 +23349,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2400923349 }
2401023350
2401123351 // special case zero bit types
24012 if (try sema.typeHasOnePossibleValue(elem_ty)) |val| {
24013 return Air.internedToRef(val.toIntern());
24014 }
23352 if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2401523353
2401623354 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
2401723355 const maybe_operand_val = try sema.resolveValue(operand);
......@@ -24260,11 +23598,11 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2426023598 return sema.fail(block, inst_src, "expected single pointer type, found '{f}'", .{parent_ptr_ty.fmt(pt)});
2426123599 }
2426223600 const parent_ty: Type = .fromInterned(parent_ptr_info.child);
23601 try sema.ensureLayoutResolved(parent_ty);
2426323602 switch (parent_ty.zigTypeTag(zcu)) {
2426423603 .@"struct", .@"union" => {},
2426523604 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{f}'", .{parent_ptr_ty.fmt(pt)}),
2426623605 }
24267 try parent_ty.resolveLayout(pt);
2426823606
2426923607 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name });
2427023608 const field_index = switch (parent_ty.zigTypeTag(zcu)) {
......@@ -24293,7 +23631,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2429323631 var actual_parent_ptr_info: InternPool.Key.PtrType = .{
2429423632 .child = parent_ty.toIntern(),
2429523633 .flags = .{
24296 .alignment = try parent_ptr_ty.ptrAlignmentSema(pt),
23634 .alignment = parent_ptr_ty.ptrAlignment(zcu),
2429723635 .is_const = field_ptr_info.flags.is_const,
2429823636 .is_volatile = field_ptr_info.flags.is_volatile,
2429923637 .is_allowzero = field_ptr_info.flags.is_allowzero,
......@@ -24305,7 +23643,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2430523643 var actual_field_ptr_info: InternPool.Key.PtrType = .{
2430623644 .child = field_ty.toIntern(),
2430723645 .flags = .{
24308 .alignment = try field_ptr_ty.ptrAlignmentSema(pt),
23646 .alignment = field_ptr_ty.ptrAlignment(zcu),
2430923647 .is_const = field_ptr_info.flags.is_const,
2431023648 .is_volatile = field_ptr_info.flags.is_volatile,
2431123649 .is_allowzero = field_ptr_info.flags.is_allowzero,
......@@ -24315,23 +23653,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2431523653 };
2431623654 switch (parent_ty.containerLayout(zcu)) {
2431723655 .auto => {
24318 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(
24319 if (zcu.typeToStruct(parent_ty)) |struct_obj|
24320 try field_ty.structFieldAlignmentSema(
24321 struct_obj.fieldAlign(ip, field_index),
24322 struct_obj.layout,
24323 pt,
24324 )
24325 else if (zcu.typeToUnion(parent_ty)) |union_obj|
24326 try field_ty.unionFieldAlignmentSema(
24327 union_obj.fieldAlign(ip, field_index),
24328 union_obj.flagsUnordered(ip).layout,
24329 pt,
24330 )
24331 else
24332 actual_field_ptr_info.flags.alignment,
24333 );
24334
23656 actual_parent_ptr_info.flags.alignment = parent_ty.resolvedFieldAlignment(field_index, zcu);
2433523657 actual_parent_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
2433623658 actual_field_ptr_info.packed_offset = .{ .bit_offset = 0, .host_size = 0 };
2433723659 },
......@@ -24357,9 +23679,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
2435723679 },
2435823680 }
2435923681
24360 const actual_field_ptr_ty = try pt.ptrTypeSema(actual_field_ptr_info);
23682 const actual_field_ptr_ty = try pt.ptrType(actual_field_ptr_info);
2436123683 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src);
24362 const actual_parent_ptr_ty = try pt.ptrTypeSema(actual_parent_ptr_info);
23684 const actual_parent_ptr_ty = try pt.ptrType(actual_parent_ptr_info);
2436323685
2436423686 const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: {
2436523687 switch (parent_ty.zigTypeTag(zcu)) {
......@@ -24590,7 +23912,7 @@ fn analyzeMinMax(
2459023912 const operand_scalar_ty = sema.typeOf(operand).scalarType(zcu);
2459123913 const want_strat: TypeStrat = switch (operand_scalar_ty.zigTypeTag(zcu)) {
2459223914 .comptime_int => s: {
24593 const val = (try sema.resolveValueResolveLazy(operand)).?;
23915 const val = (try sema.resolveValue(operand)).?;
2459423916 if (val.isUndef(zcu)) break :s .none;
2459523917 break :s .{ .int = .{
2459623918 .all_comptime_int = true,
......@@ -24609,7 +23931,7 @@ fn analyzeMinMax(
2460923931 // (replaced with just the simple calls to `Type.minInt`/`Type.maxInt`) so that we only
2461023932 // use the input *types* to determine the result type.
2461123933 const min: Value, const max: Value = bounds: {
24612 if (try sema.resolveValueResolveLazy(operand)) |operand_val| {
23934 if (try sema.resolveValue(operand)) |operand_val| {
2461323935 if (vector_len) |len| {
2461423936 var min = try operand_val.elemValue(pt, 0);
2461523937 var max = min;
......@@ -24696,6 +24018,9 @@ fn analyzeMinMax(
2469624018 .child = intermediate_scalar_ty.toIntern(),
2469724019 }) else intermediate_scalar_ty;
2469824020
24021 // We might have refined all the way down to an OPV type---check now.
24022 if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
24023
2469924024 // This value, if not `null`, will have type `intermediate_ty`.
2470024025 const comptime_part: ?Value = ct: {
2470124026 // Contains the comptime-known scalar result values.
......@@ -24712,7 +24037,7 @@ fn analyzeMinMax(
2471224037 var opt_runtime_src: ?LazySrcLoc = null;
2471324038
2471424039 for (operands, operand_srcs) |operand, operand_src| {
24715 const operand_val = try sema.resolveValueResolveLazy(operand) orelse {
24040 const operand_val = try sema.resolveValue(operand) orelse {
2471624041 if (opt_runtime_src == null) opt_runtime_src = operand_src;
2471724042 continue;
2471824043 };
......@@ -24819,7 +24144,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A
2481924144 // Already an array pointer.
2482024145 return ptr;
2482124146 }
24822 const new_ty = try pt.ptrTypeSema(.{
24147 const new_ty = try pt.ptrType(.{
2482324148 .child = (try pt.arrayType(.{
2482424149 .len = len,
2482524150 .sentinel = info.sentinel,
......@@ -24883,6 +24208,9 @@ fn zirMemcpy(
2488324208 const dest_elem_ty = dest_ty.indexablePtrElem(zcu);
2488424209 const src_elem_ty = src_ty.indexablePtrElem(zcu);
2488524210
24211 try sema.ensureLayoutResolved(dest_elem_ty);
24212 try sema.ensureLayoutResolved(src_elem_ty);
24213
2488624214 const imc = try sema.coerceInMemoryAllowed(
2488724215 block,
2488824216 dest_elem_ty,
......@@ -24946,13 +24274,13 @@ fn zirMemcpy(
2494624274 }
2494724275
2494824276 zero_bit: {
24949 const src_comptime = try src_elem_ty.comptimeOnlySema(pt);
24950 const dest_comptime = try dest_elem_ty.comptimeOnlySema(pt);
24277 const src_comptime = src_elem_ty.comptimeOnly(zcu);
24278 const dest_comptime = dest_elem_ty.comptimeOnly(zcu);
2495124279 assert(src_comptime == dest_comptime); // IMC
2495224280 if (src_comptime) break :zero_bit;
2495324281
24954 const src_has_bits = try src_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt);
24955 const dest_has_bits = try dest_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt);
24282 const src_has_bits = src_elem_ty.hasRuntimeBits(zcu);
24283 const dest_has_bits = dest_elem_ty.hasRuntimeBits(zcu);
2495624284 assert(src_has_bits == dest_has_bits); // IMC
2495724285 if (src_has_bits) break :zero_bit;
2495824286
......@@ -24968,7 +24296,7 @@ fn zirMemcpy(
2496824296 const raw_dest_ptr = if (dest_ty.isSlice(zcu)) dest_ptr_val.slicePtr(zcu) else dest_ptr_val;
2496924297 const raw_src_ptr = if (src_ty.isSlice(zcu)) src_ptr_val.slicePtr(zcu) else src_ptr_val;
2497024298
24971 const len_u64 = try len_val.?.toUnsignedIntSema(pt);
24299 const len_u64 = len_val.?.toUnsignedInt(zcu);
2497224300
2497324301 if (check_aliasing) {
2497424302 if (Value.doPointersOverlap(
......@@ -25018,7 +24346,7 @@ fn zirMemcpy(
2501824346 var new_dest_ptr = dest_ptr;
2501924347 var new_src_ptr = src_ptr;
2502024348 if (len_val) |val| {
25021 const len = try val.toUnsignedIntSema(pt);
24349 const len = val.toUnsignedInt(zcu);
2502224350 if (len == 0) {
2502324351 // This AIR instruction guarantees length > 0 if it is comptime-known.
2502424352 return;
......@@ -25067,7 +24395,7 @@ fn zirMemcpy(
2506724395 assert(dest_manyptr_ty_key.flags.size == .one);
2506824396 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();
2506924397 dest_manyptr_ty_key.flags.size = .many;
25070 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(dest_manyptr_ty_key), new_dest_ptr, dest_src);
24398 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);
2507124399 } else new_dest_ptr;
2507224400
2507324401 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
......@@ -25078,7 +24406,7 @@ fn zirMemcpy(
2507824406 assert(src_manyptr_ty_key.flags.size == .one);
2507924407 src_manyptr_ty_key.child = src_elem_ty.toIntern();
2508024408 src_manyptr_ty_key.flags.size = .many;
25081 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(src_manyptr_ty_key), new_src_ptr, src_src);
24409 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);
2508224410 } else new_src_ptr;
2508324411
2508424412 // ok1: dest >= src + len
......@@ -25148,7 +24476,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2514824476 const runtime_src = rs: {
2514924477 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), dest_src);
2515024478 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;
25151 const len_u64 = try len_val.toUnsignedIntSema(pt);
24479 const len_u64 = len_val.toUnsignedInt(zcu);
2515224480 const len = try sema.usizeCast(block, dest_src, len_u64);
2515324481 if (len == 0) {
2515424482 // This AIR instruction guarantees length > 0 if it is comptime-known.
......@@ -25436,7 +24764,7 @@ fn resolvePrefetchOptions(
2543624764
2543724765 return std.builtin.PrefetchOptions{
2543824766 .rw = try sema.interpretBuiltinType(block, rw_src, rw_val, std.builtin.PrefetchOptions.Rw),
25439 .locality = @intCast(try locality_val.toUnsignedIntSema(pt)),
24767 .locality = @intCast(locality_val.toUnsignedInt(zcu)),
2544024768 .cache = try sema.interpretBuiltinType(block, cache_src, cache_val, std.builtin.PrefetchOptions.Cache),
2544124769 };
2544224770}
......@@ -25626,7 +24954,7 @@ fn zirBuiltinExtern(
2562624954 // So, for now, just use our containing `declaration`.
2562724955 .zir_index = switch (sema.owner.unwrap()) {
2562824956 .@"comptime" => |cu| ip.getComptimeUnit(cu).zir_index,
25629 .type => |owner_ty| Type.fromInterned(owner_ty).typeDeclInst(zcu).?,
24957 .type_layout, .type_inits => |owner_ty| Type.fromInterned(owner_ty).typeDeclInstAllowGeneratedTag(zcu).?,
2563024958 .memoized_state => unreachable,
2563124959 .nav_ty, .nav_val => |nav| ip.getNav(nav).analysis.?.zir_index,
2563224960 .func => |func| zir_index: {
......@@ -25839,7 +25167,8 @@ fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc, runtime_src:
2583925167 }
2584025168}
2584125169
25842/// Emit a compile error if type cannot be used for a runtime variable.
25170/// Emit a compile error if `var_ty` cannot be used for a runtime variable.
25171/// Asserts that the layout of `var_ty` is already resolved.
2584325172pub fn validateVarType(
2584425173 sema: *Sema,
2584525174 block: *Block,
......@@ -25849,6 +25178,7 @@ pub fn validateVarType(
2584925178) CompileError!void {
2585025179 const pt = sema.pt;
2585125180 const zcu = pt.zcu;
25181 var_ty.assertHasLayout(zcu);
2585225182 if (is_extern) {
2585325183 if (!try sema.validateExternType(var_ty, .other)) {
2585425184 const msg = msg: {
......@@ -25870,7 +25200,7 @@ pub fn validateVarType(
2587025200 }
2587125201 }
2587225202
25873 if (!try var_ty.comptimeOnlySema(pt)) return;
25203 if (!var_ty.comptimeOnly(zcu)) return;
2587425204
2587525205 const msg = msg: {
2587625206 const msg = try sema.errMsg(src, "variable of type '{f}' must be const or comptime", .{var_ty.fmt(pt)});
......@@ -25886,49 +25216,28 @@ pub fn validateVarType(
2588625216 return sema.failWithOwnedErrorMsg(block, msg);
2588725217}
2588825218
25889const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void);
25890
2589125219fn explainWhyTypeIsComptime(
2589225220 sema: *Sema,
2589325221 msg: *Zcu.ErrorMsg,
25894 src_loc: LazySrcLoc,
25895 ty: Type,
25896) CompileError!void {
25897 var type_set = TypeSet{};
25898 defer type_set.deinit(sema.gpa);
25899
25900 try ty.resolveFully(sema.pt);
25901 return sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty, &type_set);
25902}
25903
25904fn explainWhyTypeIsComptimeInner(
25905 sema: *Sema,
25906 msg: *Zcu.ErrorMsg,
25907 src_loc: LazySrcLoc,
25222 src: LazySrcLoc,
2590825223 ty: Type,
25909 type_set: *TypeSet,
2591025224) CompileError!void {
2591125225 const pt = sema.pt;
2591225226 const zcu = pt.zcu;
2591325227 const ip = &zcu.intern_pool;
25228 assert(ty.comptimeOnly(zcu));
2591425229 switch (ty.zigTypeTag(zcu)) {
2591525230 .bool,
2591625231 .int,
2591725232 .float,
2591825233 .error_set,
25919 .@"enum",
2592025234 .frame,
2592125235 .@"anyframe",
2592225236 .void,
25923 => return,
25924
25925 .@"fn" => {
25926 try sema.errNote(src_loc, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)});
25927 },
25928
25929 .type => {
25930 try sema.errNote(src_loc, msg, "types are not available at runtime", .{});
25931 },
25237 .@"enum",
25238 .@"opaque",
25239 .pointer,
25240 => unreachable, // not comptime-only
2593225241
2593325242 .comptime_float,
2593425243 .comptime_int,
......@@ -25936,78 +25245,53 @@ fn explainWhyTypeIsComptimeInner(
2593625245 .noreturn,
2593725246 .undefined,
2593825247 .null,
25939 => return,
25940
25941 .@"opaque" => {
25942 try sema.errNote(src_loc, msg, "opaque type '{f}' has undefined size", .{ty.fmt(pt)});
25943 },
25944
25945 .array, .vector => {
25946 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set);
25947 },
25948 .pointer => {
25949 const elem_ty = ty.elemType2(zcu);
25950 if (elem_ty.zigTypeTag(zcu) == .@"fn") {
25951 const fn_info = zcu.typeToFunc(elem_ty).?;
25952 if (fn_info.is_generic) {
25953 try sema.errNote(src_loc, msg, "function is generic", .{});
25954 }
25955 switch (fn_info.cc) {
25956 .@"inline" => try sema.errNote(src_loc, msg, "function has inline calling convention", .{}),
25957 else => {},
25958 }
25959 if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) {
25960 try sema.errNote(src_loc, msg, "function has a comptime-only return type", .{});
25961 }
25962 return;
25963 }
25964 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(zcu), type_set);
25965 },
25966
25967 .optional => {
25968 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(zcu), type_set);
25969 },
25970 .error_union => {
25971 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(zcu), type_set);
25972 },
25248 => return, // no explanation needed
2597325249
25974 .@"struct" => {
25975 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
25250 .array, .vector => try sema.explainWhyTypeIsComptime(msg, src, ty.childType(zcu)),
25251 .optional => try sema.explainWhyTypeIsComptime(msg, src, ty.optionalChild(zcu)),
25252 .error_union => try sema.explainWhyTypeIsComptime(msg, src, ty.errorUnionPayload(zcu)),
2597625253
25977 if (zcu.typeToStruct(ty)) |struct_type| {
25978 for (0..struct_type.field_types.len) |i| {
25979 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
25980 const field_src: LazySrcLoc = .{
25981 .base_node_inst = struct_type.zir_index,
25982 .offset = .{ .container_field_type = @intCast(i) },
25983 };
25254 .@"fn" => try sema.errNote(src, msg, "use '*const {f}' for a function pointer type", .{ty.fmt(pt)}),
25255 .type => try sema.errNote(src, msg, "types are not available at runtime", .{}),
2598425256
25985 if (try field_ty.comptimeOnlySema(pt)) {
25986 try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{});
25987 try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set);
25988 }
25989 }
25257 .@"struct" => if (zcu.typeToStruct(ty)) |struct_type| {
25258 ty.assertHasLayout(zcu);
25259 for (0..struct_type.field_types.len) |i| {
25260 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
25261 if (!field_ty.comptimeOnly(zcu)) continue;
25262 const field_src: LazySrcLoc = .{
25263 .base_node_inst = struct_type.zir_index,
25264 .offset = .{ .container_field_type = @intCast(i) },
25265 };
25266 try sema.errNote(field_src, msg, "struct requires comptime because of this field", .{});
25267 return sema.explainWhyTypeIsComptime(msg, field_src, field_ty);
2599025268 }
25991 // TODO tuples
25269 unreachable;
25270 } else {
25271 const tuple = ip.indexToKey(ty.toIntern()).tuple_type;
25272 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty_ip, field_val_ip| {
25273 if (field_val_ip != .none) continue;
25274 const field_ty: Type = .fromInterned(field_ty_ip);
25275 if (!field_ty.comptimeOnly(zcu)) continue;
25276 try sema.errNote(src, msg, "tuple requires comptime because of field of type '{f}'", .{field_ty.fmt(pt)});
25277 return sema.explainWhyTypeIsComptime(msg, src, field_ty);
25278 }
25279 unreachable;
2599225280 },
2599325281
2599425282 .@"union" => {
25995 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
25996
25997 if (zcu.typeToUnion(ty)) |union_obj| {
25998 for (0..union_obj.field_types.len) |i| {
25999 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]);
26000 const field_src: LazySrcLoc = .{
26001 .base_node_inst = union_obj.zir_index,
26002 .offset = .{ .container_field_type = @intCast(i) },
26003 };
26004
26005 if (try field_ty.comptimeOnlySema(pt)) {
26006 try sema.errNote(field_src, msg, "union requires comptime because of this field", .{});
26007 try sema.explainWhyTypeIsComptimeInner(msg, field_src, field_ty, type_set);
26008 }
26009 }
25283 const union_obj = zcu.typeToUnion(ty).?;
25284 for (0..union_obj.field_types.len) |i| {
25285 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[i]);
25286 if (!field_ty.comptimeOnly(zcu)) continue;
25287 const field_src: LazySrcLoc = .{
25288 .base_node_inst = union_obj.zir_index,
25289 .offset = .{ .container_field_type = @intCast(i) },
25290 };
25291 try sema.errNote(field_src, msg, "union requires comptime because of this field", .{});
25292 return sema.explainWhyTypeIsComptime(msg, field_src, field_ty);
2601025293 }
25294 unreachable;
2601125295 },
2601225296 }
2601325297}
......@@ -26022,9 +25306,8 @@ const ExternPosition = enum {
2602225306};
2602325307
2602425308/// Returns true if `ty` is allowed in extern types.
26025/// Does *NOT* require `ty` to be resolved in any way.
26026/// Calls `resolveLayout` for packed containers.
26027fn validateExternType(
25309/// Does not require `ty` to be resolved in any way.
25310pub fn validateExternType(
2602825311 sema: *Sema,
2602925312 ty: Type,
2603025313 position: ExternPosition,
......@@ -26042,7 +25325,16 @@ fn validateExternType(
2604225325 .error_set,
2604325326 .frame,
2604425327 => return false,
26045 .void => return position == .union_field or position == .ret_ty or position == .struct_field or position == .element,
25328 .void => return switch (position) {
25329 .ret_ty,
25330 .union_field,
25331 .struct_field,
25332 .element,
25333 => true,
25334 .param_ty,
25335 .other,
25336 => false,
25337 },
2604625338 .noreturn => return position == .ret_ty,
2604725339 .@"opaque",
2604825340 .bool,
......@@ -26050,10 +25342,12 @@ fn validateExternType(
2605025342 .@"anyframe",
2605125343 => return true,
2605225344 .pointer => {
26053 if (ty.childType(zcu).zigTypeTag(zcu) == .@"fn") {
26054 return ty.isConstPtr(zcu) and try sema.validateExternType(ty.childType(zcu), .other);
25345 if (ty.isSlice(zcu)) return false;
25346 const child_ty = ty.childType(zcu);
25347 if (child_ty.zigTypeTag(zcu) == .@"fn") {
25348 return ty.isConstPtr(zcu) and try sema.validateExternType(child_ty, .other);
2605525349 }
26056 return !(ty.isSlice(zcu) or try ty.comptimeOnlySema(pt));
25350 return true;
2605725351 },
2605825352 .int => switch (ty.intInfo(zcu).bits) {
2605925353 0, 8, 16, 32, 64, 128 => return true,
......@@ -26069,29 +25363,42 @@ fn validateExternType(
2606925363 return !target_util.fnCallConvAllowsZigTypes(ty.fnCallingConvention(zcu));
2607025364 },
2607125365 .@"enum" => {
26072 return sema.validateExternType(ty.intTagType(zcu), position);
26073 },
26074 .@"struct", .@"union" => switch (ty.containerLayout(zcu)) {
26075 .@"extern" => return true,
26076 .@"packed" => {
26077 const bit_size = try ty.bitSizeSema(pt);
26078 switch (bit_size) {
26079 0, 8, 16, 32, 64, 128 => return true,
26080 else => return false,
26081 }
26082 },
26083 .auto => return !(try ty.hasRuntimeBitsSema(pt)),
25366 const enum_obj = zcu.intern_pool.loadEnumType(ty.toIntern());
25367 if (!enum_obj.int_tag_is_explicit) return false;
25368 return sema.validateExternType(.fromInterned(enum_obj.int_tag_type), position);
25369 },
25370 .@"struct" => {
25371 const struct_obj = zcu.intern_pool.loadStructType(ty.toIntern());
25372 return switch (struct_obj.layout) {
25373 .auto => false,
25374 .@"extern" => true,
25375 .@"packed" => switch (struct_obj.packed_backing_mode) {
25376 .auto => false,
25377 .explicit => try sema.validateExternType(.fromInterned(struct_obj.packed_backing_int_type), position),
25378 },
25379 };
25380 },
25381 .@"union" => {
25382 const union_obj = zcu.intern_pool.loadUnionType(ty.toIntern());
25383 return switch (union_obj.layout) {
25384 .auto => false,
25385 .@"extern" => true,
25386 .@"packed" => switch (union_obj.packed_backing_mode) {
25387 .auto => false,
25388 .explicit => try sema.validateExternType(.fromInterned(union_obj.packed_backing_int_type), position),
25389 },
25390 };
2608425391 },
2608525392 .array => {
2608625393 if (position == .ret_ty or position == .param_ty) return false;
26087 return sema.validateExternType(ty.elemType2(zcu), .element);
25394 return sema.validateExternType(ty.childType(zcu), .element);
2608825395 },
26089 .vector => return sema.validateExternType(ty.elemType2(zcu), .element),
25396 .vector => return sema.validateExternType(ty.childType(zcu), .element),
2609025397 .optional => return ty.isPtrLikeOptional(zcu),
2609125398 }
2609225399}
2609325400
26094fn explainWhyTypeIsNotExtern(
25401pub fn explainWhyTypeIsNotExtern(
2609525402 sema: *Sema,
2609625403 msg: *Zcu.ErrorMsg,
2609725404 src_loc: LazySrcLoc,
......@@ -26125,9 +25432,6 @@ fn explainWhyTypeIsNotExtern(
2612525432 const pointee_ty = ty.childType(zcu);
2612625433 if (!ty.isConstPtr(zcu) and pointee_ty.zigTypeTag(zcu) == .@"fn") {
2612725434 try sema.errNote(src_loc, msg, "pointer to extern function must be 'const'", .{});
26128 } else if (try ty.comptimeOnlySema(pt)) {
26129 try sema.errNote(src_loc, msg, "pointer to comptime-only type '{f}'", .{pointee_ty.fmt(pt)});
26130 try sema.explainWhyTypeIsComptime(msg, src_loc, ty);
2613125435 }
2613225436 try sema.explainWhyTypeIsNotExtern(msg, src_loc, pointee_ty, .other);
2613325437 }
......@@ -26157,6 +25461,7 @@ fn explainWhyTypeIsNotExtern(
2615725461 try sema.errNote(src_loc, msg, "enum tag type '{f}' is not extern compatible", .{tag_ty.fmt(pt)});
2615825462 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
2615925463 },
25464 // MLUGG TODO: these notes are bad now (because ABI sized packed type also needs explicit backing type)
2616025465 .@"struct" => try sema.errNote(src_loc, msg, "only extern structs and ABI sized packed structs are extern compatible", .{}),
2616125466 .@"union" => try sema.errNote(src_loc, msg, "only extern unions and ABI sized packed unions are extern compatible", .{}),
2616225467 .array => {
......@@ -26165,51 +25470,14 @@ fn explainWhyTypeIsNotExtern(
2616525470 } else if (position == .param_ty) {
2616625471 return sema.errNote(src_loc, msg, "arrays are not allowed as a parameter type", .{});
2616725472 }
26168 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element);
25473 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element);
2616925474 },
26170 .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(zcu), .element),
25475 .vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.childType(zcu), .element),
2617125476 .optional => try sema.errNote(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
2617225477 }
2617325478}
2617425479
26175/// Returns true if `ty` is allowed in packed types.
26176/// Does not require `ty` to be resolved in any way, but may resolve whether it is comptime-only.
26177fn validatePackedType(sema: *Sema, ty: Type) !bool {
26178 const pt = sema.pt;
26179 const zcu = pt.zcu;
26180 return switch (ty.zigTypeTag(zcu)) {
26181 .type,
26182 .comptime_float,
26183 .comptime_int,
26184 .enum_literal,
26185 .undefined,
26186 .null,
26187 .error_union,
26188 .error_set,
26189 .frame,
26190 .noreturn,
26191 .@"opaque",
26192 .@"anyframe",
26193 .@"fn",
26194 .array,
26195 => false,
26196 .optional => return ty.isPtrLikeOptional(zcu),
26197 .void,
26198 .bool,
26199 .float,
26200 .int,
26201 .vector,
26202 => true,
26203 .@"enum" => switch (zcu.intern_pool.loadEnumType(ty.toIntern()).tag_mode) {
26204 .auto => false,
26205 .explicit, .nonexhaustive => true,
26206 },
26207 .pointer => !ty.isSlice(zcu) and !try ty.comptimeOnlySema(pt),
26208 .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed",
26209 };
26210}
26211
26212fn explainWhyTypeIsNotPacked(
25480pub fn explainWhyTypeIsNotPackable(
2621325481 sema: *Sema,
2621425482 msg: *Zcu.ErrorMsg,
2621525483 src_loc: LazySrcLoc,
......@@ -26250,8 +25518,8 @@ fn explainWhyTypeIsNotPacked(
2625025518 try sema.errNote(src_loc, msg, "type has no guaranteed in-memory representation", .{});
2625125519 try sema.errNote(src_loc, msg, "use '*const ' to make a function pointer type", .{});
2625225520 },
26253 .@"struct" => try sema.errNote(src_loc, msg, "only packed structs layout are allowed in packed types", .{}),
26254 .@"union" => try sema.errNote(src_loc, msg, "only packed unions layout are allowed in packed types", .{}),
25521 .@"struct" => try sema.errNote(src_loc, msg, "struct in packed type must have packed layout", .{}),
25522 .@"union" => try sema.errNote(src_loc, msg, "union in packed type must have packed layout", .{}),
2625525523 }
2625625524}
2625725525
......@@ -26277,7 +25545,7 @@ fn getPanicIdFunc(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !In
2627725545 try sema.ensureMemoizedStateResolved(src, .panic);
2627825546 const panic_fn_index = zcu.builtin_decl_values.get(panic_id.toBuiltin());
2627925547 switch (sema.owner.unwrap()) {
26280 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
25548 .@"comptime", .nav_ty, .nav_val, .type_layout, .type_inits, .memoized_state => {},
2628125549 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(io, owner_func, true),
2628225550 }
2628325551 return panic_fn_index;
......@@ -26555,7 +25823,8 @@ fn fieldPtrLoad(
2655525823 const zcu = pt.zcu;
2655625824 const object_ptr_ty = sema.typeOf(object_ptr);
2655725825 const pointee_ty = object_ptr_ty.childType(zcu);
26558 if (try typeHasOnePossibleValue(sema, pointee_ty)) |opv| {
25826 try sema.ensureLayoutResolved(pointee_ty); // MLUGG TODO
25827 if (try pointee_ty.onePossibleValue(pt)) |opv| {
2655925828 const object: Air.Inst.Ref = .fromValue(opv);
2656025829 return fieldVal(sema, block, src, object, field_name, field_name_src);
2656125830 }
......@@ -26603,7 +25872,7 @@ fn fieldVal(
2660325872 return Air.internedToRef((try pt.intValue(.usize, inner_ty.arrayLen(zcu))).toIntern());
2660425873 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {
2660525874 const ptr_info = object_ty.ptrInfo(zcu);
26606 const result_ty = try pt.ptrTypeSema(.{
25875 const result_ty = try pt.ptrType(.{
2660725876 .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(),
2660825877 .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none,
2660925878 .flags = .{
......@@ -26693,7 +25962,6 @@ fn fieldVal(
2669325962 if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| {
2669425963 return inst;
2669525964 }
26696 try child_type.resolveFields(pt);
2669725965 if (child_type.unionTagType(zcu)) |enum_ty| {
2669825966 if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index_usize| {
2669925967 const field_index: u32 = @intCast(field_index_usize);
......@@ -26731,6 +25999,7 @@ fn fieldVal(
2673125999 },
2673226000 .@"struct" => if (is_pointer_to) {
2673326001 // Avoid loading the entire struct by fetching a pointer and loading that
26002 try sema.ensureLayoutResolved(inner_ty);
2673426003 const field_ptr = try sema.structFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false);
2673526004 return sema.analyzeLoad(block, src, field_ptr, object_src);
2673626005 } else {
......@@ -26738,6 +26007,7 @@ fn fieldVal(
2673826007 },
2673926008 .@"union" => if (is_pointer_to) {
2674026009 // Avoid loading the entire union by fetching a pointer and loading that
26010 try sema.ensureLayoutResolved(inner_ty);
2674126011 const field_ptr = try sema.unionFieldPtr(block, src, object, field_name, field_name_src, inner_ty, false);
2674226012 return sema.analyzeLoad(block, src, field_ptr, object_src);
2674326013 } else {
......@@ -26787,7 +26057,7 @@ fn fieldPtr(
2678726057 return uavRef(sema, int_val.toIntern());
2678826058 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {
2678926059 const ptr_info = object_ty.ptrInfo(zcu);
26790 const new_ptr_ty = try pt.ptrTypeSema(.{
26060 const new_ptr_ty = try pt.ptrType(.{
2679126061 .child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(),
2679226062 .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none,
2679326063 .flags = .{
......@@ -26802,7 +26072,7 @@ fn fieldPtr(
2680226072 .packed_offset = ptr_info.packed_offset,
2680326073 });
2680426074 const ptr_ptr_info = object_ptr_ty.ptrInfo(zcu);
26805 const result_ty = try pt.ptrTypeSema(.{
26075 const result_ty = try pt.ptrType(.{
2680626076 .child = new_ptr_ty.toIntern(),
2680726077 .sentinel = if (object_ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none,
2680826078 .flags = .{
......@@ -26836,7 +26106,7 @@ fn fieldPtr(
2683626106 if (field_name.eqlSlice("ptr", ip)) {
2683726107 const slice_ptr_ty = inner_ty.slicePtrFieldType(zcu);
2683826108
26839 const result_ty = try pt.ptrTypeSema(.{
26109 const result_ty = try pt.ptrType(.{
2684026110 .child = slice_ptr_ty.toIntern(),
2684126111 .flags = .{
2684226112 .is_const = !attr_ptr_ty.ptrIsMutable(zcu),
......@@ -26854,7 +26124,7 @@ fn fieldPtr(
2685426124 try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);
2685526125 return field_ptr;
2685626126 } else if (field_name.eqlSlice("len", ip)) {
26857 const result_ty = try pt.ptrTypeSema(.{
26127 const result_ty = try pt.ptrType(.{
2685826128 .child = .usize_type,
2685926129 .flags = .{
2686026130 .is_const = !attr_ptr_ty.ptrIsMutable(zcu),
......@@ -26925,7 +26195,6 @@ fn fieldPtr(
2692526195 if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(zcu), field_name)) |inst| {
2692626196 return inst;
2692726197 }
26928 try child_type.resolveFields(pt);
2692926198 if (child_type.unionTagType(zcu)) |enum_ty| {
2693026199 if (enum_ty.enumFieldIndex(field_name, zcu)) |field_index| {
2693126200 const field_index_u32: u32 = @intCast(field_index);
......@@ -26960,6 +26229,7 @@ fn fieldPtr(
2696026229 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
2696126230 else
2696226231 object_ptr;
26232 try sema.ensureLayoutResolved(inner_ty);
2696326233 const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing);
2696426234 try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);
2696526235 return field_ptr;
......@@ -26969,6 +26239,7 @@ fn fieldPtr(
2696926239 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
2697026240 else
2697126241 object_ptr;
26242 try sema.ensureLayoutResolved(inner_ty);
2697226243 const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing);
2697326244 try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);
2697426245 return field_ptr;
......@@ -27012,6 +26283,7 @@ fn fieldCallBind(
2701226283 // Optionally dereference a second pointer to get the concrete type.
2701326284 const is_double_ptr = inner_ty.zigTypeTag(zcu) == .pointer and inner_ty.ptrSize(zcu) == .one;
2701426285 const concrete_ty = if (is_double_ptr) inner_ty.childType(zcu) else inner_ty;
26286 try sema.ensureLayoutResolved(concrete_ty);
2701526287 const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty;
2701626288 const object_ptr = if (is_double_ptr)
2701726289 try sema.analyzeLoad(block, src, raw_ptr, src)
......@@ -27021,10 +26293,8 @@ fn fieldCallBind(
2702126293 find_field: {
2702226294 switch (concrete_ty.zigTypeTag(zcu)) {
2702326295 .@"struct" => {
27024 try concrete_ty.resolveFields(pt);
2702526296 if (zcu.typeToStruct(concrete_ty)) |struct_type| {
27026 const field_index = struct_type.nameIndex(ip, field_name) orelse
27027 break :find_field;
26297 const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field;
2702826298 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
2702926299
2703026300 return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr);
......@@ -27047,9 +26317,9 @@ fn fieldCallBind(
2704726317 }
2704826318 },
2704926319 .@"union" => {
27050 try concrete_ty.resolveFields(pt);
2705126320 const union_obj = zcu.typeToUnion(concrete_ty).?;
27052 _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field;
26321 const enum_obj = ip.loadEnumType(union_obj.enum_tag_type);
26322 if (enum_obj.nameIndex(ip, field_name) == null) break :find_field;
2705326323 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);
2705426324 return .{ .direct = try sema.analyzeLoad(block, src, field_ptr, src) };
2705526325 },
......@@ -27163,7 +26433,7 @@ fn finishFieldCallBind(
2716326433) CompileError!ResolvedFieldCallee {
2716426434 const pt = sema.pt;
2716526435 const zcu = pt.zcu;
27166 const ptr_field_ty = try pt.ptrTypeSema(.{
26436 const ptr_field_ty = try pt.ptrType(.{
2716726437 .child = field_ty.toIntern(),
2716826438 .flags = .{
2716926439 .is_const = !ptr_ty.ptrIsMutable(zcu),
......@@ -27174,7 +26444,9 @@ fn finishFieldCallBind(
2717426444 const container_ty = ptr_ty.childType(zcu);
2717526445 if (container_ty.zigTypeTag(zcu) == .@"struct") {
2717626446 if (container_ty.structFieldIsComptime(field_index, zcu)) {
27177 try container_ty.resolveStructFieldInits(pt);
26447 if (!container_ty.isTuple(zcu)) {
26448 try sema.ensureFieldInitsResolved(container_ty);
26449 }
2717826450 const default_val = (try container_ty.structFieldValueComptime(pt, field_index)).?;
2717926451 return .{ .direct = Air.internedToRef(default_val.toIntern()) };
2718026452 }
......@@ -27239,6 +26511,7 @@ fn namespaceLookupVal(
2723926511 return try sema.analyzeNavVal(block, src, nav);
2724026512}
2724126513
26514/// Asserts that the layout of `struct_ty` is already resolved.
2724226515fn structFieldPtr(
2724326516 sema: *Sema,
2724426517 block: *Block,
......@@ -27252,10 +26525,9 @@ fn structFieldPtr(
2725226525 const pt = sema.pt;
2725326526 const zcu = pt.zcu;
2725426527 const ip = &zcu.intern_pool;
27255 assert(struct_ty.zigTypeTag(zcu) == .@"struct");
2725626528
27257 try struct_ty.resolveFields(pt);
27258 try struct_ty.resolveLayout(pt);
26529 assert(struct_ty.zigTypeTag(zcu) == .@"struct");
26530 struct_ty.assertHasLayout(zcu);
2725926531
2726026532 if (struct_ty.isTuple(zcu)) {
2726126533 if (field_name.eqlSlice("len", ip)) {
......@@ -27274,6 +26546,7 @@ fn structFieldPtr(
2727426546 return sema.structFieldPtrByIndex(block, src, struct_ptr, field_index, struct_ty);
2727526547}
2727626548
26549/// Asserts that the layout of `struct_ty` is already resolved.
2727726550fn structFieldPtrByIndex(
2727826551 sema: *Sema,
2727926552 block: *Block,
......@@ -27286,8 +26559,10 @@ fn structFieldPtrByIndex(
2728626559 const zcu = pt.zcu;
2728726560 const ip = &zcu.intern_pool;
2728826561
26562 struct_ty.assertHasLayout(zcu);
26563
2728926564 const struct_type = zcu.typeToStruct(struct_ty).?;
27290 const field_is_comptime = struct_type.fieldIsComptime(ip, field_index);
26565 const field_is_comptime = struct_type.field_is_comptime_bits.get(ip, field_index);
2729126566
2729226567 // Comptime fields are handled later
2729326568 if (!field_is_comptime) {
......@@ -27300,6 +26575,7 @@ fn structFieldPtrByIndex(
2730026575 const field_ty = struct_type.field_types.get(ip)[field_index];
2730126576 const struct_ptr_ty = sema.typeOf(struct_ptr);
2730226577 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(zcu);
26578 assert(struct_ptr_ty_info.child == struct_ty.toIntern());
2730326579
2730426580 var ptr_ty_data: InternPool.Key.PtrType = .{
2730526581 .child = field_ty,
......@@ -27313,7 +26589,7 @@ fn structFieldPtrByIndex(
2731326589 const parent_align = if (struct_ptr_ty_info.flags.alignment != .none)
2731426590 struct_ptr_ty_info.flags.alignment
2731526591 else
27316 try Type.fromInterned(struct_ptr_ty_info.child).abiAlignmentSema(pt);
26592 struct_ty.abiAlignment(zcu);
2731726593
2731826594 if (struct_type.layout == .@"packed") {
2731926595 assert(!field_is_comptime);
......@@ -27325,31 +26601,32 @@ fn structFieldPtrByIndex(
2732526601 // For extern structs, field alignment might be bigger than type's
2732626602 // natural alignment. Eg, in `extern struct { x: u32, y: u16 }` the
2732726603 // second field is aligned as u32.
27328 const field_offset = struct_ty.structFieldOffset(field_index, zcu);
27329 ptr_ty_data.flags.alignment = if (parent_align == .none)
27330 .none
27331 else
27332 @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset)));
26604 ptr_ty_data.flags.alignment = a: {
26605 const field_off = struct_ty.structFieldOffset(field_index, zcu);
26606 if (field_off == 0) break :a struct_ptr_ty_info.flags.alignment;
26607 const true_field_align: Alignment = .fromLog2Units(@ctz(field_off));
26608 if (struct_ptr_ty_info.flags.alignment == .none and
26609 true_field_align == Type.fromInterned(field_ty).abiAlignment(zcu))
26610 {
26611 break :a .none;
26612 }
26613 break :a .minStrict(true_field_align, parent_align);
26614 };
2733326615 } else {
2733426616 // Our alignment is capped at the field alignment.
27335 const field_align = try Type.fromInterned(field_ty).structFieldAlignmentSema(
27336 struct_type.fieldAlign(ip, field_index),
27337 struct_type.layout,
27338 pt,
27339 );
2734026617 ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none)
27341 field_align
26618 struct_ty.explicitFieldAlignment(field_index, zcu)
2734226619 else
27343 field_align.min(parent_align);
26620 struct_ty.resolvedFieldAlignment(field_index, zcu).min(parent_align);
2734426621 }
2734526622
27346 const ptr_field_ty = try pt.ptrTypeSema(ptr_ty_data);
26623 const ptr_field_ty = try pt.ptrType(ptr_ty_data);
2734726624
2734826625 if (field_is_comptime) {
27349 try struct_ty.resolveStructFieldInits(pt);
26626 try sema.ensureFieldInitsResolved(struct_ty);
2735026627 const val = try pt.intern(.{ .ptr = .{
2735126628 .ty = ptr_field_ty.toIntern(),
27352 .base_addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] },
26629 .base_addr = .{ .comptime_field = struct_type.field_defaults.get(ip)[field_index] },
2735326630 .byte_offset = 0,
2735426631 } });
2735526632 return Air.internedToRef(val);
......@@ -27371,32 +26648,26 @@ fn structFieldVal(
2737126648 const ip = &zcu.intern_pool;
2737226649 assert(struct_ty.zigTypeTag(zcu) == .@"struct");
2737326650
27374 try struct_ty.resolveFields(pt);
27375
2737626651 switch (ip.indexToKey(struct_ty.toIntern())) {
2737726652 .struct_type => {
2737826653 const struct_type = ip.loadStructType(struct_ty.toIntern());
2737926654
2738026655 const field_index = struct_type.nameIndex(ip, field_name) orelse
2738126656 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);
27382 if (struct_type.fieldIsComptime(ip, field_index)) {
27383 try struct_ty.resolveStructFieldInits(pt);
27384 return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]);
26657 if (struct_type.field_is_comptime_bits.get(ip, field_index)) {
26658 try sema.ensureFieldInitsResolved(struct_ty);
26659 return .fromIntern(struct_type.field_defaults.get(ip)[field_index]);
2738526660 }
2738626661
2738726662 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
27388 if (try sema.typeHasOnePossibleValue(field_ty)) |field_val|
27389 return Air.internedToRef(field_val.toIntern());
26663 if (try field_ty.onePossibleValue(pt)) |field_val|
26664 return .fromValue(field_val);
2739026665
2739126666 if (try sema.resolveValue(struct_byval)) |struct_val| {
2739226667 if (struct_val.isUndef(zcu)) return pt.undefRef(field_ty);
27393 if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| {
27394 return Air.internedToRef(opv.toIntern());
27395 }
27396 return Air.internedToRef((try struct_val.fieldValue(pt, field_index)).toIntern());
26668 return .fromValue(try struct_val.fieldValue(pt, field_index));
2739726669 }
2739826670
27399 try field_ty.resolveLayout(pt);
2740026671 return block.addStructFieldVal(struct_byval, field_index, field_ty);
2740126672 },
2740226673 .tuple_type => {
......@@ -27457,16 +26728,13 @@ fn tupleFieldValByIndex(
2745726728 const zcu = pt.zcu;
2745826729 const field_ty = tuple_ty.fieldType(field_index, zcu);
2745926730
27460 if (tuple_ty.structFieldIsComptime(field_index, zcu))
27461 try tuple_ty.resolveStructFieldInits(pt);
2746226731 if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| {
2746326732 return Air.internedToRef(default_value.toIntern());
2746426733 }
2746526734
26735 if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
26736
2746626737 if (try sema.resolveValue(tuple_byval)) |tuple_val| {
27467 if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| {
27468 return Air.internedToRef(opv.toIntern());
27469 }
2747026738 return switch (zcu.intern_pool.indexToKey(tuple_val.toIntern())) {
2747126739 .undef => pt.undefRef(field_ty),
2747226740 .aggregate => |aggregate| Air.internedToRef(switch (aggregate.storage) {
......@@ -27478,10 +26746,10 @@ fn tupleFieldValByIndex(
2747826746 };
2747926747 }
2748026748
27481 try field_ty.resolveLayout(pt);
2748226749 return block.addStructFieldVal(tuple_byval, field_index, field_ty);
2748326750}
2748426751
26752/// Asserts that the layout of `union_ty` is already resolved.
2748526753fn unionFieldPtr(
2748626754 sema: *Sema,
2748726755 block: *Block,
......@@ -27497,31 +26765,31 @@ fn unionFieldPtr(
2749726765 const ip = &zcu.intern_pool;
2749826766
2749926767 assert(union_ty.zigTypeTag(zcu) == .@"union");
26768 union_ty.assertHasLayout(zcu);
2750026769
2750126770 const union_ptr_ty = sema.typeOf(union_ptr);
2750226771 const union_ptr_info = union_ptr_ty.ptrInfo(zcu);
27503 try union_ty.resolveFields(pt);
2750426772 const union_obj = zcu.typeToUnion(union_ty).?;
2750526773 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
2750626774 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
27507 const ptr_field_ty = try pt.ptrTypeSema(.{
26775 const ptr_field_ty = try pt.ptrType(.{
2750826776 .child = field_ty.toIntern(),
2750926777 .flags = .{
2751026778 .is_const = union_ptr_info.flags.is_const,
2751126779 .is_volatile = union_ptr_info.flags.is_volatile,
2751226780 .address_space = union_ptr_info.flags.address_space,
27513 .alignment = if (union_obj.flagsUnordered(ip).layout == .auto) blk: {
27514 const union_align = if (union_ptr_info.flags.alignment != .none)
27515 union_ptr_info.flags.alignment
27516 else
27517 try union_ty.abiAlignmentSema(pt);
27518 const field_align = try union_ty.fieldAlignmentSema(field_index, pt);
27519 break :blk union_align.min(field_align);
27520 } else union_ptr_info.flags.alignment,
26781 .alignment = a: {
26782 if (union_obj.layout != .auto) break :a union_ptr_info.flags.alignment;
26783 if (union_ptr_info.flags.alignment == .none) {
26784 break :a union_ty.explicitFieldAlignment(field_index, zcu);
26785 }
26786 const field_align = union_ty.resolvedFieldAlignment(field_index, zcu);
26787 break :a union_ptr_info.flags.alignment.min(field_align);
26788 },
2752126789 },
2752226790 .packed_offset = union_ptr_info.packed_offset,
2752326791 });
27524 const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?);
26792 const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?);
2752526793
2752626794 if (initializing and field_ty.zigTypeTag(zcu) == .noreturn) {
2752726795 const msg = msg: {
......@@ -27538,16 +26806,16 @@ fn unionFieldPtr(
2753826806 }
2753926807
2754026808 if (try sema.resolveDefinedValue(block, src, union_ptr)) |union_ptr_val| ct: {
27541 switch (union_obj.flagsUnordered(ip).layout) {
26809 switch (union_obj.layout) {
2754226810 .auto => if (initializing) {
2754326811 if (!sema.isComptimeMutablePtr(union_ptr_val)) {
2754426812 // The initialization is a runtime operation.
2754526813 break :ct;
2754626814 }
2754726815 // Store to the union to initialize the tag.
27548 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index);
26816 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index);
2754926817 const payload_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
27550 const new_union_val = try pt.unionValue(union_ty, field_tag, try pt.undefValue(payload_ty));
26818 const new_union_val = try pt.unionValue(union_ty, field_tag, try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty));
2755126819 try sema.storePtrVal(block, src, union_ptr_val, new_union_val, union_ty);
2755226820 } else {
2755326821 const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse
......@@ -27556,12 +26824,12 @@ fn unionFieldPtr(
2755626824 return sema.failWithUseOfUndef(block, src, null);
2755726825 }
2755826826 const un = ip.indexToKey(union_val.toIntern()).un;
27559 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index);
26827 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index);
2756026828 const tag_matches = un.tag == field_tag.toIntern();
2756126829 if (!tag_matches) {
2756226830 const msg = msg: {
27563 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
27564 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
26831 const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
26832 const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu);
2756526833 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
2756626834 field_name.fmt(ip),
2756726835 active_field_name.fmt(ip),
......@@ -27582,15 +26850,15 @@ fn unionFieldPtr(
2758226850 // If the union has a tag, we must either set or or safety check it depending on `initializing`.
2758326851 tag: {
2758426852 if (union_ty.containerLayout(zcu) != .auto) break :tag;
27585 const tag_ty: Type = .fromInterned(union_obj.enum_tag_ty);
27586 if (try sema.typeHasOnePossibleValue(tag_ty) != null) break :tag;
26853 const tag_ty: Type = .fromInterned(union_obj.enum_tag_type);
26854 if (try tag_ty.onePossibleValue(pt) != null) break :tag;
2758726855 // There is a hypothetical non-trivial tag. We must set it even if not there at runtime, but
2758826856 // only emit a safety check if it's available at runtime (i.e. it's safety-tagged).
2758926857 const want_tag = try pt.enumValueFieldIndex(tag_ty, enum_field_index);
2759026858 if (initializing) {
2759126859 const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, .fromValue(want_tag));
2759226860 try sema.checkComptimeKnownStore(block, set_tag_inst, .unneeded); // `unneeded` since this isn't a "proper" store
27593 } else if (block.wantSafety() and union_obj.hasTag(ip)) {
26861 } else if (block.wantSafety() and union_obj.runtime_tag != .none) {
2759426862 // The tag exists at runtime (safety tag), so emit a safety check.
2759526863 // TODO would it be better if get_union_tag supported pointers to unions?
2759626864 const union_val = try block.addTyOp(.load, union_ty, union_ptr);
......@@ -27619,26 +26887,25 @@ fn unionFieldVal(
2761926887 const ip = &zcu.intern_pool;
2762026888 assert(union_ty.zigTypeTag(zcu) == .@"union");
2762126889
27622 try union_ty.resolveFields(pt);
2762326890 const union_obj = zcu.typeToUnion(union_ty).?;
2762426891 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
2762526892 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
27626 const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_ty).enumFieldIndex(field_name, zcu).?);
26893 const enum_field_index: u32 = @intCast(Type.fromInterned(union_obj.enum_tag_type).enumFieldIndex(field_name, zcu).?);
2762726894
2762826895 if (try sema.resolveValue(union_byval)) |union_val| {
2762926896 if (union_val.isUndef(zcu)) return pt.undefRef(field_ty);
2763026897
2763126898 const un = ip.indexToKey(union_val.toIntern()).un;
27632 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index);
26899 const field_tag = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index);
2763326900 const tag_matches = un.tag == field_tag.toIntern();
27634 switch (union_obj.flagsUnordered(ip).layout) {
26901 switch (union_obj.layout) {
2763526902 .auto => {
2763626903 if (tag_matches) {
2763726904 return Air.internedToRef(un.val);
2763826905 } else {
2763926906 const msg = msg: {
27640 const active_index = Type.fromInterned(union_obj.enum_tag_ty).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
27641 const active_field_name = Type.fromInterned(union_obj.enum_tag_ty).enumFieldName(active_index, zcu);
26907 const active_index = Type.fromInterned(union_obj.enum_tag_type).enumTagFieldIndex(Value.fromInterned(un.tag), zcu).?;
26908 const active_field_name = Type.fromInterned(union_obj.enum_tag_type).enumFieldName(active_index, zcu);
2764226909 const msg = try sema.errMsg(src, "access of union field '{f}' while field '{f}' is active", .{
2764326910 field_name.fmt(ip), active_field_name.fmt(ip),
2764426911 });
......@@ -27658,18 +26925,18 @@ fn unionFieldVal(
2765826925 .@"packed" => if (tag_matches) {
2765926926 // Fast path - no need to use bitcast logic.
2766026927 return Air.internedToRef(un.val);
27661 } else if (try sema.bitCastVal(union_val, field_ty, 0, try union_ty.bitSizeSema(pt), 0)) |field_val| {
26928 } else if (try sema.bitCastVal(union_val, field_ty, 0, union_ty.bitSize(zcu), 0)) |field_val| {
2766226929 return Air.internedToRef(field_val.toIntern());
2766326930 },
2766426931 }
2766526932 }
2766626933
27667 if (union_obj.flagsUnordered(ip).layout == .auto and block.wantSafety() and
26934 if (union_obj.layout == .auto and block.wantSafety() and
2766826935 union_ty.unionTagTypeSafety(zcu) != null and union_obj.field_types.len > 1)
2766926936 {
27670 const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_ty), enum_field_index);
26937 const wanted_tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), enum_field_index);
2767126938 const wanted_tag = Air.internedToRef(wanted_tag_val.toIntern());
27672 const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_ty), union_byval);
26939 const active_tag = try block.addTyOp(.get_union_tag, .fromInterned(union_obj.enum_tag_type), union_byval);
2767326940 try sema.addSafetyCheckInactiveUnionField(block, src, active_tag, wanted_tag);
2767426941 }
2767526942
......@@ -27678,11 +26945,8 @@ fn unionFieldVal(
2767826945 return .unreachable_value;
2767926946 }
2768026947
27681 if (try sema.typeHasOnePossibleValue(field_ty)) |field_only_value| {
27682 return Air.internedToRef(field_only_value.toIntern());
27683 }
26948 if (try field_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2768426949
27685 try field_ty.resolveLayout(pt);
2768626950 return block.addStructFieldVal(union_byval, field_index, field_ty);
2768726951}
2768826952
......@@ -27706,17 +26970,19 @@ fn elemPtr(
2770626970 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{f}'", .{indexable_ptr_ty.fmt(pt)}),
2770726971 };
2770826972 try sema.checkIndexable(block, src, indexable_ty);
26973 try sema.ensureLayoutResolved(indexable_ty);
2770926974
2771026975 const elem_ptr = switch (indexable_ty.zigTypeTag(zcu)) {
2771126976 .array, .vector => try sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
2771226977 .@"struct" => blk: {
2771326978 // Tuple field access.
2771426979 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index });
27715 const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt));
26980 const index: u32 = @intCast(index_val.toUnsignedInt(zcu));
2771626981 break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);
2771726982 },
2771826983 else => {
2771926984 const indexable = try sema.analyzeLoad(block, indexable_ptr_src, indexable_ptr, indexable_ptr_src);
26985 try sema.ensureLayoutResolved(sema.typeOf(indexable).childType(zcu));
2772026986 return elemPtrOneLayerOnly(sema, block, src, indexable, elem_index, elem_index_src, init, oob_safety);
2772126987 },
2772226988 };
......@@ -27725,7 +26991,7 @@ fn elemPtr(
2772526991 return elem_ptr;
2772626992}
2772726993
27728/// Asserts that the type of indexable is pointer.
26994/// Asserts that `indexable` is an indexable pointer whose child type has its layout already resolved.
2772926995fn elemPtrOneLayerOnly(
2773026996 sema: *Sema,
2773126997 block: *Block,
......@@ -27741,7 +27007,10 @@ fn elemPtrOneLayerOnly(
2774127007 const pt = sema.pt;
2774227008 const zcu = pt.zcu;
2774327009
27744 try sema.checkIndexable(block, src, indexable_ty);
27010 assert(indexable_ty.isIndexable(zcu));
27011 assert(indexable_ty.zigTypeTag(zcu) == .pointer);
27012 const child_ty = indexable_ty.childType(zcu);
27013 child_ty.assertHasLayout(zcu);
2774527014
2774627015 switch (indexable_ty.ptrSize(zcu)) {
2774727016 .slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
......@@ -27751,7 +27020,7 @@ fn elemPtrOneLayerOnly(
2775127020 ct: {
2775227021 const ptr_val = maybe_ptr_val orelse break :ct;
2775327022 const index_val = maybe_index_val orelse break :ct;
27754 const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
27023 const index: usize = @intCast(index_val.toUnsignedInt(zcu));
2775527024 const elem_ptr = try ptr_val.ptrElem(index, pt);
2775627025 return Air.internedToRef(elem_ptr.toIntern());
2775727026 }
......@@ -27762,7 +27031,7 @@ fn elemPtrOneLayerOnly(
2776227031 try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src);
2776327032 try sema.validateRuntimeValue(block, indexable_src, indexable);
2776427033
27765 if (!try result_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
27034 if (result_ty.childType(zcu).abiSize(zcu) == 0) {
2776627035 // zero-bit child type; just bitcast the pointer
2776727036 return block.addBitCast(result_ty, indexable);
2776827037 }
......@@ -27770,13 +27039,12 @@ fn elemPtrOneLayerOnly(
2777027039 return block.addPtrElemPtr(indexable, elem_index, result_ty);
2777127040 },
2777227041 .one => {
27773 const child_ty = indexable_ty.childType(zcu);
2777427042 const elem_ptr = switch (child_ty.zigTypeTag(zcu)) {
2777527043 .array, .vector => try sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety),
2777627044 .@"struct" => blk: {
2777727045 assert(child_ty.isTuple(zcu));
2777827046 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index });
27779 const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt));
27047 const index: u32 = @intCast(index_val.toUnsignedInt(zcu));
2778027048 break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false);
2778127049 },
2778227050 else => unreachable, // Guaranteed by checkIndexable
......@@ -27808,45 +27076,45 @@ fn elemVal(
2780827076 const elem_index = try sema.coerce(block, .usize, elem_index_uncasted, elem_index_src);
2780927077
2781027078 switch (indexable_ty.zigTypeTag(zcu)) {
27811 .pointer => switch (indexable_ty.ptrSize(zcu)) {
27812 .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
27813 .many, .c => {
27814 const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
27815 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
27816 const elem_ty = indexable_ty.elemType2(zcu);
27817
27818 ct: {
27819 const indexable_val = maybe_indexable_val orelse break :ct;
27820 const index_val = maybe_index_val orelse break :ct;
27821 const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
27822 const many_ptr_ty = try pt.manyConstPtrType(elem_ty);
27823 const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty);
27824 const elem_ptr_ty = try pt.singleConstPtrType(elem_ty);
27825 const elem_ptr_val = try many_ptr_val.ptrElem(index, pt);
27826 const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct;
27827 return Air.internedToRef((try pt.getCoerced(elem_val, elem_ty)).toIntern());
27828 }
27079 .pointer => {
27080 const child_ty = indexable_ty.childType(zcu);
27081 try sema.ensureLayoutResolved(child_ty);
27082 switch (indexable_ty.ptrSize(zcu)) {
27083 .slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
27084 .many, .c => {
27085 const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
27086 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
27087
27088 ct: {
27089 const indexable_val = maybe_indexable_val orelse break :ct;
27090 const index_val = maybe_index_val orelse break :ct;
27091 const index: usize = @intCast(index_val.toUnsignedInt(zcu));
27092 const many_ptr_ty = try pt.manyConstPtrType(child_ty);
27093 const many_ptr_val = try pt.getCoerced(indexable_val, many_ptr_ty);
27094 const elem_ptr_ty = try pt.singleConstPtrType(child_ty);
27095 const elem_ptr_val = try many_ptr_val.ptrElem(index, pt);
27096 const elem_val = try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty) orelse break :ct;
27097 return Air.internedToRef((try pt.getCoerced(elem_val, child_ty)).toIntern());
27098 }
2782927099
27830 if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| {
27831 return Air.internedToRef(elem_only_value.toIntern());
27832 }
27100 if (try child_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2783327101
27834 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
27835 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
27836 },
27837 .one => {
27838 arr_sent: {
27839 const inner_ty = indexable_ty.childType(zcu);
27840 if (inner_ty.zigTypeTag(zcu) != .array) break :arr_sent;
27841 const sentinel = inner_ty.sentinel(zcu) orelse break :arr_sent;
27842 const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent;
27843 const index = try sema.usizeCast(block, src, try index_val.toUnsignedIntSema(pt));
27844 if (index != inner_ty.arrayLen(zcu)) break :arr_sent;
27845 return Air.internedToRef(sentinel.toIntern());
27846 }
27847 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
27848 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
27849 },
27102 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
27103 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
27104 },
27105 .one => {
27106 arr_sent: {
27107 if (child_ty.zigTypeTag(zcu) != .array) break :arr_sent;
27108 const sentinel = child_ty.sentinel(zcu) orelse break :arr_sent;
27109 const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent;
27110 const index = try sema.usizeCast(block, src, index_val.toUnsignedInt(zcu));
27111 if (index != child_ty.arrayLen(zcu)) break :arr_sent;
27112 return .fromValue(sentinel);
27113 }
27114 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
27115 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
27116 },
27117 }
2785027118 },
2785127119 .array => return sema.elemValArray(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
2785227120 .vector => {
......@@ -27856,7 +27124,7 @@ fn elemVal(
2785627124 .@"struct" => {
2785727125 // Tuple field access.
2785827126 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{ .simple = .tuple_field_index });
27859 const index: u32 = @intCast(try index_val.toUnsignedIntSema(pt));
27127 const index: u32 = @intCast(index_val.toUnsignedInt(zcu));
2786027128 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);
2786127129 },
2786227130 else => unreachable,
......@@ -27864,6 +27132,7 @@ fn elemVal(
2786427132}
2786527133
2786627134/// Called when the index or indexable is runtime known.
27135/// Asserts that the layout of `elem_ty` is already resolved.
2786727136fn validateRuntimeElemAccess(
2786827137 sema: *Sema,
2786927138 block: *Block,
......@@ -27875,7 +27144,7 @@ fn validateRuntimeElemAccess(
2787527144 const pt = sema.pt;
2787627145 const zcu = pt.zcu;
2787727146
27878 if (try elem_ty.comptimeOnlySema(sema.pt)) {
27147 if (elem_ty.comptimeOnly(zcu)) {
2787927148 const msg = msg: {
2788027149 const msg = try sema.errMsg(
2788127150 elem_index_src,
......@@ -27900,6 +27169,7 @@ fn validateRuntimeElemAccess(
2790027169 }
2790127170}
2790227171
27172/// Asserts that the layout of the tuple type is already resolved.
2790327173fn tupleFieldPtr(
2790427174 sema: *Sema,
2790527175 block: *Block,
......@@ -27914,9 +27184,10 @@ fn tupleFieldPtr(
2791427184 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
2791527185 const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu);
2791627186 const tuple_ty: Type = .fromInterned(tuple_ptr_info.child);
27917 try tuple_ty.resolveFields(pt);
2791827187 const field_count = tuple_ty.structFieldCount(zcu);
2791927188
27189 tuple_ty.assertHasLayout(zcu);
27190
2792027191 if (field_count == 0) {
2792127192 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
2792227193 }
......@@ -27928,7 +27199,7 @@ fn tupleFieldPtr(
2792827199 }
2792927200
2793027201 const field_ty = tuple_ty.fieldType(field_index, zcu);
27931 const ptr_field_ty = try pt.ptrTypeSema(.{
27202 const ptr_field_ty = try pt.ptrType(.{
2793227203 .child = field_ty.toIntern(),
2793327204 .flags = .{
2793427205 .is_const = tuple_ptr_info.flags.is_const,
......@@ -27938,15 +27209,12 @@ fn tupleFieldPtr(
2793827209 if (tuple_ptr_info.flags.alignment == .none) break :a .none;
2793927210 // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned.
2794027211 const tuple_align = tuple_ptr_info.flags.alignment;
27941 const field_align = try field_ty.abiAlignmentSema(pt);
27212 const field_align = field_ty.abiAlignment(zcu);
2794227213 break :a tuple_align.min(field_align);
2794327214 },
2794427215 },
2794527216 });
2794627217
27947 if (tuple_ty.structFieldIsComptime(field_index, zcu))
27948 try tuple_ty.resolveStructFieldInits(pt);
27949
2795027218 if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_val| {
2795127219 return Air.internedToRef((try pt.intern(.{ .ptr = .{
2795227220 .ty = ptr_field_ty.toIntern(),
......@@ -27978,7 +27246,6 @@ fn tupleField(
2797827246 const pt = sema.pt;
2797927247 const zcu = pt.zcu;
2798027248 const tuple_ty = sema.typeOf(tuple);
27981 try tuple_ty.resolveFields(pt);
2798227249 const field_count = tuple_ty.structFieldCount(zcu);
2798327250
2798427251 if (field_count == 0) {
......@@ -27993,8 +27260,6 @@ fn tupleField(
2799327260
2799427261 const field_ty = tuple_ty.fieldType(field_index, zcu);
2799527262
27996 if (tuple_ty.structFieldIsComptime(field_index, zcu))
27997 try tuple_ty.resolveStructFieldInits(pt);
2799827263 if (try tuple_ty.structFieldValueComptime(pt, field_index)) |default_value| {
2799927264 return Air.internedToRef(default_value.toIntern()); // comptime field
2800027265 }
......@@ -28006,7 +27271,6 @@ fn tupleField(
2800627271
2800727272 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
2800827273
28009 try field_ty.resolveLayout(pt);
2801027274 return block.addStructFieldVal(tuple, field_index, field_ty);
2801127275}
2801227276
......@@ -28037,7 +27301,7 @@ fn elemValArray(
2803727301 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
2803827302
2803927303 if (maybe_index_val) |index_val| {
28040 const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
27304 const index: usize = @intCast(index_val.toUnsignedInt(zcu));
2804127305 if (array_sent) |s| {
2804227306 if (index == array_len) {
2804327307 return Air.internedToRef(s.toIntern());
......@@ -28053,10 +27317,11 @@ fn elemValArray(
2805327317 return pt.undefRef(elem_ty);
2805427318 }
2805527319 if (maybe_index_val) |index_val| {
28056 const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
28057 const elem_val = try array_val.elemValue(pt, index);
28058 return Air.internedToRef(elem_val.toIntern());
27320 const index: usize = @intCast(index_val.toUnsignedInt(zcu));
27321 return .fromValue(try array_val.elemValue(pt, index));
2805927322 }
27323 // Since the array is comptime-known, it might be OPV, in which case the index is irrelevant.
27324 if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2806027325 }
2806127326
2806227327 try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, array_ty, array_src);
......@@ -28071,12 +27336,10 @@ fn elemValArray(
2807127336 }
2807227337 }
2807327338
28074 if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_val|
28075 return Air.internedToRef(elem_val.toIntern());
28076
2807727339 return block.addBinOp(.array_elem_val, array, elem_index);
2807827340}
2807927341
27342/// Asserts that the layout of the array or vector is already resolved.
2808027343fn elemPtrArray(
2808127344 sema: *Sema,
2808227345 block: *Block,
......@@ -28103,7 +27366,7 @@ fn elemPtrArray(
2810327366 const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr);
2810427367 // The index must not be undefined since it can be out of bounds.
2810527368 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
28106 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt));
27369 const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu));
2810727370 if (index >= array_len_s) {
2810827371 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";
2810927372 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label });
......@@ -28115,6 +27378,7 @@ fn elemPtrArray(
2811527378 return sema.fail(block, elem_index_src, "vector index not comptime known", .{});
2811627379 }
2811727380
27381 array_ty.assertHasLayout(zcu);
2811827382 const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, pt);
2811927383
2812027384 if (maybe_undef_array_ptr_val) |array_ptr_val| {
......@@ -28128,7 +27392,7 @@ fn elemPtrArray(
2812827392 }
2812927393
2813027394 if (!init) {
28131 try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(zcu), array_ty, array_ptr_src);
27395 try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.childType(zcu), array_ty, array_ptr_src);
2813227396 try sema.validateRuntimeValue(block, array_ptr_src, array_ptr);
2813327397 }
2813427398
......@@ -28142,6 +27406,7 @@ fn elemPtrArray(
2814227406 return block.addPtrElemPtr(array_ptr, elem_index, elem_ptr_ty);
2814327407}
2814427408
27409/// Asserts that the layout of the slice element type is already resolved.
2814527410fn elemValSlice(
2814627411 sema: *Sema,
2814727412 block: *Block,
......@@ -28156,9 +27421,11 @@ fn elemValSlice(
2815627421 const zcu = pt.zcu;
2815727422 const slice_ty = sema.typeOf(slice);
2815827423 const slice_sent = slice_ty.sentinel(zcu) != null;
28159 const elem_ty = slice_ty.elemType2(zcu);
27424 const elem_ty = slice_ty.childType(zcu);
2816027425 var runtime_src = slice_src;
2816127426
27427 elem_ty.assertHasLayout(zcu);
27428
2816227429 // slice must be defined since it can dereferenced as null
2816327430 const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice);
2816427431 // index must be defined since it can index out of bounds
......@@ -28166,13 +27433,13 @@ fn elemValSlice(
2816627433
2816727434 if (maybe_slice_val) |slice_val| {
2816827435 runtime_src = elem_index_src;
28169 const slice_len = try slice_val.sliceLen(pt);
27436 const slice_len = slice_val.sliceLen(zcu);
2817027437 const slice_len_s = slice_len + @intFromBool(slice_sent);
2817127438 if (slice_len_s == 0) {
2817227439 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
2817327440 }
2817427441 if (maybe_index_val) |index_val| {
28175 const index: usize = @intCast(try index_val.toUnsignedIntSema(pt));
27442 const index: usize = @intCast(index_val.toUnsignedInt(zcu));
2817627443 if (index >= slice_len_s) {
2817727444 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
2817827445 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
......@@ -28186,16 +27453,14 @@ fn elemValSlice(
2818627453 }
2818727454 }
2818827455
28189 if (try sema.typeHasOnePossibleValue(elem_ty)) |elem_only_value| {
28190 return Air.internedToRef(elem_only_value.toIntern());
28191 }
27456 if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
2819227457
2819327458 try sema.validateRuntimeElemAccess(block, elem_index_src, elem_ty, slice_ty, slice_src);
2819427459 try sema.validateRuntimeValue(block, slice_src, slice);
2819527460
2819627461 if (oob_safety and block.wantSafety()) {
2819727462 const len_inst = if (maybe_slice_val) |slice_val|
28198 try pt.intRef(.usize, try slice_val.sliceLen(pt))
27463 try pt.intRef(.usize, slice_val.sliceLen(zcu))
2819927464 else
2820027465 try block.addTyOp(.slice_len, .usize, slice);
2820127466 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
......@@ -28204,6 +27469,7 @@ fn elemValSlice(
2820427469 return block.addBinOp(.slice_elem_val, slice, elem_index);
2820527470}
2820627471
27472/// Asserts that the layout of the slice element type is already resolved.
2820727473fn elemPtrSlice(
2820827474 sema: *Sema,
2820927475 block: *Block,
......@@ -28219,11 +27485,12 @@ fn elemPtrSlice(
2821927485 const slice_ty = sema.typeOf(slice);
2822027486 const slice_sent = slice_ty.sentinel(zcu) != null;
2822127487
27488 slice_ty.childType(zcu).assertHasLayout(zcu);
27489
2822227490 const maybe_undef_slice_val = try sema.resolveValue(slice);
2822327491 // The index must not be undefined since it can be out of bounds.
2822427492 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
28225 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(pt));
28226 break :o index;
27493 break :o try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(zcu));
2822727494 } else null;
2822827495
2822927496 const elem_ptr_ty = try slice_ty.elemPtrType(offset, pt);
......@@ -28232,7 +27499,7 @@ fn elemPtrSlice(
2823227499 if (slice_val.isUndef(zcu)) {
2823327500 return pt.undefRef(elem_ptr_ty);
2823427501 }
28235 const slice_len = try slice_val.sliceLen(pt);
27502 const slice_len = slice_val.sliceLen(zcu);
2823627503 const slice_len_s = slice_len + @intFromBool(slice_sent);
2823727504 if (slice_len_s == 0) {
2823827505 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
......@@ -28254,13 +27521,13 @@ fn elemPtrSlice(
2825427521 const len_inst = len: {
2825527522 if (maybe_undef_slice_val) |slice_val|
2825627523 if (!slice_val.isUndef(zcu))
28257 break :len try pt.intRef(.usize, try slice_val.sliceLen(pt));
27524 break :len try pt.intRef(.usize, slice_val.sliceLen(zcu));
2825827525 break :len try block.addTyOp(.slice_len, .usize, slice);
2825927526 };
2826027527 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
2826127528 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
2826227529 }
28263 if (!try slice_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
27530 if (slice_ty.childType(zcu).abiSize(zcu) == 0) {
2826427531 // zero-bit child type; just extract the pointer and bitcast it
2826527532 const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice);
2826627533 return block.addBitCast(elem_ptr_ty, slice_ptr);
......@@ -28331,10 +27598,12 @@ fn coerceExtra(
2833127598 if (dest_ty.isGenericPoison()) return inst;
2833227599
2833327600 const dest_ty_src = inst_src; // TODO better source location
28334 try dest_ty.resolveFields(pt);
2833527601 const inst_ty = sema.typeOf(inst);
28336 try inst_ty.resolveFields(pt);
2833727602 const target = zcu.getTarget();
27603
27604 inst_ty.assertHasLayout(zcu);
27605 try sema.ensureLayoutResolved(dest_ty);
27606
2833827607 // If the types are the same, we can return the operand.
2833927608 if (dest_ty.eql(inst_ty, zcu))
2834027609 return inst;
......@@ -28357,7 +27626,7 @@ fn coerceExtra(
2835727626 if (maybe_inst_val) |val| {
2835827627 // undefined sets the optional bit also to undefined.
2835927628 if (val.toIntern() == .undef) {
28360 return pt.undefRef(dest_ty);
27629 return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty));
2836127630 }
2836227631
2836327632 // null to ?T
......@@ -28372,11 +27641,11 @@ fn coerceExtra(
2837227641 // cast from ?*T and ?[*]T to ?*anyopaque
2837327642 // but don't do it if the source type is a double pointer
2837427643 if (dest_ty.isPtrLikeOptional(zcu) and
28375 dest_ty.elemType2(zcu).toIntern() == .anyopaque_type and
27644 dest_ty.nullablePtrElem(zcu).toIntern() == .anyopaque_type and
2837627645 inst_ty.isPtrAtRuntime(zcu))
2837727646 anyopaque_check: {
2837827647 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
28379 const elem_ty = inst_ty.elemType2(zcu);
27648 const elem_ty = inst_ty.nullablePtrElem(zcu);
2838027649 if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) {
2838127650 in_memory_result = .{ .double_ptr_to_anyopaque = .{
2838227651 .actual = inst_ty,
......@@ -28520,7 +27789,7 @@ fn coerceExtra(
2852027789 // but don't do it if the source type is a double pointer
2852127790 if (dest_info.child == .anyopaque_type and inst_ty.zigTypeTag(zcu) == .pointer) to_anyopaque: {
2852227791 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
28523 const elem_ty = inst_ty.elemType2(zcu);
27792 const elem_ty = inst_ty.childType(zcu);
2852427793 if (elem_ty.zigTypeTag(zcu) == .pointer or elem_ty.isPtrLikeOptional(zcu)) {
2852527794 in_memory_result = .{ .double_ptr_to_anyopaque = .{
2852627795 .actual = inst_ty,
......@@ -28616,7 +27885,9 @@ fn coerceExtra(
2861627885 // empty tuple to zero-length slice
2861727886 // note that this allows coercing to a mutable slice.
2861827887 if (inst_child_ty.structFieldCount(zcu) == 0) {
28619 const align_val = try dest_ty.ptrAlignmentSema(pt);
27888 // TODO MLUGG: this is *unacceptably* stupid. we're resolving the child for the alignment value
27889 try sema.ensureLayoutResolved(dest_ty.childType(zcu));
27890 const align_val = dest_ty.ptrAlignment(zcu);
2862027891 return Air.internedToRef(try pt.intern(.{ .slice = .{
2862127892 .ty = dest_ty.toIntern(),
2862227893 .ptr = try pt.intern(.{ .ptr = .{
......@@ -28689,7 +27960,7 @@ fn coerceExtra(
2868927960 return sema.fail(block, inst_src, "type '{f}' cannot represent integer value '{f}'", .{ dest_ty.fmt(pt), val.fmtValueSema(pt, sema) });
2869027961 }
2869127962 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
28692 .undef => try pt.undefRef(dest_ty),
27963 .undef => .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty)),
2869327964 .int => |int| Air.internedToRef(
2869427965 try zcu.intern_pool.getCoercedInts(gpa, io, pt.tid, int, dest_ty.toIntern()),
2869527966 ),
......@@ -28768,7 +28039,7 @@ fn coerceExtra(
2876828039 }
2876928040 break :int;
2877028041 };
28771 const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, pt, .sema);
28042 const result_val = try pt.floatValue(dest_ty, val.toFloat(f128, zcu));
2877228043 const fits: bool = switch (ip.indexToKey(result_val.toIntern())) {
2877328044 else => unreachable,
2877428045 .undef => true,
......@@ -28905,11 +28176,11 @@ fn coerceExtra(
2890528176 else => true,
2890628177 };
2890728178
28908 if (can_coerce_to) {
28179 if (can_coerce_to and inst == .undef) {
2890928180 // undefined to anything. We do this after the big switch above so that
2891028181 // special logic has a chance to run first, such as `*[N]T` to `[]T` which
2891128182 // should initialize the length field of the slice.
28912 if (maybe_inst_val) |val| if (val.toIntern() == .undef) return pt.undefRef(dest_ty);
28183 return .fromValue(try dest_ty.onePossibleValue(pt) orelse try pt.undefValue(dest_ty));
2891328184 }
2891428185
2891528186 if (!opts.report_err) return error.NotCoercible;
......@@ -29444,17 +28715,13 @@ pub fn coerceInMemoryAllowed(
2944428715 }
2944528716
2944628717 // Pointers / Pointer-like Optionals
29447 const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty);
29448 const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty);
29449 if (maybe_dest_ptr_ty) |dest_ptr_ty| {
29450 if (maybe_src_ptr_ty) |src_ptr_ty| {
29451 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src);
29452 }
28718 if (dest_ty.isPtrAtRuntime(zcu) and src_ty.isPtrAtRuntime(zcu)) {
28719 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
2945328720 }
2945428721
2945528722 // Slices
2945628723 if (dest_ty.isSlice(zcu) and src_ty.isSlice(zcu)) {
29457 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
28724 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
2945828725 }
2945928726
2946028727 // Functions
......@@ -29554,7 +28821,8 @@ pub fn coerceInMemoryAllowed(
2955428821
2955528822 // Optionals
2955628823 if (dest_tag == .optional and src_tag == .optional) {
29557 if ((maybe_dest_ptr_ty != null) != (maybe_src_ptr_ty != null)) {
28824 if (dest_ty.isPtrAtRuntime(zcu) or src_ty.isPtrAtRuntime(zcu)) {
28825 // Only one is, because we already handled when both are.
2955828826 return .{ .optional_shape = .{
2955928827 .actual = src_ty,
2956028828 .wanted = dest_ty,
......@@ -29581,7 +28849,7 @@ pub fn coerceInMemoryAllowed(
2958128849 const field_count = dest_ty.structFieldCount(zcu);
2958228850 for (0..field_count) |field_idx| {
2958328851 if (dest_ty.structFieldIsComptime(field_idx, zcu) != src_ty.structFieldIsComptime(field_idx, zcu)) break :tuple;
29584 if (dest_ty.fieldAlignment(field_idx, zcu) != src_ty.fieldAlignment(field_idx, zcu)) break :tuple;
28852 if (dest_ty.resolvedFieldAlignment(field_idx, zcu) != src_ty.resolvedFieldAlignment(field_idx, zcu)) break :tuple;
2958528853 const dest_field_ty = dest_ty.fieldType(field_idx, zcu);
2958628854 const src_field_ty = src_ty.fieldType(field_idx, zcu);
2958728855 const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null);
......@@ -29714,11 +28982,7 @@ fn coerceInMemoryAllowedFns(
2971428982
2971528983 {
2971628984 if (dest_info.is_var_args != src_info.is_var_args) {
29717 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
29718 }
29719
29720 if (dest_info.is_generic != src_info.is_generic) {
29721 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
28985 return .{ .fn_var_args = dest_info.is_var_args };
2972228986 }
2972328987
2972428988 const callconv_ok = callconvCoerceAllowed(target, src_info.cc, dest_info.cc) and
......@@ -29731,6 +28995,12 @@ fn coerceInMemoryAllowedFns(
2973128995 } };
2973228996 }
2973328997
28998 try sema.ensureLayoutResolved(src_ty);
28999 try sema.ensureLayoutResolved(dest_ty);
29000 const src_is_runtime = src_ty.fnHasRuntimeBits(zcu);
29001 const dest_is_runtime = dest_ty.fnHasRuntimeBits(zcu);
29002 if (src_is_runtime != dest_is_runtime) return .{ .fn_generic = !dest_is_runtime };
29003
2973429004 if (!switch (src_info.return_type) {
2973529005 .generic_poison_type => true,
2973629006 .noreturn_type => !dest_is_mut,
......@@ -29780,7 +29050,8 @@ fn coerceInMemoryAllowedFns(
2978029050 const src_is_comptime = src_info.paramIsComptime(@intCast(param_i));
2978129051 const dest_is_comptime = dest_info.paramIsComptime(@intCast(param_i));
2978229052 if (src_is_comptime == dest_is_comptime) break :comptime_param;
29783 if (!dest_is_mut and src_is_comptime and !dest_is_comptime and try dest_param_ty.comptimeOnlySema(pt)) {
29053 try sema.ensureLayoutResolved(dest_param_ty);
29054 if (!dest_is_mut and src_is_comptime and !dest_is_comptime and dest_param_ty.comptimeOnly(zcu)) {
2978429055 // A parameter which is marked `comptime` can drop that annotation if the type is comptime-only.
2978529056 // The function remains generic, and the parameter is going to be comptime-resolved either way,
2978629057 // so this just affects whether or not the argument is comptime-evaluated at the call site.
......@@ -29861,8 +29132,6 @@ fn coerceInMemoryAllowedPtrs(
2986129132 block: *Block,
2986229133 dest_ty: Type,
2986329134 src_ty: Type,
29864 dest_ptr_ty: Type,
29865 src_ptr_ty: Type,
2986629135 /// If set, the coercion must be valid in both directions.
2986729136 dest_is_mut: bool,
2986829137 target: *const std.Target,
......@@ -29875,8 +29144,8 @@ fn coerceInMemoryAllowedPtrs(
2987529144 const gpa = comp.gpa;
2987629145 const io = comp.io;
2987729146
29878 const dest_info = dest_ptr_ty.ptrInfo(zcu);
29879 const src_info = src_ptr_ty.ptrInfo(zcu);
29147 const dest_info = dest_ty.ptrInfo(zcu);
29148 const src_info = src_ty.ptrInfo(zcu);
2988029149
2988129150 const ok_ptr_size = src_info.flags.size == dest_info.flags.size or
2988229151 src_info.flags.size == .c or dest_info.flags.size == .c;
......@@ -30008,16 +29277,14 @@ fn coerceInMemoryAllowedPtrs(
3000829277 if (src_info.flags.alignment != .none or dest_info.flags.alignment != .none or
3000929278 dest_info.child != src_info.child)
3001029279 {
30011 const src_align = if (src_info.flags.alignment != .none)
30012 src_info.flags.alignment
30013 else
30014 try Type.fromInterned(src_info.child).abiAlignmentSema(pt);
30015
30016 const dest_align = if (dest_info.flags.alignment != .none)
30017 dest_info.flags.alignment
30018 else
30019 try Type.fromInterned(dest_info.child).abiAlignmentSema(pt);
30020
29280 const src_align = if (src_info.flags.alignment == .none) a: {
29281 try sema.ensureLayoutResolved(src_child);
29282 break :a src_child.abiAlignment(zcu);
29283 } else src_info.flags.alignment;
29284 const dest_align = if (dest_info.flags.alignment == .none) a: {
29285 try sema.ensureLayoutResolved(dest_child);
29286 break :a dest_child.abiAlignment(zcu);
29287 } else dest_info.flags.alignment;
3002129288 if (dest_align.compare(if (dest_is_mut) .neq else .gt, src_align)) {
3002229289 return InMemoryCoercionResult{ .ptr_alignment = .{
3002329290 .actual = src_align,
......@@ -30180,9 +29447,16 @@ fn storePtr2(
3018029447 return sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
3018129448 };
3018229449
29450 // We do this after the possible comptime store above, for the case of field_ptr stores
29451 // to unions because we want the comptime tag to be set, even if the field type is void.
29452 // MLUGG TODO: that's insane, the runtime and comptime sematics should be the same. just set the tag at the same damn time
29453 if (try elem_ty.onePossibleValue(pt) != null) {
29454 return;
29455 }
29456
3018329457 // We're performing the store at runtime; as such, we need to make sure the pointee type
3018429458 // is not comptime-only. We can hit this case with a `@ptrFromInt` pointer.
30185 if (try elem_ty.comptimeOnlySema(pt)) {
29459 if (elem_ty.comptimeOnly(zcu)) {
3018629460 return sema.failWithOwnedErrorMsg(block, msg: {
3018729461 const msg = try sema.errMsg(src, "cannot store comptime-only type '{f}' at runtime", .{elem_ty.fmt(pt)});
3018829462 errdefer msg.destroy(sema.gpa);
......@@ -30191,12 +29465,6 @@ fn storePtr2(
3019129465 });
3019229466 }
3019329467
30194 // We do this after the possible comptime store above, for the case of field_ptr stores
30195 // to unions because we want the comptime tag to be set, even if the field type is void.
30196 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {
30197 return;
30198 }
30199
3020029468 try sema.requireRuntimeBlock(block, src, runtime_src);
3020129469
3020229470 const store_inst = if (is_ret)
......@@ -30361,10 +29629,10 @@ fn bitCast(
3036129629) CompileError!Air.Inst.Ref {
3036229630 const pt = sema.pt;
3036329631 const zcu = pt.zcu;
30364 try dest_ty.resolveLayout(pt);
30365
3036629632 const old_ty = sema.typeOf(inst);
30367 try old_ty.resolveLayout(pt);
29633
29634 old_ty.assertHasLayout(zcu);
29635 try sema.ensureLayoutResolved(dest_ty);
3036829636
3036929637 const dest_bits = dest_ty.bitSize(zcu);
3037029638 const old_bits = old_ty.bitSize(zcu);
......@@ -30510,9 +29778,7 @@ fn coerceCompatiblePtrs(
3051029778 }
3051129779 try sema.requireRuntimeBlock(block, inst_src, null);
3051229780 const inst_allows_zero = inst_ty.zigTypeTag(zcu) != .pointer or inst_ty.ptrAllowsZero(zcu);
30513 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu) and
30514 (try dest_ty.elemType2(zcu).hasRuntimeBitsSema(pt) or dest_ty.elemType2(zcu).zigTypeTag(zcu) == .@"fn"))
30515 {
29781 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(zcu)) {
3051629782 try sema.checkLogicalPtrOperation(block, inst_src, inst_ty);
3051729783 const actual_ptr = if (inst_ty.isSlice(zcu))
3051829784 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
......@@ -30532,6 +29798,7 @@ fn coerceCompatiblePtrs(
3053229798 return new_ptr;
3053329799}
3053429800
29801/// Asserts that the layout of `union_ty` is already resolved.
3053529802fn coerceEnumToUnion(
3053629803 sema: *Sema,
3053729804 block: *Block,
......@@ -30545,18 +29812,21 @@ fn coerceEnumToUnion(
3054529812 const ip = &zcu.intern_pool;
3054629813 const inst_ty = sema.typeOf(inst);
3054729814
30548 const tag_ty = union_ty.unionTagType(zcu) orelse {
30549 const msg = msg: {
30550 const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty);
30551 errdefer msg.destroy(sema.gpa);
30552 try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{});
30553 try sema.addDeclaredHereNote(msg, union_ty);
30554 break :msg msg;
30555 };
30556 return sema.failWithOwnedErrorMsg(block, msg);
30557 };
29815 union_ty.assertHasLayout(zcu);
29816
29817 const union_obj = zcu.typeToUnion(union_ty).?;
29818 const enum_ty: Type = .fromInterned(union_obj.enum_tag_type);
29819 const enum_obj = ip.loadEnumType(enum_ty.toIntern());
29820
29821 if (union_obj.runtime_tag != .tagged) return sema.failWithOwnedErrorMsg(block, msg: {
29822 const msg = try sema.typeMismatchErrMsg(inst_src, union_ty, inst_ty);
29823 errdefer msg.destroy(sema.gpa);
29824 try sema.errNote(union_ty_src, msg, "cannot coerce enum to untagged union", .{});
29825 try sema.addDeclaredHereNote(msg, union_ty);
29826 break :msg msg;
29827 });
3055829828
30559 const enum_tag = try sema.coerce(block, tag_ty, inst, inst_src);
29829 const enum_tag = try sema.coerce(block, enum_ty, inst, inst_src);
3056029830 if (try sema.resolveDefinedValue(block, inst_src, enum_tag)) |val| {
3056129831 const field_index = union_ty.unionTagFieldIndex(val, pt.zcu) orelse {
3056229832 return sema.fail(block, inst_src, "union '{f}' has no tag with value '{f}'", .{
......@@ -30564,15 +29834,12 @@ fn coerceEnumToUnion(
3056429834 });
3056529835 };
3056629836
30567 const union_obj = zcu.typeToUnion(union_ty).?;
29837 const field_name = enum_obj.field_names.get(ip)[field_index];
3056829838 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
30569 try field_ty.resolveFields(pt);
3057029839 if (field_ty.zigTypeTag(zcu) == .noreturn) {
3057129840 const msg = msg: {
3057229841 const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{});
3057329842 errdefer msg.destroy(sema.gpa);
30574
30575 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
3057629843 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
3057729844 field_name.fmt(ip),
3057829845 });
......@@ -30581,42 +29848,35 @@ fn coerceEnumToUnion(
3058129848 };
3058229849 return sema.failWithOwnedErrorMsg(block, msg);
3058329850 }
30584 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
30585 const msg = msg: {
30586 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
30587 const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{
30588 inst_ty.fmt(pt), union_ty.fmt(pt),
30589 field_ty.fmt(pt), field_name.fmt(ip),
30590 });
30591 errdefer msg.destroy(sema.gpa);
29851 const opv = try field_ty.onePossibleValue(pt) orelse return sema.failWithOwnedErrorMsg(block, msg: {
29852 const msg = try sema.errMsg(inst_src, "coercion from enum '{f}' to union '{f}' must initialize '{f}' field '{f}'", .{
29853 inst_ty.fmt(pt), union_ty.fmt(pt),
29854 field_ty.fmt(pt), field_name.fmt(ip),
29855 });
29856 errdefer msg.destroy(sema.gpa);
3059229857
30593 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{
30594 field_name.fmt(ip),
30595 });
30596 try sema.addDeclaredHereNote(msg, union_ty);
30597 break :msg msg;
30598 };
30599 return sema.failWithOwnedErrorMsg(block, msg);
30600 };
29858 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' declared here", .{field_name.fmt(ip)});
29859 try sema.addDeclaredHereNote(msg, union_ty);
29860 break :msg msg;
29861 });
3060129862
3060229863 return Air.internedToRef((try pt.unionValue(union_ty, val, opv)).toIntern());
3060329864 }
3060429865
3060529866 try sema.requireRuntimeBlock(block, inst_src, null);
3060629867
30607 if (tag_ty.isNonexhaustiveEnum(zcu)) {
29868 if (enum_ty.isNonexhaustiveEnum(zcu)) {
3060829869 const msg = msg: {
3060929870 const msg = try sema.errMsg(inst_src, "runtime coercion to union '{f}' from non-exhaustive enum", .{
3061029871 union_ty.fmt(pt),
3061129872 });
3061229873 errdefer msg.destroy(sema.gpa);
30613 try sema.addDeclaredHereNote(msg, tag_ty);
29874 try sema.addDeclaredHereNote(msg, enum_ty);
3061429875 break :msg msg;
3061529876 };
3061629877 return sema.failWithOwnedErrorMsg(block, msg);
3061729878 }
3061829879
30619 const union_obj = zcu.typeToUnion(union_ty).?;
3062029880 {
3062129881 var msg: ?*Zcu.ErrorMsg = null;
3062229882 errdefer if (msg) |some| some.destroy(sema.gpa);
......@@ -30626,7 +29886,7 @@ fn coerceEnumToUnion(
3062629886 const err_msg = msg orelse try sema.errMsg(
3062729887 inst_src,
3062829888 "runtime coercion from enum '{f}' to union '{f}' which has a 'noreturn' field",
30629 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
29889 .{ enum_ty.fmt(pt), union_ty.fmt(pt) },
3063029890 );
3063129891 msg = err_msg;
3063229892
......@@ -30649,14 +29909,14 @@ fn coerceEnumToUnion(
3064929909 const msg = try sema.errMsg(
3065029910 inst_src,
3065129911 "runtime coercion from enum '{f}' to union '{f}' which has non-void fields",
30652 .{ tag_ty.fmt(pt), union_ty.fmt(pt) },
29912 .{ enum_ty.fmt(pt), union_ty.fmt(pt) },
3065329913 );
3065429914 errdefer msg.destroy(sema.gpa);
3065529915
3065629916 for (0..union_obj.field_types.len) |field_index| {
30657 const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index];
29917 const field_name = enum_obj.field_names.get(ip)[field_index];
3065829918 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
30659 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;
29919 if (try field_ty.onePossibleValue(pt) != null) continue;
3066029920 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{f}' has type '{f}'", .{
3066129921 field_name.fmt(ip),
3066229922 field_ty.fmt(pt),
......@@ -30904,19 +30164,16 @@ fn coerceTupleToTuple(
3090430164 const field_i: u32 = @intCast(field_index_usize);
3090530165 const field_src = inst_src; // TODO better source location
3090630166
30907 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
30908 .tuple_type => |tuple_type| tuple_type.types.get(ip)[field_index_usize],
30909 .struct_type => ip.loadStructType(tuple_ty.toIntern()).field_types.get(ip)[field_index_usize],
30910 else => unreachable,
30911 };
30912 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
30913 .tuple_type => |tuple_type| tuple_type.values.get(ip)[field_index_usize],
30914 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, field_index_usize),
30915 else => unreachable,
30916 };
30917
3091830167 const field_index: u32 = @intCast(field_index_usize);
3091930168
30169 const field_ty, const default_val = field: {
30170 const tuple_type = ip.indexToKey(tuple_ty.toIntern()).tuple_type;
30171 break :field .{
30172 tuple_type.types.get(ip)[field_index],
30173 tuple_type.values.get(ip)[field_index],
30174 };
30175 };
30176
3092030177 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
3092130178 const coerced = try sema.coerce(block, .fromInterned(field_ty), elem_ref, field_src);
3092230179 field_refs[field_index] = coerced;
......@@ -30946,11 +30203,7 @@ fn coerceTupleToTuple(
3094630203 const i: u32 = @intCast(i_usize);
3094730204 if (field_ref.* != .none) continue;
3094830205
30949 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
30950 .tuple_type => |tuple_type| tuple_type.values.get(ip)[i],
30951 .struct_type => ip.loadStructType(tuple_ty.toIntern()).fieldInit(ip, i),
30952 else => unreachable,
30953 };
30206 const default_val = ip.indexToKey(tuple_ty.toIntern()).tuple_type.values.get(ip)[i];
3095430207
3095530208 const field_src = inst_src; // TODO better source location
3095630209 if (default_val == .none) {
......@@ -31019,13 +30272,13 @@ fn addReferenceEntry(
3101930272pub fn addTypeReferenceEntry(
3102030273 sema: *Sema,
3102130274 src: LazySrcLoc,
31022 referenced_type: InternPool.Index,
30275 referenced_type: Type,
3102330276) !void {
3102430277 const zcu = sema.pt.zcu;
3102530278 if (!zcu.comp.config.incremental and zcu.comp.reference_trace == 0) return;
31026 const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type);
30279 const gop = try sema.type_references.getOrPut(sema.gpa, referenced_type.toIntern());
3102730280 if (gop.found_existing) return;
31028 try zcu.addTypeReference(sema.owner, referenced_type, src);
30281 try zcu.addTypeReference(sema.owner, referenced_type.toIntern(), src);
3102930282}
3103030283
3103130284fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.MemoizedStateStage) SemaError!void {
......@@ -31143,7 +30396,7 @@ fn analyzeNavRefInner(sema: *Sema, block: *Block, src: LazySrcLoc, orig_nav_inde
3114330396 .type_resolved => |r| .{ r.type, r.alignment, r.@"addrspace", r.is_const },
3114430397 .fully_resolved => |r| .{ ip.typeOf(r.val), r.alignment, r.@"addrspace", r.is_const },
3114530398 };
31146 const ptr_ty = try pt.ptrTypeSema(.{
30399 const ptr_ty = try pt.ptrType(.{
3114730400 .child = ty,
3114830401 .flags = .{
3114930402 .alignment = alignment,
......@@ -31185,7 +30438,7 @@ fn maybeQueueFuncBodyAnalysis(sema: *Sema, block: *Block, src: LazySrcLoc, nav_i
3118530438 try sema.ensureNavResolved(block, src, nav_index, .type);
3118630439 const nav_ty: Type = .fromInterned(ip.getNav(nav_index).typeOf(ip));
3118730440 if (nav_ty.zigTypeTag(zcu) != .@"fn") return;
31188 if (!try nav_ty.fnHasRuntimeBitsSema(pt)) return;
30441 if (!nav_ty.fnHasRuntimeBits(zcu)) return;
3118930442
3119030443 try sema.ensureNavResolved(block, src, nav_index, .fully);
3119130444 const nav_val = zcu.navValue(nav_index);
......@@ -31218,14 +30471,14 @@ fn analyzeRef(
3121830471 // it's just that we can only use the *type* of the result, since the value is runtime-known.
3121930472
3122030473 const address_space = target_util.defaultAddressSpace(zcu.getTarget(), .local);
31221 const ptr_type = try pt.ptrTypeSema(.{
30474 const ptr_type = try pt.ptrType(.{
3122230475 .child = operand_ty.toIntern(),
3122330476 .flags = .{
3122430477 .is_const = true,
3122530478 .address_space = address_space,
3122630479 },
3122730480 });
31228 const mut_ptr_type = try pt.ptrTypeSema(.{
30481 const mut_ptr_type = try pt.ptrType(.{
3122930482 .child = operand_ty.toIntern(),
3123030483 .flags = .{ .address_space = address_space },
3123130484 });
......@@ -31261,9 +30514,8 @@ fn analyzeLoad(
3126130514 return sema.fail(block, ptr_src, "cannot load opaque type '{f}'", .{elem_ty.fmt(pt)});
3126230515 }
3126330516
31264 if (try sema.typeHasOnePossibleValue(elem_ty)) |opv| {
31265 return Air.internedToRef(opv.toIntern());
31266 }
30517 try sema.ensureLayoutResolved(elem_ty);
30518 if (try elem_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
3126730519
3126830520 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
3126930521 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
......@@ -31271,6 +30523,13 @@ fn analyzeLoad(
3127130523 }
3127230524 }
3127330525
30526 if (elem_ty.comptimeOnly(zcu)) return sema.failWithOwnedErrorMsg(block, msg: {
30527 const msg = try sema.errMsg(src, "cannot load comptime-only type '{f}'", .{elem_ty.fmt(pt)});
30528 errdefer msg.destroy(zcu.gpa);
30529 try sema.errNote(ptr_src, msg, "pointer of type '{f}' is runtime-known", .{ptr_ty.fmt(pt)});
30530 break :msg msg;
30531 });
30532
3127430533 return block.addTyOp(.load, elem_ty, ptr);
3127530534}
3127630535
......@@ -31332,7 +30591,7 @@ fn analyzeSliceLen(
3133230591 if (slice_val.isUndef(zcu)) {
3133330592 return .undef_usize;
3133430593 }
31335 return pt.intRef(.usize, try slice_val.sliceLen(pt));
30594 return pt.intRef(.usize, slice_val.sliceLen(zcu));
3133630595 }
3133730596 try sema.requireRuntimeBlock(block, src, null);
3133830597 return block.addTyOp(.slice_len, .usize, slice_inst);
......@@ -31682,6 +30941,8 @@ fn analyzeSlice(
3168230941 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{ptr_ptr_child_ty.fmt(pt)}),
3168330942 }
3168430943
30944 try sema.ensureLayoutResolved(elem_ty);
30945
3168530946 const ptr = if (slice_ty.isSlice(zcu))
3168630947 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
3168730948 else if (array_ty.zigTypeTag(zcu) == .array) ptr: {
......@@ -31690,7 +30951,7 @@ fn analyzeSlice(
3169030951 assert(manyptr_ty_key.flags.size == .one);
3169130952 manyptr_ty_key.child = elem_ty.toIntern();
3169230953 manyptr_ty_key.flags.size = .many;
31693 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrTypeSema(manyptr_ty_key), ptr_or_slice, ptr_src);
30954 break :ptr try sema.coerceCompatiblePtrs(block, try pt.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);
3169430955 } else ptr_or_slice;
3169530956
3169630957 const start = try sema.coerce(block, .usize, uncasted_start, start_src);
......@@ -31759,7 +31020,7 @@ fn analyzeSlice(
3175931020 return sema.fail(block, src, "slice of undefined", .{});
3176031021 }
3176131022 const has_sentinel = slice_ty.sentinel(zcu) != null;
31762 const slice_len = try slice_val.sliceLen(pt);
31023 const slice_len = slice_val.sliceLen(zcu);
3176331024 const len_plus_sent = slice_len + @intFromBool(has_sentinel);
3176431025 const slice_len_val_with_sentinel = try pt.intValue(.usize, len_plus_sent);
3176531026 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, .usize))) {
......@@ -31774,7 +31035,7 @@ fn analyzeSlice(
3177431035 "end index {f} out of bounds for slice of length {d}{s}",
3177531036 .{
3177631037 end_val.fmtValueSema(pt, sema),
31777 try slice_val.sliceLen(pt),
31038 slice_val.sliceLen(zcu),
3177831039 sentinel_label,
3177931040 },
3178031041 );
......@@ -31943,9 +31204,9 @@ fn analyzeSlice(
3194331204 const new_allowzero = new_ptr_ty_info.flags.is_allowzero and sema.typeOf(ptr).ptrSize(zcu) != .c;
3194431205
3194531206 if (opt_new_len_val) |new_len_val| {
31946 const new_len_int = try new_len_val.toUnsignedIntSema(pt);
31207 const new_len_int = new_len_val.toUnsignedInt(zcu);
3194731208
31948 const return_ty = try pt.ptrTypeSema(.{
31209 const return_ty = try pt.ptrType(.{
3194931210 .child = (try pt.arrayType(.{
3195031211 .len = new_len_int,
3195131212 .sentinel = if (sentinel) |s| s.toIntern() else .none,
......@@ -32009,7 +31270,7 @@ fn analyzeSlice(
3200931270 return sema.fail(block, src, "non-zero length slice of undefined pointer", .{});
3201031271 }
3201131272
32012 const return_ty = try pt.ptrTypeSema(.{
31273 const return_ty = try pt.ptrType(.{
3201331274 .child = elem_ty.toIntern(),
3201431275 .sentinel = if (sentinel) |s| s.toIntern() else .none,
3201531276 .flags = .{
......@@ -32037,7 +31298,7 @@ fn analyzeSlice(
3203731298 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
3203831299 // we don't need to add one for sentinels because the
3203931300 // underlying value data includes the sentinel
32040 break :blk try pt.intRef(.usize, try slice_val.sliceLen(pt));
31301 break :blk try pt.intRef(.usize, slice_val.sliceLen(zcu));
3204131302 }
3204231303
3204331304 const slice_len_inst = try block.addTyOp(.slice_len, .usize, ptr_or_slice);
......@@ -32158,16 +31419,10 @@ fn cmpNumeric(
3215831419
3215931420 const runtime_src: LazySrcLoc = if (maybe_lhs_val) |lhs_val| rs: {
3216031421 if (maybe_rhs_val) |rhs_val| {
32161 const res = try Value.compareHeteroSema(lhs_val, op, rhs_val, pt);
32162 return if (res) .bool_true else .bool_false;
31422 return .fromValue(.makeBool(Value.compareHetero(lhs_val, op, rhs_val, zcu)));
3216331423 } else break :rs rhs_src;
3216431424 } else lhs_src;
3216531425
32166 // TODO handle comparisons against lazy zero values
32167 // Some values can be compared against zero without being runtime-known or without forcing
32168 // a full resolution of their value, for example `@sizeOf(@Frame(function))` is known to
32169 // always be nonzero, and we benefit from not forcing the full evaluation and stack frame layout
32170 // of this function if we don't need to.
3217131426 try sema.requireRuntimeBlock(block, src, runtime_src);
3217231427
3217331428 // For floats, emit a float comparison instruction.
......@@ -32207,11 +31462,11 @@ fn cmpNumeric(
3220731462 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
3220831463 // add/subtract 1.
3220931464 const lhs_is_signed = if (maybe_lhs_val) |lhs_val|
32210 !(try lhs_val.compareAllWithZeroSema(.gte, pt))
31465 !lhs_val.compareAllWithZero(.gte, zcu)
3221131466 else
3221231467 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(zcu));
3221331468 const rhs_is_signed = if (maybe_rhs_val) |rhs_val|
32214 !(try rhs_val.compareAllWithZeroSema(.gte, pt))
31469 !rhs_val.compareAllWithZero(.gte, zcu)
3221531470 else
3221631471 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(zcu));
3221731472 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
......@@ -32219,10 +31474,9 @@ fn cmpNumeric(
3221931474 var dest_float_type: ?Type = null;
3222031475
3222131476 var lhs_bits: usize = undefined;
32222 if (maybe_lhs_val) |unresolved_lhs_val| {
32223 const lhs_val = try sema.resolveLazyValue(unresolved_lhs_val);
31477 if (maybe_lhs_val) |lhs_val| {
3222431478 if (!rhs_is_signed) {
32225 switch (lhs_val.orderAgainstZero(zcu)) {
31479 switch (Value.order(lhs_val, .zero_comptime_int, zcu)) {
3222631480 .gt => {},
3222731481 .eq => switch (op) { // LHS = 0, RHS is unsigned
3222831482 .lte => return .bool_true,
......@@ -32263,10 +31517,9 @@ fn cmpNumeric(
3226331517 }
3226431518
3226531519 var rhs_bits: usize = undefined;
32266 if (maybe_rhs_val) |unresolved_rhs_val| {
32267 const rhs_val = try sema.resolveLazyValue(unresolved_rhs_val);
31520 if (maybe_rhs_val) |rhs_val| {
3226831521 if (!lhs_is_signed) {
32269 switch (rhs_val.orderAgainstZero(zcu)) {
31522 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
3227031523 .gt => {},
3227131524 .eq => switch (op) { // RHS = 0, LHS is unsigned
3227231525 .gte => return .bool_true,
......@@ -32328,7 +31581,7 @@ fn compareIntsOnlyPossibleResult(
3232831581 lhs_val: Value,
3232931582 op: std.math.CompareOperator,
3233031583 rhs_ty: Type,
32331) SemaError!?bool {
31584) Allocator.Error!?bool {
3233231585 const pt = sema.pt;
3233331586 const zcu = pt.zcu;
3233431587
......@@ -32337,11 +31590,11 @@ fn compareIntsOnlyPossibleResult(
3233731590
3233831591 if (min_rhs.toIntern() == max_rhs.toIntern()) {
3233931592 // RHS is effectively comptime-known.
32340 return try Value.compareHeteroSema(lhs_val, op, min_rhs, pt);
31593 return Value.compareHetero(lhs_val, op, min_rhs, zcu);
3234131594 }
3234231595
32343 const against_min = try lhs_val.orderAdvanced(min_rhs, .sema, zcu, pt.tid);
32344 const against_max = try lhs_val.orderAdvanced(max_rhs, .sema, zcu, pt.tid);
31596 const against_min = lhs_val.order(min_rhs, zcu);
31597 const against_max = lhs_val.order(max_rhs, zcu);
3234531598
3234631599 switch (op) {
3234731600 .eq => {
......@@ -32529,9 +31782,7 @@ fn unionToTag(
3252931782) !Air.Inst.Ref {
3253031783 const pt = sema.pt;
3253131784 const zcu = pt.zcu;
32532 if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| {
32533 return Air.internedToRef(opv.toIntern());
32534 }
31785 if (try enum_ty.onePossibleValue(pt)) |opv| return .fromValue(opv);
3253531786 if (try sema.resolveValue(un)) |un_val| {
3253631787 const tag_val = un_val.unionTag(zcu).?;
3253731788 if (tag_val.isUndef(zcu))
......@@ -33240,18 +32491,24 @@ fn resolvePeerTypesInner(
3324032491 ptr_info.sentinel = .none;
3324132492 }
3324232493
33243 // Note that the align can be always non-zero; Zcu.ptrType will canonicalize it
33244 ptr_info.flags.alignment = InternPool.Alignment.min(
33245 if (ptr_info.flags.alignment != .none)
33246 ptr_info.flags.alignment
33247 else
33248 Type.fromInterned(ptr_info.child).abiAlignment(zcu),
33249
33250 if (peer_info.flags.alignment != .none)
33251 peer_info.flags.alignment
33252 else
33253 Type.fromInterned(peer_info.child).abiAlignment(zcu),
33254 );
32494 ptr_info.flags.alignment = a: {
32495 // If both alignments are implicit, the result alignment is implicit.
32496 // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32'
32497 if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) {
32498 break :a .none;
32499 }
32500 // Otherwise (if either alignment is explicit), the result alignment is explicit.
32501 // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32'
32502 const cur_align = switch (ptr_info.flags.alignment) {
32503 .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu),
32504 else => ptr_info.flags.alignment,
32505 };
32506 const new_align = switch (peer_info.flags.alignment) {
32507 .none => Type.fromInterned(peer_info.child).abiAlignment(zcu),
32508 else => peer_info.flags.alignment,
32509 };
32510 break :a .minStrict(cur_align, new_align);
32511 };
3325532512 if (ptr_info.flags.address_space != peer_info.flags.address_space) {
3325632513 return .{ .conflict = .{
3325732514 .peer_idx_a = first_idx,
......@@ -33273,7 +32530,7 @@ fn resolvePeerTypesInner(
3327332530
3327432531 opt_ptr_info = ptr_info;
3327532532 }
33276 return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) };
32533 return .{ .success = try pt.ptrType(opt_ptr_info.?) };
3327732534 },
3327832535
3327932536 .ptr => {
......@@ -33281,7 +32538,6 @@ fn resolvePeerTypesInner(
3328132538 // if there were no actual slices. Else, we want the slice index to report a conflict.
3328232539 var opt_slice_idx: ?usize = null;
3328332540
33284 var any_abi_aligned = false;
3328532541 var opt_ptr_info: ?InternPool.Key.PtrType = null;
3328632542 var first_idx: usize = undefined;
3328732543 var other_idx: usize = undefined; // We sometimes need a second peer index to report a generic error
......@@ -33325,15 +32581,24 @@ fn resolvePeerTypesInner(
3332532581 .peer_idx_b = i,
3332632582 } };
3332732583
33328 // Note that the align can be always non-zero; Type.ptr will canonicalize it
33329 if (peer_info.flags.alignment == .none) {
33330 any_abi_aligned = true;
33331 } else if (ptr_info.flags.alignment == .none) {
33332 any_abi_aligned = true;
33333 ptr_info.flags.alignment = peer_info.flags.alignment;
33334 } else {
33335 ptr_info.flags.alignment = ptr_info.flags.alignment.minStrict(peer_info.flags.alignment);
33336 }
32584 ptr_info.flags.alignment = a: {
32585 // If both alignments are implicit, the result alignment is implicit.
32586 // e.g. '[*c]u32' + '[*c]c_uint' -> '[*c]u32'
32587 if (ptr_info.flags.alignment == .none and peer_info.flags.alignment == .none) {
32588 break :a .none;
32589 }
32590 // Otherwise (if either alignment is explicit), the result alignment is explicit.
32591 // e.g. '[*c]u32' + '[*c]align(4) c_uint' -> '[*c]align(4) u32'
32592 const cur_align = switch (ptr_info.flags.alignment) {
32593 .none => Type.fromInterned(ptr_info.child).abiAlignment(zcu),
32594 else => ptr_info.flags.alignment,
32595 };
32596 const new_align = switch (peer_info.flags.alignment) {
32597 .none => Type.fromInterned(peer_info.child).abiAlignment(zcu),
32598 else => peer_info.flags.alignment,
32599 };
32600 break :a .minStrict(cur_align, new_align);
32601 };
3333732602
3333832603 if (ptr_info.flags.address_space != peer_info.flags.address_space) {
3333932604 return generic_err;
......@@ -33582,13 +32847,7 @@ fn resolvePeerTypesInner(
3358232847 },
3358332848 }
3358432849
33585 if (any_abi_aligned and opt_ptr_info.?.flags.alignment != .none) {
33586 opt_ptr_info.?.flags.alignment = opt_ptr_info.?.flags.alignment.minStrict(
33587 try Type.fromInterned(pointee).abiAlignmentSema(pt),
33588 );
33589 }
33590
33591 return .{ .success = try pt.ptrTypeSema(opt_ptr_info.?) };
32850 return .{ .success = try pt.ptrType(opt_ptr_info.?) };
3359232851 },
3359332852
3359432853 .func => {
......@@ -33731,7 +32990,7 @@ fn resolvePeerTypesInner(
3373132990 .peer_idx_b = i,
3373232991 } };
3373332992 any_comptime_known = true;
33734 ptr_opt_val.* = try sema.resolveLazyValue(opt_val.?);
32993 ptr_opt_val.* = opt_val.?;
3373532994 continue;
3373632995 },
3373732996 .int => {},
......@@ -33924,7 +33183,6 @@ fn resolvePeerTypesInner(
3392433183 var comptime_val: ?Value = null;
3392533184 for (peer_tys) |opt_ty| {
3392633185 const struct_ty = opt_ty orelse continue;
33927 try struct_ty.resolveStructFieldInits(pt);
3392833186
3392933187 const uncoerced_field_val = try struct_ty.structFieldValueComptime(pt, field_index) orelse {
3393033188 comptime_val = null;
......@@ -34058,344 +33316,6 @@ pub fn resolveIes(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError!void
3405833316 }
3405933317}
3406033318
34061pub fn resolveFnTypes(sema: *Sema, fn_ty: Type, src: LazySrcLoc) CompileError!void {
34062 const pt = sema.pt;
34063 const zcu = pt.zcu;
34064 const ip = &zcu.intern_pool;
34065 const fn_ty_info = zcu.typeToFunc(fn_ty).?;
34066
34067 try Type.fromInterned(fn_ty_info.return_type).resolveFully(pt);
34068
34069 if (zcu.comp.config.any_error_tracing and
34070 Type.fromInterned(fn_ty_info.return_type).isError(zcu))
34071 {
34072 // Ensure the type exists so that backends can assume that.
34073 _ = try sema.getBuiltinType(src, .StackTrace);
34074 }
34075
34076 for (0..fn_ty_info.param_types.len) |i| {
34077 try Type.fromInterned(fn_ty_info.param_types.get(ip)[i]).resolveFully(pt);
34078 }
34079}
34080
34081fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
34082 return val.resolveLazy(sema.arena, sema.pt);
34083}
34084
34085/// Resolve a struct's alignment only without triggering resolution of its layout.
34086/// Asserts that the alignment is not yet resolved and the layout is non-packed.
34087pub fn resolveStructAlignment(
34088 sema: *Sema,
34089 ty: InternPool.Index,
34090 struct_type: InternPool.LoadedStructType,
34091) SemaError!void {
34092 const pt = sema.pt;
34093 const zcu = pt.zcu;
34094 const io = zcu.comp.io;
34095 const ip = &zcu.intern_pool;
34096 const target = zcu.getTarget();
34097
34098 assert(sema.owner.unwrap().type == ty);
34099
34100 assert(struct_type.layout != .@"packed");
34101 assert(struct_type.flagsUnordered(ip).alignment == .none);
34102
34103 const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
34104
34105 // We'll guess "pointer-aligned", if the struct has an
34106 // underaligned pointer field then some allocations
34107 // might require explicit alignment.
34108 if (struct_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return;
34109
34110 try sema.resolveStructFieldTypes(ty, struct_type);
34111
34112 // We'll guess "pointer-aligned", if the struct has an
34113 // underaligned pointer field then some allocations
34114 // might require explicit alignment.
34115 if (struct_type.assumePointerAlignedIfWip(ip, io, ptr_align)) return;
34116 defer struct_type.clearAlignmentWip(ip, io);
34117
34118 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34119 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34120
34121 var alignment: Alignment = .@"1";
34122
34123 for (0..struct_type.field_types.len) |i| {
34124 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
34125 if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt))
34126 continue;
34127 const field_align = try field_ty.structFieldAlignmentSema(
34128 struct_type.fieldAlign(ip, i),
34129 struct_type.layout,
34130 pt,
34131 );
34132 alignment = alignment.maxStrict(field_align);
34133 }
34134
34135 struct_type.setAlignment(ip, io, alignment);
34136}
34137
34138pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
34139 const pt = sema.pt;
34140 const zcu = pt.zcu;
34141 const ip = &zcu.intern_pool;
34142 const io = zcu.comp.io;
34143 const struct_type = zcu.typeToStruct(ty) orelse return;
34144
34145 assert(sema.owner.unwrap().type == ty.toIntern());
34146
34147 if (struct_type.haveLayout(ip))
34148 return;
34149
34150 try sema.resolveStructFieldTypes(ty.toIntern(), struct_type);
34151
34152 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34153 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34154
34155 if (struct_type.layout == .@"packed") {
34156 sema.backingIntType(struct_type) catch |err| switch (err) {
34157 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34158 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34159 };
34160 return;
34161 }
34162
34163 if (struct_type.setLayoutWip(ip, io)) {
34164 const msg = try sema.errMsg(
34165 ty.srcLoc(zcu),
34166 "struct '{f}' depends on itself",
34167 .{ty.fmt(pt)},
34168 );
34169 return sema.failWithOwnedErrorMsg(null, msg);
34170 }
34171 defer struct_type.clearLayoutWip(ip, io);
34172
34173 const aligns = try sema.arena.alloc(Alignment, struct_type.field_types.len);
34174 const sizes = try sema.arena.alloc(u64, struct_type.field_types.len);
34175
34176 var big_align: Alignment = .@"1";
34177
34178 for (aligns, sizes, 0..) |*field_align, *field_size, i| {
34179 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
34180 if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) {
34181 struct_type.offsets.get(ip)[i] = 0;
34182 field_size.* = 0;
34183 field_align.* = .none;
34184 continue;
34185 }
34186
34187 field_size.* = field_ty.abiSizeSema(pt) catch |err| switch (err) {
34188 error.AnalysisFail => {
34189 const msg = sema.err orelse return err;
34190 try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
34191 return err;
34192 },
34193 else => return err,
34194 };
34195 field_align.* = try field_ty.structFieldAlignmentSema(
34196 struct_type.fieldAlign(ip, i),
34197 struct_type.layout,
34198 pt,
34199 );
34200 big_align = big_align.maxStrict(field_align.*);
34201 }
34202
34203 if (struct_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) {
34204 const msg = try sema.errMsg(
34205 ty.srcLoc(zcu),
34206 "struct layout depends on it having runtime bits",
34207 .{},
34208 );
34209 return sema.failWithOwnedErrorMsg(null, msg);
34210 }
34211
34212 if (struct_type.flagsUnordered(ip).assumed_pointer_aligned and
34213 big_align.compareStrict(.neq, Alignment.fromByteUnits(@divExact(zcu.getTarget().ptrBitWidth(), 8))))
34214 {
34215 const msg = try sema.errMsg(
34216 ty.srcLoc(zcu),
34217 "struct layout depends on being pointer aligned",
34218 .{},
34219 );
34220 return sema.failWithOwnedErrorMsg(null, msg);
34221 }
34222
34223 if (struct_type.hasReorderedFields()) {
34224 const runtime_order = struct_type.runtime_order.get(ip);
34225
34226 for (runtime_order, 0..) |*ro, i| {
34227 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
34228 if (struct_type.fieldIsComptime(ip, i) or try field_ty.comptimeOnlySema(pt)) {
34229 ro.* = .omitted;
34230 } else {
34231 ro.* = @enumFromInt(i);
34232 }
34233 }
34234
34235 const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder;
34236
34237 const AlignSortContext = struct {
34238 aligns: []const Alignment,
34239
34240 fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool {
34241 if (a == .omitted) return false;
34242 if (b == .omitted) return true;
34243 const a_align = ctx.aligns[@intFromEnum(a)];
34244 const b_align = ctx.aligns[@intFromEnum(b)];
34245 return a_align.compare(.gt, b_align);
34246 }
34247 };
34248 if (!zcu.backendSupportsFeature(.field_reordering)) {
34249 // TODO: we should probably also reorder tuple fields? This is a bit weird because it'll involve
34250 // mutating the `InternPool` for a non-container type.
34251 //
34252 // TODO: implement field reordering support in all the backends!
34253 //
34254 // This logic does not reorder fields; it only moves the omitted ones to the end
34255 // so that logic elsewhere does not need to special-case here.
34256 var i: usize = 0;
34257 var off: usize = 0;
34258 while (i + off < runtime_order.len) {
34259 if (runtime_order[i + off] == .omitted) {
34260 off += 1;
34261 continue;
34262 }
34263 runtime_order[i] = runtime_order[i + off];
34264 i += 1;
34265 }
34266 @memset(runtime_order[i..], .omitted);
34267 } else {
34268 mem.sortUnstable(RuntimeOrder, runtime_order, AlignSortContext{
34269 .aligns = aligns,
34270 }, AlignSortContext.lessThan);
34271 }
34272 }
34273
34274 // Calculate size, alignment, and field offsets.
34275 const offsets = struct_type.offsets.get(ip);
34276 var it = struct_type.iterateRuntimeOrder(ip);
34277 var offset: u64 = 0;
34278 while (it.next()) |i| {
34279 offsets[i] = @intCast(aligns[i].forward(offset));
34280 offset = offsets[i] + sizes[i];
34281 }
34282 const size = std.math.cast(u32, big_align.forward(offset)) orelse {
34283 const msg = try sema.errMsg(
34284 ty.srcLoc(zcu),
34285 "struct layout requires size {d}, this compiler implementation supports up to {d}",
34286 .{ big_align.forward(offset), std.math.maxInt(u32) },
34287 );
34288 return sema.failWithOwnedErrorMsg(null, msg);
34289 };
34290 struct_type.setLayoutResolved(ip, io, size, big_align);
34291 _ = try ty.comptimeOnlySema(pt);
34292}
34293
34294fn backingIntType(
34295 sema: *Sema,
34296 struct_type: InternPool.LoadedStructType,
34297) CompileError!void {
34298 const pt = sema.pt;
34299 const zcu = pt.zcu;
34300 const comp = zcu.comp;
34301 const gpa = comp.gpa;
34302 const io = comp.io;
34303 const ip = &zcu.intern_pool;
34304
34305 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
34306 defer analysis_arena.deinit();
34307
34308 var block: Block = .{
34309 .parent = null,
34310 .sema = sema,
34311 .namespace = struct_type.namespace,
34312 .instructions = .{},
34313 .inlining = null,
34314 .comptime_reason = null, // set below if needed
34315 .src_base_inst = struct_type.zir_index,
34316 .type_name_ctx = struct_type.name,
34317 };
34318 defer assert(block.instructions.items.len == 0);
34319
34320 const fields_bit_sum = blk: {
34321 var accumulator: u64 = 0;
34322 for (0..struct_type.field_types.len) |i| {
34323 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
34324 accumulator += try field_ty.bitSizeSema(pt);
34325 }
34326 break :blk accumulator;
34327 };
34328
34329 const zir = zcu.namespacePtr(struct_type.namespace).fileScope(zcu).zir.?;
34330 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
34331 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
34332 assert(extended.opcode == .struct_decl);
34333 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
34334
34335 if (small.has_backing_int) {
34336 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
34337 const captures_len = if (small.has_captures_len) blk: {
34338 const captures_len = zir.extra[extra_index];
34339 extra_index += 1;
34340 break :blk captures_len;
34341 } else 0;
34342 extra_index += @intFromBool(small.has_fields_len);
34343 extra_index += @intFromBool(small.has_decls_len);
34344
34345 extra_index += captures_len * 2;
34346
34347 const backing_int_body_len = zir.extra[extra_index];
34348 extra_index += 1;
34349
34350 const backing_int_src: LazySrcLoc = .{
34351 .base_node_inst = struct_type.zir_index,
34352 .offset = .{ .node_offset_container_tag = .zero },
34353 };
34354 block.comptime_reason = .{ .reason = .{
34355 .src = backing_int_src,
34356 .r = .{ .simple = .type },
34357 } };
34358 const backing_int_ty = blk: {
34359 if (backing_int_body_len == 0) {
34360 const backing_int_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
34361 break :blk try sema.resolveType(&block, backing_int_src, backing_int_ref);
34362 } else {
34363 const body = zir.bodySlice(extra_index, backing_int_body_len);
34364 const ty_ref = try sema.resolveInlineBody(&block, body, zir_index);
34365 break :blk try sema.analyzeAsType(&block, backing_int_src, ty_ref);
34366 }
34367 };
34368
34369 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
34370 struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern());
34371 } else {
34372 if (fields_bit_sum > std.math.maxInt(u16)) {
34373 return sema.fail(&block, block.nodeOffset(.zero), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
34374 }
34375 const backing_int_ty = try pt.intType(.unsigned, @intCast(fields_bit_sum));
34376 struct_type.setBackingIntType(ip, io, backing_int_ty.toIntern());
34377 }
34378
34379 try sema.flushExports();
34380}
34381
34382fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void {
34383 const pt = sema.pt;
34384 const zcu = pt.zcu;
34385
34386 if (!backing_int_ty.isInt(zcu)) {
34387 return sema.fail(block, src, "expected backing integer type, found '{f}'", .{backing_int_ty.fmt(pt)});
34388 }
34389 if (backing_int_ty.bitSize(zcu) != fields_bit_sum) {
34390 return sema.fail(
34391 block,
34392 src,
34393 "backing integer type '{f}' has bit size {d} but the struct fields have a total bit size of {d}",
34394 .{ backing_int_ty.fmt(pt), backing_int_ty.bitSize(zcu), fields_bit_sum },
34395 );
34396 }
34397}
34398
3439933319fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
3440033320 const pt = sema.pt;
3440133321 if (!ty.isIndexable(pt.zcu)) {
......@@ -34432,358 +33352,6 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
3443233352 return sema.failWithOwnedErrorMsg(block, msg);
3443333353}
3443433354
34435/// Resolve a unions's alignment only without triggering resolution of its layout.
34436/// Asserts that the alignment is not yet resolved.
34437pub fn resolveUnionAlignment(
34438 sema: *Sema,
34439 ty: Type,
34440 union_type: InternPool.LoadedUnionType,
34441) SemaError!void {
34442 const pt = sema.pt;
34443 const zcu = pt.zcu;
34444 const io = zcu.comp.io;
34445 const ip = &zcu.intern_pool;
34446 const target = zcu.getTarget();
34447
34448 assert(sema.owner.unwrap().type == ty.toIntern());
34449
34450 assert(!union_type.haveLayout(ip));
34451
34452 const ptr_align = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
34453
34454 // We'll guess "pointer-aligned", if the union has an
34455 // underaligned pointer field then some allocations
34456 // might require explicit alignment.
34457 if (union_type.assumePointerAlignedIfFieldTypesWip(ip, io, ptr_align)) return;
34458
34459 try sema.resolveUnionFieldTypes(ty, union_type);
34460
34461 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34462 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34463
34464 var max_align: Alignment = .@"1";
34465 for (0..union_type.field_types.len) |field_index| {
34466 const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
34467 if (!(try field_ty.hasRuntimeBitsSema(pt))) continue;
34468
34469 const explicit_align = union_type.fieldAlign(ip, field_index);
34470 const field_align = if (explicit_align != .none)
34471 explicit_align
34472 else
34473 try field_ty.abiAlignmentSema(sema.pt);
34474
34475 max_align = max_align.max(field_align);
34476 }
34477
34478 union_type.setAlignment(ip, io, max_align);
34479}
34480
34481/// This logic must be kept in sync with `Type.getUnionLayout`.
34482pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
34483 const pt = sema.pt;
34484 const io = pt.zcu.comp.io;
34485 const ip = &pt.zcu.intern_pool;
34486
34487 try sema.resolveUnionFieldTypes(ty, ip.loadUnionType(ty.ip_index));
34488
34489 // Load again, since the tag type might have changed due to resolution.
34490 const union_type = ip.loadUnionType(ty.ip_index);
34491
34492 assert(sema.owner.unwrap().type == ty.toIntern());
34493
34494 const old_flags = union_type.flagsUnordered(ip);
34495 switch (old_flags.status) {
34496 .none, .have_field_types => {},
34497 .field_types_wip, .layout_wip => {
34498 const msg = try sema.errMsg(
34499 ty.srcLoc(pt.zcu),
34500 "union '{f}' depends on itself",
34501 .{ty.fmt(pt)},
34502 );
34503 return sema.failWithOwnedErrorMsg(null, msg);
34504 },
34505 .have_layout, .fully_resolved_wip, .fully_resolved => return,
34506 }
34507
34508 errdefer union_type.setStatusIfLayoutWip(ip, io, old_flags.status);
34509
34510 union_type.setStatus(ip, io, .layout_wip);
34511
34512 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34513 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34514
34515 var max_size: u64 = 0;
34516 var max_align: Alignment = .@"1";
34517 for (0..union_type.field_types.len) |field_index| {
34518 const field_ty: Type = .fromInterned(union_type.field_types.get(ip)[field_index]);
34519 if (field_ty.isNoReturn(pt.zcu)) continue;
34520
34521 // We need to call `hasRuntimeBits` before calling `abiSize` to prevent reachable `unreachable`s,
34522 // but `hasRuntimeBits` only resolves field types and so may infinite recurse on a layout wip type,
34523 // so we must resolve the layout manually first, instead of waiting for `abiSize` to do it for us.
34524 // This is arguably just hacking around bugs in both `abiSize` for not allowing arbitrary types to
34525 // be queried, enabling failures to be handled with the emission of a compile error, and also in
34526 // `hasRuntimeBits` for ever being able to infinite recurse in the first place.
34527 try field_ty.resolveLayout(pt);
34528
34529 if (try field_ty.hasRuntimeBitsSema(pt)) {
34530 max_size = @max(max_size, field_ty.abiSizeSema(pt) catch |err| switch (err) {
34531 error.AnalysisFail => {
34532 const msg = sema.err orelse return err;
34533 try sema.addFieldErrNote(ty, field_index, msg, "while checking this field", .{});
34534 return err;
34535 },
34536 else => return err,
34537 });
34538 }
34539
34540 const explicit_align = union_type.fieldAlign(ip, field_index);
34541 const field_align = if (explicit_align != .none)
34542 explicit_align
34543 else
34544 try field_ty.abiAlignmentSema(pt);
34545 max_align = max_align.max(field_align);
34546 }
34547
34548 const has_runtime_tag = union_type.flagsUnordered(ip).runtime_tag.hasTag() and
34549 try Type.fromInterned(union_type.enum_tag_ty).hasRuntimeBitsSema(pt);
34550 const size, const alignment, const padding = if (has_runtime_tag) layout: {
34551 const enum_tag_type: Type = .fromInterned(union_type.enum_tag_ty);
34552 const tag_align = try enum_tag_type.abiAlignmentSema(pt);
34553 const tag_size = try enum_tag_type.abiSizeSema(pt);
34554
34555 // Put the tag before or after the payload depending on which one's
34556 // alignment is greater.
34557 var size: u64 = 0;
34558 var padding: u32 = 0;
34559 if (tag_align.order(max_align).compare(.gte)) {
34560 // {Tag, Payload}
34561 size += tag_size;
34562 size = max_align.forward(size);
34563 size += max_size;
34564 const prev_size = size;
34565 size = tag_align.forward(size);
34566 padding = @intCast(size - prev_size);
34567 } else {
34568 // {Payload, Tag}
34569 size += max_size;
34570 size = switch (pt.zcu.getTarget().ofmt) {
34571 .c => max_align,
34572 else => tag_align,
34573 }.forward(size);
34574 size += tag_size;
34575 const prev_size = size;
34576 size = max_align.forward(size);
34577 padding = @intCast(size - prev_size);
34578 }
34579
34580 break :layout .{ size, max_align.max(tag_align), padding };
34581 } else .{ max_align.forward(max_size), max_align, 0 };
34582
34583 const casted_size = std.math.cast(u32, size) orelse {
34584 const msg = try sema.errMsg(
34585 ty.srcLoc(pt.zcu),
34586 "union layout requires size {d}, this compiler implementation supports up to {d}",
34587 .{ size, std.math.maxInt(u32) },
34588 );
34589 return sema.failWithOwnedErrorMsg(null, msg);
34590 };
34591 union_type.setHaveLayout(ip, io, casted_size, padding, alignment);
34592
34593 if (union_type.flagsUnordered(ip).assumed_runtime_bits and !(try ty.hasRuntimeBitsSema(pt))) {
34594 const msg = try sema.errMsg(
34595 ty.srcLoc(pt.zcu),
34596 "union layout depends on it having runtime bits",
34597 .{},
34598 );
34599 return sema.failWithOwnedErrorMsg(null, msg);
34600 }
34601
34602 if (union_type.flagsUnordered(ip).assumed_pointer_aligned and
34603 alignment.compareStrict(.neq, Alignment.fromByteUnits(@divExact(pt.zcu.getTarget().ptrBitWidth(), 8))))
34604 {
34605 const msg = try sema.errMsg(
34606 ty.srcLoc(pt.zcu),
34607 "union layout depends on being pointer aligned",
34608 .{},
34609 );
34610 return sema.failWithOwnedErrorMsg(null, msg);
34611 }
34612 _ = try ty.comptimeOnlySema(pt);
34613}
34614
34615/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
34616/// be resolved.
34617pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
34618 try sema.resolveStructLayout(ty);
34619 try sema.resolveStructFieldInits(ty);
34620
34621 const pt = sema.pt;
34622 const zcu = pt.zcu;
34623 const io = zcu.comp.io;
34624 const ip = &zcu.intern_pool;
34625 const struct_type = zcu.typeToStruct(ty).?;
34626
34627 assert(sema.owner.unwrap().type == ty.toIntern());
34628
34629 if (struct_type.setFullyResolved(ip, io)) return;
34630 errdefer struct_type.clearFullyResolved(ip, io);
34631
34632 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34633 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34634
34635 // After we have resolve struct layout we have to go over the fields again to
34636 // make sure pointer fields get their child types resolved as well.
34637 // See also similar code for unions.
34638
34639 for (0..struct_type.field_types.len) |i| {
34640 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
34641 try field_ty.resolveFully(pt);
34642 }
34643}
34644
34645pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
34646 try sema.resolveUnionLayout(ty);
34647
34648 const pt = sema.pt;
34649 const zcu = pt.zcu;
34650 const io = zcu.comp.io;
34651 const ip = &zcu.intern_pool;
34652 const union_obj = zcu.typeToUnion(ty).?;
34653
34654 assert(sema.owner.unwrap().type == ty.toIntern());
34655
34656 switch (union_obj.flagsUnordered(ip).status) {
34657 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
34658 .fully_resolved_wip, .fully_resolved => return,
34659 }
34660
34661 // No `zcu.trackUnitSema` calls, since this phase isn't really doing any semantic analysis.
34662 // It's just triggering *other* analysis, alongside a simple loop over already-resolved info.
34663
34664 {
34665 // After we have resolve union layout we have to go over the fields again to
34666 // make sure pointer fields get their child types resolved as well.
34667 // See also similar code for structs.
34668 const prev_status = union_obj.flagsUnordered(ip).status;
34669 errdefer union_obj.setStatus(ip, io, prev_status);
34670
34671 union_obj.setStatus(ip, io, .fully_resolved_wip);
34672 for (0..union_obj.field_types.len) |field_index| {
34673 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
34674 try field_ty.resolveFully(pt);
34675 }
34676 union_obj.setStatus(ip, io, .fully_resolved);
34677 }
34678
34679 // And let's not forget comptime-only status.
34680 _ = try ty.comptimeOnlySema(pt);
34681}
34682
34683pub fn resolveStructFieldTypes(
34684 sema: *Sema,
34685 ty: InternPool.Index,
34686 struct_type: InternPool.LoadedStructType,
34687) SemaError!void {
34688 const pt = sema.pt;
34689 const zcu = pt.zcu;
34690 const io = zcu.comp.io;
34691 const ip = &zcu.intern_pool;
34692
34693 assert(sema.owner.unwrap().type == ty);
34694
34695 if (struct_type.haveFieldTypes(ip)) return;
34696
34697 if (struct_type.setFieldTypesWip(ip, io)) {
34698 const msg = try sema.errMsg(
34699 Type.fromInterned(ty).srcLoc(zcu),
34700 "struct '{f}' depends on itself",
34701 .{Type.fromInterned(ty).fmt(pt)},
34702 );
34703 return sema.failWithOwnedErrorMsg(null, msg);
34704 }
34705 defer struct_type.clearFieldTypesWip(ip, io);
34706
34707 // can't happen earlier than this because we only want the progress node if not already resolved
34708 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
34709 defer tracked_unit.end(zcu);
34710
34711 sema.structFields(struct_type) catch |err| switch (err) {
34712 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34713 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34714 };
34715}
34716
34717pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
34718 const pt = sema.pt;
34719 const zcu = pt.zcu;
34720 const io = zcu.comp.io;
34721 const ip = &zcu.intern_pool;
34722 const struct_type = zcu.typeToStruct(ty) orelse return;
34723
34724 assert(sema.owner.unwrap().type == ty.toIntern());
34725
34726 // Inits can start as resolved
34727 if (struct_type.haveFieldInits(ip)) return;
34728
34729 try sema.resolveStructLayout(ty);
34730
34731 if (struct_type.setInitsWip(ip, io)) {
34732 const msg = try sema.errMsg(
34733 ty.srcLoc(zcu),
34734 "struct '{f}' depends on itself",
34735 .{ty.fmt(pt)},
34736 );
34737 return sema.failWithOwnedErrorMsg(null, msg);
34738 }
34739 defer struct_type.clearInitsWip(ip, io);
34740
34741 // can't happen earlier than this because we only want the progress node if not already resolved
34742 const tracked_unit = zcu.trackUnitSema(struct_type.name.toSlice(ip), null);
34743 defer tracked_unit.end(zcu);
34744
34745 sema.structFieldInits(struct_type) catch |err| switch (err) {
34746 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34747 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34748 };
34749 struct_type.setHaveFieldInits(ip, io);
34750}
34751
34752pub fn resolveUnionFieldTypes(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void {
34753 const pt = sema.pt;
34754 const zcu = pt.zcu;
34755 const io = zcu.comp.io;
34756 const ip = &zcu.intern_pool;
34757
34758 assert(sema.owner.unwrap().type == ty.toIntern());
34759
34760 switch (union_type.flagsUnordered(ip).status) {
34761 .none => {},
34762 .field_types_wip => {
34763 const msg = try sema.errMsg(ty.srcLoc(zcu), "union '{f}' depends on itself", .{ty.fmt(pt)});
34764 return sema.failWithOwnedErrorMsg(null, msg);
34765 },
34766 .have_field_types,
34767 .have_layout,
34768 .layout_wip,
34769 .fully_resolved_wip,
34770 .fully_resolved,
34771 => return,
34772 }
34773
34774 // can't happen earlier than this because we only want the progress node if not already resolved
34775 const tracked_unit = zcu.trackUnitSema(union_type.name.toSlice(ip), null);
34776 defer tracked_unit.end(zcu);
34777
34778 union_type.setStatus(ip, io, .field_types_wip);
34779 errdefer union_type.setStatus(ip, io, .none);
34780 sema.unionFields(ty.toIntern(), union_type) catch |err| switch (err) {
34781 error.AnalysisFail, error.OutOfMemory, error.Canceled => |e| return e,
34782 error.ComptimeBreak, error.ComptimeReturn => unreachable,
34783 };
34784 union_type.setStatus(ip, io, .have_field_types);
34785}
34786
3478733355/// Returns a normal error set corresponding to the fully populated inferred
3478833356/// error set.
3478933357fn resolveInferredErrorSet(
......@@ -34798,8 +33366,9 @@ fn resolveInferredErrorSet(
3479833366 const func_index = ip.iesFuncIndex(ies_index);
3479933367 const func = zcu.funcInfo(func_index);
3480033368
34801 try sema.declareDependency(.{ .interned = func_index }); // resolved IES
33369 try sema.declareDependency(.{ .func_ies = func_index });
3480233370
33371 // MLUGG TODO: this feels kinda bad now... instead check for outdated whenver we grab this?
3480333372 try zcu.maybeUnresolveIes(func_index);
3480433373 const resolved_ty = func.resolvedErrorSetUnordered(ip);
3480533374 if (resolved_ty != .none) return resolved_ty;
......@@ -34820,7 +33389,7 @@ fn resolveInferredErrorSet(
3482033389 if (ies_func_info.return_type == .generic_poison_type) {
3482133390 assert(ies_func_info.cc == .@"inline");
3482233391 } else if (ip.errorUnionSet(ies_func_info.return_type) == ies_index) {
34823 if (ies_func_info.is_generic) {
33392 if (!Type.fromInterned(func.ty).fnHasRuntimeBits(zcu)) {
3482433393 return sema.failWithOwnedErrorMsg(block, msg: {
3482533394 const msg = try sema.errMsg(src, "unable to resolve inferred error set of generic function", .{});
3482633395 errdefer msg.destroy(sema.gpa);
......@@ -34935,1248 +33504,6 @@ fn resolveInferredErrorSetTy(
3493533504 }
3493633505}
3493733506
34938fn structZirInfo(zir: Zir, zir_index: Zir.Inst.Index) struct {
34939 /// fields_len
34940 usize,
34941 Zir.Inst.StructDecl.Small,
34942 /// extra_index
34943 usize,
34944} {
34945 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
34946 assert(extended.opcode == .struct_decl);
34947 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
34948 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
34949
34950 const captures_len = if (small.has_captures_len) blk: {
34951 const captures_len = zir.extra[extra_index];
34952 extra_index += 1;
34953 break :blk captures_len;
34954 } else 0;
34955
34956 const fields_len = if (small.has_fields_len) blk: {
34957 const fields_len = zir.extra[extra_index];
34958 extra_index += 1;
34959 break :blk fields_len;
34960 } else 0;
34961
34962 const decls_len = if (small.has_decls_len) decls_len: {
34963 const decls_len = zir.extra[extra_index];
34964 extra_index += 1;
34965 break :decls_len decls_len;
34966 } else 0;
34967
34968 extra_index += captures_len * 2;
34969
34970 // The backing integer cannot be handled until `resolveStructLayout()`.
34971 if (small.has_backing_int) {
34972 const backing_int_body_len = zir.extra[extra_index];
34973 extra_index += 1; // backing_int_body_len
34974 if (backing_int_body_len == 0) {
34975 extra_index += 1; // backing_int_ref
34976 } else {
34977 extra_index += backing_int_body_len; // backing_int_body_inst
34978 }
34979 }
34980
34981 // Skip over decls.
34982 extra_index += decls_len;
34983
34984 return .{ fields_len, small, extra_index };
34985}
34986
34987fn structFields(
34988 sema: *Sema,
34989 struct_type: InternPool.LoadedStructType,
34990) CompileError!void {
34991 const pt = sema.pt;
34992 const zcu = pt.zcu;
34993 const comp = zcu.comp;
34994 const gpa = comp.gpa;
34995 const io = comp.io;
34996 const ip = &zcu.intern_pool;
34997
34998 const namespace_index = struct_type.namespace;
34999 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?;
35000 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
35001
35002 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
35003
35004 if (fields_len == 0) switch (struct_type.layout) {
35005 .@"packed" => {
35006 try sema.backingIntType(struct_type);
35007 return;
35008 },
35009 .auto, .@"extern" => {
35010 struct_type.setLayoutResolved(ip, io, 0, .none);
35011 return;
35012 },
35013 };
35014
35015 var block_scope: Block = .{
35016 .parent = null,
35017 .sema = sema,
35018 .namespace = namespace_index,
35019 .instructions = .{},
35020 .inlining = null,
35021 .comptime_reason = .{ .reason = .{
35022 .src = .{
35023 .base_node_inst = struct_type.zir_index,
35024 .offset = .nodeOffset(.zero),
35025 },
35026 .r = .{ .simple = .type },
35027 } },
35028 .src_base_inst = struct_type.zir_index,
35029 .type_name_ctx = struct_type.name,
35030 };
35031 defer assert(block_scope.instructions.items.len == 0);
35032
35033 const Field = struct {
35034 type_body_len: u32 = 0,
35035 align_body_len: u32 = 0,
35036 init_body_len: u32 = 0,
35037 type_ref: Zir.Inst.Ref = .none,
35038 };
35039 const fields = try sema.arena.alloc(Field, fields_len);
35040
35041 var any_inits = false;
35042 var any_aligned = false;
35043
35044 {
35045 const bits_per_field = 4;
35046 const fields_per_u32 = 32 / bits_per_field;
35047 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
35048 const flags_index = extra_index;
35049 var bit_bag_index: usize = flags_index;
35050 extra_index += bit_bags_count;
35051 var cur_bit_bag: u32 = undefined;
35052 var field_i: u32 = 0;
35053 while (field_i < fields_len) : (field_i += 1) {
35054 if (field_i % fields_per_u32 == 0) {
35055 cur_bit_bag = zir.extra[bit_bag_index];
35056 bit_bag_index += 1;
35057 }
35058 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
35059 cur_bit_bag >>= 1;
35060 const has_init = @as(u1, @truncate(cur_bit_bag)) != 0;
35061 cur_bit_bag >>= 1;
35062 const is_comptime = @as(u1, @truncate(cur_bit_bag)) != 0;
35063 cur_bit_bag >>= 1;
35064 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
35065 cur_bit_bag >>= 1;
35066
35067 if (is_comptime) struct_type.setFieldComptime(ip, field_i);
35068
35069 const field_name_zir: [:0]const u8 = zir.nullTerminatedString(@enumFromInt(zir.extra[extra_index]));
35070 extra_index += 1; // field_name
35071
35072 fields[field_i] = .{};
35073
35074 if (has_type_body) {
35075 fields[field_i].type_body_len = zir.extra[extra_index];
35076 } else {
35077 fields[field_i].type_ref = @enumFromInt(zir.extra[extra_index]);
35078 }
35079 extra_index += 1;
35080
35081 // This string needs to outlive the ZIR code.
35082 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
35083 assert(struct_type.addFieldName(ip, field_name) == null);
35084
35085 if (has_align) {
35086 fields[field_i].align_body_len = zir.extra[extra_index];
35087 extra_index += 1;
35088 any_aligned = true;
35089 }
35090 if (has_init) {
35091 fields[field_i].init_body_len = zir.extra[extra_index];
35092 extra_index += 1;
35093 any_inits = true;
35094 }
35095 }
35096 }
35097
35098 // Next we do only types and alignments, saving the inits for a second pass,
35099 // so that init values may depend on type layout.
35100
35101 for (fields, 0..) |zir_field, field_i| {
35102 const ty_src: LazySrcLoc = .{
35103 .base_node_inst = struct_type.zir_index,
35104 .offset = .{ .container_field_type = @intCast(field_i) },
35105 };
35106 const field_ty: Type = ty: {
35107 if (zir_field.type_ref != .none) {
35108 break :ty try sema.resolveType(&block_scope, ty_src, zir_field.type_ref);
35109 }
35110 assert(zir_field.type_body_len != 0);
35111 const body = zir.bodySlice(extra_index, zir_field.type_body_len);
35112 extra_index += body.len;
35113 const ty_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
35114 break :ty try sema.analyzeAsType(&block_scope, ty_src, ty_ref);
35115 };
35116
35117 struct_type.field_types.get(ip)[field_i] = field_ty.toIntern();
35118
35119 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
35120 const msg = msg: {
35121 const msg = try sema.errMsg(ty_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
35122 errdefer msg.destroy(sema.gpa);
35123
35124 try sema.addDeclaredHereNote(msg, field_ty);
35125 break :msg msg;
35126 };
35127 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35128 }
35129 if (field_ty.zigTypeTag(zcu) == .noreturn) {
35130 const msg = msg: {
35131 const msg = try sema.errMsg(ty_src, "struct fields cannot be 'noreturn'", .{});
35132 errdefer msg.destroy(sema.gpa);
35133
35134 try sema.addDeclaredHereNote(msg, field_ty);
35135 break :msg msg;
35136 };
35137 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35138 }
35139 switch (struct_type.layout) {
35140 .@"extern" => if (!try sema.validateExternType(field_ty, .struct_field)) {
35141 const msg = msg: {
35142 const msg = try sema.errMsg(ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35143 errdefer msg.destroy(sema.gpa);
35144
35145 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .struct_field);
35146
35147 try sema.addDeclaredHereNote(msg, field_ty);
35148 break :msg msg;
35149 };
35150 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35151 },
35152 .@"packed" => if (!try sema.validatePackedType(field_ty)) {
35153 const msg = msg: {
35154 const msg = try sema.errMsg(ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35155 errdefer msg.destroy(sema.gpa);
35156
35157 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
35158
35159 try sema.addDeclaredHereNote(msg, field_ty);
35160 break :msg msg;
35161 };
35162 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35163 },
35164 else => {},
35165 }
35166
35167 if (zir_field.align_body_len > 0) {
35168 const body = zir.bodySlice(extra_index, zir_field.align_body_len);
35169 extra_index += body.len;
35170 const align_ref = try sema.resolveInlineBody(&block_scope, body, zir_index);
35171 const align_src: LazySrcLoc = .{
35172 .base_node_inst = struct_type.zir_index,
35173 .offset = .{ .container_field_align = @intCast(field_i) },
35174 };
35175 const field_align = try sema.analyzeAsAlign(&block_scope, align_src, align_ref);
35176 struct_type.field_aligns.get(ip)[field_i] = field_align;
35177 }
35178
35179 extra_index += zir_field.init_body_len;
35180 }
35181
35182 struct_type.clearFieldTypesWip(ip, io);
35183 if (!any_inits) struct_type.setHaveFieldInits(ip, io);
35184
35185 try sema.flushExports();
35186}
35187
35188// This logic must be kept in sync with `structFields`
35189fn structFieldInits(
35190 sema: *Sema,
35191 struct_type: InternPool.LoadedStructType,
35192) CompileError!void {
35193 const pt = sema.pt;
35194 const zcu = pt.zcu;
35195 const ip = &zcu.intern_pool;
35196
35197 assert(!struct_type.haveFieldInits(ip));
35198
35199 const namespace_index = struct_type.namespace;
35200 const zir = zcu.namespacePtr(namespace_index).fileScope(zcu).zir.?;
35201 const zir_index = struct_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
35202 const fields_len, _, var extra_index = structZirInfo(zir, zir_index);
35203
35204 var block_scope: Block = .{
35205 .parent = null,
35206 .sema = sema,
35207 .namespace = namespace_index,
35208 .instructions = .{},
35209 .inlining = null,
35210 .comptime_reason = undefined, // set when `block_scope` is used
35211 .src_base_inst = struct_type.zir_index,
35212 .type_name_ctx = struct_type.name,
35213 };
35214 defer assert(block_scope.instructions.items.len == 0);
35215
35216 const Field = struct {
35217 type_body_len: u32 = 0,
35218 align_body_len: u32 = 0,
35219 init_body_len: u32 = 0,
35220 };
35221 const fields = try sema.arena.alloc(Field, fields_len);
35222
35223 var any_inits = false;
35224
35225 {
35226 const bits_per_field = 4;
35227 const fields_per_u32 = 32 / bits_per_field;
35228 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
35229 const flags_index = extra_index;
35230 var bit_bag_index: usize = flags_index;
35231 extra_index += bit_bags_count;
35232 var cur_bit_bag: u32 = undefined;
35233 var field_i: u32 = 0;
35234 while (field_i < fields_len) : (field_i += 1) {
35235 if (field_i % fields_per_u32 == 0) {
35236 cur_bit_bag = zir.extra[bit_bag_index];
35237 bit_bag_index += 1;
35238 }
35239 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
35240 cur_bit_bag >>= 1;
35241 const has_init = @as(u1, @truncate(cur_bit_bag)) != 0;
35242 cur_bit_bag >>= 2;
35243 const has_type_body = @as(u1, @truncate(cur_bit_bag)) != 0;
35244 cur_bit_bag >>= 1;
35245
35246 extra_index += 1; // field_name
35247
35248 fields[field_i] = .{};
35249
35250 if (has_type_body) fields[field_i].type_body_len = zir.extra[extra_index];
35251 extra_index += 1;
35252
35253 if (has_align) {
35254 fields[field_i].align_body_len = zir.extra[extra_index];
35255 extra_index += 1;
35256 }
35257 if (has_init) {
35258 fields[field_i].init_body_len = zir.extra[extra_index];
35259 extra_index += 1;
35260 any_inits = true;
35261 }
35262 }
35263 }
35264
35265 if (any_inits) {
35266 for (fields, 0..) |zir_field, field_i| {
35267 extra_index += zir_field.type_body_len;
35268 extra_index += zir_field.align_body_len;
35269 const body = zir.bodySlice(extra_index, zir_field.init_body_len);
35270 extra_index += zir_field.init_body_len;
35271
35272 if (body.len == 0) continue;
35273
35274 // Pre-populate the type mapping the body expects to be there.
35275 // In init bodies, the zir index of the struct itself is used
35276 // to refer to the current field type.
35277
35278 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_i]);
35279 const type_ref = Air.internedToRef(field_ty.toIntern());
35280 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, &.{zir_index});
35281 sema.inst_map.putAssumeCapacity(zir_index, type_ref);
35282
35283 const init_src: LazySrcLoc = .{
35284 .base_node_inst = struct_type.zir_index,
35285 .offset = .{ .container_field_value = @intCast(field_i) },
35286 };
35287
35288 block_scope.comptime_reason = .{ .reason = .{
35289 .src = init_src,
35290 .r = .{ .simple = .struct_field_default_value },
35291 } };
35292 const init = try sema.resolveInlineBody(&block_scope, body, zir_index);
35293 const coerced = try sema.coerce(&block_scope, field_ty, init, init_src);
35294 const default_val = try sema.resolveConstValue(&block_scope, init_src, coerced, null);
35295
35296 if (default_val.canMutateComptimeVarState(zcu)) {
35297 return sema.failWithContainsReferenceToComptimeVar(
35298 &block_scope,
35299 init_src,
35300 struct_type.fieldName(ip, field_i),
35301 "field default value",
35302 default_val,
35303 );
35304 }
35305 struct_type.field_inits.get(ip)[field_i] = default_val.toIntern();
35306 }
35307 }
35308
35309 try sema.flushExports();
35310}
35311
35312fn unionFields(
35313 sema: *Sema,
35314 union_ty: InternPool.Index,
35315 union_type: InternPool.LoadedUnionType,
35316) CompileError!void {
35317 const tracy = trace(@src());
35318 defer tracy.end();
35319
35320 const pt = sema.pt;
35321 const zcu = pt.zcu;
35322 const comp = zcu.comp;
35323 const gpa = comp.gpa;
35324 const io = comp.io;
35325 const ip = &zcu.intern_pool;
35326
35327 const zir = zcu.namespacePtr(union_type.namespace).fileScope(zcu).zir.?;
35328 const zir_index = union_type.zir_index.resolve(ip) orelse return error.AnalysisFail;
35329 const extended = zir.instructions.items(.data)[@intFromEnum(zir_index)].extended;
35330 assert(extended.opcode == .union_decl);
35331 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
35332 const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand);
35333 var extra_index: usize = extra.end;
35334
35335 const tag_type_ref: Zir.Inst.Ref = if (small.has_tag_type) blk: {
35336 const ty_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
35337 extra_index += 1;
35338 break :blk ty_ref;
35339 } else .none;
35340
35341 const captures_len = if (small.has_captures_len) blk: {
35342 const captures_len = zir.extra[extra_index];
35343 extra_index += 1;
35344 break :blk captures_len;
35345 } else 0;
35346
35347 const body_len = if (small.has_body_len) blk: {
35348 const body_len = zir.extra[extra_index];
35349 extra_index += 1;
35350 break :blk body_len;
35351 } else 0;
35352
35353 const fields_len = if (small.has_fields_len) blk: {
35354 const fields_len = zir.extra[extra_index];
35355 extra_index += 1;
35356 break :blk fields_len;
35357 } else 0;
35358
35359 const decls_len = if (small.has_decls_len) decls_len: {
35360 const decls_len = zir.extra[extra_index];
35361 extra_index += 1;
35362 break :decls_len decls_len;
35363 } else 0;
35364
35365 // Skip over captures and decls.
35366 extra_index += captures_len * 2 + decls_len;
35367
35368 const body = zir.bodySlice(extra_index, body_len);
35369 extra_index += body.len;
35370
35371 const src: LazySrcLoc = .{
35372 .base_node_inst = union_type.zir_index,
35373 .offset = .nodeOffset(.zero),
35374 };
35375
35376 var block_scope: Block = .{
35377 .parent = null,
35378 .sema = sema,
35379 .namespace = union_type.namespace,
35380 .instructions = .{},
35381 .inlining = null,
35382 .comptime_reason = .{ .reason = .{
35383 .src = src,
35384 .r = .{ .simple = .type },
35385 } },
35386 .src_base_inst = union_type.zir_index,
35387 .type_name_ctx = union_type.name,
35388 };
35389 defer assert(block_scope.instructions.items.len == 0);
35390
35391 if (body.len != 0) {
35392 _ = try sema.analyzeInlineBody(&block_scope, body, zir_index);
35393 }
35394
35395 var int_tag_ty: Type = undefined;
35396 var enum_field_names: []InternPool.NullTerminatedString = &.{};
35397 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .empty;
35398 var explicit_tags_seen: []bool = &.{};
35399 if (tag_type_ref != .none) {
35400 const tag_ty_src: LazySrcLoc = .{
35401 .base_node_inst = union_type.zir_index,
35402 .offset = .{ .node_offset_container_tag = .zero },
35403 };
35404 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
35405 if (small.auto_enum_tag) {
35406 // The provided type is an integer type and we must construct the enum tag type here.
35407 int_tag_ty = provided_ty;
35408 if (int_tag_ty.zigTypeTag(zcu) != .int and int_tag_ty.zigTypeTag(zcu) != .comptime_int) {
35409 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{f}'", .{int_tag_ty.fmt(pt)});
35410 }
35411
35412 if (fields_len > 0) {
35413 const field_count_val = try pt.intValue(.comptime_int, fields_len - 1);
35414 if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) {
35415 const msg = msg: {
35416 const msg = try sema.errMsg(tag_ty_src, "specified integer tag type cannot represent every field", .{});
35417 errdefer msg.destroy(sema.gpa);
35418 try sema.errNote(tag_ty_src, msg, "type '{f}' cannot fit values in range 0...{d}", .{
35419 int_tag_ty.fmt(pt),
35420 fields_len - 1,
35421 });
35422 break :msg msg;
35423 };
35424 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35425 }
35426 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
35427 try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len);
35428 }
35429 } else {
35430 // The provided type is the enum tag type.
35431 const enum_type = switch (ip.indexToKey(provided_ty.toIntern())) {
35432 .enum_type => ip.loadEnumType(provided_ty.toIntern()),
35433 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{f}'", .{provided_ty.fmt(pt)}),
35434 };
35435 union_type.setTagType(ip, io, provided_ty.toIntern());
35436 // The fields of the union must match the enum exactly.
35437 // A flag per field is used to check for missing and extraneous fields.
35438 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
35439 @memset(explicit_tags_seen, false);
35440 }
35441 } else {
35442 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
35443 // purposes, we still auto-generate an enum tag type the same way. That the union is
35444 // untagged is represented by the Type tag (union vs union_tagged).
35445 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
35446 }
35447
35448 var field_types: std.ArrayList(InternPool.Index) = .empty;
35449 var field_aligns: std.ArrayList(InternPool.Alignment) = .empty;
35450
35451 try field_types.ensureTotalCapacityPrecise(sema.arena, fields_len);
35452 if (small.any_aligned_fields)
35453 try field_aligns.ensureTotalCapacityPrecise(sema.arena, fields_len);
35454
35455 var max_bits: u64 = 0;
35456 var min_bits: u64 = std.math.maxInt(u64);
35457 var max_bits_src: LazySrcLoc = undefined;
35458 var min_bits_src: LazySrcLoc = undefined;
35459 var max_bits_ty: Type = undefined;
35460 var min_bits_ty: Type = undefined;
35461 const bits_per_field = 4;
35462 const fields_per_u32 = 32 / bits_per_field;
35463 const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
35464 var bit_bag_index: usize = extra_index;
35465 extra_index += bit_bags_count;
35466 var cur_bit_bag: u32 = undefined;
35467 var field_i: u32 = 0;
35468 var last_tag_val: ?Value = null;
35469 const layout = union_type.flagsUnordered(ip).layout;
35470 while (field_i < fields_len) : (field_i += 1) {
35471 if (field_i % fields_per_u32 == 0) {
35472 cur_bit_bag = zir.extra[bit_bag_index];
35473 bit_bag_index += 1;
35474 }
35475 const has_type = @as(u1, @truncate(cur_bit_bag)) != 0;
35476 cur_bit_bag >>= 1;
35477 const has_align = @as(u1, @truncate(cur_bit_bag)) != 0;
35478 cur_bit_bag >>= 1;
35479 const has_tag = @as(u1, @truncate(cur_bit_bag)) != 0;
35480 cur_bit_bag >>= 1;
35481 const unused = @as(u1, @truncate(cur_bit_bag)) != 0;
35482 cur_bit_bag >>= 1;
35483 _ = unused;
35484
35485 const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]);
35486 const field_name_zir = zir.nullTerminatedString(field_name_index);
35487 extra_index += 1;
35488
35489 const field_type_ref: Zir.Inst.Ref = if (has_type) blk: {
35490 const field_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
35491 extra_index += 1;
35492 break :blk field_type_ref;
35493 } else .none;
35494
35495 const align_ref: Zir.Inst.Ref = if (has_align) blk: {
35496 const align_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
35497 extra_index += 1;
35498 break :blk align_ref;
35499 } else .none;
35500
35501 const tag_ref: Air.Inst.Ref = if (has_tag) blk: {
35502 const tag_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
35503 extra_index += 1;
35504 break :blk try sema.resolveInst(tag_ref);
35505 } else .none;
35506
35507 const name_src: LazySrcLoc = .{
35508 .base_node_inst = union_type.zir_index,
35509 .offset = .{ .container_field_name = field_i },
35510 };
35511 const value_src: LazySrcLoc = .{
35512 .base_node_inst = union_type.zir_index,
35513 .offset = .{ .container_field_value = field_i },
35514 };
35515 const align_src: LazySrcLoc = .{
35516 .base_node_inst = union_type.zir_index,
35517 .offset = .{ .container_field_align = field_i },
35518 };
35519 const type_src: LazySrcLoc = .{
35520 .base_node_inst = union_type.zir_index,
35521 .offset = .{ .container_field_type = field_i },
35522 };
35523
35524 if (enum_field_vals.capacity() > 0) {
35525 const enum_tag_val = if (tag_ref != .none) blk: {
35526 const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, value_src);
35527 const val = try sema.resolveConstDefinedValue(&block_scope, value_src, coerced, .{ .simple = .enum_field_tag_value });
35528 last_tag_val = val;
35529
35530 break :blk val;
35531 } else blk: {
35532 if (last_tag_val) |last_tag| {
35533 const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag);
35534 if (result.overflow) return sema.fail(
35535 &block_scope,
35536 value_src,
35537 "enumeration value '{f}' too large for type '{f}'",
35538 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
35539 );
35540 last_tag_val = result.val;
35541 } else {
35542 last_tag_val = try pt.intValue(int_tag_ty, 0);
35543 }
35544 break :blk last_tag_val.?;
35545 };
35546 const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern());
35547 if (gop.found_existing) {
35548 const other_value_src: LazySrcLoc = .{
35549 .base_node_inst = union_type.zir_index,
35550 .offset = .{ .container_field_value = @intCast(gop.index) },
35551 };
35552 const msg = msg: {
35553 const msg = try sema.errMsg(
35554 value_src,
35555 "enum tag value {f} already taken",
35556 .{enum_tag_val.fmtValueSema(pt, sema)},
35557 );
35558 errdefer msg.destroy(gpa);
35559 try sema.errNote(other_value_src, msg, "other occurrence here", .{});
35560 break :msg msg;
35561 };
35562 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35563 }
35564 }
35565
35566 // This string needs to outlive the ZIR code.
35567 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
35568 if (enum_field_names.len != 0) {
35569 enum_field_names[field_i] = field_name;
35570 }
35571
35572 const field_ty: Type = if (!has_type)
35573 .void
35574 else if (field_type_ref == .none)
35575 .noreturn
35576 else
35577 try sema.resolveType(&block_scope, type_src, field_type_ref);
35578
35579 if (explicit_tags_seen.len > 0) {
35580 const tag_ty = union_type.tagTypeUnordered(ip);
35581 const tag_info = ip.loadEnumType(tag_ty);
35582 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
35583 return sema.fail(&block_scope, name_src, "no field named '{f}' in enum '{f}'", .{
35584 field_name.fmt(ip), Type.fromInterned(tag_ty).fmt(pt),
35585 });
35586 };
35587
35588 // No check for duplicate because the check already happened in order
35589 // to create the enum type in the first place.
35590 assert(!explicit_tags_seen[enum_index]);
35591 explicit_tags_seen[enum_index] = true;
35592
35593 // Enforce the enum fields and the union fields being in the same order.
35594 if (enum_index != field_i) {
35595 const msg = msg: {
35596 const enum_field_src: LazySrcLoc = .{
35597 .base_node_inst = Type.fromInterned(tag_ty).typeDeclInstAllowGeneratedTag(zcu).?,
35598 .offset = .{ .container_field_name = enum_index },
35599 };
35600 const msg = try sema.errMsg(name_src, "union field '{f}' ordered differently than corresponding enum field", .{
35601 field_name.fmt(ip),
35602 });
35603 errdefer msg.destroy(sema.gpa);
35604 try sema.errNote(enum_field_src, msg, "enum field here", .{});
35605 break :msg msg;
35606 };
35607 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35608 }
35609 }
35610
35611 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
35612 const msg = msg: {
35613 const msg = try sema.errMsg(type_src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
35614 errdefer msg.destroy(sema.gpa);
35615
35616 try sema.addDeclaredHereNote(msg, field_ty);
35617 break :msg msg;
35618 };
35619 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35620 }
35621 switch (layout) {
35622 .@"extern" => if (!try sema.validateExternType(field_ty, .union_field)) {
35623 const msg = msg: {
35624 const msg = try sema.errMsg(type_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35625 errdefer msg.destroy(sema.gpa);
35626
35627 try sema.explainWhyTypeIsNotExtern(msg, type_src, field_ty, .union_field);
35628
35629 try sema.addDeclaredHereNote(msg, field_ty);
35630 break :msg msg;
35631 };
35632 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35633 },
35634 .@"packed" => {
35635 if (!try sema.validatePackedType(field_ty)) {
35636 const msg = msg: {
35637 const msg = try sema.errMsg(type_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
35638 errdefer msg.destroy(sema.gpa);
35639
35640 try sema.explainWhyTypeIsNotPacked(msg, type_src, field_ty);
35641
35642 try sema.addDeclaredHereNote(msg, field_ty);
35643 break :msg msg;
35644 };
35645 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35646 }
35647 const field_bits = try field_ty.bitSizeSema(pt);
35648 if (field_bits >= max_bits) {
35649 max_bits = field_bits;
35650 max_bits_src = type_src;
35651 max_bits_ty = field_ty;
35652 }
35653 if (field_bits <= min_bits) {
35654 min_bits = field_bits;
35655 min_bits_src = type_src;
35656 min_bits_ty = field_ty;
35657 }
35658 },
35659 .auto => {},
35660 }
35661
35662 field_types.appendAssumeCapacity(field_ty.toIntern());
35663
35664 if (small.any_aligned_fields) {
35665 field_aligns.appendAssumeCapacity(if (align_ref != .none)
35666 try sema.resolveAlign(&block_scope, align_src, align_ref)
35667 else
35668 .none);
35669 } else {
35670 assert(align_ref == .none);
35671 }
35672 }
35673
35674 union_type.setFieldTypes(ip, field_types.items);
35675 union_type.setFieldAligns(ip, field_aligns.items);
35676
35677 if (layout == .@"packed" and fields_len != 0 and min_bits != max_bits) {
35678 const msg = msg: {
35679 const msg = try sema.errMsg(src, "packed union has fields with mismatching bit sizes", .{});
35680 errdefer msg.destroy(sema.gpa);
35681 try sema.errNote(min_bits_src, msg, "{d} bits here", .{min_bits});
35682 try sema.addDeclaredHereNote(msg, min_bits_ty);
35683 try sema.errNote(max_bits_src, msg, "{d} bits here", .{max_bits});
35684 try sema.addDeclaredHereNote(msg, max_bits_ty);
35685 break :msg msg;
35686 };
35687 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35688 }
35689
35690 if (explicit_tags_seen.len > 0) {
35691 const tag_ty = union_type.tagTypeUnordered(ip);
35692 const tag_info = ip.loadEnumType(tag_ty);
35693 if (tag_info.names.len > fields_len) {
35694 const msg = msg: {
35695 const msg = try sema.errMsg(src, "enum field(s) missing in union", .{});
35696 errdefer msg.destroy(sema.gpa);
35697
35698 for (tag_info.names.get(ip), 0..) |field_name, field_index| {
35699 if (explicit_tags_seen[field_index]) continue;
35700 try sema.addFieldErrNote(.fromInterned(tag_ty), field_index, msg, "field '{f}' missing, declared here", .{
35701 field_name.fmt(ip),
35702 });
35703 }
35704 try sema.addDeclaredHereNote(msg, .fromInterned(tag_ty));
35705 break :msg msg;
35706 };
35707 return sema.failWithOwnedErrorMsg(&block_scope, msg);
35708 }
35709 } else if (enum_field_vals.count() > 0) {
35710 const enum_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_ty, union_type.name);
35711 union_type.setTagType(ip, io, enum_ty);
35712 } else {
35713 const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_ty, union_type.name);
35714 union_type.setTagType(ip, io, enum_ty);
35715 }
35716
35717 try sema.flushExports();
35718}
35719
35720fn generateUnionTagTypeNumbered(
35721 sema: *Sema,
35722 block: *Block,
35723 enum_field_names: []const InternPool.NullTerminatedString,
35724 enum_field_vals: []const InternPool.Index,
35725 union_type: InternPool.Index,
35726 union_name: InternPool.NullTerminatedString,
35727) !InternPool.Index {
35728 const pt = sema.pt;
35729 const zcu = pt.zcu;
35730 const comp = zcu.comp;
35731 const gpa = comp.gpa;
35732 const io = comp.io;
35733 const ip = &zcu.intern_pool;
35734
35735 const name = try ip.getOrPutStringFmt(
35736 gpa,
35737 io,
35738 pt.tid,
35739 "@typeInfo({f}).@\"union\".tag_type.?",
35740 .{union_name.fmt(ip)},
35741 .no_embedded_nulls,
35742 );
35743
35744 const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{
35745 .name = name,
35746 .owner_union_ty = union_type,
35747 .tag_ty = if (enum_field_vals.len == 0)
35748 (try pt.intType(.unsigned, 0)).toIntern()
35749 else
35750 ip.typeOf(enum_field_vals[0]),
35751 .names = enum_field_names,
35752 .values = enum_field_vals,
35753 .tag_mode = .explicit,
35754 .parent_namespace = block.namespace,
35755 });
35756
35757 return enum_ty;
35758}
35759
35760fn generateUnionTagTypeSimple(
35761 sema: *Sema,
35762 block: *Block,
35763 enum_field_names: []const InternPool.NullTerminatedString,
35764 union_type: InternPool.Index,
35765 union_name: InternPool.NullTerminatedString,
35766) !InternPool.Index {
35767 const pt = sema.pt;
35768 const zcu = pt.zcu;
35769 const comp = zcu.comp;
35770 const gpa = comp.gpa;
35771 const io = comp.io;
35772 const ip = &zcu.intern_pool;
35773
35774 const name = try ip.getOrPutStringFmt(
35775 gpa,
35776 io,
35777 pt.tid,
35778 "@typeInfo({f}).@\"union\".tag_type.?",
35779 .{union_name.fmt(ip)},
35780 .no_embedded_nulls,
35781 );
35782
35783 const enum_ty = try ip.getGeneratedTagEnumType(gpa, io, pt.tid, .{
35784 .name = name,
35785 .owner_union_ty = union_type,
35786 .tag_ty = (try pt.smallestUnsignedInt(enum_field_names.len -| 1)).toIntern(),
35787 .names = enum_field_names,
35788 .values = &.{},
35789 .tag_mode = .auto,
35790 .parent_namespace = block.namespace,
35791 });
35792
35793 return enum_ty;
35794}
35795
35796/// There is another implementation of this in `Type.onePossibleValue`. This one
35797/// in `Sema` is for calling during semantic analysis, and performs field resolution
35798/// to get the answer. The one in `Type` is for calling during codegen and asserts
35799/// that the types are already resolved.
35800/// TODO assert the return value matches `ty.onePossibleValue`
35801pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
35802 const pt = sema.pt;
35803 const zcu = pt.zcu;
35804 const comp = zcu.comp;
35805 const gpa = comp.gpa;
35806 const io = comp.io;
35807 const ip = &zcu.intern_pool;
35808
35809 return switch (ty.toIntern()) {
35810 .u0_type,
35811 .i0_type,
35812 => try pt.intValue(ty, 0),
35813 .u1_type,
35814 .u8_type,
35815 .i8_type,
35816 .u16_type,
35817 .i16_type,
35818 .u29_type,
35819 .u32_type,
35820 .i32_type,
35821 .u64_type,
35822 .i64_type,
35823 .u80_type,
35824 .u128_type,
35825 .i128_type,
35826 .u256_type,
35827 .usize_type,
35828 .isize_type,
35829 .c_char_type,
35830 .c_short_type,
35831 .c_ushort_type,
35832 .c_int_type,
35833 .c_uint_type,
35834 .c_long_type,
35835 .c_ulong_type,
35836 .c_longlong_type,
35837 .c_ulonglong_type,
35838 .c_longdouble_type,
35839 .f16_type,
35840 .f32_type,
35841 .f64_type,
35842 .f80_type,
35843 .f128_type,
35844 .anyopaque_type,
35845 .bool_type,
35846 .type_type,
35847 .anyerror_type,
35848 .adhoc_inferred_error_set_type,
35849 .comptime_int_type,
35850 .comptime_float_type,
35851 .enum_literal_type,
35852 .ptr_usize_type,
35853 .ptr_const_comptime_int_type,
35854 .manyptr_u8_type,
35855 .manyptr_const_u8_type,
35856 .manyptr_const_u8_sentinel_0_type,
35857 .manyptr_const_slice_const_u8_type,
35858 .slice_const_u8_type,
35859 .slice_const_u8_sentinel_0_type,
35860 .slice_const_slice_const_u8_type,
35861 .optional_type_type,
35862 .manyptr_const_type_type,
35863 .slice_const_type_type,
35864 .vector_8_i8_type,
35865 .vector_16_i8_type,
35866 .vector_32_i8_type,
35867 .vector_64_i8_type,
35868 .vector_1_u8_type,
35869 .vector_2_u8_type,
35870 .vector_4_u8_type,
35871 .vector_8_u8_type,
35872 .vector_16_u8_type,
35873 .vector_32_u8_type,
35874 .vector_64_u8_type,
35875 .vector_2_i16_type,
35876 .vector_4_i16_type,
35877 .vector_8_i16_type,
35878 .vector_16_i16_type,
35879 .vector_32_i16_type,
35880 .vector_4_u16_type,
35881 .vector_8_u16_type,
35882 .vector_16_u16_type,
35883 .vector_32_u16_type,
35884 .vector_2_i32_type,
35885 .vector_4_i32_type,
35886 .vector_8_i32_type,
35887 .vector_16_i32_type,
35888 .vector_4_u32_type,
35889 .vector_8_u32_type,
35890 .vector_16_u32_type,
35891 .vector_2_i64_type,
35892 .vector_4_i64_type,
35893 .vector_8_i64_type,
35894 .vector_2_u64_type,
35895 .vector_4_u64_type,
35896 .vector_8_u64_type,
35897 .vector_1_u128_type,
35898 .vector_2_u128_type,
35899 .vector_1_u256_type,
35900 .vector_4_f16_type,
35901 .vector_8_f16_type,
35902 .vector_16_f16_type,
35903 .vector_32_f16_type,
35904 .vector_2_f32_type,
35905 .vector_4_f32_type,
35906 .vector_8_f32_type,
35907 .vector_16_f32_type,
35908 .vector_2_f64_type,
35909 .vector_4_f64_type,
35910 .vector_8_f64_type,
35911 .anyerror_void_error_union_type,
35912 => null,
35913 .void_type => Value.void,
35914 .noreturn_type => Value.@"unreachable",
35915 .anyframe_type => unreachable,
35916 .null_type => Value.null,
35917 .undefined_type => Value.undef,
35918 .optional_noreturn_type => try pt.nullValue(ty),
35919 .generic_poison_type => unreachable,
35920 .empty_tuple_type => Value.empty_tuple,
35921 // values, not types
35922 .undef,
35923 .undef_bool,
35924 .undef_usize,
35925 .undef_u1,
35926 .zero,
35927 .zero_usize,
35928 .zero_u1,
35929 .zero_u8,
35930 .one,
35931 .one_usize,
35932 .one_u1,
35933 .one_u8,
35934 .four_u8,
35935 .negative_one,
35936 .void_value,
35937 .unreachable_value,
35938 .null_value,
35939 .bool_true,
35940 .bool_false,
35941 .empty_tuple,
35942 // invalid
35943 .none,
35944 => unreachable,
35945
35946 _ => switch (ty.toIntern().unwrap(ip).getTag(ip)) {
35947 .removed => unreachable,
35948
35949 .type_int_signed, // i0 handled above
35950 .type_int_unsigned, // u0 handled above
35951 .type_pointer,
35952 .type_slice,
35953 .type_anyframe,
35954 .type_error_union,
35955 .type_anyerror_union,
35956 .type_error_set,
35957 .type_inferred_error_set,
35958 .type_opaque,
35959 .type_function,
35960 => null,
35961
35962 .simple_type, // handled above
35963 // values, not types
35964 .undef,
35965 .simple_value,
35966 .ptr_nav,
35967 .ptr_uav,
35968 .ptr_uav_aligned,
35969 .ptr_comptime_alloc,
35970 .ptr_comptime_field,
35971 .ptr_int,
35972 .ptr_eu_payload,
35973 .ptr_opt_payload,
35974 .ptr_elem,
35975 .ptr_field,
35976 .ptr_slice,
35977 .opt_payload,
35978 .opt_null,
35979 .int_u8,
35980 .int_u16,
35981 .int_u32,
35982 .int_i32,
35983 .int_usize,
35984 .int_comptime_int_u32,
35985 .int_comptime_int_i32,
35986 .int_small,
35987 .int_positive,
35988 .int_negative,
35989 .int_lazy_align,
35990 .int_lazy_size,
35991 .error_set_error,
35992 .error_union_error,
35993 .error_union_payload,
35994 .enum_literal,
35995 .enum_tag,
35996 .float_f16,
35997 .float_f32,
35998 .float_f64,
35999 .float_f80,
36000 .float_f128,
36001 .float_c_longdouble_f80,
36002 .float_c_longdouble_f128,
36003 .float_comptime_float,
36004 .variable,
36005 .threadlocal_variable,
36006 .@"extern",
36007 .func_decl,
36008 .func_instance,
36009 .func_coerced,
36010 .only_possible_value,
36011 .union_value,
36012 .bytes,
36013 .aggregate,
36014 .repeated,
36015 // memoized value, not types
36016 .memoized_call,
36017 => unreachable,
36018
36019 .type_array_big,
36020 .type_array_small,
36021 .type_vector,
36022 .type_enum_auto,
36023 .type_enum_explicit,
36024 .type_enum_nonexhaustive,
36025 .type_struct,
36026 .type_struct_packed,
36027 .type_struct_packed_inits,
36028 .type_tuple,
36029 .type_union,
36030 => switch (ip.indexToKey(ty.toIntern())) {
36031 inline .array_type, .vector_type => |seq_type, seq_tag| {
36032 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
36033 if (seq_type.len + @intFromBool(has_sentinel) == 0) return try pt.aggregateValue(ty, &.{});
36034 if (try sema.typeHasOnePossibleValue(.fromInterned(seq_type.child))) |opv| {
36035 return try pt.aggregateSplatValue(ty, opv);
36036 }
36037 return null;
36038 },
36039
36040 .struct_type => {
36041 // Resolving the layout first helps to avoid loops.
36042 // If the type has a coherent layout, we can recurse through fields safely.
36043 try ty.resolveLayout(pt);
36044
36045 const struct_type = ip.loadStructType(ty.toIntern());
36046
36047 if (struct_type.field_types.len == 0) {
36048 // In this case the struct has no fields at all and
36049 // therefore has one possible value.
36050 return try pt.aggregateValue(ty, &.{});
36051 }
36052
36053 const field_vals = try sema.arena.alloc(
36054 InternPool.Index,
36055 struct_type.field_types.len,
36056 );
36057 for (field_vals, 0..) |*field_val, i| {
36058 if (struct_type.fieldIsComptime(ip, i)) {
36059 try ty.resolveStructFieldInits(pt);
36060 field_val.* = struct_type.field_inits.get(ip)[i];
36061 continue;
36062 }
36063 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[i]);
36064 if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| {
36065 field_val.* = field_opv.toIntern();
36066 } else return null;
36067 }
36068
36069 // In this case the struct has no runtime-known fields and
36070 // therefore has one possible value.
36071 return try pt.aggregateValue(ty, field_vals);
36072 },
36073
36074 .tuple_type => |tuple| {
36075 try ty.resolveLayout(pt);
36076
36077 if (tuple.types.len == 0) {
36078 return try pt.aggregateValue(ty, &.{});
36079 }
36080
36081 const field_vals = try sema.arena.alloc(
36082 InternPool.Index,
36083 tuple.types.len,
36084 );
36085 for (
36086 field_vals,
36087 tuple.types.get(ip),
36088 tuple.values.get(ip),
36089 ) |*field_val, field_ty, field_comptime_val| {
36090 if (field_comptime_val != .none) {
36091 field_val.* = field_comptime_val;
36092 continue;
36093 }
36094 if (try sema.typeHasOnePossibleValue(.fromInterned(field_ty))) |opv| {
36095 field_val.* = opv.toIntern();
36096 } else return null;
36097 }
36098
36099 return try pt.aggregateValue(ty, field_vals);
36100 },
36101
36102 .union_type => {
36103 // Resolving the layout first helps to avoid loops.
36104 // If the type has a coherent layout, we can recurse through fields safely.
36105 try ty.resolveLayout(pt);
36106
36107 const union_obj = ip.loadUnionType(ty.toIntern());
36108 const tag_val = (try sema.typeHasOnePossibleValue(.fromInterned(union_obj.tagTypeUnordered(ip)))) orelse
36109 return null;
36110 if (union_obj.field_types.len == 0) {
36111 const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() });
36112 return Value.fromInterned(only);
36113 }
36114 const only_field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[0]);
36115 const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse
36116 return null;
36117 const only = try pt.internUnion(.{
36118 .ty = ty.toIntern(),
36119 .tag = tag_val.toIntern(),
36120 .val = val_val.toIntern(),
36121 });
36122 return Value.fromInterned(only);
36123 },
36124
36125 .enum_type => {
36126 const enum_type = ip.loadEnumType(ty.toIntern());
36127 switch (enum_type.tag_mode) {
36128 .nonexhaustive => {
36129 if (enum_type.tag_ty == .comptime_int_type) return null;
36130
36131 if (try sema.typeHasOnePossibleValue(.fromInterned(enum_type.tag_ty))) |int_opv| {
36132 const only = try pt.intern(.{ .enum_tag = .{
36133 .ty = ty.toIntern(),
36134 .int = int_opv.toIntern(),
36135 } });
36136 return Value.fromInterned(only);
36137 }
36138
36139 return null;
36140 },
36141 .auto, .explicit => {
36142 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null;
36143
36144 return Value.fromInterned(switch (enum_type.names.len) {
36145 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }),
36146 1 => try pt.intern(.{ .enum_tag = .{
36147 .ty = ty.toIntern(),
36148 .int = if (enum_type.values.len == 0)
36149 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
36150 else
36151 try ip.getCoercedInts(
36152 gpa,
36153 io,
36154 pt.tid,
36155 ip.indexToKey(enum_type.values.get(ip)[0]).int,
36156 enum_type.tag_ty,
36157 ),
36158 } }),
36159 else => return null,
36160 });
36161 },
36162 }
36163 },
36164
36165 else => unreachable,
36166 },
36167
36168 .type_optional => {
36169 const payload_ip = ip.indexToKey(ty.toIntern()).opt_type;
36170 // Although ?noreturn is handled above, the element type
36171 // can be effectively noreturn for example via an empty
36172 // enum or error set.
36173 if (ip.isNoReturn(payload_ip)) return try pt.nullValue(ty);
36174 return null;
36175 },
36176 },
36177 };
36178}
36179
3618033507/// Returns the type of the AIR instruction.
3618133508fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
3618233509 return sema.getTmpAir().typeOf(inst, &sema.pt.zcu.intern_pool);
......@@ -36235,6 +33562,7 @@ fn isComptimeKnown(
3623533562 return (try sema.resolveValue(inst)) != null;
3623633563}
3623733564
33565/// Asserts that the layout of `var_type` has already been resolved.
3623833566fn analyzeComptimeAlloc(
3623933567 sema: *Sema,
3624033568 block: *Block,
......@@ -36245,10 +33573,9 @@ fn analyzeComptimeAlloc(
3624533573 const pt = sema.pt;
3624633574 const zcu = pt.zcu;
3624733575
36248 // Needed to make an anon decl with type `var_type` (the `finish()` call below).
36249 _ = try sema.typeHasOnePossibleValue(var_type);
33576 var_type.assertHasLayout(zcu);
3625033577
36251 const ptr_type = try pt.ptrTypeSema(.{
33578 const ptr_type = try pt.ptrType(.{
3625233579 .child = var_type.toIntern(),
3625333580 .flags = .{
3625433581 .alignment = alignment,
......@@ -36256,13 +33583,23 @@ fn analyzeComptimeAlloc(
3625633583 },
3625733584 });
3625833585
36259 const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment);
36260
36261 return Air.internedToRef((try pt.intern(.{ .ptr = .{
36262 .ty = ptr_type.toIntern(),
36263 .base_addr = .{ .comptime_alloc = alloc },
36264 .byte_offset = 0,
36265 } })));
33586 if (try var_type.onePossibleValue(pt)) |opv| {
33587 return .fromIntern(try pt.intern(.{ .ptr = .{
33588 .ty = ptr_type.toIntern(),
33589 .base_addr = .{ .uav = .{
33590 .val = opv.toIntern(),
33591 .orig_ty = ptr_type.toIntern(),
33592 } },
33593 .byte_offset = 0,
33594 } }));
33595 } else {
33596 const alloc = try sema.newComptimeAlloc(block, src, var_type, alignment);
33597 return .fromIntern(try pt.intern(.{ .ptr = .{
33598 .ty = ptr_type.toIntern(),
33599 .base_addr = .{ .comptime_alloc = alloc },
33600 .byte_offset = 0,
33601 } }));
33602 }
3626633603}
3626733604
3626833605fn resolveAddressSpace(
......@@ -36363,40 +33700,6 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
3636333700 return std.math.cast(usize, int) orelse return sema.fail(block, src, "expression produces integer value '{d}' which is too big for this compiler implementation to handle", .{int});
3636433701}
3636533702
36366/// For pointer-like optionals, it returns the pointer type. For pointers,
36367/// the type is returned unmodified.
36368/// This can return `error.AnalysisFail` because it sometimes requires resolving whether
36369/// a type has zero bits, which can cause a "foo depends on itself" compile error.
36370/// This logic must be kept in sync with `Type.isPtrLikeOptional`.
36371fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
36372 const pt = sema.pt;
36373 const zcu = pt.zcu;
36374 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
36375 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
36376 .one, .many, .c => ty,
36377 .slice => null,
36378 },
36379 .opt_type => |opt_child| switch (zcu.intern_pool.indexToKey(opt_child)) {
36380 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
36381 .slice, .c => null,
36382 .many, .one => {
36383 if (ptr_type.flags.is_allowzero) return null;
36384
36385 // optionals of zero sized types behave like bools, not pointers
36386 const payload_ty: Type = .fromInterned(opt_child);
36387 if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) {
36388 return null;
36389 }
36390
36391 return payload_ty;
36392 },
36393 },
36394 else => null,
36395 },
36396 else => null,
36397 };
36398}
36399
3640033703fn unionFieldIndex(
3640133704 sema: *Sema,
3640233705 block: *Block,
......@@ -36407,9 +33710,9 @@ fn unionFieldIndex(
3640733710 const pt = sema.pt;
3640833711 const zcu = pt.zcu;
3640933712 const ip = &zcu.intern_pool;
36410 try union_ty.resolveFields(pt);
3641133713 const union_obj = zcu.typeToUnion(union_ty).?;
36412 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
33714 const enum_obj = ip.loadEnumType(union_obj.enum_tag_type);
33715 const field_index = enum_obj.nameIndex(ip, field_name) orelse
3641333716 return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name);
3641433717 return @intCast(field_index);
3641533718}
......@@ -36424,7 +33727,6 @@ fn structFieldIndex(
3642433727 const pt = sema.pt;
3642533728 const zcu = pt.zcu;
3642633729 const ip = &zcu.intern_pool;
36427 try struct_ty.resolveFields(pt);
3642833730 const struct_type = zcu.typeToStruct(struct_ty).?;
3642933731 return struct_type.nameIndex(ip, field_name) orelse
3643033732 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_src, field_name);
......@@ -36513,6 +33815,7 @@ fn intFromFloatScalar(
3651333815/// Vectors are also accepted. Vector results are reduced with AND.
3651433816///
3651533817/// If provided, `vector_index` reports the first element that failed the range check.
33818/// MLUGG TODO: move to `Value` or `Type`?
3651633819fn intFitsInType(
3651733820 sema: *Sema,
3651833821 val: Value,
......@@ -36535,30 +33838,10 @@ fn intFitsInType(
3653533838 .unsigned => info.bits >= ptr_bits,
3653633839 };
3653733840 },
36538 .int => |int| switch (int.storage) {
36539 .u64, .i64, .big_int => {
36540 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
36541 const big_int = int.storage.toBigInt(&buffer);
36542 return big_int.fitsInTwosComp(info.signedness, info.bits);
36543 },
36544 .lazy_align => |lazy_ty| {
36545 const max_needed_bits = @as(u16, 16) + @intFromBool(info.signedness == .signed);
36546 // If it is u16 or bigger we know the alignment fits without resolving it.
36547 if (info.bits >= max_needed_bits) return true;
36548 const x = try Type.fromInterned(lazy_ty).abiAlignmentSema(pt);
36549 if (x == .none) return true;
36550 const actual_needed_bits = @as(usize, x.toLog2Units()) + 1 + @intFromBool(info.signedness == .signed);
36551 return info.bits >= actual_needed_bits;
36552 },
36553 .lazy_size => |lazy_ty| {
36554 const max_needed_bits = @as(u16, 64) + @intFromBool(info.signedness == .signed);
36555 // If it is u64 or bigger we know the size fits without resolving it.
36556 if (info.bits >= max_needed_bits) return true;
36557 const x = try Type.fromInterned(lazy_ty).abiSizeSema(pt);
36558 if (x == 0) return true;
36559 const actual_needed_bits = std.math.log2(x) + 1 + @intFromBool(info.signedness == .signed);
36560 return info.bits >= actual_needed_bits;
36561 },
33841 .int => |int| {
33842 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
33843 const big_int = int.storage.toBigInt(&buffer);
33844 return big_int.fitsInTwosComp(info.signedness, info.bits);
3656233845 },
3656333846 .aggregate => |aggregate| {
3656433847 assert(ty.zigTypeTag(zcu) == .vector);
......@@ -36588,23 +33871,23 @@ fn intFitsInType(
3658833871
3658933872fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
3659033873 const pt = sema.pt;
36591 if (!(try int_val.compareAllWithZeroSema(.gte, pt))) return false;
33874 if (!int_val.compareAllWithZero(.gte, pt.zcu)) return false;
3659233875 const end_val = try pt.intValue(tag_ty, end);
3659333876 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;
3659433877 return true;
3659533878}
3659633879
36597/// Asserts the type is an enum.
33880/// Asserts the type is an exhaustive enum.
3659833881fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
3659933882 const pt = sema.pt;
3660033883 const zcu = pt.zcu;
3660133884 const enum_type = zcu.intern_pool.loadEnumType(ty.toIntern());
36602 assert(enum_type.tag_mode != .nonexhaustive);
33885 assert(!enum_type.nonexhaustive);
3660333886 // The `tagValueIndex` function call below relies on the type being the integer tag type.
3660433887 // `getCoerced` assumes the value will fit the new type.
36605 if (!(try sema.intFitsInType(int, .fromInterned(enum_type.tag_ty), null))) return false;
36606 const int_coerced = try pt.getCoerced(int, .fromInterned(enum_type.tag_ty));
36607
33888 const int_tag_ty: Type = .fromInterned(enum_type.int_tag_type);
33889 if (!try sema.intFitsInType(int, int_tag_ty, null)) return false;
33890 const int_coerced = try pt.getCoerced(int, int_tag_ty);
3660833891 return enum_type.tagValueIndex(&zcu.intern_pool, int_coerced.toIntern()) != null;
3660933892}
3661033893
......@@ -36636,6 +33919,7 @@ fn compareAll(
3663633919}
3663733920
3663833921/// Asserts the values are comparable. Both operands have type `ty`.
33922/// MLUGG TODO: move to `Value`?
3663933923fn compareScalar(
3664033924 sema: *Sema,
3664133925 lhs: Value,
......@@ -36644,17 +33928,19 @@ fn compareScalar(
3664433928 ty: Type,
3664533929) CompileError!bool {
3664633930 const pt = sema.pt;
33931 const zcu = pt.zcu;
33932
3664733933 const coerced_lhs = try pt.getCoerced(lhs, ty);
3664833934 const coerced_rhs = try pt.getCoerced(rhs, ty);
3664933935
3665033936 // Equality comparisons of signed zero and NaN need to use floating point semantics
36651 if (coerced_lhs.isFloat(pt.zcu) or coerced_rhs.isFloat(pt.zcu))
36652 return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt);
33937 if (coerced_lhs.isFloat(zcu) or coerced_rhs.isFloat(zcu))
33938 return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu);
3665333939
3665433940 switch (op) {
36655 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
36656 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
36657 else => return Value.compareHeteroSema(coerced_lhs, op, coerced_rhs, pt),
33941 .eq => return Value.eql(coerced_lhs, coerced_rhs, ty, zcu),
33942 .neq => return !Value.eql(coerced_lhs, coerced_rhs, ty, zcu),
33943 else => return Value.compareHetero(coerced_lhs, op, coerced_rhs, zcu),
3665833944 }
3665933945}
3666033946
......@@ -36799,7 +34085,7 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai
3679934085 });
3680034086}
3680134087
36802fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError {
34088pub fn failWithContainsReferenceToComptimeVar(sema: *Sema, block: *Block, src: LazySrcLoc, value_name: InternPool.NullTerminatedString, kind_of_value: []const u8, val: ?Value) CompileError {
3680334089 return sema.failWithOwnedErrorMsg(block, msg: {
3680434090 const msg = try sema.errMsg(src, "{s} contains reference to comptime var", .{kind_of_value});
3680534091 errdefer msg.destroy(sema.gpa);
......@@ -36867,11 +34153,7 @@ fn notePathToComptimeAllocPtr(
3686734153 else => {}, // there will be another stage
3686834154 }
3686934155
36870 const derivation = comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema) catch |err| switch (err) {
36871 error.OutOfMemory => |e| return e,
36872 error.Canceled => @panic("TODO"), // pls don't be cancelable mlugg
36873 error.AnalysisFail => unreachable,
36874 };
34156 const derivation = try comptime_ptr.pointerDerivationAdvanced(arena, pt, false, sema);
3687534157
3687634158 var second_path_aw: std.Io.Writer.Allocating = .init(arena);
3687734159 defer second_path_aw.deinit();
......@@ -37058,12 +34340,12 @@ fn maybeDerefSliceAsArray(
3705834340 else => unreachable,
3705934341 };
3706034342 const elem_ty = Type.fromInterned(slice.ty).childType(zcu);
37061 const len = try Value.fromInterned(slice.len).toUnsignedIntSema(pt);
34343 const len = Value.fromInterned(slice.len).toUnsignedInt(zcu);
3706234344 const array_ty = try pt.arrayType(.{
3706334345 .child = elem_ty.toIntern(),
3706434346 .len = len,
3706534347 });
37066 const ptr_ty = try pt.ptrTypeSema(p: {
34348 const ptr_ty = try pt.ptrType(p: {
3706734349 var p = Type.fromInterned(slice.ty).ptrInfo(zcu);
3706834350 p.flags.size = .one;
3706934351 p.child = array_ty.toIntern();
......@@ -37129,238 +34411,6 @@ pub fn flushExports(sema: *Sema) !void {
3712934411 }
3713034412}
3713134413
37132/// Called as soon as a `declared` enum type is created.
37133/// Resolves the tag type and field inits.
37134/// Marks the `src_inst` dependency on the enum's declaration, so call sites need not do this.
37135pub fn resolveDeclaredEnum(
37136 pt: Zcu.PerThread,
37137 wip_ty: InternPool.WipEnumType,
37138 inst: Zir.Inst.Index,
37139 tracked_inst: InternPool.TrackedInst.Index,
37140 namespace: InternPool.NamespaceIndex,
37141 type_name: InternPool.NullTerminatedString,
37142 small: Zir.Inst.EnumDecl.Small,
37143 body: []const Zir.Inst.Index,
37144 tag_type_ref: Zir.Inst.Ref,
37145 any_values: bool,
37146 fields_len: u32,
37147 zir: Zir,
37148 body_end: usize,
37149) Zcu.SemaError!void {
37150 const zcu = pt.zcu;
37151 const gpa = zcu.gpa;
37152
37153 const src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = LazySrcLoc.Offset.nodeOffset(.zero) };
37154
37155 var arena: std.heap.ArenaAllocator = .init(gpa);
37156 defer arena.deinit();
37157
37158 var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa);
37159 defer comptime_err_ret_trace.deinit();
37160
37161 var sema: Sema = .{
37162 .pt = pt,
37163 .gpa = gpa,
37164 .arena = arena.allocator(),
37165 .code = zir,
37166 .owner = .wrap(.{ .type = wip_ty.index }),
37167 .func_index = .none,
37168 .func_is_naked = false,
37169 .fn_ret_ty = .void,
37170 .fn_ret_ty_ies = null,
37171 .comptime_err_ret_trace = &comptime_err_ret_trace,
37172 };
37173 defer sema.deinit();
37174
37175 if (zcu.comp.debugIncremental()) {
37176 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, sema.owner);
37177 info.last_update_gen = zcu.generation;
37178 }
37179
37180 try sema.declareDependency(.{ .src_hash = tracked_inst });
37181
37182 var block: Block = .{
37183 .parent = null,
37184 .sema = &sema,
37185 .namespace = namespace,
37186 .instructions = .{},
37187 .inlining = null,
37188 .comptime_reason = .{ .reason = .{
37189 .src = src,
37190 .r = .{ .simple = .enum_field_values },
37191 } },
37192 .src_base_inst = tracked_inst,
37193 .type_name_ctx = type_name,
37194 };
37195 defer block.instructions.deinit(gpa);
37196
37197 sema.resolveDeclaredEnumInner(
37198 &block,
37199 wip_ty,
37200 inst,
37201 tracked_inst,
37202 src,
37203 small,
37204 body,
37205 tag_type_ref,
37206 any_values,
37207 fields_len,
37208 zir,
37209 body_end,
37210 ) catch |err| switch (err) {
37211 error.ComptimeBreak => unreachable,
37212 error.ComptimeReturn => unreachable,
37213 error.OutOfMemory, error.Canceled => |e| return e,
37214 error.AnalysisFail => {
37215 if (!zcu.failed_analysis.contains(sema.owner)) {
37216 try zcu.transitive_failed_analysis.put(gpa, sema.owner, {});
37217 }
37218 return error.AnalysisFail;
37219 },
37220 };
37221}
37222
37223fn resolveDeclaredEnumInner(
37224 sema: *Sema,
37225 block: *Block,
37226 wip_ty: InternPool.WipEnumType,
37227 inst: Zir.Inst.Index,
37228 tracked_inst: InternPool.TrackedInst.Index,
37229 src: LazySrcLoc,
37230 small: Zir.Inst.EnumDecl.Small,
37231 body: []const Zir.Inst.Index,
37232 tag_type_ref: Zir.Inst.Ref,
37233 any_values: bool,
37234 fields_len: u32,
37235 zir: Zir,
37236 body_end: usize,
37237) Zcu.CompileError!void {
37238 const pt = sema.pt;
37239 const zcu = pt.zcu;
37240 const comp = zcu.comp;
37241 const gpa = comp.gpa;
37242 const io = comp.io;
37243 const ip = &zcu.intern_pool;
37244
37245 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
37246
37247 const tag_ty_src: LazySrcLoc = .{ .base_node_inst = tracked_inst, .offset = .{ .node_offset_container_tag = .zero } };
37248
37249 const int_tag_ty = ty: {
37250 if (body.len != 0) {
37251 _ = try sema.analyzeInlineBody(block, body, inst);
37252 }
37253
37254 if (tag_type_ref != .none) {
37255 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
37256 if (ty.zigTypeTag(zcu) != .int and ty.zigTypeTag(zcu) != .comptime_int) {
37257 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{f}'", .{ty.fmt(pt)});
37258 }
37259 break :ty ty;
37260 } else if (fields_len == 0) {
37261 break :ty try pt.intType(.unsigned, 0);
37262 } else {
37263 const bits = std.math.log2_int_ceil(usize, fields_len);
37264 break :ty try pt.intType(.unsigned, bits);
37265 }
37266 };
37267
37268 wip_ty.setTagTy(ip, int_tag_ty.toIntern());
37269
37270 var extra_index = body_end + bit_bags_count;
37271 var bit_bag_index: usize = body_end;
37272 var cur_bit_bag: u32 = undefined;
37273 var last_tag_val: ?Value = null;
37274 for (0..fields_len) |field_i_usize| {
37275 const field_i: u32 = @intCast(field_i_usize);
37276 if (field_i % 32 == 0) {
37277 cur_bit_bag = zir.extra[bit_bag_index];
37278 bit_bag_index += 1;
37279 }
37280 const has_tag_value = @as(u1, @truncate(cur_bit_bag)) != 0;
37281 cur_bit_bag >>= 1;
37282
37283 const field_name_index: Zir.NullTerminatedString = @enumFromInt(zir.extra[extra_index]);
37284 const field_name_zir = zir.nullTerminatedString(field_name_index);
37285 extra_index += 1; // field name
37286
37287 const field_name = try ip.getOrPutString(gpa, io, pt.tid, field_name_zir, .no_embedded_nulls);
37288
37289 const value_src: LazySrcLoc = .{
37290 .base_node_inst = tracked_inst,
37291 .offset = .{ .container_field_value = field_i },
37292 };
37293
37294 const tag_overflow = if (has_tag_value) overflow: {
37295 const tag_val_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
37296 extra_index += 1;
37297 const tag_inst = try sema.resolveInst(tag_val_ref);
37298 last_tag_val = try sema.resolveConstDefinedValue(block, .{
37299 .base_node_inst = tracked_inst,
37300 .offset = .{ .container_field_name = field_i },
37301 }, tag_inst, .{ .simple = .enum_field_tag_value });
37302 if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true;
37303 last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty);
37304 if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| {
37305 assert(conflict.kind == .value); // AstGen validated names are unique
37306 const other_field_src: LazySrcLoc = .{
37307 .base_node_inst = tracked_inst,
37308 .offset = .{ .container_field_value = conflict.prev_field_idx },
37309 };
37310 const msg = msg: {
37311 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37312 errdefer msg.destroy(gpa);
37313 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37314 break :msg msg;
37315 };
37316 return sema.failWithOwnedErrorMsg(block, msg);
37317 }
37318 break :overflow false;
37319 } else if (any_values) overflow: {
37320 if (last_tag_val) |last_tag| {
37321 const result = try arith.incrementDefinedInt(sema, int_tag_ty, last_tag);
37322 last_tag_val = result.val;
37323 if (result.overflow) break :overflow true;
37324 } else {
37325 last_tag_val = try pt.intValue(int_tag_ty, 0);
37326 }
37327 if (wip_ty.nextField(ip, field_name, last_tag_val.?.toIntern())) |conflict| {
37328 assert(conflict.kind == .value); // AstGen validated names are unique
37329 const other_field_src: LazySrcLoc = .{
37330 .base_node_inst = tracked_inst,
37331 .offset = .{ .container_field_value = conflict.prev_field_idx },
37332 };
37333 const msg = msg: {
37334 const msg = try sema.errMsg(value_src, "enum tag value {f} already taken", .{last_tag_val.?.fmtValueSema(pt, sema)});
37335 errdefer msg.destroy(gpa);
37336 try sema.errNote(other_field_src, msg, "other occurrence here", .{});
37337 break :msg msg;
37338 };
37339 return sema.failWithOwnedErrorMsg(block, msg);
37340 }
37341 break :overflow false;
37342 } else overflow: {
37343 assert(wip_ty.nextField(ip, field_name, .none) == null);
37344 last_tag_val = try pt.intValue(.comptime_int, field_i);
37345 if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true;
37346 last_tag_val = try pt.getCoerced(last_tag_val.?, int_tag_ty);
37347 break :overflow false;
37348 };
37349
37350 if (tag_overflow) {
37351 const msg = try sema.errMsg(value_src, "enumeration value '{f}' too large for type '{f}'", .{
37352 last_tag_val.?.fmtValueSema(pt, sema), int_tag_ty.fmt(pt),
37353 });
37354 return sema.failWithOwnedErrorMsg(block, msg);
37355 }
37356 }
37357 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
37358 if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) {
37359 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});
37360 }
37361 }
37362}
37363
3736434414pub const bitCastVal = @import("Sema/bitcast.zig").bitCast;
3736534415pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice;
3736634416
......@@ -37369,6 +34419,11 @@ const ComptimeLoadResult = @import("Sema/comptime_ptr_access.zig").ComptimeLoadR
3736934419const storeComptimePtr = @import("Sema/comptime_ptr_access.zig").storeComptimePtr;
3737034420const ComptimeStoreResult = @import("Sema/comptime_ptr_access.zig").ComptimeStoreResult;
3737134421
34422// MLUGG TODO: decide how to do the namespacing here
34423pub const type_resolution = @import("Sema/type_resolution.zig");
34424pub const ensureLayoutResolved = type_resolution.ensureLayoutResolved;
34425pub const ensureFieldInitsResolved = type_resolution.ensureFieldInitsResolved;
34426
3737234427pub fn getBuiltinType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) SemaError!Type {
3737334428 assert(decl.kind() == .type);
3737434429 try sema.ensureMemoizedStateResolved(src, decl.stage());
......@@ -37483,11 +34538,11 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3748334538 const result = try sema.analyzeNavVal(block, src, nav);
3748434539
3748534540 const uncoerced_val = try sema.resolveConstDefinedValue(block, src, result, null);
37486 const maybe_lazy_val: Value = switch (builtin_decl.kind()) {
34541 const val: Value = switch (builtin_decl.kind()) {
3748734542 .type => if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .type) {
3748834543 return sema.fail(block, src, "{s}.{s} is not a type", .{ parent_name, name });
3748934544 } else val: {
37490 try uncoerced_val.toType().resolveFully(pt);
34545 try sema.ensureLayoutResolved(uncoerced_val.toType());
3749134546 break :val uncoerced_val;
3749234547 },
3749334548 .func => val: {
......@@ -37500,7 +34555,6 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3750034555 break :val .fromInterned(coerced.toInterned().?);
3750134556 },
3750234557 };
37503 const val = try sema.resolveLazyValue(maybe_lazy_val);
3750434558
3750534559 const prev = zcu.builtin_decl_values.get(builtin_decl);
3750634560 if (val.toIntern() != prev) {
......@@ -37539,7 +34593,6 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ
3753934593 => try pt.funcType(.{
3754034594 .param_types = &.{ .generic_poison_type, .generic_poison_type },
3754134595 .return_type = .noreturn_type,
37542 .is_generic = true,
3754334596 }),
3754434597
3754534598 // `fn (anyerror) noreturn`
......@@ -37590,3 +34643,823 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.BuiltinDecl) CompileError!Typ
3759034643 else => unreachable,
3759134644 };
3759234645}
34646
34647/// TODO MLUGG: this is a gnarly hack
34648const PartialTypeName = union(enum) {
34649 exact: struct {
34650 name: InternPool.NullTerminatedString,
34651 nav: InternPool.Nav.Index.Optional,
34652 },
34653 anon_prefix: []const u8,
34654 fn apply(
34655 name: PartialTypeName,
34656 wip: *const InternPool.WipContainerType,
34657 pt: Zcu.PerThread,
34658 ) (Allocator.Error || std.Io.Cancelable)!InternPool.NullTerminatedString {
34659 const zcu = pt.zcu;
34660 const comp = zcu.comp;
34661 const ip = &zcu.intern_pool;
34662 switch (name) {
34663 .exact => |e| {
34664 wip.setName(ip, e.name, e.nav);
34665 return e.name;
34666 },
34667 .anon_prefix => |prefix| {
34668 const resolved_name = try ip.getOrPutStringFmt(
34669 comp.gpa,
34670 comp.io,
34671 pt.tid,
34672 "{s}_{d}",
34673 .{ prefix, @intFromEnum(wip.index) },
34674 .no_embedded_nulls,
34675 );
34676 wip.setName(ip, resolved_name, .none);
34677 return resolved_name;
34678 },
34679 }
34680 }
34681};
34682pub fn createTypeName(
34683 sema: *Sema,
34684 block: *Block,
34685 name_strategy: Zir.Inst.NameStrategy,
34686 anon_prefix: []const u8,
34687 inst: Zir.Inst.Index,
34688) CompileError!PartialTypeName {
34689 const pt = sema.pt;
34690 const zcu = pt.zcu;
34691 const comp = zcu.comp;
34692 const gpa = comp.gpa;
34693 const io = comp.io;
34694 const ip = &zcu.intern_pool;
34695
34696 switch (name_strategy) {
34697 .anon => {}, // handled after switch
34698 .parent => return .{ .exact = .{
34699 .name = block.type_name_ctx,
34700 .nav = sema.owner.unwrap().nav_val.toOptional(),
34701 } },
34702 .func => func_strat: {
34703 const fn_info = sema.code.getFnInfo(ip.funcZirBodyInst(sema.func_index).resolve(ip) orelse return error.AnalysisFail);
34704 const zir_tags = sema.code.instructions.items(.tag);
34705
34706 var aw: std.Io.Writer.Allocating = .init(gpa);
34707 defer aw.deinit();
34708 const w = &aw.writer;
34709 w.print("{f}(", .{block.type_name_ctx.fmt(ip)}) catch return error.OutOfMemory;
34710
34711 var arg_i: usize = 0;
34712 for (fn_info.param_body) |zir_inst| switch (zir_tags[@intFromEnum(zir_inst)]) {
34713 .param, .param_comptime, .param_anytype, .param_anytype_comptime => {
34714 const arg = sema.inst_map.get(zir_inst).?;
34715 // If this is being called in a generic function then analyzeCall will
34716 // have already resolved the args and this will work.
34717 // If not then this is a struct type being returned from a non-generic
34718 // function and the name doesn't matter since it will later
34719 // result in a compile error.
34720 const arg_val = try sema.resolveValue(arg) orelse break :func_strat; // fall through to anon strat
34721
34722 if (arg_i != 0) w.writeByte(',') catch return error.OutOfMemory;
34723
34724 // Limiting the depth here helps avoid type names getting too long, which
34725 // in turn helps to avoid unreasonably long symbol names for namespaced
34726 // symbols. Such names should ideally be human-readable, and additionally,
34727 // some tooling may not support very long symbol names.
34728 w.print("{f}", .{Value.fmtValueSemaFull(.{
34729 .val = arg_val,
34730 .pt = pt,
34731 .opt_sema = sema,
34732 .depth = 1,
34733 })}) catch return error.OutOfMemory;
34734
34735 arg_i += 1;
34736 continue;
34737 },
34738 else => continue,
34739 };
34740
34741 w.writeByte(')') catch return error.OutOfMemory;
34742 return .{ .exact = .{
34743 .name = try ip.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls),
34744 .nav = .none,
34745 } };
34746 },
34747 .dbg_var => {
34748 // TODO: this logic is questionable. We ideally should be traversing the `Block` rather than relying on the order of AstGen instructions.
34749 const ref = inst.toRef();
34750 const zir_tags = sema.code.instructions.items(.tag);
34751 const zir_data = sema.code.instructions.items(.data);
34752 for (@intFromEnum(inst)..zir_tags.len) |i| switch (zir_tags[i]) {
34753 .dbg_var_ptr, .dbg_var_val => if (zir_data[i].str_op.operand == ref) {
34754 return .{ .exact = .{
34755 .name = try ip.getOrPutStringFmt(gpa, io, pt.tid, "{f}.{s}", .{
34756 block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
34757 }, .no_embedded_nulls),
34758 .nav = .none,
34759 } };
34760 },
34761 else => {},
34762 };
34763 // fall through to anon strat
34764 },
34765 }
34766
34767 // anon strat handling
34768
34769 // It would be neat to have "struct:line:column" but this name has
34770 // to survive incremental updates, where it may have been shifted down
34771 // or up to a different line, but unchanged, and thus not unnecessarily
34772 // semantically analyzed.
34773 // TODO: that would be possible, by detecting line number changes and renaming
34774 // types appropriately. However, `@typeName` becomes a problem then. If we remove
34775 // that builtin from the language, we can consider this.
34776
34777 return .{ .anon_prefix = try std.fmt.allocPrint(
34778 sema.arena,
34779 "{f}__{s}",
34780 .{ block.type_name_ctx.fmt(ip), anon_prefix },
34781 ) };
34782}
34783
34784pub fn analyzeStructDecl(
34785 pt: Zcu.PerThread,
34786 file_index: Zcu.File.Index,
34787 zir: *const Zir,
34788 parent_namespace: InternPool.OptionalNamespaceIndex,
34789 tracked_inst: InternPool.TrackedInst.Index,
34790 struct_decl: *const Zir.UnwrappedStructDecl,
34791 explicit_backing_type: ?Type,
34792 captures: []const InternPool.CaptureValue,
34793 type_name: PartialTypeName,
34794) (Allocator.Error || std.Io.Cancelable)!Type {
34795 const zcu = pt.zcu;
34796 const comp = zcu.comp;
34797 const gpa = comp.gpa;
34798 const io = comp.io;
34799 const ip = &zcu.intern_pool;
34800
34801 const wip = switch (try ip.getStructType(gpa, io, pt.tid, .{
34802 .fields_len = @intCast(struct_decl.field_names.len),
34803 .layout = struct_decl.layout,
34804 .explicit_packed_backing_type = if (explicit_backing_type) |ty| ty.toIntern() else .none,
34805 .any_comptime_fields = struct_decl.field_comptime_bits != null,
34806 .any_field_defaults = struct_decl.field_default_body_lens != null,
34807 .any_field_aligns = struct_decl.field_align_body_lens != null,
34808 .key = .{ .declared = .{
34809 .zir_index = tracked_inst,
34810 .captures = captures,
34811 } },
34812 })) {
34813 .existing => |ty| return .fromInterned(ty),
34814 .wip => |wip| wip,
34815 };
34816 errdefer wip.cancel(ip, pt.tid);
34817
34818 _ = try type_name.apply(&wip, pt);
34819
34820 var field_it = struct_decl.iterateFields();
34821 while (field_it.next()) |field| {
34822 const name_slice = zir.nullTerminatedString(field.name);
34823 const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls);
34824 assert(wip.nextField(ip, name, field.is_comptime) == null); // AstGen validated this for us
34825 }
34826
34827 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
34828 .parent = parent_namespace,
34829 .owner_type = wip.index,
34830 .file_scope = file_index,
34831 .generation = zcu.generation,
34832 });
34833 errdefer pt.destroyNamespace(new_namespace_index);
34834
34835 try pt.scanNamespace(new_namespace_index, struct_decl.decls);
34836
34837 // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind
34838 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) });
34839 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) });
34840
34841 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
34842
34843 try zcu.outdated.ensureUnusedCapacity(gpa, 2);
34844 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2);
34845 errdefer comptime unreachable; // because we don't remove the `outdated` entries
34846 zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0);
34847 zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0);
34848 zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {});
34849 zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {});
34850
34851 return .fromInterned(wip.finish(ip, new_namespace_index));
34852}
34853const AnalyzeUnionDeclError = error{
34854 OutOfMemory,
34855 Canceled,
34856 /// `packed union(T)` syntax was used, but `T` was not an integer type.
34857 ExplicitBackingNotInt,
34858 /// `union(enum(T))` syntax was used, but `T` was not an integer type.
34859 ExplicitTagNotInt,
34860 /// `union(T)` syntax was used, but `T` was not an enum type.
34861 ExplicitTagNotEnum,
34862 /// `union(T)` syntax was used, but the fields of the union do not exactly
34863 /// correspond to the fields of the enum `T`.
34864 ExplicitTagFieldMismatch,
34865};
34866fn analyzeUnionDecl(
34867 pt: Zcu.PerThread,
34868 file_index: Zcu.File.Index,
34869 zir: *const Zir,
34870 parent_namespace: InternPool.OptionalNamespaceIndex,
34871 want_safe_types: bool,
34872 tracked_inst: InternPool.TrackedInst.Index,
34873 union_decl: *const Zir.UnwrappedUnionDecl,
34874 arg_type: ?Type,
34875 captures: []const InternPool.CaptureValue,
34876 type_name: PartialTypeName,
34877) AnalyzeUnionDeclError!Type {
34878 const zcu = pt.zcu;
34879 const comp = zcu.comp;
34880 const gpa = comp.gpa;
34881 const io = comp.io;
34882 const ip = &zcu.intern_pool;
34883
34884 switch (union_decl.kind) {
34885 .tagged_explicit => if (arg_type.?.zigTypeTag(zcu) != .@"enum") {
34886 return error.ExplicitTagNotEnum;
34887 },
34888 .tagged_enum_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) {
34889 return error.ExplicitTagNotInt;
34890 },
34891 .packed_explicit => if (arg_type.?.zigTypeTag(zcu) != .int) {
34892 return error.ExplicitBackingNotInt;
34893 },
34894 .auto,
34895 .tagged_enum,
34896 .@"extern",
34897 .@"packed",
34898 => assert(arg_type == null),
34899 }
34900
34901 const wip = switch (try ip.getUnionType(gpa, io, pt.tid, .{
34902 .fields_len = @intCast(union_decl.field_names.len),
34903 .layout = union_decl.kind.layout(),
34904 .explicit_packed_backing_type = switch (union_decl.kind) {
34905 .packed_explicit => arg_type.?.toIntern(),
34906 else => .none,
34907 },
34908 .runtime_tag = switch (union_decl.kind) {
34909 .auto => if (want_safe_types) .safety else .none,
34910
34911 .tagged_explicit,
34912 .tagged_enum,
34913 .tagged_enum_explicit,
34914 => .tagged,
34915
34916 .@"extern",
34917 .@"packed",
34918 .packed_explicit,
34919 => .none,
34920 },
34921 .have_explicit_enum_tag = union_decl.kind == .tagged_explicit,
34922 .any_field_aligns = union_decl.field_align_body_lens != null,
34923 .key = .{ .declared = .{
34924 .zir_index = tracked_inst,
34925 .captures = captures,
34926 .arg_ty = if (arg_type) |t| t.toIntern() else .none,
34927 } },
34928 })) {
34929 .existing => |ty| return .fromInterned(ty),
34930 .wip => |wip| wip,
34931 };
34932 errdefer wip.cancel(ip, pt.tid);
34933
34934 const resolved_type_name = try type_name.apply(&wip, pt);
34935
34936 const generated_tag_ty: InternPool.Index = if (union_decl.kind == .tagged_explicit) generated_tag_ty: {
34937 const tag_type = arg_type.?;
34938 const enum_field_names = ip.loadEnumType(tag_type.toIntern()).field_names;
34939 // Check that the enum field names match the union field names
34940 if (union_decl.field_names.len != enum_field_names.len) {
34941 return error.ExplicitTagFieldMismatch;
34942 }
34943 for (union_decl.field_names, enum_field_names.get(ip)) |union_field_zir, enum_field_ip| {
34944 const union_field_name = zir.nullTerminatedString(union_field_zir);
34945 const enum_field_name = enum_field_ip.toSlice(ip);
34946 if (!std.mem.eql(u8, union_field_name, enum_field_name)) {
34947 return error.ExplicitTagFieldMismatch;
34948 }
34949 }
34950 wip.setTagType(ip, tag_type.toIntern());
34951 break :generated_tag_ty .none;
34952 } else generated_tag_ty: {
34953 // Generate a tag type. Even if the union is untagged (`.none`), we still generate a
34954 // hypothetical tag type.
34955 const wip_tag_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
34956 .fields_len = @intCast(union_decl.field_names.len),
34957 .explicit_int_tag_type = switch (union_decl.kind) {
34958 .tagged_enum_explicit => arg_type.?.toIntern(),
34959 else => .none,
34960 },
34961 .nonexhaustive = false,
34962 .key = .{ .generated_union_tag = wip.index },
34963 })) {
34964 .existing => unreachable, // enum type is keyed on this union type which we're only just creating
34965 .wip => |wip_tag_ty| wip_tag_ty,
34966 };
34967 errdefer wip_tag_ty.cancel(ip, pt.tid);
34968 // Populate the generated tag type's name
34969 const tag_type_name = try ip.getOrPutStringFmt(
34970 gpa,
34971 io,
34972 pt.tid,
34973 "@typeInfo({f}).@\"union\".tag_type.?",
34974 .{resolved_type_name.fmt(ip)},
34975 .no_embedded_nulls,
34976 );
34977 wip_tag_ty.setName(ip, tag_type_name, .none);
34978 // Populate the generated tag type's field names
34979 for (union_decl.field_names) |zir_name| {
34980 const name_slice = zir.nullTerminatedString(zir_name);
34981 const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls);
34982 assert(wip_tag_ty.nextField(ip, name, false) == null); // AstGen validated this for us
34983 }
34984 // If not explicitly given, populate the generated tag type's *integer* tag type
34985 switch (union_decl.kind) {
34986 .tagged_enum_explicit => {}, // already set by `getEnumType`
34987 else => {
34988 // Infer the int tag type from the field count
34989 const bits = Type.smallestUnsignedBits(union_decl.field_names.len -| 1);
34990 const int_tag_type = try pt.intType(.unsigned, bits);
34991 wip_tag_ty.setTagType(ip, int_tag_type.toIntern());
34992 },
34993 }
34994 // Create a dummy namespace for the generated tag type
34995 const new_namespace_index = try pt.createNamespace(.{
34996 .parent = parent_namespace,
34997 .owner_type = wip_tag_ty.index,
34998 .file_scope = file_index,
34999 .generation = zcu.generation,
35000 });
35001 errdefer pt.destroyNamespace(new_namespace_index);
35002 wip.setTagType(ip, wip_tag_ty.index);
35003 break :generated_tag_ty wip_tag_ty.finish(ip, new_namespace_index);
35004 };
35005 // If we fail to create the union type, we must delete the generated enum tag type, since it
35006 // would hold a reference to the deleted union.
35007 errdefer if (generated_tag_ty != .none) ip.remove(pt.tid, generated_tag_ty);
35008
35009 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
35010 .parent = parent_namespace,
35011 .owner_type = wip.index,
35012 .file_scope = file_index,
35013 .generation = zcu.generation,
35014 });
35015 errdefer pt.destroyNamespace(new_namespace_index);
35016
35017 try pt.scanNamespace(new_namespace_index, union_decl.decls);
35018
35019 // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind
35020 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_layout = wip.index }) });
35021 if (generated_tag_ty != .none) {
35022 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = generated_tag_ty }) });
35023 }
35024
35025 if (zcu.comp.debugIncremental()) {
35026 try zcu.incremental_debug_state.newType(zcu, wip.index);
35027 if (generated_tag_ty != .none) {
35028 try zcu.incremental_debug_state.newType(zcu, generated_tag_ty);
35029 }
35030 }
35031
35032 try zcu.outdated.ensureUnusedCapacity(gpa, 2);
35033 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 2);
35034 errdefer comptime unreachable; // because we don't remove the `outdated` entry
35035 zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), 0);
35036 zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_layout = wip.index }), {});
35037 if (generated_tag_ty != .none) {
35038 zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), 0);
35039 zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = generated_tag_ty }), {});
35040 }
35041
35042 return .fromInterned(wip.finish(ip, new_namespace_index));
35043}
35044const AnalyzeEnumDeclError = error{
35045 OutOfMemory,
35046 Canceled,
35047 /// `enum(T)` syntax was used, but `T` was not an integer type.
35048 ExplicitTagNotInt,
35049};
35050fn analyzeEnumDecl(
35051 pt: Zcu.PerThread,
35052 file_index: Zcu.File.Index,
35053 zir: *const Zir,
35054 parent_namespace: InternPool.OptionalNamespaceIndex,
35055 tracked_inst: InternPool.TrackedInst.Index,
35056 enum_decl: *const Zir.UnwrappedEnumDecl,
35057 explicit_tag_type: ?Type,
35058 captures: []const InternPool.CaptureValue,
35059 type_name: PartialTypeName,
35060) AnalyzeEnumDeclError!Type {
35061 const zcu = pt.zcu;
35062 const comp = zcu.comp;
35063 const gpa = comp.gpa;
35064 const io = comp.io;
35065 const ip = &zcu.intern_pool;
35066
35067 if (explicit_tag_type) |ty| {
35068 // MLUGG TODO: make a final call on whether comptime_int is a valid int tag type, and follow it everywhere.
35069 // i think not in the name of simplicity, but my opinion might depend on whether it's broken in practice today
35070 switch (ty.zigTypeTag(zcu)) {
35071 .int, .comptime_int => {},
35072 else => return error.ExplicitTagNotInt,
35073 }
35074 }
35075
35076 const wip = switch (try ip.getEnumType(gpa, io, pt.tid, .{
35077 .fields_len = @intCast(enum_decl.field_names.len),
35078 .explicit_int_tag_type = if (explicit_tag_type) |ty| ty.toIntern() else .none,
35079 .nonexhaustive = enum_decl.nonexhaustive,
35080 .key = .{ .declared = .{
35081 .zir_index = tracked_inst,
35082 .captures = captures,
35083 } },
35084 })) {
35085 .existing => |ty| return .fromInterned(ty),
35086 .wip => |wip| wip,
35087 };
35088 errdefer wip.cancel(ip, pt.tid);
35089
35090 _ = try type_name.apply(&wip, pt);
35091
35092 var field_it = enum_decl.iterateFields();
35093 while (field_it.next()) |field| {
35094 const name_slice = zir.nullTerminatedString(field.name);
35095 const name = try ip.getOrPutString(gpa, io, pt.tid, name_slice, .no_embedded_nulls);
35096 assert(wip.nextField(ip, name, false) == null); // AstGen validated this for us
35097 }
35098
35099 if (explicit_tag_type == null) {
35100 // Infer the int tag type from the field count
35101 const bits = Type.smallestUnsignedBits(enum_decl.field_names.len -| 1);
35102 const int_tag_ty = try pt.intType(.unsigned, bits);
35103 wip.setTagType(ip, int_tag_ty.toIntern());
35104 }
35105
35106 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
35107 .parent = parent_namespace,
35108 .owner_type = wip.index,
35109 .file_scope = file_index,
35110 .generation = zcu.generation,
35111 });
35112 errdefer pt.destroyNamespace(new_namespace_index);
35113
35114 try pt.scanNamespace(new_namespace_index, enum_decl.decls);
35115
35116 // MLUGG TODO: we could potentially revert this language change if we wanted? don't mind
35117 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .type_inits = wip.index }) });
35118
35119 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
35120
35121 try zcu.outdated.ensureUnusedCapacity(gpa, 1);
35122 try zcu.outdated_ready.ensureUnusedCapacity(gpa, 1);
35123 errdefer comptime unreachable; // because we don't remove the `outdated` entry
35124 zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), 0);
35125 zcu.outdated_ready.putAssumeCapacityNoClobber(.wrap(.{ .type_inits = wip.index }), {});
35126
35127 return .fromInterned(wip.finish(ip, new_namespace_index));
35128}
35129fn analyzeOpaqueDecl(
35130 pt: Zcu.PerThread,
35131 file_index: Zcu.File.Index,
35132 parent_namespace: InternPool.OptionalNamespaceIndex,
35133 tracked_inst: InternPool.TrackedInst.Index,
35134 opaque_decl: *const Zir.UnwrappedOpaqueDecl,
35135 captures: []const InternPool.CaptureValue,
35136 type_name: PartialTypeName,
35137) (Allocator.Error || std.Io.Cancelable)!Type {
35138 const zcu = pt.zcu;
35139 const comp = zcu.comp;
35140 const gpa = comp.gpa;
35141 const io = comp.io;
35142 const ip = &zcu.intern_pool;
35143
35144 const wip = switch (try ip.getOpaqueType(gpa, io, pt.tid, .{
35145 .zir_index = tracked_inst,
35146 .captures = captures,
35147 })) {
35148 .existing => |ty| return .fromInterned(ty),
35149 .wip => |wip| wip,
35150 };
35151 errdefer wip.cancel(ip, pt.tid);
35152
35153 _ = try type_name.apply(&wip, pt);
35154
35155 const new_namespace_index: InternPool.NamespaceIndex = try pt.createNamespace(.{
35156 .parent = parent_namespace,
35157 .owner_type = wip.index,
35158 .file_scope = file_index,
35159 .generation = zcu.generation,
35160 });
35161 errdefer pt.destroyNamespace(new_namespace_index);
35162
35163 try pt.scanNamespace(new_namespace_index, opaque_decl.decls);
35164
35165 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
35166 return .fromInterned(wip.finish(ip, new_namespace_index));
35167}
35168
35169fn zirStructDecl(
35170 sema: *Sema,
35171 block: *Block,
35172 inst: Zir.Inst.Index,
35173) CompileError!Air.Inst.Ref {
35174 const pt = sema.pt;
35175 const zcu = pt.zcu;
35176
35177 const tracked_inst = try block.trackZir(inst);
35178
35179 const src: LazySrcLoc = .{
35180 .base_node_inst = tracked_inst,
35181 .offset = .nodeOffset(.zero),
35182 };
35183 const backing_ty_src: LazySrcLoc = .{
35184 .base_node_inst = tracked_inst,
35185 .offset = .{ .node_offset_container_tag = .zero },
35186 };
35187
35188 const struct_decl = sema.code.getStructDecl(inst);
35189
35190 const captures = try sema.getCaptures(block, src, struct_decl.captures, struct_decl.capture_names);
35191
35192 const backing_int_type: ?Type = ty: {
35193 if (struct_decl.backing_int_type == .none) break :ty null;
35194 break :ty try sema.resolveType(block, backing_ty_src, struct_decl.backing_int_type);
35195 // MLUGG TODO validate it's an int!
35196 };
35197
35198 const ty = try analyzeStructDecl(
35199 pt,
35200 block.getFileScopeIndex(zcu),
35201 &sema.code,
35202 block.namespace.toOptional(),
35203 tracked_inst,
35204 &struct_decl,
35205 backing_int_type,
35206 captures,
35207 try sema.createTypeName(block, struct_decl.name_strategy, "struct", inst),
35208 );
35209
35210 try sema.addTypeReferenceEntry(src, ty);
35211
35212 // Make sure we update the namespace if the declaration is re-analyzed, to pick
35213 // up on e.g. changed comptime decls.
35214 // TODO MLUGG: me no likey, maybe model namespaces less badly idk
35215 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35216
35217 return .fromIntern(ty.toIntern());
35218}
35219fn zirUnionDecl(
35220 sema: *Sema,
35221 block: *Block,
35222 inst: Zir.Inst.Index,
35223) CompileError!Air.Inst.Ref {
35224 const pt = sema.pt;
35225 const zcu = pt.zcu;
35226 const comp = zcu.comp;
35227 const gpa = comp.gpa;
35228 const io = comp.io;
35229 const ip = &zcu.intern_pool;
35230
35231 const tracked_inst = try block.trackZir(inst);
35232
35233 const src: LazySrcLoc = .{
35234 .base_node_inst = tracked_inst,
35235 .offset = .nodeOffset(.zero),
35236 };
35237 const arg_ty_src: LazySrcLoc = .{
35238 .base_node_inst = tracked_inst,
35239 .offset = .{ .node_offset_container_tag = .zero },
35240 };
35241
35242 const union_decl = sema.code.getUnionDecl(inst);
35243
35244 const captures = try sema.getCaptures(block, src, union_decl.captures, union_decl.capture_names);
35245
35246 const arg_type: ?Type = ty: {
35247 if (union_decl.arg_type == .none) break :ty null;
35248 break :ty try sema.resolveType(block, arg_ty_src, union_decl.arg_type);
35249 };
35250
35251 const ty = analyzeUnionDecl(
35252 pt,
35253 block.getFileScopeIndex(zcu),
35254 &sema.code,
35255 block.namespace.toOptional(),
35256 block.wantSafeTypes(),
35257 tracked_inst,
35258 &union_decl,
35259 arg_type,
35260 captures,
35261 try sema.createTypeName(block, union_decl.name_strategy, "union", inst),
35262 ) catch |err| switch (err) {
35263 error.OutOfMemory,
35264 error.Canceled,
35265 => |e| return e,
35266
35267 error.ExplicitBackingNotInt => return sema.fail(
35268 block,
35269 arg_ty_src,
35270 "expected integer backing type, found '{f}'",
35271 .{arg_type.?.fmt(pt)},
35272 ),
35273 error.ExplicitTagNotInt => return sema.fail(
35274 block,
35275 arg_ty_src,
35276 "expected integer tag type, found '{f}'",
35277 .{arg_type.?.fmt(pt)},
35278 ),
35279 error.ExplicitTagNotEnum => return sema.fail(
35280 block,
35281 arg_ty_src,
35282 "expected enum tag type, found '{f}'",
35283 .{arg_type.?.fmt(pt)},
35284 ),
35285 error.ExplicitTagFieldMismatch => {
35286 const enum_obj = ip.loadEnumType(arg_type.?.toIntern());
35287 const enum_to_union_map = try sema.arena.alloc(?u32, enum_obj.field_names.len);
35288 @memset(enum_to_union_map, null);
35289 for (union_decl.field_names, 0..) |field_name_zir, union_field_idx| {
35290 const field_name_ip = try ip.getOrPutString(gpa, io, pt.tid, sema.code.nullTerminatedString(field_name_zir), .no_embedded_nulls);
35291 if (enum_obj.nameIndex(ip, field_name_ip)) |enum_field_idx| {
35292 enum_to_union_map[enum_field_idx] = @intCast(union_field_idx);
35293 continue;
35294 }
35295 const union_field_src: LazySrcLoc = .{
35296 .base_node_inst = tracked_inst,
35297 .offset = .{ .container_field_name = @intCast(union_field_idx) },
35298 };
35299 return sema.failWithOwnedErrorMsg(block, msg: {
35300 const msg = try sema.errMsg(union_field_src, "no field named '{f}' in enum '{f}'", .{ field_name_ip.fmt(ip), arg_type.?.fmt(pt) });
35301 errdefer msg.destroy(gpa);
35302 try sema.addDeclaredHereNote(msg, arg_type.?);
35303 break :msg msg;
35304 });
35305 }
35306 for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| {
35307 if (union_field_idx != null) continue;
35308 const field_name_ip = enum_obj.field_names.get(ip)[enum_field_idx];
35309 const enum_field_src: LazySrcLoc = .{
35310 .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?,
35311 .offset = .{ .container_field_name = @intCast(enum_field_idx) },
35312 };
35313 return sema.failWithOwnedErrorMsg(block, msg: {
35314 const msg = try sema.errMsg(src, "enum field '{f}' missing from union", .{field_name_ip.fmt(ip)});
35315 errdefer msg.destroy(gpa);
35316 try sema.errNote(enum_field_src, msg, "enum field here", .{});
35317 break :msg msg;
35318 });
35319 }
35320 for (enum_to_union_map, 0..) |union_field_idx, enum_field_idx| {
35321 if (union_field_idx.? == enum_field_idx) continue;
35322 const field_name = sema.code.nullTerminatedString(
35323 union_decl.field_names[union_field_idx.?],
35324 );
35325 const union_field_src: LazySrcLoc = .{
35326 .base_node_inst = tracked_inst,
35327 .offset = .{ .container_field_name = union_field_idx.? },
35328 };
35329 const enum_field_src: LazySrcLoc = .{
35330 .base_node_inst = arg_type.?.typeDeclInstAllowGeneratedTag(zcu).?,
35331 .offset = .{ .container_field_name = @intCast(enum_field_idx) },
35332 };
35333 return sema.failWithOwnedErrorMsg(block, msg: {
35334 const msg = try sema.errMsg(src, "union field order does not match tag enum field order", .{});
35335 errdefer msg.destroy(gpa);
35336 try sema.errNote(union_field_src, msg, "union field '{s}' is index {d}", .{ field_name, union_field_idx.? });
35337 try sema.errNote(enum_field_src, msg, "enum field '{s}' is index {d}", .{ field_name, enum_field_idx });
35338 break :msg msg;
35339 });
35340 }
35341 unreachable;
35342 },
35343 };
35344
35345 const enum_tag_ty = ty.unionTagTypeHypothetical(zcu);
35346 switch (ip.indexToKey(enum_tag_ty.toIntern()).enum_type) {
35347 .declared, .reified => {},
35348 .generated_union_tag => |owner_union_ty| {
35349 assert(owner_union_ty == ty.toIntern());
35350 // generated tag type [MLUGG]
35351 // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol
35352 try sema.ensureFieldInitsResolved(.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type));
35353 },
35354 }
35355
35356 try sema.addTypeReferenceEntry(src, ty);
35357
35358 // Make sure we update the namespace if the declaration is re-analyzed, to pick
35359 // up on e.g. changed comptime decls.
35360 // TODO MLUGG: me no likey, maybe model namespaces less badly idk
35361 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35362
35363 return .fromIntern(ty.toIntern());
35364}
35365fn zirEnumDecl(
35366 sema: *Sema,
35367 block: *Block,
35368 inst: Zir.Inst.Index,
35369) CompileError!Air.Inst.Ref {
35370 const pt = sema.pt;
35371 const zcu = pt.zcu;
35372
35373 const tracked_inst = try block.trackZir(inst);
35374
35375 const src: LazySrcLoc = .{
35376 .base_node_inst = tracked_inst,
35377 .offset = .nodeOffset(.zero),
35378 };
35379 const tag_ty_src: LazySrcLoc = .{
35380 .base_node_inst = tracked_inst,
35381 .offset = .{ .node_offset_container_tag = .zero },
35382 };
35383
35384 const enum_decl = sema.code.getEnumDecl(inst);
35385
35386 const captures = try sema.getCaptures(block, src, enum_decl.captures, enum_decl.capture_names);
35387
35388 const tag_type: ?Type = ty: {
35389 if (enum_decl.tag_type == .none) break :ty null;
35390 break :ty try sema.resolveType(block, tag_ty_src, enum_decl.tag_type);
35391 };
35392
35393 const ty = analyzeEnumDecl(
35394 pt,
35395 block.getFileScopeIndex(zcu),
35396 &sema.code,
35397 block.namespace.toOptional(),
35398 tracked_inst,
35399 &enum_decl,
35400 tag_type,
35401 captures,
35402 try sema.createTypeName(block, enum_decl.name_strategy, "enum", inst),
35403 ) catch |err| switch (err) {
35404 error.OutOfMemory,
35405 error.Canceled,
35406 => |e| return e,
35407
35408 error.ExplicitTagNotInt => return sema.fail(
35409 block,
35410 tag_ty_src,
35411 "expected integer tag type, found '{f}'",
35412 .{tag_type.?.fmt(pt)},
35413 ),
35414 };
35415
35416 // Enum inits are resolved eagerly. TODO MLUGG: honestly i don't think they SHOULD be lol
35417 try sema.ensureFieldInitsResolved(ty);
35418
35419 try sema.addTypeReferenceEntry(src, ty);
35420
35421 // Make sure we update the namespace if the declaration is re-analyzed, to pick
35422 // up on e.g. changed comptime decls.
35423 // TODO MLUGG: me no likey, maybe model namespaces less badly idk
35424 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35425
35426 return .fromIntern(ty.toIntern());
35427}
35428fn zirOpaqueDecl(
35429 sema: *Sema,
35430 block: *Block,
35431 inst: Zir.Inst.Index,
35432) CompileError!Air.Inst.Ref {
35433 const pt = sema.pt;
35434 const zcu = pt.zcu;
35435
35436 const tracked_inst = try block.trackZir(inst);
35437
35438 const src: LazySrcLoc = .{
35439 .base_node_inst = tracked_inst,
35440 .offset = .nodeOffset(.zero),
35441 };
35442
35443 const opaque_decl = sema.code.getOpaqueDecl(inst);
35444
35445 const captures = try sema.getCaptures(block, src, opaque_decl.captures, opaque_decl.capture_names);
35446
35447 const ty = try analyzeOpaqueDecl(
35448 pt,
35449 block.getFileScopeIndex(zcu),
35450 block.namespace.toOptional(),
35451 tracked_inst,
35452 &opaque_decl,
35453 captures,
35454 try sema.createTypeName(block, opaque_decl.name_strategy, "opaque", inst),
35455 );
35456
35457 try sema.addTypeReferenceEntry(src, ty);
35458
35459 // Make sure we update the namespace if the declaration is re-analyzed, to pick
35460 // up on e.g. changed comptime decls.
35461 // TODO MLUGG: me no likey, maybe model namespaces less badly idk
35462 try pt.ensureNamespaceUpToDate(ty.getNamespaceIndex(zcu));
35463
35464 return .fromIntern(ty.toIntern());
35465}
src/Sema/LowerZon.zig+11-10
......@@ -125,6 +125,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
125125 return (try pt.aggregateValue(.fromInterned(ty), values)).toIntern();
126126 },
127127 .struct_literal => |init| {
128 if (true) @panic("MLUGG TODO");
128129 const elems = try self.sema.arena.alloc(InternPool.Index, init.names.len);
129130 for (0..init.names.len) |i| {
130131 elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i)));
......@@ -299,7 +300,7 @@ fn checkTypeInner(
299300 } else {
300301 const gop = try visited.getOrPut(sema.arena, ty.toIntern());
301302 if (gop.found_existing) return;
302 try ty.resolveFields(pt);
303 try sema.ensureLayoutResolved(ty);
303304 const struct_info = zcu.typeToStruct(ty).?;
304305 for (struct_info.field_types.get(ip)) |field_type| {
305306 try self.checkTypeInner(.fromInterned(field_type), null, visited);
......@@ -308,7 +309,7 @@ fn checkTypeInner(
308309 .@"union" => {
309310 const gop = try visited.getOrPut(sema.arena, ty.toIntern());
310311 if (gop.found_existing) return;
311 try ty.resolveFields(pt);
312 try sema.ensureLayoutResolved(ty);
312313 const union_info = zcu.typeToUnion(ty).?;
313314 for (union_info.field_types.get(ip)) |field_type| {
314315 if (field_type != .void_type) {
......@@ -767,8 +768,8 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
767768 const io = comp.io;
768769 const ip = &pt.zcu.intern_pool;
769770
770 try res_ty.resolveFields(self.sema.pt);
771 try res_ty.resolveStructFieldInits(self.sema.pt);
771 try self.sema.ensureLayoutResolved(res_ty);
772 try self.sema.ensureFieldInitsResolved(res_ty);
772773 const struct_info = self.sema.pt.zcu.typeToStruct(res_ty).?;
773774
774775 const fields: @FieldType(Zoir.Node, "struct_literal") = switch (node.get(self.file.zoir.?)) {
......@@ -779,7 +780,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
779780
780781 const field_values = try self.sema.arena.alloc(InternPool.Index, struct_info.field_names.len);
781782
782 const field_defaults = struct_info.field_inits.get(ip);
783 const field_defaults = struct_info.field_defaults.get(ip);
783784 if (field_defaults.len > 0) {
784785 @memcpy(field_values, field_defaults);
785786 } else {
......@@ -803,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool
803804 const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]);
804805 field_values[name_index] = try self.lowerExprKnownResTy(field_node, field_type);
805806
806 if (struct_info.comptime_bits.getBit(ip, name_index)) {
807 if (struct_info.field_is_comptime_bits.get(ip, name_index)) {
807808 const val = ip.indexToKey(field_values[name_index]);
808809 const default = ip.indexToKey(field_defaults[name_index]);
809810 if (!val.eql(default, ip)) {
......@@ -918,9 +919,9 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
918919 const gpa = comp.gpa;
919920 const io = comp.io;
920921 const ip = &pt.zcu.intern_pool;
921 try res_ty.resolveFields(self.sema.pt);
922 const union_info = self.sema.pt.zcu.typeToUnion(res_ty).?;
923 const enum_tag_info = union_info.loadTagType(ip);
922 try self.sema.ensureLayoutResolved(res_ty);
923 const union_info = pt.zcu.typeToUnion(res_ty).?;
924 const enum_tag_info = ip.loadEnumType(union_info.enum_tag_type);
924925
925926 const field_name, const maybe_field_node = switch (node.get(self.file.zoir.?)) {
926927 .enum_literal => |name| b: {
......@@ -956,7 +957,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool.
956957 const name_index = enum_tag_info.nameIndex(ip, field_name) orelse {
957958 return error.WrongType;
958959 };
959 const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_ty), name_index);
960 const tag = try self.sema.pt.enumValueFieldIndex(.fromInterned(union_info.enum_tag_type), name_index);
960961 const field_type: Type = .fromInterned(union_info.field_types.get(ip)[name_index]);
961962 const val = if (maybe_field_node) |field_node| b: {
962963 if (field_type.toIntern() == .void_type) {
src/Sema/arith.zig+20-19
......@@ -1053,7 +1053,7 @@ fn shlScalar(
10531053 if (rhs_val.isUndef(zcu)) return rhs_val;
10541054 },
10551055 }
1056 switch (try rhs_val.orderAgainstZeroSema(pt)) {
1056 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
10571057 .gt => {},
10581058 .eq => return lhs_val,
10591059 .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx),
......@@ -1090,7 +1090,7 @@ fn shlWithOverflowScalar(
10901090 if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx);
10911091 if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx);
10921092
1093 switch (try rhs_val.orderAgainstZeroSema(pt)) {
1093 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
10941094 .gt => {},
10951095 .eq => return .{ .overflow_bit = .zero_u1, .wrapped_result = lhs_val },
10961096 .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx),
......@@ -1169,7 +1169,7 @@ fn shrScalar(
11691169 if (lhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, lhs_src, vec_idx);
11701170 if (rhs_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, rhs_src, vec_idx);
11711171
1172 switch (try rhs_val.orderAgainstZeroSema(pt)) {
1172 switch (Value.order(rhs_val, .zero_comptime_int, zcu)) {
11731173 .gt => {},
11741174 .eq => return lhs_val,
11751175 .lt => return sema.failWithNegativeShiftAmount(block, rhs_src, rhs_val, vec_idx),
......@@ -1430,8 +1430,8 @@ fn intAddWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value
14301430 const info = ty.intInfo(zcu);
14311431 var lhs_space: Value.BigIntSpace = undefined;
14321432 var rhs_space: Value.BigIntSpace = undefined;
1433 const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt);
1434 const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt);
1433 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
1434 const rhs_bigint = rhs.toBigInt(&rhs_space, zcu);
14351435 const limbs = try sema.arena.alloc(
14361436 std.math.big.Limb,
14371437 std.math.big.int.calcTwosCompLimbCount(info.bits),
......@@ -1512,8 +1512,8 @@ fn intSubWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value
15121512 const info = ty.intInfo(zcu);
15131513 var lhs_space: Value.BigIntSpace = undefined;
15141514 var rhs_space: Value.BigIntSpace = undefined;
1515 const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt);
1516 const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt);
1515 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
1516 const rhs_bigint = rhs.toBigInt(&rhs_space, zcu);
15171517 const limbs = try sema.arena.alloc(
15181518 std.math.big.Limb,
15191519 std.math.big.int.calcTwosCompLimbCount(info.bits),
......@@ -1597,8 +1597,8 @@ fn intMulWithOverflowInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value
15971597 const info = ty.intInfo(zcu);
15981598 var lhs_space: Value.BigIntSpace = undefined;
15991599 var rhs_space: Value.BigIntSpace = undefined;
1600 const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt);
1601 const rhs_bigint = try rhs.toBigIntSema(&rhs_space, pt);
1600 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
1601 const rhs_bigint = rhs.toBigInt(&rhs_space, zcu);
16021602 const limbs = try sema.arena.alloc(
16031603 std.math.big.Limb,
16041604 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
......@@ -1840,7 +1840,7 @@ fn intShl(
18401840 var lhs_space: Value.BigIntSpace = undefined;
18411841 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
18421842
1843 const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt));
1843 const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu));
18441844 if (shift_amt >= info.bits) {
18451845 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx);
18461846 }
......@@ -1862,7 +1862,7 @@ fn intShlSat(
18621862 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
18631863
18641864 const shift_amt: usize = amt: {
1865 if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| {
1865 if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| {
18661866 if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt;
18671867 }
18681868 // We only support ints with up to 2^16 - 1 bits, so this
......@@ -1895,9 +1895,9 @@ fn intShlWithOverflow(
18951895 const info = lhs_ty.intInfo(zcu);
18961896
18971897 var lhs_space: Value.BigIntSpace = undefined;
1898 const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt);
1898 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
18991899
1900 const shift_amt: usize = @intCast(try rhs.toUnsignedIntSema(pt));
1900 const shift_amt: usize = @intCast(rhs.toUnsignedInt(zcu));
19011901 if (shift_amt >= info.bits) {
19021902 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx);
19031903 }
......@@ -1924,9 +1924,10 @@ fn comptimeIntShl(
19241924 vec_idx: ?usize,
19251925) !Value {
19261926 const pt = sema.pt;
1927 const zcu = pt.zcu;
19271928 var lhs_space: Value.BigIntSpace = undefined;
1928 const lhs_bigint = try lhs.toBigIntSema(&lhs_space, pt);
1929 if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| {
1929 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
1930 if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| {
19301931 if (std.math.cast(usize, shift_amt_u64)) |shift_amt| {
19311932 const result_bigint = try intShlInner(sema, lhs_bigint, shift_amt);
19321933 return pt.intValue_big(.comptime_int, result_bigint.toConst());
......@@ -1963,15 +1964,15 @@ fn intShr(
19631964 const lhs_bigint = lhs.toBigInt(&lhs_space, zcu);
19641965
19651966 const shift_amt: usize = if (rhs_ty.toIntern() == .comptime_int_type) amt: {
1966 if (try rhs.getUnsignedIntSema(pt)) |shift_amt_u64| {
1967 if (rhs.getUnsignedInt(zcu)) |shift_amt_u64| {
19671968 if (std.math.cast(usize, shift_amt_u64)) |shift_amt| break :amt shift_amt;
19681969 }
1969 if (try rhs.compareAllWithZeroSema(.lt, pt)) {
1970 if (rhs.compareAllWithZero(.lt, zcu)) {
19701971 return sema.failWithNegativeShiftAmount(block, rhs_src, rhs, vec_idx);
19711972 } else {
19721973 return sema.failWithUnsupportedComptimeShiftAmount(block, rhs_src, vec_idx);
19731974 }
1974 } else @intCast(try rhs.toUnsignedIntSema(pt));
1975 } else @intCast(rhs.toUnsignedInt(zcu));
19751976
19761977 if (lhs_ty.toIntern() != .comptime_int_type and shift_amt >= lhs_ty.intInfo(zcu).bits) {
19771978 return sema.failWithTooLargeShiftAmount(block, lhs_ty, rhs, rhs_src, vec_idx);
......@@ -2006,7 +2007,7 @@ fn intBitReverse(sema: *Sema, val: Value, ty: Type) !Value {
20062007 const info = ty.intInfo(zcu);
20072008
20082009 var val_space: Value.BigIntSpace = undefined;
2009 const val_bigint = try val.toBigIntSema(&val_space, pt);
2010 const val_bigint = val.toBigInt(&val_space, zcu);
20102011
20112012 const limbs = try sema.arena.alloc(
20122013 std.math.big.Limb,
src/Sema/bitcast.zig+7-4
......@@ -79,8 +79,8 @@ fn bitCastInner(
7979
8080 const val_ty = val.typeOf(zcu);
8181
82 try val_ty.resolveLayout(pt);
83 try dest_ty.resolveLayout(pt);
82 val_ty.assertHasLayout(zcu);
83 try sema.ensureLayoutResolved(dest_ty);
8484
8585 assert(val_ty.hasWellDefinedLayout(zcu));
8686
......@@ -138,8 +138,8 @@ fn bitCastSpliceInner(
138138 const val_ty = val.typeOf(zcu);
139139 const splice_val_ty = splice_val.typeOf(zcu);
140140
141 try val_ty.resolveLayout(pt);
142 try splice_val_ty.resolveLayout(pt);
141 try sema.ensureLayoutResolved(val_ty);
142 try sema.ensureLayoutResolved(splice_val_ty);
143143
144144 const splice_bits = splice_val_ty.bitSize(zcu);
145145
......@@ -673,6 +673,9 @@ const PackValueBits = struct {
673673 fn primitive(pack: *PackValueBits, want_ty: Type) BitCastError!Value {
674674 const pt = pack.pt;
675675 const zcu = pt.zcu;
676
677 if (try want_ty.onePossibleValue(pt)) |opv| return opv;
678
676679 const vals, const bit_offset = pack.prepareBits(want_ty.bitSize(zcu));
677680
678681 for (vals) |val| {
src/Sema/comptime_ptr_access.zig+19-19
......@@ -67,7 +67,7 @@ pub fn storeComptimePtr(
6767
6868 {
6969 const store_ty: Type = .fromInterned(ptr_info.child);
70 if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) {
70 if (!store_ty.comptimeOnly(zcu) and !store_ty.hasRuntimeBits(zcu)) {
7171 // zero-bit store; nothing to do
7272 return .success;
7373 }
......@@ -354,8 +354,8 @@ fn loadComptimePtrInner(
354354 const load_one_ty, const load_count = load_ty.arrayBase(zcu);
355355
356356 const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: {
357 if (try load_one_ty.comptimeOnlySema(pt)) break :restructure_array;
358 const elem_len = try load_one_ty.abiSizeSema(pt);
357 if (load_one_ty.comptimeOnly(zcu)) break :restructure_array;
358 const elem_len = load_one_ty.abiSize(zcu);
359359 if (ptr.byte_offset % elem_len != 0) break :restructure_array;
360360 break :idx @divExact(ptr.byte_offset, elem_len);
361361 };
......@@ -401,12 +401,12 @@ fn loadComptimePtrInner(
401401 var cur_offset = ptr.byte_offset;
402402
403403 if (load_ty.zigTypeTag(zcu) == .array and array_offset > 0) {
404 cur_offset += try load_ty.childType(zcu).abiSizeSema(pt) * array_offset;
404 cur_offset += load_ty.childType(zcu).abiSize(zcu) * array_offset;
405405 }
406406
407 const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else try load_ty.abiSizeSema(pt);
407 const need_bytes = if (host_bits > 0) (host_bits + 7) / 8 else load_ty.abiSize(zcu);
408408
409 if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) {
409 if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) {
410410 return .{ .out_of_bounds = cur_val.typeOf(zcu) };
411411 }
412412
......@@ -441,7 +441,7 @@ fn loadComptimePtrInner(
441441 .optional => break, // this can only be a pointer-like optional so is terminal
442442 .array => {
443443 const elem_ty = cur_ty.childType(zcu);
444 const elem_size = try elem_ty.abiSizeSema(pt);
444 const elem_size = elem_ty.abiSize(zcu);
445445 const elem_idx = cur_offset / elem_size;
446446 const next_elem_off = elem_size * (elem_idx + 1);
447447 if (cur_offset + need_bytes <= next_elem_off) {
......@@ -457,7 +457,7 @@ fn loadComptimePtrInner(
457457 .@"packed" => break, // let the bitcast logic handle this
458458 .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| {
459459 const start_off = cur_ty.structFieldOffset(field_idx, zcu);
460 const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt);
460 const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu);
461461 if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) {
462462 cur_val = try cur_val.getElem(sema.pt, field_idx);
463463 cur_offset -= start_off;
......@@ -484,7 +484,7 @@ fn loadComptimePtrInner(
484484 };
485485 // The payload always has offset 0. If it's big enough
486486 // to represent the whole load type, we can use it.
487 if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) {
487 if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) {
488488 cur_val = payload;
489489 } else {
490490 break;
......@@ -753,8 +753,8 @@ fn prepareComptimePtrStore(
753753
754754 const store_one_ty, const store_count = store_ty.arrayBase(zcu);
755755 const extra_base_index: u64 = if (ptr.byte_offset == 0) 0 else idx: {
756 if (try store_one_ty.comptimeOnlySema(pt)) break :restructure_array;
757 const elem_len = try store_one_ty.abiSizeSema(pt);
756 if (store_one_ty.comptimeOnly(zcu)) break :restructure_array;
757 const elem_len = store_one_ty.abiSize(zcu);
758758 if (ptr.byte_offset % elem_len != 0) break :restructure_array;
759759 break :idx @divExact(ptr.byte_offset, elem_len);
760760 };
......@@ -807,11 +807,11 @@ fn prepareComptimePtrStore(
807807 var cur_val: *MutableValue, var cur_offset: u64 = switch (base_strat) {
808808 .direct => |direct| .{ direct.val, 0 },
809809 // It's okay to do `abiSize` - the comptime-only case will be caught below.
810 .index => |index| .{ index.val, index.elem_index * try index.val.typeOf(zcu).childType(zcu).abiSizeSema(pt) },
810 .index => |index| .{ index.val, index.elem_index * index.val.typeOf(zcu).childType(zcu).abiSize(zcu) },
811811 .flat_index => |flat_index| .{
812812 flat_index.val,
813813 // It's okay to do `abiSize` - the comptime-only case will be caught below.
814 flat_index.flat_elem_index * try flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSizeSema(pt),
814 flat_index.flat_elem_index * flat_index.val.typeOf(zcu).arrayBase(zcu)[0].abiSize(zcu),
815815 },
816816 .reinterpret => |r| .{ r.val, r.byte_offset },
817817 else => unreachable,
......@@ -823,12 +823,12 @@ fn prepareComptimePtrStore(
823823 }
824824
825825 if (store_ty.zigTypeTag(zcu) == .array and array_offset > 0) {
826 cur_offset += try store_ty.childType(zcu).abiSizeSema(pt) * array_offset;
826 cur_offset += store_ty.childType(zcu).abiSize(zcu) * array_offset;
827827 }
828828
829 const need_bytes = try store_ty.abiSizeSema(pt);
829 const need_bytes = store_ty.abiSize(zcu);
830830
831 if (cur_offset + need_bytes > try cur_val.typeOf(zcu).abiSizeSema(pt)) {
831 if (cur_offset + need_bytes > cur_val.typeOf(zcu).abiSize(zcu)) {
832832 return .{ .out_of_bounds = cur_val.typeOf(zcu) };
833833 }
834834
......@@ -863,7 +863,7 @@ fn prepareComptimePtrStore(
863863 .optional => break, // this can only be a pointer-like optional so is terminal
864864 .array => {
865865 const elem_ty = cur_ty.childType(zcu);
866 const elem_size = try elem_ty.abiSizeSema(pt);
866 const elem_size = elem_ty.abiSize(zcu);
867867 const elem_idx = cur_offset / elem_size;
868868 const next_elem_off = elem_size * (elem_idx + 1);
869869 if (cur_offset + need_bytes <= next_elem_off) {
......@@ -879,7 +879,7 @@ fn prepareComptimePtrStore(
879879 .@"packed" => break, // let the bitcast logic handle this
880880 .@"extern" => for (0..cur_ty.structFieldCount(zcu)) |field_idx| {
881881 const start_off = cur_ty.structFieldOffset(field_idx, zcu);
882 const end_off = start_off + try cur_ty.fieldType(field_idx, zcu).abiSizeSema(pt);
882 const end_off = start_off + cur_ty.fieldType(field_idx, zcu).abiSize(zcu);
883883 if (cur_offset >= start_off and cur_offset + need_bytes <= end_off) {
884884 cur_val = try cur_val.elem(pt, sema.arena, field_idx);
885885 cur_offset -= start_off;
......@@ -902,7 +902,7 @@ fn prepareComptimePtrStore(
902902 };
903903 // The payload always has offset 0. If it's big enough
904904 // to represent the whole load type, we can use it.
905 if (try payload.typeOf(zcu).abiSizeSema(pt) >= need_bytes) {
905 if (payload.typeOf(zcu).abiSize(zcu) >= need_bytes) {
906906 cur_val = payload;
907907 } else {
908908 break;
src/Sema/type_resolution.zig created+993
......@@ -0,0 +1,993 @@
1const std = @import("std");
2const assert = std.debug.assert;
3const mem = std.mem;
4
5const Sema = @import("../Sema.zig");
6const Block = Sema.Block;
7const Type = @import("../Type.zig");
8const Value = @import("../Value.zig");
9const Zcu = @import("../Zcu.zig");
10const CompileError = Zcu.CompileError;
11const SemaError = Zcu.SemaError;
12const LazySrcLoc = Zcu.LazySrcLoc;
13const InternPool = @import("../InternPool.zig");
14const Alignment = InternPool.Alignment;
15const arith = @import("arith.zig");
16
17/// Ensures that `ty` has known layout, including alignment, size, and (where relevant) field offsets.
18/// `ty` may be any type; its layout is resolved *recursively* if necessary.
19/// Adds incremental dependencies tracking any required type resolution.
20/// MLUGG TODO: to make the langspec non-stupid, we need to call this from WAY fewer places (the conditions need to be less specific).
21/// e.g. I think creating the type `fn (A, B) C` should force layout resolution of `A`,`B`,`C`, which will simplify some `analyzeCall` logic.
22/// wait i just realised that's probably a terrible idea, fns are a common cause of dep loops rn... so maybe not lol idk...
23/// perhaps "layout resolution" for a function should resolve layout of ret ty and stuff, idk. justification: the "layout" of a function is whether
24/// fnHasRuntimeBits, which depends whether the ret ty is comptime-only, i.e. the ret ty layout
25/// MLUGG TODO: to be clear, i should audit EVERY use of this before PRing
26pub fn ensureLayoutResolved(sema: *Sema, ty: Type) SemaError!void {
27 const pt = sema.pt;
28 const zcu = pt.zcu;
29 const ip = &zcu.intern_pool;
30 switch (ip.indexToKey(ty.toIntern())) {
31 .int_type,
32 .ptr_type,
33 .anyframe_type,
34 .simple_type,
35 .opaque_type,
36 .enum_type,
37 .error_set_type,
38 .inferred_error_set_type,
39 => {},
40
41 .func_type => |func_type| {
42 for (func_type.param_types.get(ip)) |param_ty| {
43 try ensureLayoutResolved(sema, .fromInterned(param_ty));
44 }
45 try ensureLayoutResolved(sema, .fromInterned(func_type.return_type));
46 },
47
48 .array_type => |arr| return ensureLayoutResolved(sema, .fromInterned(arr.child)),
49 .vector_type => |vec| return ensureLayoutResolved(sema, .fromInterned(vec.child)),
50 .opt_type => |child| return ensureLayoutResolved(sema, .fromInterned(child)),
51 .error_union_type => |eu| return ensureLayoutResolved(sema, .fromInterned(eu.payload_type)),
52 .tuple_type => |tuple| for (tuple.types.get(ip)) |field_ty| {
53 try ensureLayoutResolved(sema, .fromInterned(field_ty));
54 },
55 .struct_type, .union_type => {
56 try sema.declareDependency(.{ .type_layout = ty.toIntern() });
57 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) {
58 // TODO: better error message
59 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(
60 ty.srcLoc(zcu),
61 "{s} '{f}' depends on itself",
62 .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) },
63 ));
64 }
65 try pt.ensureTypeLayoutUpToDate(ty);
66 },
67
68 // values, not types
69 .undef,
70 .simple_value,
71 .variable,
72 .@"extern",
73 .func,
74 .int,
75 .err,
76 .error_union,
77 .enum_literal,
78 .enum_tag,
79 .empty_enum_value,
80 .float,
81 .ptr,
82 .slice,
83 .opt,
84 .aggregate,
85 .un,
86 // memoization, not types
87 .memoized_call,
88 => unreachable,
89 }
90}
91
92/// Asserts that `ty` is either a `struct` type, or an `enum` type.
93/// If `ty` is a struct, ensures that fields' default values are resolved.
94/// If `ty` is an enum, ensures that fields' integer tag valus are resolved.
95/// Adds incremental dependencies tracking the required type resolution.
96pub fn ensureFieldInitsResolved(sema: *Sema, ty: Type) SemaError!void {
97 const pt = sema.pt;
98 const zcu = pt.zcu;
99 const ip = &zcu.intern_pool;
100 switch (ip.indexToKey(ty.toIntern())) {
101 .struct_type, .enum_type => {},
102 else => unreachable, // assertion failure
103 }
104
105 try sema.declareDependency(.{ .type_inits = ty.toIntern() });
106 if (zcu.analysis_in_progress.contains(.wrap(.{ .type_inits = ty.toIntern() }))) {
107 // TODO: better error message
108 return sema.failWithOwnedErrorMsg(null, try sema.errMsg(
109 ty.srcLoc(zcu),
110 "{s} '{f}' depends on itself",
111 .{ @tagName(ty.zigTypeTag(zcu)), ty.fmt(pt) },
112 ));
113 }
114 try pt.ensureTypeInitsUpToDate(ty);
115}
116/// Asserts that `struct_ty` is a non-packed non-tuple struct, and that `sema.owner` is that type.
117/// This function *does* register the `src_hash` dependency on the struct.
118pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
119 const pt = sema.pt;
120 const zcu = pt.zcu;
121 const comp = zcu.comp;
122 const gpa = comp.gpa;
123 const ip = &zcu.intern_pool;
124
125 assert(sema.owner.unwrap().type_layout == struct_ty.toIntern());
126
127 const struct_obj = ip.loadStructType(struct_ty.toIntern());
128 const zir_index = struct_obj.zir_index.resolve(ip).?;
129
130 assert(struct_obj.layout != .@"packed");
131
132 try sema.declareDependency(.{ .src_hash = struct_obj.zir_index });
133
134 var block: Block = .{
135 .parent = null,
136 .sema = sema,
137 .namespace = struct_obj.namespace,
138 .instructions = .{},
139 .inlining = null,
140 .comptime_reason = undefined, // always set before using `block`
141 .src_base_inst = struct_obj.zir_index,
142 .type_name_ctx = struct_obj.name,
143 };
144 defer assert(block.instructions.items.len == 0);
145
146 const zir_struct = sema.code.getStructDecl(zir_index);
147 var field_it = zir_struct.iterateFields();
148 while (field_it.next()) |zir_field| {
149 const field_ty_src: LazySrcLoc = .{
150 .base_node_inst = struct_obj.zir_index,
151 .offset = .{ .container_field_type = zir_field.idx },
152 };
153 const field_align_src: LazySrcLoc = .{
154 .base_node_inst = struct_obj.zir_index,
155 .offset = .{ .container_field_align = zir_field.idx },
156 };
157
158 const field_ty: Type = field_ty: {
159 block.comptime_reason = .{ .reason = .{
160 .src = field_ty_src,
161 .r = .{ .simple = .struct_field_types },
162 } };
163 const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
164 break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref);
165 };
166 assert(!field_ty.isGenericPoison());
167
168 try sema.ensureLayoutResolved(field_ty);
169
170 const explicit_field_align: Alignment = a: {
171 block.comptime_reason = .{ .reason = .{
172 .src = field_align_src,
173 .r = .{ .simple = .struct_field_attrs },
174 } };
175 const align_body = zir_field.align_body orelse break :a .none;
176 const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index);
177 break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref);
178 };
179
180 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
181 return sema.failWithOwnedErrorMsg(&block, msg: {
182 const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)});
183 errdefer msg.destroy(gpa);
184 try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
185 try sema.addDeclaredHereNote(msg, field_ty);
186 break :msg msg;
187 });
188 }
189 if (struct_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .struct_field)) {
190 return sema.failWithOwnedErrorMsg(&block, msg: {
191 const msg = try sema.errMsg(field_ty_src, "extern structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
192 errdefer msg.destroy(gpa);
193 try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .struct_field);
194 try sema.addDeclaredHereNote(msg, field_ty);
195 break :msg msg;
196 });
197 }
198
199 struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
200 if (struct_obj.field_aligns.len != 0) {
201 struct_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align;
202 } else {
203 assert(explicit_field_align == .none);
204 }
205 }
206
207 try finishStructLayout(sema, &block, struct_ty.srcLoc(zcu), struct_ty.toIntern(), &struct_obj);
208}
209
210/// Called after populating field types and alignments; populates field offsets, runtime order, and
211/// overall struct layout information (size, alignment, comptime-only state, etc).
212pub fn finishStructLayout(
213 sema: *Sema,
214 /// Only used to report compile errors.
215 block: *Block,
216 struct_src: LazySrcLoc,
217 struct_ty: InternPool.Index,
218 struct_obj: *const InternPool.LoadedStructType,
219) SemaError!void {
220 const pt = sema.pt;
221 const zcu = pt.zcu;
222 const comp = zcu.comp;
223 const io = comp.io;
224 const ip = &zcu.intern_pool;
225 var comptime_only = false;
226 var one_possible_value = true;
227 var struct_align: Alignment = .@"1";
228 // Unlike `struct_obj.field_aligns`, these are not `.none`.
229 const resolved_field_aligns = try sema.arena.alloc(Alignment, struct_obj.field_names.len);
230 for (resolved_field_aligns, 0..) |*align_out, field_idx| {
231 const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]);
232 const field_align: Alignment = a: {
233 if (struct_obj.field_aligns.len != 0) {
234 const a = struct_obj.field_aligns.get(ip)[field_idx];
235 if (a != .none) break :a a;
236 }
237 break :a field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu);
238 };
239 if (!struct_obj.field_is_comptime_bits.get(ip, field_idx)) {
240 // Non-`comptime` fields contribute to the struct's layout.
241 struct_align = struct_align.maxStrict(field_align);
242 if (field_ty.comptimeOnly(zcu)) comptime_only = true;
243 if (try field_ty.onePossibleValue(pt) == null) one_possible_value = false;
244 if (struct_obj.layout == .auto) {
245 struct_obj.field_runtime_order.get(ip)[field_idx] = @enumFromInt(field_idx);
246 }
247 } else if (struct_obj.layout == .auto) {
248 struct_obj.field_runtime_order.get(ip)[field_idx] = .omitted; // comptime fields are not in the runtime order
249 }
250 align_out.* = field_align;
251 }
252 if (struct_obj.layout == .auto) {
253 const runtime_order = struct_obj.field_runtime_order.get(ip);
254 // This logic does not reorder fields; it only moves the omitted ones to the end so that logic
255 // elsewhere does not need to special-case. TODO: support field reordering in all the backends!
256 if (!zcu.backendSupportsFeature(.field_reordering)) {
257 var i: usize = 0;
258 var off: usize = 0;
259 while (i + off < runtime_order.len) {
260 if (runtime_order[i + off] == .omitted) {
261 off += 1;
262 } else {
263 runtime_order[i] = runtime_order[i + off];
264 i += 1;
265 }
266 }
267 } else {
268 // Sort by descending alignment to minimize padding.
269 const RuntimeOrder = InternPool.LoadedStructType.RuntimeOrder;
270 const AlignSortCtx = struct {
271 aligns: []const Alignment,
272 fn lessThan(ctx: @This(), a: RuntimeOrder, b: RuntimeOrder) bool {
273 assert(a != .unresolved);
274 assert(b != .unresolved);
275 if (a == .omitted) return false;
276 if (b == .omitted) return true;
277 const a_align = ctx.aligns[@intFromEnum(a)];
278 const b_align = ctx.aligns[@intFromEnum(b)];
279 return a_align.compare(.gt, b_align);
280 }
281 };
282 mem.sortUnstable(
283 RuntimeOrder,
284 runtime_order,
285 @as(AlignSortCtx, .{ .aligns = resolved_field_aligns }),
286 AlignSortCtx.lessThan,
287 );
288 }
289 }
290
291 var runtime_order_it = struct_obj.iterateRuntimeOrder(ip);
292 var cur_offset: u64 = 0;
293 while (runtime_order_it.next()) |field_idx| {
294 const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[field_idx]);
295 const offset = resolved_field_aligns[field_idx].forward(cur_offset);
296 struct_obj.field_offsets.get(ip)[field_idx] = @truncate(offset); // truncate because the overflow is handled below
297 cur_offset = offset + field_ty.abiSize(zcu);
298 }
299 const struct_size = std.math.cast(u32, struct_align.forward(cur_offset)) orelse return sema.fail(
300 block,
301 struct_src,
302 "struct layout requires size {d}, this compiler implementation supports up to {d}",
303 .{ struct_align.forward(cur_offset), std.math.maxInt(u32) },
304 );
305 ip.resolveStructLayout(
306 io,
307 struct_ty,
308 struct_size,
309 struct_align,
310 false, // MLUGG TODO XXX NPV
311 one_possible_value,
312 comptime_only,
313 );
314}
315
316/// Asserts that `struct_ty` is a packed struct, and that `sema.owner` is that type.
317/// This function *does* register the `src_hash` dependency on the struct.
318pub fn resolvePackedStructLayout(sema: *Sema, struct_ty: Type) CompileError!void {
319 const pt = sema.pt;
320 const zcu = pt.zcu;
321 const comp = zcu.comp;
322 const gpa = comp.gpa;
323 const ip = &zcu.intern_pool;
324
325 assert(sema.owner.unwrap().type_layout == struct_ty.toIntern());
326
327 const struct_obj = ip.loadStructType(struct_ty.toIntern());
328 const zir_index = struct_obj.zir_index.resolve(ip).?;
329
330 assert(struct_obj.layout == .@"packed");
331
332 try sema.declareDependency(.{ .src_hash = struct_obj.zir_index });
333
334 var block: Block = .{
335 .parent = null,
336 .sema = sema,
337 .namespace = struct_obj.namespace,
338 .instructions = .{},
339 .inlining = null,
340 .comptime_reason = undefined, // always set before using `block`
341 .src_base_inst = struct_obj.zir_index,
342 .type_name_ctx = struct_obj.name,
343 };
344 defer assert(block.instructions.items.len == 0);
345
346 var field_bits: u64 = 0;
347 const zir_struct = sema.code.getStructDecl(zir_index);
348 var field_it = zir_struct.iterateFields();
349 while (field_it.next()) |zir_field| {
350 const field_ty_src: LazySrcLoc = .{
351 .base_node_inst = struct_obj.zir_index,
352 .offset = .{ .container_field_type = zir_field.idx },
353 };
354 const field_ty: Type = field_ty: {
355 block.comptime_reason = .{ .reason = .{
356 .src = field_ty_src,
357 .r = .{ .simple = .struct_field_types },
358 } };
359 const type_ref = try sema.resolveInlineBody(&block, zir_field.type_body, zir_index);
360 break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref);
361 };
362 assert(!field_ty.isGenericPoison());
363 struct_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
364
365 try sema.ensureLayoutResolved(field_ty);
366
367 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
368 return sema.failWithOwnedErrorMsg(&block, msg: {
369 const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in struct", .{field_ty.fmt(pt)});
370 errdefer msg.destroy(gpa);
371 try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
372 try sema.addDeclaredHereNote(msg, field_ty);
373 break :msg msg;
374 });
375 }
376 if (!field_ty.packable(zcu)) {
377 return sema.failWithOwnedErrorMsg(&block, msg: {
378 const msg = try sema.errMsg(field_ty_src, "packed structs cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
379 errdefer msg.destroy(gpa);
380 try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty);
381 try sema.addDeclaredHereNote(msg, field_ty);
382 break :msg msg;
383 });
384 }
385 assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only
386 field_bits += field_ty.bitSize(zcu);
387 }
388
389 try resolvePackedStructBackingInt(sema, &block, field_bits, struct_ty, &struct_obj);
390}
391
392pub fn resolvePackedStructBackingInt(
393 sema: *Sema,
394 block: *Block,
395 field_bits: u64,
396 struct_ty: Type,
397 struct_obj: *const InternPool.LoadedStructType,
398) SemaError!void {
399 const pt = sema.pt;
400 const zcu = pt.zcu;
401 const comp = zcu.comp;
402 const gpa = comp.gpa;
403 const io = comp.io;
404 const ip = &zcu.intern_pool;
405
406 switch (struct_obj.packed_backing_mode) {
407 .explicit => {
408 // We only need to validate the type.
409 const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type);
410 assert(backing_ty.zigTypeTag(zcu) == .int);
411 if (field_bits != backing_ty.intInfo(zcu).bits) return sema.failWithOwnedErrorMsg(block, msg: {
412 const src = struct_ty.srcLoc(zcu);
413 const msg = try sema.errMsg(src, "backing integer bit width does not match total bit width of fields", .{});
414 errdefer msg.destroy(gpa);
415 try sema.errNote(src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_ty.fmt(pt), backing_ty.bitSize(zcu) });
416 try sema.errNote(src, msg, "struct fields have total bit width '{d}'", .{field_bits});
417 break :msg msg;
418 });
419 },
420 .auto => {
421 // We need to generate the inferred tag.
422 const want_bits = std.math.cast(u16, field_bits) orelse return sema.fail(
423 block,
424 struct_ty.srcLoc(zcu),
425 "packed struct bit width '{d}' exceeds maximum bit width of 65535",
426 .{field_bits},
427 );
428 const backing_int = try pt.intType(.unsigned, want_bits);
429 ip.resolvePackedStructBackingInt(io, struct_ty.toIntern(), backing_int.toIntern());
430 },
431 }
432}
433
434/// Asserts that `struct_ty` is a non-tuple struct, and that `sema.owner` is that type.
435/// This function *does* register the `src_hash` dependency on the struct.
436pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void {
437 const pt = sema.pt;
438 const zcu = pt.zcu;
439 const comp = zcu.comp;
440 const gpa = comp.gpa;
441 const ip = &zcu.intern_pool;
442
443 assert(sema.owner.unwrap().type_inits == struct_ty.toIntern());
444
445 try sema.ensureLayoutResolved(struct_ty);
446
447 const struct_obj = ip.loadStructType(struct_ty.toIntern());
448 const zir_index = struct_obj.zir_index.resolve(ip).?;
449
450 try sema.declareDependency(.{ .src_hash = struct_obj.zir_index });
451
452 if (struct_obj.field_defaults.len == 0) {
453 // The struct has no default field values, so the slice has been omitted.
454 return;
455 }
456
457 const field_types = struct_obj.field_types.get(ip);
458
459 var block: Block = .{
460 .parent = null,
461 .sema = sema,
462 .namespace = struct_obj.namespace,
463 .instructions = .{},
464 .inlining = null,
465 .comptime_reason = undefined, // always set before using `block`
466 .src_base_inst = struct_obj.zir_index,
467 .type_name_ctx = struct_obj.name,
468 };
469 defer assert(block.instructions.items.len == 0);
470
471 // We'll need to map the struct decl instruction to provide result types
472 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
473
474 const zir_struct = sema.code.getStructDecl(zir_index);
475 var field_it = zir_struct.iterateFields();
476 while (field_it.next()) |zir_field| {
477 const default_val_src: LazySrcLoc = .{
478 .base_node_inst = struct_obj.zir_index,
479 .offset = .{ .container_field_value = zir_field.idx },
480 };
481 block.comptime_reason = .{ .reason = .{
482 .src = default_val_src,
483 .r = .{ .simple = .struct_field_default_value },
484 } };
485 const default_body = zir_field.default_body orelse {
486 struct_obj.field_defaults.get(ip)[zir_field.idx] = .none;
487 continue;
488 };
489 const field_ty: Type = .fromInterned(field_types[zir_field.idx]);
490 const uncoerced = ref: {
491 // Provide the result type
492 sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(field_ty.toIntern()));
493 defer assert(sema.inst_map.remove(zir_index));
494 break :ref try sema.resolveInlineBody(&block, default_body, zir_index);
495 };
496 const coerced = try sema.coerce(&block, field_ty, uncoerced, default_val_src);
497 const default_val = try sema.resolveConstValue(&block, default_val_src, coerced, null);
498 if (default_val.canMutateComptimeVarState(zcu)) {
499 const field_name = struct_obj.field_names.get(ip)[zir_field.idx];
500 return sema.failWithContainsReferenceToComptimeVar(&block, default_val_src, field_name, "field default value", default_val);
501 }
502 struct_obj.field_defaults.get(ip)[zir_field.idx] = default_val.toIntern();
503 }
504}
505
506/// This logic must be kept in sync with `Type.getUnionLayout`.
507pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
508 const pt = sema.pt;
509 const zcu = pt.zcu;
510 const comp = zcu.comp;
511 const gpa = comp.gpa;
512 const ip = &zcu.intern_pool;
513
514 assert(sema.owner.unwrap().type_layout == union_ty.toIntern());
515
516 const union_obj = ip.loadUnionType(union_ty.toIntern());
517 const zir_index = union_obj.zir_index.resolve(ip).?;
518
519 assert(union_obj.layout != .@"packed");
520
521 try sema.declareDependency(.{ .src_hash = union_obj.zir_index });
522
523 var block: Block = .{
524 .parent = null,
525 .sema = sema,
526 .namespace = union_obj.namespace,
527 .instructions = .{},
528 .inlining = null,
529 .comptime_reason = undefined, // always set before using `block`
530 .src_base_inst = union_obj.zir_index,
531 .type_name_ctx = union_obj.name,
532 };
533 defer assert(block.instructions.items.len == 0);
534
535 const zir_union = sema.code.getUnionDecl(zir_index);
536 var field_it = zir_union.iterateFields();
537 while (field_it.next()) |zir_field| {
538 const field_ty_src: LazySrcLoc = .{
539 .base_node_inst = union_obj.zir_index,
540 .offset = .{ .container_field_type = zir_field.idx },
541 };
542 const field_align_src: LazySrcLoc = .{
543 .base_node_inst = union_obj.zir_index,
544 .offset = .{ .container_field_align = zir_field.idx },
545 };
546
547 const field_ty: Type = field_ty: {
548 block.comptime_reason = .{ .reason = .{
549 .src = field_ty_src,
550 .r = .{ .simple = .union_field_types },
551 } };
552 const type_body = zir_field.type_body orelse break :field_ty .void;
553 const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index);
554 break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref);
555 };
556 assert(!field_ty.isGenericPoison());
557 union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
558
559 try sema.ensureLayoutResolved(field_ty);
560
561 const explicit_field_align: Alignment = a: {
562 block.comptime_reason = .{ .reason = .{
563 .src = field_align_src,
564 .r = .{ .simple = .union_field_attrs },
565 } };
566 const align_body = zir_field.align_body orelse break :a .none;
567 const align_ref = try sema.resolveInlineBody(&block, align_body, zir_index);
568 break :a try sema.analyzeAsAlign(&block, field_align_src, align_ref);
569 };
570
571 if (union_obj.field_aligns.len != 0) {
572 union_obj.field_aligns.get(ip)[zir_field.idx] = explicit_field_align;
573 } else {
574 assert(explicit_field_align == .none);
575 }
576
577 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
578 return sema.failWithOwnedErrorMsg(&block, msg: {
579 const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)});
580 errdefer msg.destroy(gpa);
581 try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
582 try sema.addDeclaredHereNote(msg, field_ty);
583 break :msg msg;
584 });
585 }
586 if (union_obj.layout == .@"extern" and !try sema.validateExternType(field_ty, .union_field)) {
587 return sema.failWithOwnedErrorMsg(&block, msg: {
588 const msg = try sema.errMsg(field_ty_src, "extern unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
589 errdefer msg.destroy(gpa);
590 try sema.explainWhyTypeIsNotExtern(msg, field_ty_src, field_ty, .union_field);
591 try sema.addDeclaredHereNote(msg, field_ty);
592 break :msg msg;
593 });
594 }
595 }
596
597 try finishUnionLayout(
598 sema,
599 &block,
600 union_ty.srcLoc(zcu),
601 union_ty.toIntern(),
602 &union_obj,
603 .fromInterned(union_obj.enum_tag_type),
604 );
605}
606
607/// Called after populating field types and alignments; populates overall union layout
608/// information (size, alignment, comptime-only state, etc).
609pub fn finishUnionLayout(
610 sema: *Sema,
611 /// Only used to report compile errors.
612 block: *Block,
613 union_src: LazySrcLoc,
614 union_ty: InternPool.Index,
615 union_obj: *const InternPool.LoadedUnionType,
616 enum_tag_ty: Type,
617) SemaError!void {
618 const pt = sema.pt;
619 const zcu = pt.zcu;
620 const comp = zcu.comp;
621 const io = comp.io;
622 const ip = &zcu.intern_pool;
623
624 var payload_align: Alignment = .@"1";
625 var payload_size: u64 = 0;
626 var comptime_only = false;
627 var possible_values: enum { none, one, many } = .none;
628 for (0..union_obj.field_types.len) |field_idx| {
629 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_idx]);
630 const field_align: Alignment = a: {
631 if (union_obj.field_aligns.len != 0) {
632 const a = union_obj.field_aligns.get(ip)[field_idx];
633 if (a != .none) break :a a;
634 }
635 break :a field_ty.abiAlignment(zcu);
636 };
637 payload_align = payload_align.maxStrict(field_align);
638 payload_size = @max(payload_size, field_ty.abiSize(zcu));
639 if (field_ty.comptimeOnly(zcu)) comptime_only = true;
640 if (!field_ty.isNoReturn(zcu)) {
641 if (try field_ty.onePossibleValue(pt) != null) {
642 possible_values = .many; // this field alone has many possible values
643 } else switch (possible_values) {
644 .none => possible_values = .one, // there were none, now there is this field's OPV
645 .one => possible_values = .many, // there was one, now there are two
646 .many => {},
647 }
648 }
649 }
650
651 const size: u64, const padding: u64, const alignment: Alignment = layout: {
652 if (union_obj.runtime_tag == .none) {
653 break :layout .{ payload_align.forward(payload_size), 0, payload_align };
654 }
655 const tag_align = enum_tag_ty.abiAlignment(zcu);
656 const tag_size = enum_tag_ty.abiSize(zcu);
657 // The layout will either be (tag, payload, padding) or (payload, tag, padding) depending on
658 // which has larger alignment. So the overall size is just the tag and payload sizes, added,
659 // and padded to the larger alignment.
660 const alignment = tag_align.maxStrict(payload_align);
661 const unpadded_size = tag_size + payload_size;
662 const size = alignment.forward(unpadded_size);
663 break :layout .{ size, size - unpadded_size, alignment };
664 };
665
666 const casted_size = std.math.cast(u32, size) orelse return sema.fail(
667 block,
668 union_src,
669 "union layout requires size {d}, this compiler implementation supports up to {d}",
670 .{ size, std.math.maxInt(u32) },
671 );
672 ip.resolveUnionLayout(
673 io,
674 union_ty,
675 casted_size,
676 @intCast(padding), // okay because padding is no greater than size
677 alignment,
678 possible_values == .none, // MLUGG TODO: make sure queries use `LoadedUnionType.has_no_possible_value`!
679 possible_values == .one,
680 comptime_only,
681 );
682}
683
684pub fn resolvePackedUnionLayout(sema: *Sema, union_ty: Type) CompileError!void {
685 const pt = sema.pt;
686 const zcu = pt.zcu;
687 const comp = zcu.comp;
688 const gpa = comp.gpa;
689 const ip = &zcu.intern_pool;
690
691 assert(sema.owner.unwrap().type_layout == union_ty.toIntern());
692
693 const union_obj = ip.loadUnionType(union_ty.toIntern());
694 const zir_index = union_obj.zir_index.resolve(ip).?;
695
696 assert(union_obj.layout == .@"packed");
697
698 try sema.declareDependency(.{ .src_hash = union_obj.zir_index });
699
700 var block: Block = .{
701 .parent = null,
702 .sema = sema,
703 .namespace = union_obj.namespace,
704 .instructions = .{},
705 .inlining = null,
706 .comptime_reason = undefined, // always set before using `block`
707 .src_base_inst = union_obj.zir_index,
708 .type_name_ctx = union_obj.name,
709 };
710 defer assert(block.instructions.items.len == 0);
711
712 const zir_union = sema.code.getUnionDecl(zir_index);
713 var field_it = zir_union.iterateFields();
714 while (field_it.next()) |zir_field| {
715 const field_ty_src: LazySrcLoc = .{
716 .base_node_inst = union_obj.zir_index,
717 .offset = .{ .container_field_type = zir_field.idx },
718 };
719 const field_ty: Type = field_ty: {
720 block.comptime_reason = .{ .reason = .{
721 .src = field_ty_src,
722 .r = .{ .simple = .union_field_types },
723 } };
724 // MLUGG TODO: i think this should probably be a compile error? (if so, it's an astgen one, right?)
725 const type_body = zir_field.type_body orelse break :field_ty .void;
726 const type_ref = try sema.resolveInlineBody(&block, type_body, zir_index);
727 break :field_ty try sema.analyzeAsType(&block, field_ty_src, type_ref);
728 };
729 assert(!field_ty.isGenericPoison());
730 union_obj.field_types.get(ip)[zir_field.idx] = field_ty.toIntern();
731
732 assert(zir_field.align_body == null); // packed union fields cannot be aligned
733 assert(zir_field.value_body == null); // packed union fields cannot have tag values
734
735 try sema.ensureLayoutResolved(field_ty);
736
737 if (field_ty.zigTypeTag(zcu) == .@"opaque") {
738 return sema.failWithOwnedErrorMsg(&block, msg: {
739 const msg = try sema.errMsg(field_ty_src, "cannot directly embed opaque type '{f}' in union", .{field_ty.fmt(pt)});
740 errdefer msg.destroy(gpa);
741 try sema.errNote(field_ty_src, msg, "opaque types have unknown size", .{});
742 try sema.addDeclaredHereNote(msg, field_ty);
743 break :msg msg;
744 });
745 }
746 if (!field_ty.packable(zcu)) {
747 return sema.failWithOwnedErrorMsg(&block, msg: {
748 const msg = try sema.errMsg(field_ty_src, "packed unions cannot contain fields of type '{f}'", .{field_ty.fmt(pt)});
749 errdefer msg.destroy(gpa);
750 try sema.explainWhyTypeIsNotPackable(msg, field_ty_src, field_ty);
751 try sema.addDeclaredHereNote(msg, field_ty);
752 break :msg msg;
753 });
754 }
755 assert(!field_ty.comptimeOnly(zcu)); // packable types are not comptime-only
756 }
757
758 try resolvePackedUnionBackingInt(sema, &block, union_ty, &union_obj, false);
759}
760
761/// MLUGG TODO doc comment; asserts all fields are resolved or whatever
762pub fn resolvePackedUnionBackingInt(
763 sema: *Sema,
764 block: *Block,
765 union_ty: Type,
766 union_obj: *const InternPool.LoadedUnionType,
767 is_reified: bool,
768) SemaError!void {
769 const pt = sema.pt;
770 const zcu = pt.zcu;
771 const comp = zcu.comp;
772 const gpa = comp.gpa;
773 const io = comp.io;
774 const ip = &zcu.intern_pool;
775 switch (union_obj.packed_backing_mode) {
776 .explicit => {
777 const backing_int_type: Type = .fromInterned(union_obj.packed_backing_int_type);
778 const backing_int_bits = backing_int_type.intInfo(zcu).bits;
779 for (union_obj.field_types.get(ip), 0..) |field_type_ip, field_idx| {
780 const field_type: Type = .fromInterned(field_type_ip);
781 const field_bits = field_type.bitSize(zcu);
782 if (field_bits != backing_int_bits) return sema.failWithOwnedErrorMsg(block, msg: {
783 const field_ty_src: LazySrcLoc = .{
784 .base_node_inst = union_obj.zir_index,
785 .offset = if (is_reified)
786 .nodeOffset(.zero)
787 else
788 .{ .container_field_type = @intCast(field_idx) },
789 };
790 const msg = try sema.errMsg(field_ty_src, "field bit width does not match backing integer", .{});
791 errdefer msg.destroy(gpa);
792 try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });
793 try sema.errNote(field_ty_src, msg, "backing integer '{f}' has bit width '{d}'", .{ backing_int_type.fmt(pt), backing_int_bits });
794 try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});
795 break :msg msg;
796 });
797 }
798 },
799 .auto => switch (union_obj.field_types.len) {
800 0 => ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), .u0_type),
801 else => {
802 const field_types = union_obj.field_types.get(ip);
803 const first_field_type: Type = .fromInterned(field_types[0]);
804 const first_field_bits = first_field_type.bitSize(zcu);
805 for (field_types[1..], 1..) |field_type_ip, field_idx| {
806 const field_type: Type = .fromInterned(field_type_ip);
807 const field_bits = field_type.bitSize(zcu);
808 if (field_bits != first_field_bits) return sema.failWithOwnedErrorMsg(block, msg: {
809 const first_field_ty_src: LazySrcLoc = .{
810 .base_node_inst = union_obj.zir_index,
811 .offset = if (is_reified)
812 .nodeOffset(.zero)
813 else
814 .{ .container_field_type = 0 },
815 };
816 const field_ty_src: LazySrcLoc = .{
817 .base_node_inst = union_obj.zir_index,
818 .offset = if (is_reified)
819 .nodeOffset(.zero)
820 else
821 .{ .container_field_type = @intCast(field_idx) },
822 };
823 const msg = try sema.errMsg(field_ty_src, "field bit width does not match earlier field", .{});
824 errdefer msg.destroy(gpa);
825 try sema.errNote(field_ty_src, msg, "field type '{f}' has bit width '{d}'", .{ field_type.fmt(pt), field_bits });
826 try sema.errNote(first_field_ty_src, msg, "other field type '{f}' has bit width '{d}'", .{ first_field_type.fmt(pt), first_field_bits });
827 try sema.errNote(field_ty_src, msg, "all fields in a packed union must have the same bit width", .{});
828 break :msg msg;
829 });
830 }
831 const backing_int_bits = std.math.cast(u16, first_field_bits) orelse return sema.fail(
832 block,
833 block.nodeOffset(.zero),
834 "packed union bit width '{d}' exceeds maximum bit width of 65535",
835 .{first_field_bits},
836 );
837 const backing_int_type = try pt.intType(.unsigned, backing_int_bits);
838 ip.resolvePackedUnionBackingInt(io, union_ty.toIntern(), backing_int_type.toIntern());
839 },
840 },
841 }
842}
843
844/// Asserts that `enum_ty` is an enum and that `sema.owner` is that type.
845/// This function *does* register the `src_hash` dependency on the enum.
846pub fn resolveEnumValues(sema: *Sema, enum_ty: Type) CompileError!void {
847 const pt = sema.pt;
848 const zcu = pt.zcu;
849 const comp = zcu.comp;
850 const gpa = comp.gpa;
851 const ip = &zcu.intern_pool;
852
853 assert(sema.owner.unwrap().type_inits == enum_ty.toIntern());
854
855 const enum_obj = ip.loadEnumType(enum_ty.toIntern());
856
857 // We'll populate this map.
858 const field_value_map = enum_obj.field_value_map.unwrap() orelse {
859 // The enum has an automatically generated tag and is auto-numbered. We know that we have
860 // generated a suitably large type in `analyzeEnumDecl`, so we have no work to do.
861 return;
862 };
863
864 const maybe_parent_union_obj: ?InternPool.LoadedUnionType = un: {
865 if (enum_obj.owner_union == .none) break :un null;
866 break :un ip.loadUnionType(enum_obj.owner_union);
867 };
868 const tracked_inst = enum_obj.zir_index.unwrap() orelse maybe_parent_union_obj.?.zir_index;
869 const zir_index = tracked_inst.resolve(ip).?;
870
871 try sema.declareDependency(.{ .src_hash = tracked_inst });
872
873 var block: Block = .{
874 .parent = null,
875 .sema = sema,
876 .namespace = enum_obj.namespace,
877 .instructions = .{},
878 .inlining = null,
879 .comptime_reason = undefined, // always set before using `block`
880 .src_base_inst = tracked_inst,
881 .type_name_ctx = enum_obj.name,
882 };
883 defer assert(block.instructions.items.len == 0);
884
885 const int_tag_ty: Type = .fromInterned(enum_obj.int_tag_type);
886
887 // Map the enum (or union) decl instruction to provide the tag type as the result type
888 try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index});
889 sema.inst_map.putAssumeCapacity(zir_index, .fromIntern(int_tag_ty.toIntern()));
890 defer assert(sema.inst_map.remove(zir_index));
891
892 // First, populate any explicitly provided values. This is the part that actually depends on
893 // the ZIR, and hence depends on whether this is a declared or generated enum. If any explicit
894 // value is invalid, we'll emit an error here.
895 if (maybe_parent_union_obj) |union_obj| {
896 const zir_union = sema.code.getUnionDecl(zir_index);
897 var field_it = zir_union.iterateFields();
898 while (field_it.next()) |zir_field| {
899 const field_val_src: LazySrcLoc = .{
900 .base_node_inst = union_obj.zir_index,
901 .offset = .{ .container_field_value = zir_field.idx },
902 };
903 block.comptime_reason = .{ .reason = .{
904 .src = field_val_src,
905 .r = .{ .simple = .enum_field_values },
906 } };
907 const value_body = zir_field.value_body orelse {
908 enum_obj.field_values.get(ip)[zir_field.idx] = .none;
909 continue;
910 };
911 const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index);
912 const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src);
913 const val = try sema.resolveConstValue(&block, field_val_src, coerced, null);
914 enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern();
915 }
916 } else {
917 const zir_enum = sema.code.getEnumDecl(zir_index);
918 var field_it = zir_enum.iterateFields();
919 while (field_it.next()) |zir_field| {
920 const field_val_src: LazySrcLoc = .{
921 .base_node_inst = enum_obj.zir_index.unwrap().?,
922 .offset = .{ .container_field_value = zir_field.idx },
923 };
924 block.comptime_reason = .{ .reason = .{
925 .src = field_val_src,
926 .r = .{ .simple = .enum_field_values },
927 } };
928 const value_body = zir_field.value_body orelse {
929 enum_obj.field_values.get(ip)[zir_field.idx] = .none;
930 continue;
931 };
932 const uncoerced = try sema.resolveInlineBody(&block, value_body, zir_index);
933 const coerced = try sema.coerce(&block, int_tag_ty, uncoerced, field_val_src);
934 const val = try sema.resolveConstDefinedValue(&block, field_val_src, coerced, null);
935 enum_obj.field_values.get(ip)[zir_field.idx] = val.toIntern();
936 }
937 }
938
939 // Explicit values are set. Now we'll go through the whole array and figure out the final
940 // field values. This is also where we'll detect duplicates.
941
942 for (0..enum_obj.field_names.len) |field_idx| {
943 const field_val_src: LazySrcLoc = .{
944 .base_node_inst = tracked_inst,
945 .offset = .{ .container_field_value = @intCast(field_idx) },
946 };
947 // If the field value was not specified, compute the implicit value.
948 const field_val = val: {
949 const explicit_val = enum_obj.field_values.get(ip)[field_idx];
950 if (explicit_val != .none) break :val explicit_val;
951 if (field_idx == 0) {
952 // Implicit value is 0, which is valid for every integer type.
953 const val = (try pt.intValue(int_tag_ty, 0)).toIntern();
954 enum_obj.field_values.get(ip)[field_idx] = val;
955 break :val val;
956 }
957 // Implicit non-initial value: take the previous field value and add one.
958 const prev_field_val: Value = .fromInterned(enum_obj.field_values.get(ip)[field_idx - 1]);
959 const result = try arith.incrementDefinedInt(sema, int_tag_ty, prev_field_val);
960 if (result.overflow) return sema.fail(
961 &block,
962 field_val_src,
963 "enum tag value '{f}' too large for type '{f}'",
964 .{ result.val.fmtValueSema(pt, sema), int_tag_ty.fmt(pt) },
965 );
966 const val = result.val.toIntern();
967 enum_obj.field_values.get(ip)[field_idx] = val;
968 break :val val;
969 };
970 const adapter: InternPool.Index.Adapter = .{ .indexes = enum_obj.field_values.get(ip)[0..field_idx] };
971 const gop = field_value_map.get(ip).getOrPutAssumeCapacityAdapted(field_val, adapter);
972 if (!gop.found_existing) continue;
973 const prev_field_val_src: LazySrcLoc = .{
974 .base_node_inst = tracked_inst,
975 .offset = .{ .container_field_value = @intCast(gop.index) },
976 };
977 return sema.failWithOwnedErrorMsg(&block, msg: {
978 const msg = try sema.errMsg(field_val_src, "enum tag value '{f}' already taken", .{
979 Value.fromInterned(field_val).fmtValueSema(pt, sema),
980 });
981 errdefer msg.destroy(gpa);
982 try sema.errNote(prev_field_val_src, msg, "previous occurrence here", .{});
983 break :msg msg;
984 });
985 }
986
987 if (enum_obj.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
988 const fields_len = enum_obj.field_names.len;
989 if (fields_len >= 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(zcu)) {
990 return sema.fail(&block, block.nodeOffset(.zero), "non-exhaustive enum specifies every value", .{});
991 }
992 }
993}
src/Type.zig+883-2010
......@@ -12,12 +12,10 @@ const Target = std.Target;
1212const Zcu = @import("Zcu.zig");
1313const log = std.log.scoped(.Type);
1414const target_util = @import("target.zig");
15const Sema = @import("Sema.zig");
1615const InternPool = @import("InternPool.zig");
1716const Alignment = InternPool.Alignment;
1817const Zir = std.zig.Zir;
1918const Type = @This();
20const SemaError = Zcu.SemaError;
2119
2220ip_index: InternPool.Index,
2321
......@@ -25,16 +23,6 @@ pub fn zigTypeTag(ty: Type, zcu: *const Zcu) std.builtin.TypeId {
2523 return zcu.intern_pool.zigTypeTag(ty.toIntern());
2624}
2725
28pub fn baseZigTypeTag(self: Type, mod: *Zcu) std.builtin.TypeId {
29 return switch (self.zigTypeTag(mod)) {
30 .error_union => self.errorUnionPayload(mod).baseZigTypeTag(mod),
31 .optional => {
32 return self.optionalChild(mod).baseZigTypeTag(mod);
33 },
34 else => |t| t,
35 };
36}
37
3826/// Asserts the type is resolved.
3927pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool {
4028 return switch (ty.zigTypeTag(zcu)) {
......@@ -44,7 +32,7 @@ pub fn isSelfComparable(ty: Type, zcu: *const Zcu, is_equality_cmp: bool) bool {
4432 .comptime_int,
4533 => true,
4634
47 .vector => ty.elemType2(zcu).isSelfComparable(zcu, is_equality_cmp),
35 .vector => ty.childType(zcu).isSelfComparable(zcu, is_equality_cmp),
4836
4937 .bool,
5038 .type,
......@@ -121,11 +109,7 @@ pub fn eql(a: Type, b: Type, zcu: *const Zcu) bool {
121109 return a.toIntern() == b.toIntern();
122110}
123111
124pub fn format(ty: Type, writer: *std.Io.Writer) !void {
125 _ = ty;
126 _ = writer;
127 @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
128}
112pub const format = @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
129113
130114pub const Formatter = std.fmt.Alt(Format, Format.default);
131115
......@@ -440,31 +424,7 @@ pub fn toIntern(ty: Type) InternPool.Index {
440424}
441425
442426pub fn toValue(self: Type) Value {
443 return Value.fromInterned(self.toIntern());
444}
445
446const RuntimeBitsError = SemaError || error{NeedLazy};
447
448pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool {
449 return hasRuntimeBitsInner(ty, false, .eager, zcu, {}) catch unreachable;
450}
451
452pub fn hasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool {
453 return hasRuntimeBitsInner(ty, false, .sema, pt.zcu, pt.tid) catch |err| switch (err) {
454 error.NeedLazy => unreachable, // this would require a resolve strat of lazy
455 else => |e| return e,
456 };
457}
458
459pub fn hasRuntimeBitsIgnoreComptime(ty: Type, zcu: *const Zcu) bool {
460 return hasRuntimeBitsInner(ty, true, .eager, zcu, {}) catch unreachable;
461}
462
463pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!bool {
464 return hasRuntimeBitsInner(ty, true, .sema, pt.zcu, pt.tid) catch |err| switch (err) {
465 error.NeedLazy => unreachable, // this would require a resolve strat of lazy
466 else => |e| return e,
467 };
427 return .fromInterned(self.toIntern());
468428}
469429
470430/// true if and only if the type takes up space in memory at runtime.
......@@ -476,205 +436,126 @@ pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!b
476436/// * the type has only one possible value, making its ABI size 0.
477437/// - an enum with an explicit tag type has the ABI size of the integer tag type,
478438/// making it one-possible-value only if the integer tag type has 0 bits.
479/// When `ignore_comptime_only` is true, then types that are comptime-only
480/// may return false positives.
481pub fn hasRuntimeBitsInner(
482 ty: Type,
483 ignore_comptime_only: bool,
484 comptime strat: ResolveStratLazy,
485 zcu: strat.ZcuPtr(),
486 tid: strat.Tid(),
487) RuntimeBitsError!bool {
439pub fn hasRuntimeBits(ty: Type, zcu: *const Zcu) bool {
488440 const ip = &zcu.intern_pool;
489 const io = zcu.comp.io;
490 return switch (ty.toIntern()) {
491 .empty_tuple_type => false,
492 else => switch (ip.indexToKey(ty.toIntern())) {
493 .int_type => |int_type| int_type.bits != 0,
494 .ptr_type => {
495 // Pointers to zero-bit types still have a runtime address; however, pointers
496 // to comptime-only types do not, with the exception of function pointers.
497 if (ignore_comptime_only) return true;
498 return switch (strat) {
499 .sema => {
500 const pt = strat.pt(zcu, tid);
501 return !try ty.comptimeOnlySema(pt);
502 },
503 .eager => !ty.comptimeOnly(zcu),
504 .lazy => error.NeedLazy,
505 };
506 },
507 .anyframe_type => true,
508 .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and
509 try Type.fromInterned(array_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid),
510 .vector_type => |vector_type| return vector_type.len > 0 and
511 try Type.fromInterned(vector_type.child).hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid),
512 .opt_type => |child| {
513 const child_ty = Type.fromInterned(child);
514 if (child_ty.isNoReturn(zcu)) {
515 // Then the optional is comptime-known to be null.
516 return false;
517 }
518 if (ignore_comptime_only) return true;
519 return switch (strat) {
520 .sema => !try child_ty.comptimeOnlyInner(.sema, zcu, tid),
521 .eager => !child_ty.comptimeOnly(zcu),
522 .lazy => error.NeedLazy,
523 };
524 },
525 .error_union_type,
526 .error_set_type,
527 .inferred_error_set_type,
528 => true,
529
530 // These are function *bodies*, not pointers.
531 // They return false here because they are comptime-only types.
532 // Special exceptions have to be made when emitting functions due to
533 // this returning false.
534 .func_type => false,
535
536 .simple_type => |t| switch (t) {
537 .f16,
538 .f32,
539 .f64,
540 .f80,
541 .f128,
542 .usize,
543 .isize,
544 .c_char,
545 .c_short,
546 .c_ushort,
547 .c_int,
548 .c_uint,
549 .c_long,
550 .c_ulong,
551 .c_longlong,
552 .c_ulonglong,
553 .c_longdouble,
554 .bool,
555 .anyerror,
556 .adhoc_inferred_error_set,
557 .anyopaque,
558 => true,
441 return switch (ip.indexToKey(ty.toIntern())) {
442 .int_type => |int_type| int_type.bits != 0,
443 .ptr_type => true,
444 .anyframe_type => true,
445 .array_type => |array_type| array_type.lenIncludingSentinel() > 0 and
446 Type.fromInterned(array_type.child).hasRuntimeBits(zcu),
447 .vector_type => |vector_type| vector_type.len > 0 and
448 Type.fromInterned(vector_type.child).hasRuntimeBits(zcu),
449 .opt_type => |child| !Type.fromInterned(child).isNoReturn(zcu),
559450
560 // These are false because they are comptime-only types.
561 .void,
562 .type,
563 .comptime_int,
564 .comptime_float,
565 .noreturn,
566 .null,
567 .undefined,
568 .enum_literal,
569 => false,
451 .error_union_type,
452 .error_set_type,
453 .inferred_error_set_type,
454 => true,
570455
571 .generic_poison => unreachable,
572 },
573 .struct_type => {
574 const struct_type = ip.loadStructType(ty.toIntern());
575 if (strat != .eager and struct_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) {
576 // In this case, we guess that hasRuntimeBits() for this type is true,
577 // and then later if our guess was incorrect, we emit a compile error.
578 return true;
579 }
580 switch (strat) {
581 .sema => try ty.resolveFields(strat.pt(zcu, tid)),
582 .eager => assert(struct_type.haveFieldTypes(ip)),
583 .lazy => if (!struct_type.haveFieldTypes(ip)) return error.NeedLazy,
584 }
585 for (0..struct_type.field_types.len) |i| {
586 if (struct_type.comptime_bits.getBit(ip, i)) continue;
587 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
588 if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid))
589 return true;
590 } else {
591 return false;
592 }
593 },
594 .tuple_type => |tuple| {
595 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
596 if (val != .none) continue; // comptime field
597 if (try Type.fromInterned(field_ty).hasRuntimeBitsInner(
598 ignore_comptime_only,
599 strat,
600 zcu,
601 tid,
602 )) return true;
603 }
604 return false;
605 },
456 // These are function *bodies*, not pointers.
457 // They return false here because they are comptime-only types.
458 // Special exceptions have to be made when emitting functions due to
459 // this returning false.
460 .func_type => false,
606461
607 .union_type => {
608 const union_type = ip.loadUnionType(ty.toIntern());
609 const union_flags = union_type.flagsUnordered(ip);
610 switch (union_flags.runtime_tag) {
611 .none => if (strat != .eager) {
612 // In this case, we guess that hasRuntimeBits() for this type is true,
613 // and then later if our guess was incorrect, we emit a compile error.
614 if (union_type.assumeRuntimeBitsIfFieldTypesWip(ip, io)) return true;
615 },
616 .safety, .tagged => {},
617 }
618 switch (strat) {
619 .sema => try ty.resolveFields(strat.pt(zcu, tid)),
620 .eager => assert(union_flags.status.haveFieldTypes()),
621 .lazy => if (!union_flags.status.haveFieldTypes())
622 return error.NeedLazy,
623 }
624 switch (union_flags.runtime_tag) {
625 .none => {},
626 .safety, .tagged => {
627 const tag_ty = union_type.tagTypeUnordered(ip);
628 assert(tag_ty != .none); // tag_ty should have been resolved above
629 if (try Type.fromInterned(tag_ty).hasRuntimeBitsInner(
630 ignore_comptime_only,
631 strat,
632 zcu,
633 tid,
634 )) {
635 return true;
636 }
637 },
638 }
639 for (0..union_type.field_types.len) |field_index| {
640 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
641 if (try field_ty.hasRuntimeBitsInner(ignore_comptime_only, strat, zcu, tid))
642 return true;
643 } else {
644 return false;
645 }
646 },
462 .simple_type => |t| switch (t) {
463 .f16,
464 .f32,
465 .f64,
466 .f80,
467 .f128,
468 .usize,
469 .isize,
470 .c_char,
471 .c_short,
472 .c_ushort,
473 .c_int,
474 .c_uint,
475 .c_long,
476 .c_ulong,
477 .c_longlong,
478 .c_ulonglong,
479 .c_longdouble,
480 .bool,
481 .anyerror,
482 .adhoc_inferred_error_set,
483 .anyopaque,
484 => true,
647485
648 .opaque_type => true,
649 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsInner(
650 ignore_comptime_only,
651 strat,
652 zcu,
653 tid,
654 ),
486 .void,
487 .noreturn,
488 => false,
655489
656 // values, not types
657 .undef,
658 .simple_value,
659 .variable,
660 .@"extern",
661 .func,
662 .int,
663 .err,
664 .error_union,
490 // primitive comptime-only types
491 .type,
492 .comptime_int,
493 .comptime_float,
494 .null,
495 .undefined,
665496 .enum_literal,
666 .enum_tag,
667 .empty_enum_value,
668 .float,
669 .ptr,
670 .slice,
671 .opt,
672 .aggregate,
673 .un,
674 // memoization, not types
675 .memoized_call,
676 => unreachable,
497 => false,
498
499 .generic_poison => unreachable,
677500 },
501 .struct_type => {
502 // TODO MLUGG: memoize this state when resolving struct?
503 const struct_obj = ip.loadStructType(ty.toIntern());
504 for (struct_obj.field_types.get(ip), 0..) |field_ty_ip, field_idx| {
505 if (struct_obj.field_is_comptime_bits.get(ip, field_idx)) continue;
506 const field_ty: Type = .fromInterned(field_ty_ip);
507 if (field_ty.hasRuntimeBits(zcu)) return true;
508 }
509 return false;
510 },
511 .tuple_type => |tuple| {
512 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
513 if (val != .none) continue; // comptime field
514 if (Type.fromInterned(field_ty).hasRuntimeBits(zcu)) return true;
515 }
516 return false;
517 },
518 .union_type => {
519 // TODO MLUGG: memoize this state when resolving union?
520 const union_obj = ip.loadUnionType(ty.toIntern());
521 switch (union_obj.runtime_tag) {
522 .none => {},
523 .safety, .tagged => {
524 if (Type.fromInterned(union_obj.enum_tag_type).hasRuntimeBits(zcu)) return true;
525 },
526 }
527 for (union_obj.field_types.get(ip)) |field_ty_ip| {
528 const field_ty: Type = .fromInterned(field_ty_ip);
529 if (field_ty.hasRuntimeBits(zcu)) return true;
530 }
531 return false;
532 },
533
534 // MLUGG TODO: i think this can go away and the assert move to the defer?
535 .opaque_type => true,
536 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).hasRuntimeBits(zcu),
537
538 // values, not types
539 .undef,
540 .simple_value,
541 .variable,
542 .@"extern",
543 .func,
544 .int,
545 .err,
546 .error_union,
547 .enum_literal,
548 .enum_tag,
549 .empty_enum_value,
550 .float,
551 .ptr,
552 .slice,
553 .opt,
554 .aggregate,
555 .un,
556 // memoization, not types
557 .memoized_call,
558 => unreachable,
678559 };
679560}
680561
......@@ -739,16 +620,15 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
739620 },
740621 .struct_type => ip.loadStructType(ty.toIntern()).layout != .auto,
741622 .union_type => {
742 const union_type = ip.loadUnionType(ty.toIntern());
743 return switch (union_type.flagsUnordered(ip).runtime_tag) {
744 .none, .safety => union_type.flagsUnordered(ip).layout != .auto,
623 const union_obj = ip.loadUnionType(ty.toIntern());
624 if (union_obj.layout == .auto) return false;
625 return switch (union_obj.runtime_tag) {
626 .none => true,
745627 .tagged => false,
628 .safety => unreachable, // well-defined layout can't have a safety tag
746629 };
747630 },
748 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
749 .auto => false,
750 .explicit, .nonexhaustive => true,
751 },
631 .enum_type => ip.loadEnumType(ty.toIntern()).int_tag_is_explicit,
752632
753633 // values, not types
754634 .undef,
......@@ -774,28 +654,20 @@ pub fn hasWellDefinedLayout(ty: Type, zcu: *const Zcu) bool {
774654 };
775655}
776656
777pub fn fnHasRuntimeBits(ty: Type, zcu: *Zcu) bool {
778 return ty.fnHasRuntimeBitsInner(.normal, zcu, {}) catch unreachable;
779}
780
781pub fn fnHasRuntimeBitsSema(ty: Type, pt: Zcu.PerThread) SemaError!bool {
782 return try ty.fnHasRuntimeBitsInner(.sema, pt.zcu, pt.tid);
783}
784
785657/// Determines whether a function type has runtime bits, i.e. whether a
786658/// function with this type can exist at runtime.
787659/// Asserts that `ty` is a function type.
788pub fn fnHasRuntimeBitsInner(
789 ty: Type,
790 comptime strat: ResolveStrat,
791 zcu: strat.ZcuPtr(),
792 tid: strat.Tid(),
793) SemaError!bool {
794 const fn_info = zcu.typeToFunc(ty).?;
795 if (fn_info.is_generic) return false;
796 if (fn_info.is_var_args) return true;
660pub fn fnHasRuntimeBits(fn_ty: Type, zcu: *Zcu) bool {
661 const fn_info = zcu.typeToFunc(fn_ty).?;
662 if (fn_info.comptime_bits != 0) return false;
663 for (fn_info.param_types.get(&zcu.intern_pool)) |param_ty| {
664 if (param_ty == .generic_poison_type) return false;
665 if (Type.fromInterned(param_ty).comptimeOnly(zcu)) return false;
666 }
667 if (fn_info.return_type == .generic_poison_type) return false;
668 if (Type.fromInterned(fn_info.return_type).comptimeOnly(zcu)) return false;
797669 if (fn_info.cc == .@"inline") return false;
798 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyInner(strat, zcu, tid);
670 return true;
799671}
800672
801673pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool {
......@@ -806,10 +678,11 @@ pub fn isFnOrHasRuntimeBits(ty: Type, zcu: *Zcu) bool {
806678}
807679
808680/// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.
681/// MLUGG TODO: this function is a bit silly now...
809682pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, zcu: *Zcu) bool {
810683 return switch (ty.zigTypeTag(zcu)) {
811684 .@"fn" => true,
812 else => return ty.hasRuntimeBitsIgnoreComptime(zcu),
685 else => return ty.hasRuntimeBits(zcu),
813686 };
814687}
815688
......@@ -818,29 +691,15 @@ pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool {
818691}
819692
820693/// Never returns `none`. Asserts that all necessary type resolution is already done.
821pub fn ptrAlignment(ty: Type, zcu: *Zcu) Alignment {
822 return ptrAlignmentInner(ty, .normal, zcu, {}) catch unreachable;
823}
824
825pub fn ptrAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment {
826 return try ty.ptrAlignmentInner(.sema, pt.zcu, pt.tid);
827}
828
829pub fn ptrAlignmentInner(
830 ty: Type,
831 comptime strat: ResolveStrat,
832 zcu: strat.ZcuPtr(),
833 tid: strat.Tid(),
834) !Alignment {
835 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
836 .ptr_type => |ptr_type| {
837 if (ptr_type.flags.alignment != .none) return ptr_type.flags.alignment;
838 const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(strat.toLazy(), zcu, tid);
839 return res.scalar;
840 },
841 .opt_type => |child| Type.fromInterned(child).ptrAlignmentInner(strat, zcu, tid),
694pub fn ptrAlignment(ptr_ty: Type, zcu: *Zcu) Alignment {
695 const ip = &zcu.intern_pool;
696 const ptr_key: InternPool.Key.PtrType = switch (ip.indexToKey(ptr_ty.toIntern())) {
697 .ptr_type => |key| key,
698 .opt_type => |child| ip.indexToKey(child).ptr_type,
842699 else => unreachable,
843700 };
701 if (ptr_key.flags.alignment != .none) return ptr_key.flags.alignment;
702 return Type.fromInterned(ptr_key.child).abiAlignment(zcu);
844703}
845704
846705pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace {
......@@ -851,861 +710,347 @@ pub fn ptrAddressSpace(ty: Type, zcu: *const Zcu) std.builtin.AddressSpace {
851710 };
852711}
853712
854/// May capture a reference to `ty`.
855/// Returned value has type `comptime_int`.
856pub fn lazyAbiAlignment(ty: Type, pt: Zcu.PerThread) !Value {
857 switch (try ty.abiAlignmentInner(.lazy, pt.zcu, pt.tid)) {
858 .val => |val| return val,
859 .scalar => |x| return pt.intValue(Type.comptime_int, x.toByteUnits() orelse 0),
860 }
861}
862
863pub const AbiAlignmentInner = union(enum) {
864 scalar: Alignment,
865 val: Value,
866};
867
868pub const ResolveStratLazy = enum {
869 /// Return a `lazy_size` or `lazy_align` value if necessary.
870 /// This value can be resolved later using `Value.resolveLazy`.
871 lazy,
872 /// Return a scalar result, expecting all necessary type resolution to be completed.
873 /// Backends should typically use this, since they must not perform type resolution.
874 eager,
875 /// Return a scalar result, performing type resolution as necessary.
876 /// This should typically be used from semantic analysis.
877 sema,
878
879 pub fn Tid(strat: ResolveStratLazy) type {
880 return switch (strat) {
881 .lazy, .sema => Zcu.PerThread.Id,
882 .eager => void,
883 };
884 }
885
886 pub fn ZcuPtr(strat: ResolveStratLazy) type {
887 return switch (strat) {
888 .eager => *const Zcu,
889 .sema, .lazy => *Zcu,
890 };
891 }
892
893 pub fn pt(
894 comptime strat: ResolveStratLazy,
895 zcu: strat.ZcuPtr(),
896 tid: strat.Tid(),
897 ) switch (strat) {
898 .lazy, .sema => Zcu.PerThread,
899 .eager => void,
900 } {
901 return switch (strat) {
902 .lazy, .sema => .{ .tid = tid, .zcu = zcu },
903 else => {},
904 };
905 }
906};
907
908/// The chosen strategy can be easily optimized away in release builds.
909/// However, in debug builds, it helps to avoid accidentally resolving types in backends.
910pub const ResolveStrat = enum {
911 /// Assert that all necessary resolution is completed.
912 /// Backends should typically use this, since they must not perform type resolution.
913 normal,
914 /// Perform type resolution as necessary using `Zcu`.
915 /// This should typically be used from semantic analysis.
916 sema,
917
918 pub fn Tid(strat: ResolveStrat) type {
919 return switch (strat) {
920 .sema => Zcu.PerThread.Id,
921 .normal => void,
922 };
923 }
924
925 pub fn ZcuPtr(strat: ResolveStrat) type {
926 return switch (strat) {
927 .normal => *const Zcu,
928 .sema => *Zcu,
929 };
930 }
931
932 pub fn pt(comptime strat: ResolveStrat, zcu: strat.ZcuPtr(), tid: strat.Tid()) switch (strat) {
933 .sema => Zcu.PerThread,
934 .normal => void,
935 } {
936 return switch (strat) {
937 .sema => .{ .tid = tid, .zcu = zcu },
938 .normal => {},
939 };
940 }
941
942 pub inline fn toLazy(strat: ResolveStrat) ResolveStratLazy {
943 return switch (strat) {
944 .normal => .eager,
945 .sema => .sema,
946 };
947 }
948};
949
950713/// Never returns `none`. Asserts that all necessary type resolution is already done.
714/// MLUGG TODO: check that it really does never return `.none`
951715pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment {
952 return (ty.abiAlignmentInner(.eager, zcu, {}) catch unreachable).scalar;
953}
954
955pub fn abiAlignmentSema(ty: Type, pt: Zcu.PerThread) SemaError!Alignment {
956 return (try ty.abiAlignmentInner(.sema, pt.zcu, pt.tid)).scalar;
957}
958
959/// If you pass `eager` you will get back `scalar` and assert the type is resolved.
960/// In this case there will be no error, guaranteed.
961/// If you pass `lazy` you may get back `scalar` or `val`.
962/// If `val` is returned, a reference to `ty` has been captured.
963/// If you pass `sema` you will get back `scalar` and resolve the type if
964/// necessary, possibly returning a CompileError.
965pub fn abiAlignmentInner(
966 ty: Type,
967 comptime strat: ResolveStratLazy,
968 zcu: strat.ZcuPtr(),
969 tid: strat.Tid(),
970) SemaError!AbiAlignmentInner {
971 const pt = strat.pt(zcu, tid);
972 const target = zcu.getTarget();
973716 const ip = &zcu.intern_pool;
974
975 switch (ty.toIntern()) {
976 .empty_tuple_type => return .{ .scalar = .@"1" },
977 else => switch (ip.indexToKey(ty.toIntern())) {
978 .int_type => |int_type| {
979 if (int_type.bits == 0) return .{ .scalar = .@"1" };
980 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits)) };
981 },
982 .ptr_type, .anyframe_type => {
983 return .{ .scalar = ptrAbiAlignment(target) };
984 },
985 .array_type => |array_type| {
986 return Type.fromInterned(array_type.child).abiAlignmentInner(strat, zcu, tid);
987 },
988 .vector_type => |vector_type| {
989 if (vector_type.len == 0) return .{ .scalar = .@"1" };
990 switch (zcu.comp.getZigBackend()) {
991 else => {
992 // This is fine because the child type of a vector always has a bit-size known
993 // without needing any type resolution.
994 const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu));
995 if (elem_bits == 0) return .{ .scalar = .@"1" };
996 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
997 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
998 return .{ .scalar = Alignment.fromByteUnits(alignment) };
999 },
1000 .stage2_c => {
1001 return Type.fromInterned(vector_type.child).abiAlignmentInner(strat, zcu, tid);
1002 },
1003 .stage2_x86_64 => {
1004 if (vector_type.child == .bool_type) {
1005 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" };
1006 if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" };
1007 if (vector_type.len > 64) return .{ .scalar = .@"16" };
1008 const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
1009 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
1010 return .{ .scalar = Alignment.fromByteUnits(alignment) };
1011 }
1012 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar);
1013 if (elem_bytes == 0) return .{ .scalar = .@"1" };
1014 const bytes = elem_bytes * vector_type.len;
1015 if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .{ .scalar = .@"64" };
1016 if (bytes > 16 and target.cpu.has(.x86, .avx)) return .{ .scalar = .@"32" };
1017 return .{ .scalar = .@"16" };
1018 },
1019 }
1020 },
1021
1022 .opt_type => return ty.abiAlignmentInnerOptional(strat, zcu, tid),
1023 .error_union_type => |info| return ty.abiAlignmentInnerErrorUnion(
1024 strat,
1025 zcu,
1026 tid,
1027 Type.fromInterned(info.payload_type),
1028 ),
1029
1030 .error_set_type, .inferred_error_set_type => {
1031 const bits = zcu.errorSetBits();
1032 if (bits == 0) return .{ .scalar = .@"1" };
1033 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) };
1034 },
1035
1036 // represents machine code; not a pointer
1037 .func_type => return .{ .scalar = target_util.minFunctionAlignment(target) },
1038
1039 .simple_type => |t| switch (t) {
1040 .bool,
1041 .anyopaque,
1042 => return .{ .scalar = .@"1" },
1043
1044 .usize,
1045 .isize,
1046 => return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())) },
1047
1048 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
1049 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
1050 .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) },
1051 .c_int => return .{ .scalar = cTypeAlign(target, .int) },
1052 .c_uint => return .{ .scalar = cTypeAlign(target, .uint) },
1053 .c_long => return .{ .scalar = cTypeAlign(target, .long) },
1054 .c_ulong => return .{ .scalar = cTypeAlign(target, .ulong) },
1055 .c_longlong => return .{ .scalar = cTypeAlign(target, .longlong) },
1056 .c_ulonglong => return .{ .scalar = cTypeAlign(target, .ulonglong) },
1057 .c_longdouble => return .{ .scalar = cTypeAlign(target, .longdouble) },
1058
1059 .f16 => return .{ .scalar = .@"2" },
1060 .f32 => return .{ .scalar = cTypeAlign(target, .float) },
1061 .f64 => switch (target.cTypeBitSize(.double)) {
1062 64 => return .{ .scalar = cTypeAlign(target, .double) },
1063 else => return .{ .scalar = .@"8" },
1064 },
1065 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1066 80 => return .{ .scalar = cTypeAlign(target, .longdouble) },
1067 else => return .{ .scalar = Type.u80.abiAlignment(zcu) },
1068 },
1069 .f128 => switch (target.cTypeBitSize(.longdouble)) {
1070 128 => return .{ .scalar = cTypeAlign(target, .longdouble) },
1071 else => return .{ .scalar = .@"16" },
717 const target = zcu.getTarget();
718 assertHasLayout(ty, zcu);
719 return switch (ip.indexToKey(ty.toIntern())) {
720 .int_type => |int_type| {
721 if (int_type.bits == 0) return .@"1";
722 return .fromByteUnits(std.zig.target.intAlignment(target, int_type.bits));
723 },
724 .ptr_type, .anyframe_type => ptrAbiAlignment(target),
725 .array_type => |array_type| Type.fromInterned(array_type.child).abiAlignment(zcu),
726 .vector_type => |vector_type| {
727 if (vector_type.len == 0) return .@"1";
728 switch (zcu.comp.getZigBackend()) {
729 else => {
730 const elem_bits: u32 = @intCast(Type.fromInterned(vector_type.child).bitSize(zcu));
731 if (elem_bits == 0) return .@"1";
732 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
733 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
1072734 },
1073
1074 .anyerror, .adhoc_inferred_error_set => {
1075 const bits = zcu.errorSetBits();
1076 if (bits == 0) return .{ .scalar = .@"1" };
1077 return .{ .scalar = .fromByteUnits(std.zig.target.intAlignment(target, bits)) };
735 .stage2_c => return Type.fromInterned(vector_type.child).abiAlignment(zcu),
736 .stage2_x86_64 => {
737 if (vector_type.child == .bool_type) {
738 if (vector_type.len > 256 and target.cpu.has(.x86, .avx512f)) return .@"64";
739 if (vector_type.len > 128 and target.cpu.has(.x86, .avx)) return .@"32";
740 if (vector_type.len > 64) return .@"16";
741 const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
742 return .fromByteUnits(std.math.ceilPowerOfTwoAssert(u32, bytes));
743 }
744 const elem_bytes: u32 = @intCast(Type.fromInterned(vector_type.child).abiSize(zcu));
745 if (elem_bytes == 0) return .@"1";
746 const bytes = elem_bytes * vector_type.len;
747 if (bytes > 32 and target.cpu.has(.x86, .avx512f)) return .@"64";
748 if (bytes > 16 and target.cpu.has(.x86, .avx)) return .@"32";
749 return .@"16";
1078750 },
751 }
752 },
1079753
1080 .void,
1081 .type,
1082 .comptime_int,
1083 .comptime_float,
1084 .null,
1085 .undefined,
1086 .enum_literal,
1087 => return .{ .scalar = .@"1" },
754 .opt_type => |child| Type.fromInterned(child).abiAlignment(zcu),
755 .error_union_type => |eu| Alignment.maxStrict(
756 Type.fromInterned(eu.payload_type).abiAlignment(zcu),
757 errorAbiAlignment(zcu),
758 ),
1088759
1089 .noreturn => unreachable,
1090 .generic_poison => unreachable,
1091 },
1092 .struct_type => {
1093 const struct_type = ip.loadStructType(ty.toIntern());
1094 if (struct_type.layout == .@"packed") {
1095 switch (strat) {
1096 .sema => try ty.resolveLayout(pt),
1097 .lazy => if (struct_type.backingIntTypeUnordered(ip) == .none) return .{
1098 .val = Value.fromInterned(try pt.intern(.{ .int = .{
1099 .ty = .comptime_int_type,
1100 .storage = .{ .lazy_align = ty.toIntern() },
1101 } })),
1102 },
1103 .eager => {},
1104 }
1105 return .{ .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiAlignment(zcu) };
1106 }
760 .error_set_type, .inferred_error_set_type => errorAbiAlignment(zcu),
1107761
1108 if (struct_type.flagsUnordered(ip).alignment == .none) switch (strat) {
1109 .eager => unreachable, // struct alignment not resolved
1110 .sema => try ty.resolveStructAlignment(pt),
1111 .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1112 .ty = .comptime_int_type,
1113 .storage = .{ .lazy_align = ty.toIntern() },
1114 } })) },
1115 };
762 .func_type => target_util.minFunctionAlignment(target),
1116763
1117 return .{ .scalar = struct_type.flagsUnordered(ip).alignment };
1118 },
1119 .tuple_type => |tuple| {
1120 var big_align: Alignment = .@"1";
1121 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
1122 if (val != .none) continue; // comptime field
1123 switch (try Type.fromInterned(field_ty).abiAlignmentInner(strat, zcu, tid)) {
1124 .scalar => |field_align| big_align = big_align.max(field_align),
1125 .val => switch (strat) {
1126 .eager => unreachable, // field type alignment not resolved
1127 .sema => unreachable, // passed to abiAlignmentInner above
1128 .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1129 .ty = .comptime_int_type,
1130 .storage = .{ .lazy_align = ty.toIntern() },
1131 } })) },
1132 },
1133 }
1134 }
1135 return .{ .scalar = big_align };
764 .simple_type => |t| switch (t) {
765 .bool,
766 .void,
767 .noreturn,
768 .anyopaque,
769 .type,
770 .comptime_int,
771 .comptime_float,
772 .null,
773 .undefined,
774 .enum_literal,
775 => .@"1",
776
777 .anyerror, .adhoc_inferred_error_set => errorAbiAlignment(zcu),
778 .usize, .isize => .fromByteUnits(std.zig.target.intAlignment(target, target.ptrBitWidth())),
779
780 .c_char => cTypeAlign(target, .char),
781 .c_short => cTypeAlign(target, .short),
782 .c_ushort => cTypeAlign(target, .ushort),
783 .c_int => cTypeAlign(target, .int),
784 .c_uint => cTypeAlign(target, .uint),
785 .c_long => cTypeAlign(target, .long),
786 .c_ulong => cTypeAlign(target, .ulong),
787 .c_longlong => cTypeAlign(target, .longlong),
788 .c_ulonglong => cTypeAlign(target, .ulonglong),
789 .c_longdouble => cTypeAlign(target, .longdouble),
790
791 .f16 => .@"2",
792 .f32 => cTypeAlign(target, .float),
793 .f64 => switch (target.cTypeBitSize(.double)) {
794 64 => cTypeAlign(target, .double),
795 else => .@"8",
1136796 },
1137 .union_type => {
1138 const union_type = ip.loadUnionType(ty.toIntern());
1139
1140 if (union_type.flagsUnordered(ip).alignment == .none) switch (strat) {
1141 .eager => unreachable, // union layout not resolved
1142 .sema => try ty.resolveUnionAlignment(pt),
1143 .lazy => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1144 .ty = .comptime_int_type,
1145 .storage = .{ .lazy_align = ty.toIntern() },
1146 } })) },
1147 };
1148
1149 return .{ .scalar = union_type.flagsUnordered(ip).alignment };
797 .f80 => switch (target.cTypeBitSize(.longdouble)) {
798 80 => cTypeAlign(target, .longdouble),
799 else => Type.u80.abiAlignment(zcu),
1150800 },
1151 .opaque_type => return .{ .scalar = .@"1" },
1152 .enum_type => return .{
1153 .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(zcu),
801 .f128 => switch (target.cTypeBitSize(.longdouble)) {
802 128 => cTypeAlign(target, .longdouble),
803 else => .@"16",
1154804 },
1155805
1156 // values, not types
1157 .undef,
1158 .simple_value,
1159 .variable,
1160 .@"extern",
1161 .func,
1162 .int,
1163 .err,
1164 .error_union,
1165 .enum_literal,
1166 .enum_tag,
1167 .empty_enum_value,
1168 .float,
1169 .ptr,
1170 .slice,
1171 .opt,
1172 .aggregate,
1173 .un,
1174 // memoization, not types
1175 .memoized_call,
1176 => unreachable,
806 .generic_poison => unreachable,
1177807 },
1178 }
1179}
1180
1181fn abiAlignmentInnerErrorUnion(
1182 ty: Type,
1183 comptime strat: ResolveStratLazy,
1184 zcu: strat.ZcuPtr(),
1185 tid: strat.Tid(),
1186 payload_ty: Type,
1187) SemaError!AbiAlignmentInner {
1188 // This code needs to be kept in sync with the equivalent switch prong
1189 // in abiSizeInner.
1190 const code_align = Type.anyerror.abiAlignment(zcu);
1191 switch (strat) {
1192 .eager, .sema => {
1193 if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) {
1194 error.NeedLazy => if (strat == .lazy) {
1195 const pt = strat.pt(zcu, tid);
1196 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1197 .ty = .comptime_int_type,
1198 .storage = .{ .lazy_align = ty.toIntern() },
1199 } })) };
1200 } else unreachable,
1201 else => |e| return e,
1202 })) {
1203 return .{ .scalar = code_align };
808 .tuple_type => |tuple| {
809 var big_align: Alignment = .@"1";
810 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
811 if (val != .none) continue; // comptime field
812 const field_align = Type.fromInterned(field_ty).abiAlignment(zcu);
813 big_align = big_align.max(field_align);
1204814 }
1205 return .{ .scalar = code_align.max(
1206 (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar,
1207 ) };
815 return big_align;
1208816 },
1209 .lazy => {
1210 const pt = strat.pt(zcu, tid);
1211 switch (try payload_ty.abiAlignmentInner(strat, zcu, tid)) {
1212 .scalar => |payload_align| return .{ .scalar = code_align.max(payload_align) },
1213 .val => {},
817 .struct_type => {
818 const struct_obj = ip.loadStructType(ty.toIntern());
819 switch (struct_obj.layout) {
820 .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiAlignment(zcu),
821 .auto, .@"extern" => return struct_obj.alignment,
1214822 }
1215 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1216 .ty = .comptime_int_type,
1217 .storage = .{ .lazy_align = ty.toIntern() },
1218 } })) };
1219823 },
1220 }
1221}
1222
1223fn abiAlignmentInnerOptional(
1224 ty: Type,
1225 comptime strat: ResolveStratLazy,
1226 zcu: strat.ZcuPtr(),
1227 tid: strat.Tid(),
1228) SemaError!AbiAlignmentInner {
1229 const pt = strat.pt(zcu, tid);
1230 const target = zcu.getTarget();
1231 const child_type = ty.optionalChild(zcu);
1232
1233 switch (child_type.zigTypeTag(zcu)) {
1234 .pointer => return .{ .scalar = ptrAbiAlignment(target) },
1235 .error_set => return Type.anyerror.abiAlignmentInner(strat, zcu, tid),
1236 .noreturn => return .{ .scalar = .@"1" },
1237 else => {},
1238 }
1239
1240 switch (strat) {
1241 .eager, .sema => {
1242 if (!(child_type.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) {
1243 error.NeedLazy => if (strat == .lazy) {
1244 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1245 .ty = .comptime_int_type,
1246 .storage = .{ .lazy_align = ty.toIntern() },
1247 } })) };
1248 } else unreachable,
1249 else => |e| return e,
1250 })) {
1251 return .{ .scalar = .@"1" };
824 .union_type => {
825 const union_obj = ip.loadUnionType(ty.toIntern());
826 switch (union_obj.layout) {
827 .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiAlignment(zcu),
828 .auto, .@"extern" => return getUnionLayout(union_obj, zcu).abi_align,
1252829 }
1253 return child_type.abiAlignmentInner(strat, zcu, tid);
1254 },
1255 .lazy => switch (try child_type.abiAlignmentInner(strat, zcu, tid)) {
1256 .scalar => |x| return .{ .scalar = x.max(.@"1") },
1257 .val => return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1258 .ty = .comptime_int_type,
1259 .storage = .{ .lazy_align = ty.toIntern() },
1260 } })) },
1261830 },
1262 }
1263}
1264
1265const AbiSizeInner = union(enum) {
1266 scalar: u64,
1267 val: Value,
1268};
1269
1270/// Asserts the type has the ABI size already resolved.
1271/// Types that return false for hasRuntimeBits() return 0.
1272pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
1273 return (abiSizeInner(ty, .eager, zcu, {}) catch unreachable).scalar;
1274}
1275
1276/// May capture a reference to `ty`.
1277pub fn abiSizeLazy(ty: Type, pt: Zcu.PerThread) !Value {
1278 switch (try ty.abiSizeInner(.lazy, pt.zcu, pt.tid)) {
1279 .val => |val| return val,
1280 .scalar => |x| return pt.intValue(Type.comptime_int, x),
1281 }
1282}
831 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiAlignment(zcu),
832 .opaque_type => .@"1",
1283833
1284pub fn abiSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 {
1285 return (try abiSizeInner(ty, .sema, pt.zcu, pt.tid)).scalar;
834 // values, not types
835 .undef,
836 .simple_value,
837 .variable,
838 .@"extern",
839 .func,
840 .int,
841 .err,
842 .error_union,
843 .enum_literal,
844 .enum_tag,
845 .empty_enum_value,
846 .float,
847 .ptr,
848 .slice,
849 .opt,
850 .aggregate,
851 .un,
852 // memoization, not types
853 .memoized_call,
854 => unreachable,
855 };
1286856}
1287857
1288/// If you pass `eager` you will get back `scalar` and assert the type is resolved.
1289/// In this case there will be no error, guaranteed.
1290/// If you pass `lazy` you may get back `scalar` or `val`.
1291/// If `val` is returned, a reference to `ty` has been captured.
1292/// If you pass `sema` you will get back `scalar` and resolve the type if
1293/// necessary, possibly returning a CompileError.
1294pub fn abiSizeInner(
1295 ty: Type,
1296 comptime strat: ResolveStratLazy,
1297 zcu: strat.ZcuPtr(),
1298 tid: strat.Tid(),
1299) SemaError!AbiSizeInner {
1300 const target = zcu.getTarget();
858/// Asserts that `ty` is not an opaque type.
859pub fn abiSize(ty: Type, zcu: *const Zcu) u64 {
1301860 const ip = &zcu.intern_pool;
1302
1303 switch (ty.toIntern()) {
1304 .empty_tuple_type => return .{ .scalar = 0 },
1305
1306 else => switch (ip.indexToKey(ty.toIntern())) {
1307 .int_type => |int_type| {
1308 if (int_type.bits == 0) return .{ .scalar = 0 };
1309 return .{ .scalar = std.zig.target.intByteSize(target, int_type.bits) };
1310 },
1311 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1312 .slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
1313 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1314 },
1315 .anyframe_type => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1316
1317 .array_type => |array_type| {
1318 const len = array_type.lenIncludingSentinel();
1319 if (len == 0) return .{ .scalar = 0 };
1320 switch (try Type.fromInterned(array_type.child).abiSizeInner(strat, zcu, tid)) {
1321 .scalar => |elem_size| return .{ .scalar = len * elem_size },
1322 .val => switch (strat) {
1323 .sema, .eager => unreachable,
1324 .lazy => {
1325 const pt = strat.pt(zcu, tid);
1326 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1327 .ty = .comptime_int_type,
1328 .storage = .{ .lazy_size = ty.toIntern() },
1329 } })) };
1330 },
1331 },
1332 }
1333 },
1334 .vector_type => |vector_type| {
1335 const sub_strat: ResolveStrat = switch (strat) {
1336 .sema => .sema,
1337 .eager => .normal,
1338 .lazy => {
1339 const pt = strat.pt(zcu, tid);
1340 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1341 .ty = .comptime_int_type,
1342 .storage = .{ .lazy_size = ty.toIntern() },
1343 } })) };
1344 },
1345 };
1346 const alignment = (try ty.abiAlignmentInner(strat, zcu, tid)).scalar;
1347 const total_bytes = switch (zcu.comp.getZigBackend()) {
1348 else => total_bytes: {
1349 const elem_bits = try Type.fromInterned(vector_type.child).bitSizeInner(sub_strat, zcu, tid);
1350 const total_bits = elem_bits * vector_type.len;
1351 break :total_bytes (total_bits + 7) / 8;
1352 },
1353 .stage2_c => total_bytes: {
1354 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar);
1355 break :total_bytes elem_bytes * vector_type.len;
1356 },
1357 .stage2_x86_64 => total_bytes: {
1358 if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
1359 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeInner(strat, zcu, tid)).scalar);
1360 break :total_bytes elem_bytes * vector_type.len;
1361 },
1362 };
1363 return .{ .scalar = alignment.forward(total_bytes) };
1364 },
1365
1366 .opt_type => return ty.abiSizeInnerOptional(strat, zcu, tid),
1367
1368 .error_set_type, .inferred_error_set_type => {
1369 const bits = zcu.errorSetBits();
1370 if (bits == 0) return .{ .scalar = 0 };
1371 return .{ .scalar = std.zig.target.intByteSize(target, bits) };
1372 },
1373
1374 .error_union_type => |error_union_type| {
1375 const payload_ty = Type.fromInterned(error_union_type.payload_type);
1376 // This code needs to be kept in sync with the equivalent switch prong
1377 // in abiAlignmentInner.
1378 const code_size = Type.anyerror.abiSize(zcu);
1379 if (!(payload_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) {
1380 error.NeedLazy => if (strat == .lazy) {
1381 const pt = strat.pt(zcu, tid);
1382 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1383 .ty = .comptime_int_type,
1384 .storage = .{ .lazy_size = ty.toIntern() },
1385 } })) };
1386 } else unreachable,
1387 else => |e| return e,
1388 })) {
1389 // Same as anyerror.
1390 return .{ .scalar = code_size };
1391 }
1392 const code_align = Type.anyerror.abiAlignment(zcu);
1393 const payload_align = (try payload_ty.abiAlignmentInner(strat, zcu, tid)).scalar;
1394 const payload_size = switch (try payload_ty.abiSizeInner(strat, zcu, tid)) {
1395 .scalar => |elem_size| elem_size,
1396 .val => switch (strat) {
1397 .sema => unreachable,
1398 .eager => unreachable,
1399 .lazy => {
1400 const pt = strat.pt(zcu, tid);
1401 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1402 .ty = .comptime_int_type,
1403 .storage = .{ .lazy_size = ty.toIntern() },
1404 } })) };
1405 },
1406 },
1407 };
1408
1409 var size: u64 = 0;
1410 if (code_align.compare(.gt, payload_align)) {
1411 size += code_size;
1412 size = payload_align.forward(size);
1413 size += payload_size;
1414 size = code_align.forward(size);
1415 } else {
1416 size += payload_size;
1417 size = code_align.forward(size);
1418 size += code_size;
1419 size = payload_align.forward(size);
1420 }
1421 return .{ .scalar = size };
1422 },
1423 .func_type => unreachable, // represents machine code; not a pointer
1424 .simple_type => |t| switch (t) {
1425 .bool => return .{ .scalar = 1 },
1426
1427 .f16 => return .{ .scalar = 2 },
1428 .f32 => return .{ .scalar = 4 },
1429 .f64 => return .{ .scalar = 8 },
1430 .f128 => return .{ .scalar = 16 },
1431 .f80 => switch (target.cTypeBitSize(.longdouble)) {
1432 80 => return .{ .scalar = target.cTypeByteSize(.longdouble) },
1433 else => return .{ .scalar = Type.u80.abiSize(zcu) },
1434 },
1435
1436 .usize,
1437 .isize,
1438 => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1439
1440 .c_char => return .{ .scalar = target.cTypeByteSize(.char) },
1441 .c_short => return .{ .scalar = target.cTypeByteSize(.short) },
1442 .c_ushort => return .{ .scalar = target.cTypeByteSize(.ushort) },
1443 .c_int => return .{ .scalar = target.cTypeByteSize(.int) },
1444 .c_uint => return .{ .scalar = target.cTypeByteSize(.uint) },
1445 .c_long => return .{ .scalar = target.cTypeByteSize(.long) },
1446 .c_ulong => return .{ .scalar = target.cTypeByteSize(.ulong) },
1447 .c_longlong => return .{ .scalar = target.cTypeByteSize(.longlong) },
1448 .c_ulonglong => return .{ .scalar = target.cTypeByteSize(.ulonglong) },
1449 .c_longdouble => return .{ .scalar = target.cTypeByteSize(.longdouble) },
1450
1451 .anyopaque,
1452 .void,
1453 .type,
1454 .comptime_int,
1455 .comptime_float,
1456 .null,
1457 .undefined,
1458 .enum_literal,
1459 => return .{ .scalar = 0 },
1460
1461 .anyerror, .adhoc_inferred_error_set => {
1462 const bits = zcu.errorSetBits();
1463 if (bits == 0) return .{ .scalar = 0 };
1464 return .{ .scalar = std.zig.target.intByteSize(target, bits) };
861 const target = zcu.getTarget();
862 assertHasLayout(ty, zcu);
863 return switch (ip.indexToKey(ty.toIntern())) {
864 .int_type => |int_type| std.zig.target.intByteSize(target, int_type.bits),
865 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
866 .slice => ptrAbiSize(target) * 2,
867 .one, .many, .c => ptrAbiSize(target),
868 },
869 .anyframe_type => ptrAbiSize(target),
870 .array_type => |arr| arr.lenIncludingSentinel() * Type.fromInterned(arr.child).abiSize(zcu),
871 .vector_type => |vec| {
872 const elem_ty: Type = .fromInterned(vec.child);
873 const bytes = switch (zcu.comp.getZigBackend()) {
874 else => std.math.divCeil(u64, vec.len * elem_ty.bitSize(zcu), 8) catch unreachable,
875 .stage2_c => vec.len * elem_ty.abiSize(zcu),
876 .stage2_x86_64 => switch (elem_ty.toIntern()) {
877 .bool_type => std.math.divCeil(u64, vec.len, 8) catch unreachable,
878 else => vec.len * elem_ty.abiSize(zcu),
1465879 },
1466
1467 .noreturn => unreachable,
1468 .generic_poison => unreachable,
1469 },
1470 .struct_type => {
1471 const struct_type = ip.loadStructType(ty.toIntern());
1472 switch (strat) {
1473 .sema => try ty.resolveLayout(strat.pt(zcu, tid)),
1474 .lazy => {
1475 const pt = strat.pt(zcu, tid);
1476 switch (struct_type.layout) {
1477 .@"packed" => {
1478 if (struct_type.backingIntTypeUnordered(ip) == .none) return .{
1479 .val = Value.fromInterned(try pt.intern(.{ .int = .{
1480 .ty = .comptime_int_type,
1481 .storage = .{ .lazy_size = ty.toIntern() },
1482 } })),
1483 };
1484 },
1485 .auto, .@"extern" => {
1486 if (!struct_type.haveLayout(ip)) return .{
1487 .val = Value.fromInterned(try pt.intern(.{ .int = .{
1488 .ty = .comptime_int_type,
1489 .storage = .{ .lazy_size = ty.toIntern() },
1490 } })),
1491 };
1492 },
1493 }
1494 },
1495 .eager => {},
1496 }
1497 switch (struct_type.layout) {
1498 .@"packed" => return .{
1499 .scalar = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)).abiSize(zcu),
1500 },
1501 .auto, .@"extern" => {
1502 assert(struct_type.haveLayout(ip));
1503 return .{ .scalar = struct_type.sizeUnordered(ip) };
1504 },
1505 }
1506 },
1507 .tuple_type => |tuple| {
1508 switch (strat) {
1509 .sema => try ty.resolveLayout(strat.pt(zcu, tid)),
1510 .lazy, .eager => {},
1511 }
1512 const field_count = tuple.types.len;
1513 if (field_count == 0) {
1514 return .{ .scalar = 0 };
1515 }
1516 return .{ .scalar = ty.structFieldOffset(field_count, zcu) };
1517 },
1518
1519 .union_type => {
1520 const union_type = ip.loadUnionType(ty.toIntern());
1521 switch (strat) {
1522 .sema => try ty.resolveLayout(strat.pt(zcu, tid)),
1523 .lazy => {
1524 const pt = strat.pt(zcu, tid);
1525 if (!union_type.flagsUnordered(ip).status.haveLayout()) return .{
1526 .val = Value.fromInterned(try pt.intern(.{ .int = .{
1527 .ty = .comptime_int_type,
1528 .storage = .{ .lazy_size = ty.toIntern() },
1529 } })),
1530 };
1531 },
1532 .eager => {},
1533 }
1534
1535 assert(union_type.haveLayout(ip));
1536 return .{ .scalar = union_type.sizeUnordered(ip) };
880 };
881 return ty.abiAlignment(zcu).forward(bytes);
882 },
883 .opt_type => |child_ty_ip| {
884 const child_ty: Type = .fromInterned(child_ty_ip);
885 if (child_ty.isNoReturn(zcu)) return 0;
886 const child_size = child_ty.abiSize(zcu);
887 if (ty.optionalReprIsPayload(zcu)) return child_size;
888 // Optional types are represented as a struct with the child type as the first
889 // field and a boolean as the second. Since the child type's abi alignment is
890 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
891 // to the child type's ABI alignment.
892 return child_size + child_ty.abiAlignment(zcu).toByteUnits().?;
893 },
894 .error_set_type, .inferred_error_set_type => errorAbiSize(zcu),
895 .error_union_type => |error_union| {
896 const payload_ty: Type = .fromInterned(error_union.payload_type);
897 // This code needs to be kept in sync with the equivalent switch prong
898 // in abiAlignmentInner.
899 const code_size = errorAbiSize(zcu);
900 const code_align = errorAbiAlignment(zcu);
901 const payload_size = payload_ty.abiSize(zcu);
902 const payload_align = payload_ty.abiAlignment(zcu);
903 // The layout will either be (code, payload, padding) or (payload, code, padding)
904 // depending on which has larger alignment. So the overall size is just the code
905 // and payload sizes added and padded to the larger alignment.
906 const big_align = code_align.maxStrict(payload_align);
907 return big_align.forward(payload_size + code_size);
908 },
909 .func_type => 0,
910 .simple_type => |t| switch (t) {
911 .void,
912 .noreturn,
913 .type,
914 .comptime_int,
915 .comptime_float,
916 .null,
917 .undefined,
918 .enum_literal,
919 => 0,
920
921 .bool => 1,
922 .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu),
923 .usize, .isize => ptrAbiSize(target),
924
925 .c_char => target.cTypeByteSize(.char),
926 .c_short => target.cTypeByteSize(.short),
927 .c_ushort => target.cTypeByteSize(.ushort),
928 .c_int => target.cTypeByteSize(.int),
929 .c_uint => target.cTypeByteSize(.uint),
930 .c_long => target.cTypeByteSize(.long),
931 .c_ulong => target.cTypeByteSize(.ulong),
932 .c_longlong => target.cTypeByteSize(.longlong),
933 .c_ulonglong => target.cTypeByteSize(.ulonglong),
934 .c_longdouble => target.cTypeByteSize(.longdouble),
935
936 .f16 => 2,
937 .f32 => 4,
938 .f64 => 8,
939 .f80 => switch (target.cTypeBitSize(.longdouble)) {
940 80 => target.cTypeByteSize(.longdouble),
941 else => Type.u80.abiSize(zcu),
1537942 },
1538 .opaque_type => unreachable, // no size available
1539 .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(zcu) },
943 .f128 => 16,
1540944
1541 // values, not types
1542 .undef,
1543 .simple_value,
1544 .variable,
1545 .@"extern",
1546 .func,
1547 .int,
1548 .err,
1549 .error_union,
1550 .enum_literal,
1551 .enum_tag,
1552 .empty_enum_value,
1553 .float,
1554 .ptr,
1555 .slice,
1556 .opt,
1557 .aggregate,
1558 .un,
1559 // memoization, not types
1560 .memoized_call,
1561 => unreachable,
945 .anyopaque => unreachable,
946 .generic_poison => unreachable,
1562947 },
1563 }
1564}
1565
1566fn abiSizeInnerOptional(
1567 ty: Type,
1568 comptime strat: ResolveStratLazy,
1569 zcu: strat.ZcuPtr(),
1570 tid: strat.Tid(),
1571) SemaError!AbiSizeInner {
1572 const child_ty = ty.optionalChild(zcu);
1573
1574 if (child_ty.isNoReturn(zcu)) {
1575 return .{ .scalar = 0 };
1576 }
1577
1578 if (!(child_ty.hasRuntimeBitsInner(false, strat, zcu, tid) catch |err| switch (err) {
1579 error.NeedLazy => if (strat == .lazy) {
1580 const pt = strat.pt(zcu, tid);
1581 return .{ .val = Value.fromInterned(try pt.intern(.{ .int = .{
1582 .ty = .comptime_int_type,
1583 .storage = .{ .lazy_size = ty.toIntern() },
1584 } })) };
1585 } else unreachable,
1586 else => |e| return e,
1587 })) return .{ .scalar = 1 };
1588
1589 if (ty.optionalReprIsPayload(zcu)) {
1590 return child_ty.abiSizeInner(strat, zcu, tid);
1591 }
1592
1593 const payload_size = switch (try child_ty.abiSizeInner(strat, zcu, tid)) {
1594 .scalar => |elem_size| elem_size,
1595 .val => switch (strat) {
1596 .sema => unreachable,
1597 .eager => unreachable,
1598 .lazy => return .{ .val = Value.fromInterned(try strat.pt(zcu, tid).intern(.{ .int = .{
1599 .ty = .comptime_int_type,
1600 .storage = .{ .lazy_size = ty.toIntern() },
1601 } })) },
948 .tuple_type => |tuple| ty.structFieldOffset(tuple.types.len, zcu),
949 .struct_type => {
950 const struct_obj = ip.loadStructType(ty.toIntern());
951 switch (struct_obj.layout) {
952 .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).abiSize(zcu),
953 .auto, .@"extern" => return struct_obj.size,
954 }
1602955 },
1603 };
956 .union_type => {
957 const union_obj = ip.loadUnionType(ty.toIntern());
958 switch (union_obj.layout) {
959 .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).abiSize(zcu),
960 .auto, .@"extern" => return union_obj.size,
961 }
962 },
963 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).abiSize(zcu),
964 .opaque_type => unreachable,
1604965
1605 // Optional types are represented as a struct with the child type as the first
1606 // field and a boolean as the second. Since the child type's abi alignment is
1607 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1608 // to the child type's ABI alignment.
1609 return .{
1610 .scalar = (child_ty.abiAlignment(zcu).toByteUnits() orelse 0) + payload_size,
966 // values, not types
967 .undef,
968 .simple_value,
969 .variable,
970 .@"extern",
971 .func,
972 .int,
973 .err,
974 .error_union,
975 .enum_literal,
976 .enum_tag,
977 .empty_enum_value,
978 .float,
979 .ptr,
980 .slice,
981 .opt,
982 .aggregate,
983 .un,
984 // memoization, not types
985 .memoized_call,
986 => unreachable,
1611987 };
1612988}
1613989
1614990pub fn ptrAbiAlignment(target: *const Target) Alignment {
1615 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
991 return .fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1616992}
1617
1618pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
1619 return bitSizeInner(ty, .normal, zcu, {}) catch unreachable;
993pub fn ptrAbiSize(target: *const Target) u64 {
994 return @divExact(target.ptrBitWidth(), 8);
1620995}
1621
1622pub fn bitSizeSema(ty: Type, pt: Zcu.PerThread) SemaError!u64 {
1623 return bitSizeInner(ty, .sema, pt.zcu, pt.tid);
996pub fn errorAbiAlignment(zcu: *const Zcu) Alignment {
997 return .fromNonzeroByteUnits(std.zig.target.intAlignment(zcu.getTarget(), zcu.errorSetBits()));
998}
999pub fn errorAbiSize(zcu: *const Zcu) u64 {
1000 return std.zig.target.intByteSize(zcu.getTarget(), zcu.errorSetBits());
16241001}
16251002
1626pub fn bitSizeInner(
1627 ty: Type,
1628 comptime strat: ResolveStrat,
1629 zcu: strat.ZcuPtr(),
1630 tid: strat.Tid(),
1631) SemaError!u64 {
1003/// Asserts that `ty` is not an opaque or comptime-only type.
1004/// Once #19755 is implemented, this query will only work on types with a defined bit-level representation.
1005pub fn bitSize(ty: Type, zcu: *const Zcu) u64 {
16321006 const target = zcu.getTarget();
16331007 const ip = &zcu.intern_pool;
1634
1635 const strat_lazy: ResolveStratLazy = strat.toLazy();
1636
1637 switch (ip.indexToKey(ty.toIntern())) {
1638 .int_type => |int_type| return int_type.bits,
1008 assertHasLayout(ty, zcu);
1009 return switch (ip.indexToKey(ty.toIntern())) {
1010 .int_type => |int_type| int_type.bits,
16391011 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1640 .slice => return target.ptrBitWidth() * 2,
1641 else => return target.ptrBitWidth(),
1012 .slice => target.ptrBitWidth() * 2,
1013 else => target.ptrBitWidth(),
16421014 },
1643 .anyframe_type => return target.ptrBitWidth(),
1644
1015 .anyframe_type => target.ptrBitWidth(),
16451016 .array_type => |array_type| {
1646 const len = array_type.lenIncludingSentinel();
1647 if (len == 0) return 0;
16481017 const elem_ty: Type = .fromInterned(array_type.child);
1649 switch (zcu.comp.getZigBackend()) {
1650 else => {
1651 const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar;
1652 if (elem_size == 0) return 0;
1653 const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
1654 return (len - 1) * 8 * elem_size + elem_bit_size;
1655 },
1656 .stage2_x86_64 => {
1657 const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid);
1658 return elem_bit_size * len;
1018 const len = array_type.lenIncludingSentinel();
1019 return switch (zcu.comp.getZigBackend()) {
1020 .stage2_x86_64 => len * elem_ty.bitSize(zcu),
1021 // this case will be removed under #19755
1022 else => switch (len) {
1023 0 => 0,
1024 else => (len - 1) * 8 * elem_ty.abiSize(zcu) + elem_ty.bitSize(zcu),
16591025 },
1660 }
1661 },
1662 .vector_type => |vector_type| {
1663 const child_ty: Type = .fromInterned(vector_type.child);
1664 const elem_bit_size = try child_ty.bitSizeInner(strat, zcu, tid);
1665 return elem_bit_size * vector_type.len;
1666 },
1667 .opt_type => {
1668 // Optionals and error unions are not packed so their bitsize
1669 // includes padding bits.
1670 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1026 };
16711027 },
1028 .vector_type => |vec| vec.len * Type.fromInterned(vec.child).bitSize(zcu),
1029 .error_set_type, .inferred_error_set_type => zcu.errorSetBits(),
1030 .func_type => unreachable,
16721031
1673 .error_set_type, .inferred_error_set_type => return zcu.errorSetBits(),
1674
1675 .error_union_type => {
1676 // Optionals and error unions are not packed so their bitsize
1677 // includes padding bits.
1678 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1679 },
1680 .func_type => unreachable, // represents machine code; not a pointer
16811032 .simple_type => |t| switch (t) {
1682 .f16 => return 16,
1683 .f32 => return 32,
1684 .f64 => return 64,
1685 .f80 => return 80,
1686 .f128 => return 128,
1687
1688 .usize,
1689 .isize,
1690 => return target.ptrBitWidth(),
1691
1692 .c_char => return target.cTypeBitSize(.char),
1693 .c_short => return target.cTypeBitSize(.short),
1694 .c_ushort => return target.cTypeBitSize(.ushort),
1695 .c_int => return target.cTypeBitSize(.int),
1696 .c_uint => return target.cTypeBitSize(.uint),
1697 .c_long => return target.cTypeBitSize(.long),
1698 .c_ulong => return target.cTypeBitSize(.ulong),
1699 .c_longlong => return target.cTypeBitSize(.longlong),
1700 .c_ulonglong => return target.cTypeBitSize(.ulonglong),
1701 .c_longdouble => return target.cTypeBitSize(.longdouble),
1702
1703 .bool => return 1,
1704 .void => return 0,
1705
1706 .anyerror,
1707 .adhoc_inferred_error_set,
1708 => return zcu.errorSetBits(),
1033 .void => 0,
1034 .bool => 1,
1035 .anyerror, .adhoc_inferred_error_set => zcu.errorSetBits(),
1036 .usize, .isize => target.ptrBitWidth(),
1037
1038 .c_char => target.cTypeBitSize(.char),
1039 .c_short => target.cTypeBitSize(.short),
1040 .c_ushort => target.cTypeBitSize(.ushort),
1041 .c_int => target.cTypeBitSize(.int),
1042 .c_uint => target.cTypeBitSize(.uint),
1043 .c_long => target.cTypeBitSize(.long),
1044 .c_ulong => target.cTypeBitSize(.ulong),
1045 .c_longlong => target.cTypeBitSize(.longlong),
1046 .c_ulonglong => target.cTypeBitSize(.ulonglong),
1047 .c_longdouble => target.cTypeBitSize(.longdouble),
1048
1049 .f16 => 16,
1050 .f32 => 32,
1051 .f64 => 64,
1052 .f80 => 80,
1053 .f128 => 128,
17091054
17101055 .anyopaque => unreachable,
17111056 .type => unreachable,
......@@ -1717,49 +1062,30 @@ pub fn bitSizeInner(
17171062 .enum_literal => unreachable,
17181063 .generic_poison => unreachable,
17191064 },
1065
17201066 .struct_type => {
1721 const struct_type = ip.loadStructType(ty.toIntern());
1722 const is_packed = struct_type.layout == .@"packed";
1723 if (strat == .sema) {
1724 const pt = strat.pt(zcu, tid);
1725 try ty.resolveFields(pt);
1726 if (is_packed) try ty.resolveLayout(pt);
1727 }
1728 if (is_packed) {
1729 return try Type.fromInterned(struct_type.backingIntTypeUnordered(ip))
1730 .bitSizeInner(strat, zcu, tid);
1067 const struct_obj = ip.loadStructType(ty.toIntern());
1068 switch (struct_obj.layout) {
1069 .@"packed" => return Type.fromInterned(struct_obj.packed_backing_int_type).bitSize(zcu),
1070 .auto, .@"extern" => return struct_obj.size * 8, // will be `unreachable` under #19755
17311071 }
1732 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1733 },
1734
1735 .tuple_type => {
1736 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
17371072 },
1738
17391073 .union_type => {
1740 const union_type = ip.loadUnionType(ty.toIntern());
1741 const is_packed = ty.containerLayout(zcu) == .@"packed";
1742 if (strat == .sema) {
1743 const pt = strat.pt(zcu, tid);
1744 try ty.resolveFields(pt);
1745 if (is_packed) try ty.resolveLayout(pt);
1746 }
1747 if (!is_packed) {
1748 return (try ty.abiSizeInner(strat_lazy, zcu, tid)).scalar * 8;
1074 const union_obj = ip.loadUnionType(ty.toIntern());
1075 switch (union_obj.layout) {
1076 .@"packed" => return Type.fromInterned(union_obj.packed_backing_int_type).bitSize(zcu),
1077 .auto, .@"extern" => return union_obj.size * 8, // will be `unreachable` under #19755
17491078 }
1750 assert(union_type.flagsUnordered(ip).status.haveFieldTypes());
1079 },
1080 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).bitSize(zcu),
17511081
1752 var size: u64 = 0;
1753 for (0..union_type.field_types.len) |field_index| {
1754 const field_ty = union_type.field_types.get(ip)[field_index];
1755 size = @max(size, try Type.fromInterned(field_ty).bitSizeInner(strat, zcu, tid));
1756 }
1082 // will be `unreachable` under #19755
1083 .opt_type,
1084 .error_union_type,
1085 .tuple_type,
1086 => ty.abiSize(zcu) * 8,
17571087
1758 return size;
1759 },
17601088 .opaque_type => unreachable,
1761 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty)
1762 .bitSizeInner(strat, zcu, tid),
17631089
17641090 // values, not types
17651091 .undef,
......@@ -1782,23 +1108,6 @@ pub fn bitSizeInner(
17821108 // memoization, not types
17831109 .memoized_call,
17841110 => unreachable,
1785 }
1786}
1787
1788/// Returns true if the type's layout is already resolved and it is safe
1789/// to use `abiSize`, `abiAlignment` and `bitSize` on it.
1790pub fn layoutIsResolved(ty: Type, zcu: *const Zcu) bool {
1791 const ip = &zcu.intern_pool;
1792 return switch (ip.indexToKey(ty.toIntern())) {
1793 .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
1794 .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
1795 .array_type => |array_type| {
1796 if (array_type.lenIncludingSentinel() == 0) return true;
1797 return Type.fromInterned(array_type.child).layoutIsResolved(zcu);
1798 },
1799 .opt_type => |child| Type.fromInterned(child).layoutIsResolved(zcu),
1800 .error_union_type => |k| Type.fromInterned(k.payload_type).layoutIsResolved(zcu),
1801 else => true,
18021111 };
18031112}
18041113
......@@ -1841,7 +1150,7 @@ pub fn isSliceAtRuntime(ty: Type, zcu: *const Zcu) bool {
18411150}
18421151
18431152pub fn slicePtrFieldType(ty: Type, zcu: *const Zcu) Type {
1844 return Type.fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern()));
1153 return .fromInterned(zcu.intern_pool.slicePtrType(ty.toIntern()));
18451154}
18461155
18471156pub fn isConstPtr(ty: Type, zcu: *const Zcu) bool {
......@@ -1897,10 +1206,7 @@ pub fn isPtrAtRuntime(ty: Type, zcu: *const Zcu) bool {
18971206/// For pointer-like optionals, returns true, otherwise returns the allowzero property
18981207/// of pointers.
18991208pub fn ptrAllowsZero(ty: Type, zcu: *const Zcu) bool {
1900 if (ty.isPtrLikeOptional(zcu)) {
1901 return true;
1902 }
1903 return ty.ptrInfo(zcu).flags.is_allowzero;
1209 return ty.isPtrLikeOptional(zcu) or ty.ptrInfo(zcu).flags.is_allowzero;
19041210}
19051211
19061212/// See also `isPtrLikeOptional`.
......@@ -1918,7 +1224,6 @@ pub fn optionalReprIsPayload(ty: Type, zcu: *const Zcu) bool {
19181224
19191225/// Returns true if the type is optional and would be lowered to a single pointer
19201226/// address value, using 0 for null. Note that this returns true for C pointers.
1921/// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
19221227pub fn isPtrLikeOptional(ty: Type, zcu: *const Zcu) bool {
19231228 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
19241229 .ptr_type => |ptr_type| ptr_type.flags.size == .c,
......@@ -1947,52 +1252,75 @@ pub fn childTypeIp(ty: Type, ip: *const InternPool) Type {
19471252 return Type.fromInterned(ip.childType(ty.toIntern()));
19481253}
19491254
1950/// For `*[N]T`, returns `T`.
1951/// For `?*T`, returns `T`.
1952/// For `?*[N]T`, returns `T`.
1953/// For `?[*]T`, returns `T`.
1954/// For `*T`, returns `T`.
1955/// For `[*]T`, returns `T`.
1956/// For `[N]T`, returns `T`.
1957/// For `[]T`, returns `T`.
1958/// For `anyframe->T`, returns `T`.
1959pub fn elemType2(ty: Type, zcu: *const Zcu) Type {
1960 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
1961 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1962 .one => Type.fromInterned(ptr_type.child).shallowElemType(zcu),
1963 .many, .c, .slice => Type.fromInterned(ptr_type.child),
1964 },
1965 .anyframe_type => |child| {
1966 assert(child != .none);
1967 return Type.fromInterned(child);
1255/// Similar to `childType`, but for pointer-like (or slice-like) optionals, gets the child type
1256/// of the *pointer* type. Asserts that `ty` is either a pointer or a pointer-like optional.
1257///
1258/// Essentially, unwraps any one of the following into `T`:
1259/// ```
1260/// *T ?*T *allowzero T
1261/// [*]T ?[*]T [*]allowzero T
1262/// []T ?[]T []allowzero T
1263/// [*c]T
1264/// ```
1265/// This is primarily useful in Sema to implement operations which can act on optional pointers.
1266pub fn nullablePtrElem(ty: Type, zcu: *const Zcu) Type {
1267 switch (ty.zigTypeTag(zcu)) {
1268 .pointer => return ty.childType(zcu),
1269 .optional => {
1270 const ptr_ty = ty.childType(zcu);
1271 const ptr_info = zcu.intern_pool.indexToKey(ptr_ty.toIntern()).ptr_type;
1272 assert(ptr_info.flags.size != .c);
1273 assert(!ptr_info.flags.is_allowzero);
1274 return .fromInterned(ptr_info.child);
19681275 },
1969 .vector_type => |vector_type| Type.fromInterned(vector_type.child),
1970 .array_type => |array_type| Type.fromInterned(array_type.child),
1971 .opt_type => |child| Type.fromInterned(zcu.intern_pool.childType(child)),
19721276 else => unreachable,
1973 };
1277 }
19741278}
19751279
19761280/// Given that `ty` is an indexable pointer, returns its element type. Specifically:
19771281/// * for `*[n]T`, returns `T`
1282/// * for `*@Vector(n, T)`, returns `T`
19781283/// * for `[]T`, returns `T`
19791284/// * for `[*]T`, returns `T`
19801285/// * for `[*c]T`, returns `T`
1286///
1287/// Tuples are not supported because they do not have a single element type.
1288///
1289/// MLUGG TODO: should i even have this one? it's a subset of indexableElem
19811290pub fn indexablePtrElem(ty: Type, zcu: *const Zcu) Type {
19821291 const ip = &zcu.intern_pool;
19831292 const ptr_type = ip.indexToKey(ty.toIntern()).ptr_type;
1984 switch (ptr_type.flags.size) {
1293 return switch (ptr_type.flags.size) {
19851294 .many, .slice, .c => return .fromInterned(ptr_type.child),
1986 .one => {},
1987 }
1988 const array_type = ip.indexToKey(ptr_type.child).array_type;
1989 return .fromInterned(array_type.child);
1295 .one => switch (ip.indexToKey(ptr_type.child)) {
1296 inline .array_type, .vector_type => |arr| return .fromInterned(arr.child),
1297 else => unreachable,
1298 },
1299 };
19901300}
19911301
1992fn shallowElemType(child_ty: Type, zcu: *const Zcu) Type {
1993 return switch (child_ty.zigTypeTag(zcu)) {
1994 .array, .vector => child_ty.childType(zcu),
1995 else => child_ty,
1302/// Given that `ty` is an indexable type, returns its element type. Specifically:
1303/// * for `[n]T`, returns `T`
1304/// * for `@Vector(n, T)`, returns `T`
1305/// * for `*[n]T`, returns `T`
1306/// * for `*@Vector(n, T)`, returns `T`
1307/// * for `[]T`, returns `T`
1308/// * for `[*]T`, returns `T`
1309/// * for `[*c]T`, returns `T`
1310///
1311/// Tuples are not supported because they do not have a single element type.
1312pub fn indexableElem(ty: Type, zcu: *const Zcu) Type {
1313 const ip = &zcu.intern_pool;
1314 return switch (ip.indexToKey(ty.toIntern())) {
1315 inline .array_type, .vector_type => |arr| .fromInterned(arr.child),
1316 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1317 .many, .slice, .c => .fromInterned(ptr_type.child),
1318 .one => switch (ip.indexToKey(ptr_type.child)) {
1319 inline .array_type, .vector_type => |arr| .fromInterned(arr.child),
1320 else => unreachable,
1321 },
1322 },
1323 else => unreachable,
19961324 };
19971325}
19981326
......@@ -2004,17 +1332,17 @@ pub fn scalarType(ty: Type, zcu: *const Zcu) Type {
20041332 };
20051333}
20061334
2007/// Asserts that the type is an optional.
2008/// Note that for C pointers this returns the type unmodified.
1335/// Asserts that the type is an optional, or a C pointer.
1336/// For C pointers this returns the type unmodified.
20091337pub fn optionalChild(ty: Type, zcu: *const Zcu) Type {
2010 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
2011 .opt_type => |child| Type.fromInterned(child),
2012 .ptr_type => |ptr_type| b: {
1338 switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
1339 .opt_type => |child| return .fromInterned(child),
1340 .ptr_type => |ptr_type| {
20131341 assert(ptr_type.flags.size == .c);
2014 break :b ty;
1342 return ty;
20151343 },
20161344 else => unreachable,
2017 };
1345 }
20181346}
20191347
20201348/// Returns the tag type of a union, if the type is a union and it has a tag type.
......@@ -2025,15 +1353,11 @@ pub fn unionTagType(ty: Type, zcu: *const Zcu) ?Type {
20251353 .union_type => {},
20261354 else => return null,
20271355 }
2028 const union_type = ip.loadUnionType(ty.toIntern());
2029 const union_flags = union_type.flagsUnordered(ip);
2030 switch (union_flags.runtime_tag) {
2031 .tagged => {
2032 assert(union_flags.status.haveFieldTypes());
2033 return Type.fromInterned(union_type.enum_tag_ty);
2034 },
2035 else => return null,
2036 }
1356 const union_obj = ip.loadUnionType(ty.toIntern());
1357 return switch (union_obj.runtime_tag) {
1358 .tagged => .fromInterned(union_obj.enum_tag_type),
1359 .none, .safety => null,
1360 };
20371361}
20381362
20391363/// Same as `unionTagType` but includes safety tag.
......@@ -2043,9 +1367,8 @@ pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type {
20431367 return switch (ip.indexToKey(ty.toIntern())) {
20441368 .union_type => {
20451369 const union_type = ip.loadUnionType(ty.toIntern());
2046 if (!union_type.hasTag(ip)) return null;
2047 assert(union_type.haveFieldTypes(ip));
2048 return Type.fromInterned(union_type.enum_tag_ty);
1370 if (union_type.runtime_tag == .none) return null;
1371 return Type.fromInterned(union_type.enum_tag_type);
20491372 },
20501373 else => null,
20511374 };
......@@ -2055,7 +1378,7 @@ pub fn unionTagTypeSafety(ty: Type, zcu: *const Zcu) ?Type {
20551378/// not be stored at runtime.
20561379pub fn unionTagTypeHypothetical(ty: Type, zcu: *const Zcu) Type {
20571380 const union_obj = zcu.typeToUnion(ty).?;
2058 return Type.fromInterned(union_obj.enum_tag_ty);
1381 return Type.fromInterned(union_obj.enum_tag_type);
20591382}
20601383
20611384pub fn unionFieldType(ty: Type, enum_tag: Value, zcu: *const Zcu) ?Type {
......@@ -2105,9 +1428,9 @@ pub fn unionGetLayout(ty: Type, zcu: *const Zcu) Zcu.UnionLayout {
21051428pub fn containerLayout(ty: Type, zcu: *const Zcu) std.builtin.Type.ContainerLayout {
21061429 const ip = &zcu.intern_pool;
21071430 return switch (ip.indexToKey(ty.toIntern())) {
2108 .struct_type => ip.loadStructType(ty.toIntern()).layout,
21091431 .tuple_type => .auto,
2110 .union_type => ip.loadUnionType(ty.toIntern()).flagsUnordered(ip).layout,
1432 .struct_type => ip.loadStructType(ty.toIntern()).layout,
1433 .union_type => ip.loadUnionType(ty.toIntern()).layout,
21111434 else => unreachable,
21121435 };
21131436}
......@@ -2182,33 +1505,6 @@ pub fn errorSetHasFieldIp(
21821505 };
21831506}
21841507
2185/// Returns whether ty, which must be an error set, includes an error `name`.
2186/// Might return a false negative if `ty` is an inferred error set and not fully
2187/// resolved yet.
2188pub fn errorSetHasField(ty: Type, name: []const u8, zcu: *const Zcu) bool {
2189 const ip = &zcu.intern_pool;
2190 return switch (ty.toIntern()) {
2191 .anyerror_type => true,
2192 else => switch (ip.indexToKey(ty.toIntern())) {
2193 .error_set_type => |error_set_type| {
2194 // If the string is not interned, then the field certainly is not present.
2195 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2196 return error_set_type.nameIndex(ip, field_name_interned) != null;
2197 },
2198 .inferred_error_set_type => |i| switch (ip.funcIesResolvedUnordered(i)) {
2199 .anyerror_type => true,
2200 .none => false,
2201 else => |t| {
2202 // If the string is not interned, then the field certainly is not present.
2203 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2204 return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null;
2205 },
2206 },
2207 else => unreachable,
2208 },
2209 };
2210}
2211
22121508/// Asserts the type is an array or vector or struct.
22131509pub fn arrayLen(ty: Type, zcu: *const Zcu) u64 {
22141510 return ty.arrayLenIp(&zcu.intern_pool);
......@@ -2308,8 +1604,12 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
23081604 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) },
23091605 else => switch (ip.indexToKey(ty.toIntern())) {
23101606 .int_type => |int_type| return int_type,
2311 .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntTypeUnordered(ip)),
2312 .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
1607 .struct_type => {
1608 const struct_obj = ip.loadStructType(ty.toIntern());
1609 assert(struct_obj.layout == .@"packed");
1610 ty = .fromInterned(struct_obj.packed_backing_int_type);
1611 },
1612 .enum_type => ty = .fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type),
23131613 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
23141614
23151615 .error_set_type, .inferred_error_set_type => {
......@@ -2355,25 +1655,6 @@ pub fn intInfo(starting_ty: Type, zcu: *const Zcu) InternPool.Key.IntType {
23551655 };
23561656}
23571657
2358pub fn isNamedInt(ty: Type) bool {
2359 return switch (ty.toIntern()) {
2360 .usize_type,
2361 .isize_type,
2362 .c_char_type,
2363 .c_short_type,
2364 .c_ushort_type,
2365 .c_int_type,
2366 .c_uint_type,
2367 .c_long_type,
2368 .c_ulong_type,
2369 .c_longlong_type,
2370 .c_ulonglong_type,
2371 => true,
2372
2373 else => false,
2374 };
2375}
2376
23771658/// Returns `false` for `comptime_float`.
23781659pub fn isRuntimeFloat(ty: Type) bool {
23791660 return switch (ty.toIntern()) {
......@@ -2488,17 +1769,16 @@ pub fn isNumeric(ty: Type, zcu: *const Zcu) bool {
24881769 };
24891770}
24901771
2491/// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
2492/// resolves field types rather than asserting they are already resolved.
1772/// MLUGG TODO: deal with our friends structs and unions
24931773pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
24941774 const zcu = pt.zcu;
24951775 const comp = zcu.comp;
24961776 const gpa = comp.gpa;
2497 const io = comp.io;
24981777 const ip = &zcu.intern_pool;
1778 assertHasLayout(starting_type, zcu);
24991779 var ty = starting_type;
25001780 while (true) switch (ty.toIntern()) {
2501 .empty_tuple_type => return Value.empty_tuple,
1781 .empty_tuple_type => return .empty_tuple,
25021782
25031783 else => switch (ip.indexToKey(ty.toIntern())) {
25041784 .int_type => |int_type| {
......@@ -2563,31 +1843,37 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
25631843 .adhoc_inferred_error_set,
25641844 => return null,
25651845
2566 .void => return Value.void,
2567 .noreturn => return Value.@"unreachable",
2568 .null => return Value.null,
2569 .undefined => return Value.undef,
1846 .void => return .void,
1847 .noreturn => return .@"unreachable",
1848 .null => return .null,
1849 .undefined => return .undef,
25701850
25711851 .generic_poison => unreachable,
25721852 },
25731853 .struct_type => {
2574 const struct_type = ip.loadStructType(ty.toIntern());
2575 assert(struct_type.haveFieldTypes(ip));
2576 if (struct_type.knownNonOpv(ip))
2577 return null;
2578 const field_vals = try zcu.gpa.alloc(InternPool.Index, struct_type.field_types.len);
2579 defer zcu.gpa.free(field_vals);
1854 const struct_obj = ip.loadStructType(ty.toIntern());
1855 if (struct_obj.layout == .@"packed") {
1856 const backing_ty: Type = .fromInterned(struct_obj.packed_backing_int_type);
1857 const backing_val = try backing_ty.onePossibleValue(pt) orelse return null;
1858 _ = backing_val; // MLUGG TODO: represent unions as their bits!
1859 } else {
1860 if (!struct_obj.has_one_possible_value) return null;
1861 }
1862 // There is an OPV.
1863 const field_vals = try gpa.alloc(InternPool.Index, struct_obj.field_types.len);
1864 defer gpa.free(field_vals);
25801865 for (field_vals, 0..) |*field_val, i_usize| {
25811866 const i: u32 = @intCast(i_usize);
2582 if (struct_type.fieldIsComptime(ip, i)) {
2583 assert(struct_type.haveFieldInits(ip));
2584 field_val.* = struct_type.field_inits.get(ip)[i];
1867 if (struct_obj.field_is_comptime_bits.get(ip, i)) {
1868 // MLUGG TODO: this is kinda a problem... we don't necessarily know the opv field vals!
1869 // for now i'm just not letting structs with comptime fields be opv :)
1870 if (true) return null;
1871 assertHasInits(ty, zcu);
1872 field_val.* = struct_obj.field_defaults.get(ip)[i];
25851873 continue;
25861874 }
2587 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
2588 if (try field_ty.onePossibleValue(pt)) |field_opv| {
2589 field_val.* = field_opv.toIntern();
2590 } else return null;
1875 const field_ty = Type.fromInterned(struct_obj.field_types.get(ip)[i]);
1876 field_val.* = (try field_ty.onePossibleValue(pt)).?.toIntern();
25911877 }
25921878
25931879 // In this case the struct has no runtime-known fields and
......@@ -2623,12 +1909,13 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
26231909 },
26241910
26251911 .union_type => {
1912 // MLUGG TODO: is this nonsensical or what!!!!!!
26261913 const union_obj = ip.loadUnionType(ty.toIntern());
2627 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(pt)) orelse
1914 const tag_val = (try Type.fromInterned(union_obj.enum_tag_type).onePossibleValue(pt)) orelse
26281915 return null;
26291916 if (union_obj.field_types.len == 0) {
26301917 const only = try pt.intern(.{ .empty_enum_value = ty.toIntern() });
2631 return Value.fromInterned(only);
1918 return .fromInterned(only);
26321919 }
26331920 const only_field_ty = union_obj.field_types.get(ip)[0];
26341921 const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(pt)) orelse
......@@ -2638,47 +1925,34 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
26381925 .tag = tag_val.toIntern(),
26391926 .val = val_val.toIntern(),
26401927 });
2641 return Value.fromInterned(only);
1928 return .fromInterned(only);
26421929 },
26431930 .opaque_type => return null,
26441931 .enum_type => {
2645 const enum_type = ip.loadEnumType(ty.toIntern());
2646 switch (enum_type.tag_mode) {
2647 .nonexhaustive => {
2648 if (enum_type.tag_ty == .comptime_int_type) return null;
2649
2650 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(pt)) |int_opv| {
2651 const only = try pt.intern(.{ .enum_tag = .{
2652 .ty = ty.toIntern(),
2653 .int = int_opv.toIntern(),
2654 } });
2655 return Value.fromInterned(only);
2656 }
2657
2658 return null;
2659 },
2660 .auto, .explicit => {
2661 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(zcu)) return null;
2662
2663 return Value.fromInterned(switch (enum_type.names.len) {
2664 0 => try pt.intern(.{ .empty_enum_value = ty.toIntern() }),
2665 1 => try pt.intern(.{ .enum_tag = .{
2666 .ty = ty.toIntern(),
2667 .int = if (enum_type.values.len == 0)
2668 (try pt.intValue(.fromInterned(enum_type.tag_ty), 0)).toIntern()
2669 else
2670 try ip.getCoercedInts(
2671 gpa,
2672 io,
2673 pt.tid,
2674 ip.indexToKey(enum_type.values.get(ip)[0]).int,
2675 enum_type.tag_ty,
2676 ),
2677 } }),
2678 else => return null,
2679 });
2680 },
1932 const enum_obj = ip.loadEnumType(ty.toIntern());
1933 if (enum_obj.nonexhaustive) {
1934 const int_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null;
1935 return .fromInterned(try pt.intern(.{ .enum_tag = .{
1936 .ty = ty.toIntern(),
1937 .int = int_opv.toIntern(),
1938 } }));
1939 }
1940 // MLUGG TODO: this is to preserve existing semantics, i REALLY don't fuck with it...
1941 if (enum_obj.int_tag_type == .comptime_int_type) {
1942 return switch (enum_obj.field_names.len) {
1943 0 => .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() })),
1944 1 => try pt.enumValueFieldIndex(ty, 0),
1945 else => null,
1946 };
26811947 }
1948 const int_tag_opv = try Type.fromInterned(enum_obj.int_tag_type).onePossibleValue(pt) orelse return null;
1949 if (enum_obj.field_names.len == 0) {
1950 return .fromInterned(try pt.intern(.{ .empty_enum_value = ty.toIntern() }));
1951 }
1952 return .fromInterned(try pt.intern(.{ .enum_tag = .{
1953 .ty = ty.toIntern(),
1954 .int = int_tag_opv.toIntern(),
1955 } }));
26821956 },
26831957
26841958 // values, not types
......@@ -2706,211 +1980,106 @@ pub fn onePossibleValue(starting_type: Type, pt: Zcu.PerThread) !?Value {
27061980 };
27071981}
27081982
2709/// During semantic analysis, instead call `ty.comptimeOnlySema` which
2710/// resolves field types rather than asserting they are already resolved.
1983/// Asserts that `ty` has its layout resolved. `generic_poison` will return `false`.
27111984pub fn comptimeOnly(ty: Type, zcu: *const Zcu) bool {
2712 return ty.comptimeOnlyInner(.normal, zcu, {}) catch unreachable;
2713}
2714
2715pub fn comptimeOnlySema(ty: Type, pt: Zcu.PerThread) SemaError!bool {
2716 return try ty.comptimeOnlyInner(.sema, pt.zcu, pt.tid);
2717}
2718
2719/// `generic_poison` will return false.
2720/// May return false negatives when structs and unions are having their field types resolved.
2721pub fn comptimeOnlyInner(
2722 ty: Type,
2723 comptime strat: ResolveStrat,
2724 zcu: strat.ZcuPtr(),
2725 tid: strat.Tid(),
2726) SemaError!bool {
27271985 const ip = &zcu.intern_pool;
2728 const io = zcu.comp.io;
2729 return switch (ty.toIntern()) {
2730 .empty_tuple_type => false,
2731
2732 else => switch (ip.indexToKey(ty.toIntern())) {
2733 .int_type => false,
2734 .ptr_type => |ptr_type| {
2735 const child_ty = Type.fromInterned(ptr_type.child);
2736 switch (child_ty.zigTypeTag(zcu)) {
2737 .@"fn" => return !try child_ty.fnHasRuntimeBitsInner(strat, zcu, tid),
2738 .@"opaque" => return false,
2739 else => return child_ty.comptimeOnlyInner(strat, zcu, tid),
2740 }
2741 },
2742 .anyframe_type => |child| {
2743 if (child == .none) return false;
2744 return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid);
2745 },
2746 .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnlyInner(strat, zcu, tid),
2747 .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnlyInner(strat, zcu, tid),
2748 .opt_type => |child| return Type.fromInterned(child).comptimeOnlyInner(strat, zcu, tid),
2749 .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnlyInner(strat, zcu, tid),
2750
2751 .error_set_type,
2752 .inferred_error_set_type,
2753 => false,
2754
2755 // These are function bodies, not function pointers.
2756 .func_type => true,
2757
2758 .simple_type => |t| switch (t) {
2759 .f16,
2760 .f32,
2761 .f64,
2762 .f80,
2763 .f128,
2764 .usize,
2765 .isize,
2766 .c_char,
2767 .c_short,
2768 .c_ushort,
2769 .c_int,
2770 .c_uint,
2771 .c_long,
2772 .c_ulong,
2773 .c_longlong,
2774 .c_ulonglong,
2775 .c_longdouble,
2776 .anyopaque,
2777 .bool,
2778 .void,
2779 .anyerror,
2780 .adhoc_inferred_error_set,
2781 .noreturn,
2782 .generic_poison,
2783 => false,
2784
2785 .type,
2786 .comptime_int,
2787 .comptime_float,
2788 .null,
2789 .undefined,
2790 .enum_literal,
2791 => true,
2792 },
2793 .struct_type => {
2794 const struct_type = ip.loadStructType(ty.toIntern());
2795 // packed structs cannot be comptime-only because they have a well-defined
2796 // memory layout and every field has a well-defined bit pattern.
2797 if (struct_type.layout == .@"packed")
2798 return false;
2799
2800 return switch (strat) {
2801 .normal => switch (struct_type.requiresComptime(ip)) {
2802 .wip => unreachable,
2803 .no => false,
2804 .yes => true,
2805 .unknown => unreachable,
2806 },
2807 .sema => switch (struct_type.setRequiresComptimeWip(ip, io)) {
2808 .no, .wip => false,
2809 .yes => true,
2810 .unknown => {
2811 if (struct_type.flagsUnordered(ip).field_types_wip) {
2812 struct_type.setRequiresComptime(ip, io, .unknown);
2813 return false;
2814 }
2815
2816 errdefer struct_type.setRequiresComptime(ip, io, .unknown);
2817
2818 const pt = strat.pt(zcu, tid);
2819 try ty.resolveFields(pt);
2820
2821 for (0..struct_type.field_types.len) |i_usize| {
2822 const i: u32 = @intCast(i_usize);
2823 if (struct_type.fieldIsComptime(ip, i)) continue;
2824 const field_ty = struct_type.field_types.get(ip)[i];
2825 if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) {
2826 // Note that this does not cause the layout to
2827 // be considered resolved. Comptime-only types
2828 // still maintain a layout of their
2829 // runtime-known fields.
2830 struct_type.setRequiresComptime(ip, io, .yes);
2831 return true;
2832 }
2833 }
2834
2835 struct_type.setRequiresComptime(ip, io, .no);
2836 return false;
2837 },
2838 },
2839 };
2840 },
2841
2842 .tuple_type => |tuple| {
2843 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2844 const have_comptime_val = val != .none;
2845 if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) return true;
2846 }
2847 return false;
2848 },
1986 return switch (ip.indexToKey(ty.toIntern())) {
1987 .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnly(zcu),
1988 .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnly(zcu),
1989 .opt_type => |child| return Type.fromInterned(child).comptimeOnly(zcu),
1990 .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnly(zcu),
1991 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).int_tag_type).comptimeOnly(zcu),
28491992
2850 .union_type => {
2851 const union_type = ip.loadUnionType(ty.toIntern());
2852 return switch (strat) {
2853 .normal => switch (union_type.requiresComptime(ip)) {
2854 .wip => unreachable,
2855 .no => false,
2856 .yes => true,
2857 .unknown => unreachable,
2858 },
2859 .sema => switch (union_type.setRequiresComptimeWip(ip, io)) {
2860 .no, .wip => return false,
2861 .yes => return true,
2862 .unknown => {
2863 if (union_type.flagsUnordered(ip).status == .field_types_wip) {
2864 union_type.setRequiresComptime(ip, io, .unknown);
2865 return false;
2866 }
2867
2868 errdefer union_type.setRequiresComptime(ip, io, .unknown);
2869
2870 const pt = strat.pt(zcu, tid);
2871 try ty.resolveFields(pt);
2872
2873 for (0..union_type.field_types.len) |field_idx| {
2874 const field_ty = union_type.field_types.get(ip)[field_idx];
2875 if (try Type.fromInterned(field_ty).comptimeOnlyInner(strat, zcu, tid)) {
2876 union_type.setRequiresComptime(ip, io, .yes);
2877 return true;
2878 }
2879 }
2880
2881 union_type.setRequiresComptime(ip, io, .no);
2882 return false;
2883 },
2884 },
2885 };
2886 },
1993 .int_type,
1994 .ptr_type,
1995 .anyframe_type,
1996 .error_set_type,
1997 .inferred_error_set_type,
1998 .opaque_type,
1999 => false,
28872000
2888 .opaque_type => false,
2001 // These are function bodies, not function pointers.
2002 .func_type => true,
28892003
2890 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyInner(strat, zcu, tid),
2004 .simple_type => |t| switch (t) {
2005 .f16,
2006 .f32,
2007 .f64,
2008 .f80,
2009 .f128,
2010 .usize,
2011 .isize,
2012 .c_char,
2013 .c_short,
2014 .c_ushort,
2015 .c_int,
2016 .c_uint,
2017 .c_long,
2018 .c_ulong,
2019 .c_longlong,
2020 .c_ulonglong,
2021 .c_longdouble,
2022 .anyopaque,
2023 .bool,
2024 .void,
2025 .anyerror,
2026 .adhoc_inferred_error_set,
2027 .noreturn,
2028 .generic_poison,
2029 => false,
28912030
2892 // values, not types
2893 .undef,
2894 .simple_value,
2895 .variable,
2896 .@"extern",
2897 .func,
2898 .int,
2899 .err,
2900 .error_union,
2031 .type,
2032 .comptime_int,
2033 .comptime_float,
2034 .null,
2035 .undefined,
29012036 .enum_literal,
2902 .enum_tag,
2903 .empty_enum_value,
2904 .float,
2905 .ptr,
2906 .slice,
2907 .opt,
2908 .aggregate,
2909 .un,
2910 // memoization, not types
2911 .memoized_call,
2912 => unreachable,
2037 => true,
2038 },
2039 .struct_type => {
2040 const struct_obj = ip.loadStructType(ty.toIntern());
2041 return switch (struct_obj.layout) {
2042 .@"packed" => false,
2043 .auto, .@"extern" => struct_obj.comptime_only,
2044 };
2045 },
2046 .union_type => {
2047 const union_obj = ip.loadUnionType(ty.toIntern());
2048 return switch (union_obj.layout) {
2049 .@"packed" => false,
2050 .auto, .@"extern" => union_obj.comptime_only,
2051 };
29132052 },
2053 .tuple_type => |tuple| {
2054 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2055 if (val != .none) continue;
2056 if (!Type.fromInterned(field_ty).comptimeOnly(zcu)) continue;
2057 return true;
2058 }
2059 return false;
2060 },
2061
2062 // values, not types
2063 .undef,
2064 .simple_value,
2065 .variable,
2066 .@"extern",
2067 .func,
2068 .int,
2069 .err,
2070 .error_union,
2071 .enum_literal,
2072 .enum_tag,
2073 .empty_enum_value,
2074 .float,
2075 .ptr,
2076 .slice,
2077 .opt,
2078 .aggregate,
2079 .un,
2080 // memoization, not types
2081 .memoized_call,
2082 => unreachable,
29142083 };
29152084}
29162085
......@@ -3056,20 +2225,18 @@ pub fn maxIntScalar(ty: Type, pt: Zcu.PerThread, dest_ty: Type) !Value {
30562225/// Asserts the type is an enum or a union.
30572226pub fn intTagType(ty: Type, zcu: *const Zcu) Type {
30582227 const ip = &zcu.intern_pool;
3059 return switch (ip.indexToKey(ty.toIntern())) {
3060 .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(zcu),
3061 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
2228 const enum_ty: Type = switch (ip.indexToKey(ty.toIntern())) {
2229 .union_type => .fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_type),
2230 .enum_type => ty,
30622231 else => unreachable,
30632232 };
2233 return .fromInterned(ip.loadEnumType(enum_ty.toIntern()).int_tag_type);
30642234}
30652235
30662236pub fn isNonexhaustiveEnum(ty: Type, zcu: *const Zcu) bool {
30672237 const ip = &zcu.intern_pool;
30682238 return switch (ip.indexToKey(ty.toIntern())) {
3069 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
3070 .nonexhaustive => true,
3071 .auto, .explicit => false,
3072 },
2239 .enum_type => ip.loadEnumType(ty.toIntern()).nonexhaustive,
30732240 else => false,
30742241 };
30752242}
......@@ -3090,16 +2257,16 @@ pub fn errorSetNames(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString.
30902257}
30912258
30922259pub fn enumFields(ty: Type, zcu: *const Zcu) InternPool.NullTerminatedString.Slice {
3093 return zcu.intern_pool.loadEnumType(ty.toIntern()).names;
2260 return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names;
30942261}
30952262
30962263pub fn enumFieldCount(ty: Type, zcu: *const Zcu) usize {
3097 return zcu.intern_pool.loadEnumType(ty.toIntern()).names.len;
2264 return zcu.intern_pool.loadEnumType(ty.toIntern()).field_names.len;
30982265}
30992266
31002267pub fn enumFieldName(ty: Type, field_index: usize, zcu: *const Zcu) InternPool.NullTerminatedString {
31012268 const ip = &zcu.intern_pool;
3102 return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index];
2269 return ip.loadEnumType(ty.toIntern()).field_names.get(ip)[field_index];
31032270}
31042271
31052272pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, zcu: *const Zcu) ?u32 {
......@@ -3119,7 +2286,7 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 {
31192286 .enum_tag => |info| info.int,
31202287 else => unreachable,
31212288 };
3122 assert(ip.typeOf(int_tag) == enum_type.tag_ty);
2289 assert(ip.typeOf(int_tag) == enum_type.int_tag_type);
31232290 return enum_type.tagValueIndex(ip, int_tag);
31242291}
31252292
......@@ -3127,7 +2294,7 @@ pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, zcu: *const Zcu) ?u32 {
31272294pub fn structFieldName(ty: Type, index: usize, zcu: *const Zcu) InternPool.OptionalNullTerminatedString {
31282295 const ip = &zcu.intern_pool;
31292296 return switch (ip.indexToKey(ty.toIntern())) {
3130 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index).toOptional(),
2297 .struct_type => ip.loadStructType(ty.toIntern()).field_names.get(ip)[index].toOptional(),
31312298 .tuple_type => .none,
31322299 else => unreachable,
31332300 };
......@@ -3144,175 +2311,96 @@ pub fn structFieldCount(ty: Type, zcu: *const Zcu) u32 {
31442311
31452312/// Returns the field type. Supports structs and unions.
31462313pub fn fieldType(ty: Type, index: usize, zcu: *const Zcu) Type {
2314 const ip = &zcu.intern_pool;
2315 const types = switch (ip.indexToKey(ty.toIntern())) {
2316 .struct_type => ip.loadStructType(ty.toIntern()).field_types,
2317 .union_type => ip.loadUnionType(ty.toIntern()).field_types,
2318 .tuple_type => |tuple| tuple.types,
2319 else => unreachable,
2320 };
2321 return .fromInterned(types.get(ip)[index]);
2322}
2323
2324// TODO MLUGG: clean up doc comments and usages of `{resolved,explicit}FieldAlignment`
2325
2326/// Returns the alignment of the given struct, tuple, or union field.
2327/// Asserts that the layout of `ty` is resolved. Asserts that `ty` is not packed.
2328/// Never returns `.none`, even if the field's alignment was not specified.
2329pub fn resolvedFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment {
2330 switch (ty.explicitFieldAlignment(index, zcu)) {
2331 .none => {},
2332 else => |explicit| return explicit,
2333 }
31472334 const ip = &zcu.intern_pool;
31482335 return switch (ip.indexToKey(ty.toIntern())) {
3149 .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
2336 .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]).abiAlignment(zcu),
2337 .struct_type => {
2338 const struct_obj = ip.loadStructType(ty.toIntern());
2339 const field_ty: Type = .fromInterned(struct_obj.field_types.get(ip)[index]);
2340 return field_ty.defaultStructFieldAlignment(struct_obj.layout, zcu);
2341 },
31502342 .union_type => {
31512343 const union_obj = ip.loadUnionType(ty.toIntern());
3152 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
2344 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[index]);
2345 return field_ty.abiAlignment(zcu);
31532346 },
3154 .tuple_type => |tuple| Type.fromInterned(tuple.types.get(ip)[index]),
31552347 else => unreachable,
31562348 };
31572349}
31582350
3159pub fn fieldAlignment(ty: Type, index: usize, zcu: *Zcu) Alignment {
3160 return ty.fieldAlignmentInner(index, .normal, zcu, {}) catch unreachable;
3161}
3162
3163pub fn fieldAlignmentSema(ty: Type, index: usize, pt: Zcu.PerThread) SemaError!Alignment {
3164 return try ty.fieldAlignmentInner(index, .sema, pt.zcu, pt.tid);
3165}
3166
3167/// Returns the field alignment. Supports structs and unions.
3168/// If `strat` is `.sema`, may perform type resolution.
3169/// Asserts the layout is not packed.
3170///
3171/// Provide the struct field as the `ty`.
3172pub fn fieldAlignmentInner(
3173 ty: Type,
3174 index: usize,
3175 comptime strat: ResolveStrat,
3176 zcu: strat.ZcuPtr(),
3177 tid: strat.Tid(),
3178) SemaError!Alignment {
2351pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment {
31792352 const ip = &zcu.intern_pool;
3180 switch (ip.indexToKey(ty.toIntern())) {
2353 return switch (ip.indexToKey(ty.toIntern())) {
2354 .tuple_type => .none,
31812355 .struct_type => {
3182 const struct_type = ip.loadStructType(ty.toIntern());
3183 assert(struct_type.layout != .@"packed");
3184 const explicit_align = struct_type.fieldAlign(ip, index);
3185 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
3186 return field_ty.structFieldAlignmentInner(explicit_align, struct_type.layout, strat, zcu, tid);
3187 },
3188 .tuple_type => |tuple| {
3189 return (try Type.fromInterned(tuple.types.get(ip)[index]).abiAlignmentInner(
3190 strat.toLazy(),
3191 zcu,
3192 tid,
3193 )).scalar;
2356 const struct_obj = ip.loadStructType(ty.toIntern());
2357 assert(struct_obj.layout != .@"packed");
2358 if (struct_obj.field_aligns.len == 0) return .none;
2359 return struct_obj.field_aligns.get(ip)[index];
31942360 },
31952361 .union_type => {
31962362 const union_obj = ip.loadUnionType(ty.toIntern());
3197 const layout = union_obj.flagsUnordered(ip).layout;
3198 assert(layout != .@"packed");
3199 const explicit_align = union_obj.fieldAlign(ip, index);
3200 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[index]);
3201 return field_ty.unionFieldAlignmentInner(explicit_align, layout, strat, zcu, tid);
2363 assert(union_obj.layout != .@"packed");
2364 if (union_obj.field_aligns.len == 0) return .none;
2365 return union_obj.field_aligns.get(ip)[index];
32022366 },
32032367 else => unreachable,
3204 }
2368 };
32052369}
32062370
3207/// Returns the alignment of a non-packed struct field. Assert the layout is not packed.
3208///
3209/// Asserts that all resolution needed was done.
3210pub fn structFieldAlignment(
2371/// Returns the alignment a struct field will have if not explicitly specified.
2372/// Asserts that the layout of `field_ty` is resolved. Asserts that `layout` is not `.@"packed"`.
2373pub fn defaultStructFieldAlignment(
32112374 field_ty: Type,
3212 explicit_alignment: InternPool.Alignment,
32132375 layout: std.builtin.Type.ContainerLayout,
3214 zcu: *Zcu,
2376 zcu: *const Zcu,
32152377) Alignment {
3216 return field_ty.structFieldAlignmentInner(
3217 explicit_alignment,
3218 layout,
3219 .normal,
3220 zcu,
3221 {},
3222 ) catch unreachable;
3223}
3224
3225/// Returns the alignment of a non-packed struct field. Assert the layout is not packed.
3226/// May do type resolution when needed.
3227/// Asserts that all resolution needed was done.
3228pub fn structFieldAlignmentSema(
3229 field_ty: Type,
3230 explicit_alignment: InternPool.Alignment,
3231 layout: std.builtin.Type.ContainerLayout,
3232 pt: Zcu.PerThread,
3233) SemaError!Alignment {
3234 return try field_ty.structFieldAlignmentInner(
3235 explicit_alignment,
3236 layout,
3237 .sema,
3238 pt.zcu,
3239 pt.tid,
3240 );
3241}
3242
3243/// Returns the alignment of a non-packed struct field. Asserts the layout is not packed.
3244/// If `strat` is `.sema`, may perform type resolution.
3245pub fn structFieldAlignmentInner(
3246 field_ty: Type,
3247 explicit_alignment: Alignment,
3248 layout: std.builtin.Type.ContainerLayout,
3249 comptime strat: Type.ResolveStrat,
3250 zcu: strat.ZcuPtr(),
3251 tid: strat.Tid(),
3252) SemaError!Alignment {
3253 assert(layout != .@"packed");
3254 if (explicit_alignment != .none) return explicit_alignment;
3255 const ty_abi_align = (try field_ty.abiAlignmentInner(
3256 strat.toLazy(),
3257 zcu,
3258 tid,
3259 )).scalar;
3260 switch (layout) {
2378 const overalign_big_int = switch (layout) {
32612379 .@"packed" => unreachable,
3262 .auto => if (zcu.getTarget().ofmt != .c) return ty_abi_align,
3263 .@"extern" => {},
3264 }
3265 // extern
3266 if (field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) {
3267 return ty_abi_align.maxStrict(.@"16");
2380 .auto => zcu.getTarget().ofmt == .c,
2381 .@"extern" => true,
2382 };
2383 const abi_align = field_ty.abiAlignment(zcu);
2384 assert(abi_align != .none);
2385 if (overalign_big_int and field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) {
2386 return abi_align.maxStrict(.@"16");
32682387 }
3269 return ty_abi_align;
3270}
3271
3272pub fn unionFieldAlignmentSema(
3273 field_ty: Type,
3274 explicit_alignment: Alignment,
3275 layout: std.builtin.Type.ContainerLayout,
3276 pt: Zcu.PerThread,
3277) SemaError!Alignment {
3278 return field_ty.unionFieldAlignmentInner(
3279 explicit_alignment,
3280 layout,
3281 .sema,
3282 pt.zcu,
3283 pt.tid,
3284 );
2388 return abi_align;
32852389}
32862390
3287pub fn unionFieldAlignmentInner(
3288 field_ty: Type,
3289 explicit_alignment: Alignment,
3290 layout: std.builtin.Type.ContainerLayout,
3291 comptime strat: Type.ResolveStrat,
3292 zcu: strat.ZcuPtr(),
3293 tid: strat.Tid(),
3294) SemaError!Alignment {
3295 assert(layout != .@"packed");
3296 if (explicit_alignment != .none) return explicit_alignment;
3297 if (field_ty.isNoReturn(zcu)) return .none;
3298 return (try field_ty.abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar;
3299}
3300
3301pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) Value {
2391pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value {
33022392 const ip = &zcu.intern_pool;
33032393 switch (ip.indexToKey(ty.toIntern())) {
33042394 .struct_type => {
3305 const struct_type = ip.loadStructType(ty.toIntern());
3306 const val = struct_type.fieldInit(ip, index);
3307 // TODO: avoid using `unreachable` to indicate this.
3308 if (val == .none) return Value.@"unreachable";
3309 return Value.fromInterned(val);
2395 const field_defaults = ip.loadStructType(ty.toIntern()).field_defaults.get(ip);
2396 if (field_defaults.len == 0) return null;
2397 if (field_defaults[index] == .none) return null;
2398 return .fromInterned(field_defaults[index]);
33102399 },
33112400 .tuple_type => |tuple| {
33122401 const val = tuple.values.get(ip)[index];
3313 // TODO: avoid using `unreachable` to indicate this.
3314 if (val == .none) return Value.@"unreachable";
3315 return Value.fromInterned(val);
2402 if (val == .none) return null;
2403 return .fromInterned(val);
33162404 },
33172405 else => unreachable,
33182406 }
......@@ -3324,9 +2412,9 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val
33242412 switch (ip.indexToKey(ty.toIntern())) {
33252413 .struct_type => {
33262414 const struct_type = ip.loadStructType(ty.toIntern());
3327 if (struct_type.fieldIsComptime(ip, index)) {
3328 assert(struct_type.haveFieldInits(ip));
3329 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
2415 if (struct_type.field_is_comptime_bits.get(ip, index)) {
2416 assertHasInits(ty, zcu);
2417 return .fromInterned(struct_type.field_defaults.get(ip)[index]);
33302418 } else {
33312419 return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(pt);
33322420 }
......@@ -3336,7 +2424,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val
33362424 if (val == .none) {
33372425 return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(pt);
33382426 } else {
3339 return Value.fromInterned(val);
2427 return .fromInterned(val);
33402428 }
33412429 },
33422430 else => unreachable,
......@@ -3346,7 +2434,7 @@ pub fn structFieldValueComptime(ty: Type, pt: Zcu.PerThread, index: usize) !?Val
33462434pub fn structFieldIsComptime(ty: Type, index: usize, zcu: *const Zcu) bool {
33472435 const ip = &zcu.intern_pool;
33482436 return switch (ip.indexToKey(ty.toIntern())) {
3349 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
2437 .struct_type => ip.loadStructType(ty.toIntern()).field_is_comptime_bits.get(ip, index),
33502438 .tuple_type => |tuple| tuple.values.get(ip)[index] != .none,
33512439 else => unreachable,
33522440 };
......@@ -3357,15 +2445,15 @@ pub const FieldOffset = struct {
33572445 offset: u64,
33582446};
33592447
3360/// Supports structs and unions.
2448/// Supports structs, tuples, and unions.
33612449pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 {
2450 assertHasLayout(ty, zcu);
33622451 const ip = &zcu.intern_pool;
33632452 switch (ip.indexToKey(ty.toIntern())) {
33642453 .struct_type => {
33652454 const struct_type = ip.loadStructType(ty.toIntern());
3366 assert(struct_type.haveLayout(ip));
33672455 assert(struct_type.layout != .@"packed");
3368 return struct_type.offsets.get(ip)[index];
2456 return struct_type.field_offsets.get(ip)[index];
33692457 },
33702458
33712459 .tuple_type => |tuple| {
......@@ -3391,7 +2479,7 @@ pub fn structFieldOffset(ty: Type, index: usize, zcu: *const Zcu) u64 {
33912479
33922480 .union_type => {
33932481 const union_type = ip.loadUnionType(ty.toIntern());
3394 if (!union_type.hasTag(ip))
2482 if (union_type.runtime_tag == .none)
33952483 return 0;
33962484 const layout = Type.getUnionLayout(union_type, zcu);
33972485 if (layout.tag_align.compare(.gte, layout.payload_align)) {
......@@ -3414,7 +2502,7 @@ pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Zcu.LazySrcLoc {
34142502 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
34152503 .declared => |d| d.zir_index,
34162504 .reified => |r| r.zir_index,
3417 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
2505 .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index,
34182506 },
34192507 else => return null,
34202508 },
......@@ -3438,8 +2526,8 @@ pub fn isTuple(ty: Type, zcu: *const Zcu) bool {
34382526 };
34392527}
34402528
3441/// Traverses optional child types and error union payloads until the type
3442/// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
2529/// Traverses optional child types and error union payloads until the type is neither of those.
2530/// For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
34432531pub fn optEuBaseType(ty: Type, zcu: *const Zcu) Type {
34442532 var cur = ty;
34452533 while (true) switch (cur.zigTypeTag(zcu)) {
......@@ -3488,7 +2576,7 @@ pub fn typeDeclInstAllowGeneratedTag(ty: Type, zcu: *const Zcu) ?InternPool.Trac
34882576 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
34892577 .enum_type => |e| switch (e) {
34902578 .declared, .reified => ip.loadEnumType(ty.toIntern()).zir_index.unwrap().?,
3491 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
2579 .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index,
34922580 },
34932581 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
34942582 else => null,
......@@ -3505,7 +2593,7 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
35052593 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
35062594 .declared => |d| d.zir_index,
35072595 .reified => |r| r.zir_index,
3508 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
2596 .generated_union_tag => |union_ty| ip.loadUnionType(union_ty).zir_index,
35092597 },
35102598 else => return null,
35112599 };
......@@ -3520,10 +2608,10 @@ pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
35202608 .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_line,
35212609 .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_line,
35222610 .extended => switch (inst.data.extended.opcode) {
3523 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line,
3524 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3525 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3526 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
2611 .struct_decl => zir.getStructDecl(info.inst).src_line,
2612 .union_decl => zir.getUnionDecl(info.inst).src_line,
2613 .enum_decl => zir.getEnumDecl(info.inst).src_line,
2614 .opaque_decl => zir.getOpaqueDecl(info.inst).src_line,
35272615 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.src_line,
35282616 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.src_line,
35292617 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.src_line,
......@@ -3594,330 +2682,8 @@ pub fn packedStructFieldPtrInfo(
35942682 };
35952683}
35962684
3597pub fn resolveLayout(ty: Type, pt: Zcu.PerThread) SemaError!void {
3598 const zcu = pt.zcu;
3599 const ip = &zcu.intern_pool;
3600 switch (ty.zigTypeTag(zcu)) {
3601 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
3602 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| {
3603 const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]);
3604 try field_ty.resolveLayout(pt);
3605 },
3606 .struct_type => return ty.resolveStructInner(pt, .layout),
3607 else => unreachable,
3608 },
3609 .@"union" => return ty.resolveUnionInner(pt, .layout),
3610 .array => {
3611 if (ty.arrayLenIncludingSentinel(zcu) == 0) return;
3612 const elem_ty = ty.childType(zcu);
3613 return elem_ty.resolveLayout(pt);
3614 },
3615 .optional => {
3616 const payload_ty = ty.optionalChild(zcu);
3617 return payload_ty.resolveLayout(pt);
3618 },
3619 .error_union => {
3620 const payload_ty = ty.errorUnionPayload(zcu);
3621 return payload_ty.resolveLayout(pt);
3622 },
3623 .@"fn" => {
3624 const info = zcu.typeToFunc(ty).?;
3625 if (info.is_generic) {
3626 // Resolving of generic function types is deferred to when
3627 // the function is instantiated.
3628 return;
3629 }
3630 for (0..info.param_types.len) |i| {
3631 const param_ty = info.param_types.get(ip)[i];
3632 try Type.fromInterned(param_ty).resolveLayout(pt);
3633 }
3634 try Type.fromInterned(info.return_type).resolveLayout(pt);
3635 },
3636 else => {},
3637 }
3638}
3639
3640pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
3641 const ip = &pt.zcu.intern_pool;
3642 const ty_ip = ty.toIntern();
3643
3644 switch (ty_ip) {
3645 .none => unreachable,
3646
3647 .u0_type,
3648 .i0_type,
3649 .u1_type,
3650 .u8_type,
3651 .i8_type,
3652 .u16_type,
3653 .i16_type,
3654 .u29_type,
3655 .u32_type,
3656 .i32_type,
3657 .u64_type,
3658 .i64_type,
3659 .u80_type,
3660 .u128_type,
3661 .i128_type,
3662 .usize_type,
3663 .isize_type,
3664 .c_char_type,
3665 .c_short_type,
3666 .c_ushort_type,
3667 .c_int_type,
3668 .c_uint_type,
3669 .c_long_type,
3670 .c_ulong_type,
3671 .c_longlong_type,
3672 .c_ulonglong_type,
3673 .c_longdouble_type,
3674 .f16_type,
3675 .f32_type,
3676 .f64_type,
3677 .f80_type,
3678 .f128_type,
3679 .anyopaque_type,
3680 .bool_type,
3681 .void_type,
3682 .type_type,
3683 .anyerror_type,
3684 .adhoc_inferred_error_set_type,
3685 .comptime_int_type,
3686 .comptime_float_type,
3687 .noreturn_type,
3688 .anyframe_type,
3689 .null_type,
3690 .undefined_type,
3691 .enum_literal_type,
3692 .ptr_usize_type,
3693 .ptr_const_comptime_int_type,
3694 .manyptr_u8_type,
3695 .manyptr_const_u8_type,
3696 .manyptr_const_u8_sentinel_0_type,
3697 .slice_const_u8_type,
3698 .slice_const_u8_sentinel_0_type,
3699 .optional_noreturn_type,
3700 .anyerror_void_error_union_type,
3701 .generic_poison_type,
3702 .empty_tuple_type,
3703 => {},
3704
3705 .undef => unreachable,
3706 .zero => unreachable,
3707 .zero_usize => unreachable,
3708 .zero_u1 => unreachable,
3709 .zero_u8 => unreachable,
3710 .one => unreachable,
3711 .one_usize => unreachable,
3712 .one_u1 => unreachable,
3713 .one_u8 => unreachable,
3714 .four_u8 => unreachable,
3715 .negative_one => unreachable,
3716 .void_value => unreachable,
3717 .unreachable_value => unreachable,
3718 .null_value => unreachable,
3719 .bool_true => unreachable,
3720 .bool_false => unreachable,
3721 .empty_tuple => unreachable,
3722
3723 else => switch (ty_ip.unwrap(ip).getTag(ip)) {
3724 .type_struct,
3725 .type_struct_packed,
3726 .type_struct_packed_inits,
3727 => return ty.resolveStructInner(pt, .fields),
3728
3729 .type_union => return ty.resolveUnionInner(pt, .fields),
3730
3731 else => {},
3732 },
3733 }
3734}
3735
3736pub fn resolveFully(ty: Type, pt: Zcu.PerThread) SemaError!void {
3737 const zcu = pt.zcu;
3738 const ip = &zcu.intern_pool;
3739
3740 switch (ty.zigTypeTag(zcu)) {
3741 .type,
3742 .void,
3743 .bool,
3744 .noreturn,
3745 .int,
3746 .float,
3747 .comptime_float,
3748 .comptime_int,
3749 .undefined,
3750 .null,
3751 .error_set,
3752 .@"enum",
3753 .@"opaque",
3754 .frame,
3755 .@"anyframe",
3756 .vector,
3757 .enum_literal,
3758 => {},
3759
3760 .pointer => return ty.childType(zcu).resolveFully(pt),
3761 .array => return ty.childType(zcu).resolveFully(pt),
3762 .optional => return ty.optionalChild(zcu).resolveFully(pt),
3763 .error_union => return ty.errorUnionPayload(zcu).resolveFully(pt),
3764 .@"fn" => {
3765 const info = zcu.typeToFunc(ty).?;
3766 if (info.is_generic) return;
3767 for (0..info.param_types.len) |i| {
3768 const param_ty = info.param_types.get(ip)[i];
3769 try Type.fromInterned(param_ty).resolveFully(pt);
3770 }
3771 try Type.fromInterned(info.return_type).resolveFully(pt);
3772 },
3773
3774 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
3775 .tuple_type => |tuple_type| for (0..tuple_type.types.len) |i| {
3776 const field_ty = Type.fromInterned(tuple_type.types.get(ip)[i]);
3777 try field_ty.resolveFully(pt);
3778 },
3779 .struct_type => return ty.resolveStructInner(pt, .full),
3780 else => unreachable,
3781 },
3782 .@"union" => return ty.resolveUnionInner(pt, .full),
3783 }
3784}
3785
3786pub fn resolveStructFieldInits(ty: Type, pt: Zcu.PerThread) SemaError!void {
3787 // TODO: stop calling this for tuples!
3788 _ = pt.zcu.typeToStruct(ty) orelse return;
3789 return ty.resolveStructInner(pt, .inits);
3790}
3791
3792pub fn resolveStructAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void {
3793 return ty.resolveStructInner(pt, .alignment);
3794}
3795
3796pub fn resolveUnionAlignment(ty: Type, pt: Zcu.PerThread) SemaError!void {
3797 return ty.resolveUnionInner(pt, .alignment);
3798}
3799
3800/// `ty` must be a struct.
3801fn resolveStructInner(
3802 ty: Type,
3803 pt: Zcu.PerThread,
3804 resolution: enum { fields, inits, alignment, layout, full },
3805) SemaError!void {
3806 const zcu = pt.zcu;
3807 const gpa = zcu.gpa;
3808
3809 const struct_obj = zcu.typeToStruct(ty).?;
3810 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
3811
3812 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3813 return error.AnalysisFail;
3814 }
3815
3816 if (zcu.comp.debugIncremental()) {
3817 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner);
3818 info.last_update_gen = zcu.generation;
3819 }
3820
3821 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3822 defer analysis_arena.deinit();
3823
3824 var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa);
3825 defer comptime_err_ret_trace.deinit();
3826
3827 const zir = zcu.namespacePtr(struct_obj.namespace).fileScope(zcu).zir.?;
3828 var sema: Sema = .{
3829 .pt = pt,
3830 .gpa = gpa,
3831 .arena = analysis_arena.allocator(),
3832 .code = zir,
3833 .owner = owner,
3834 .func_index = .none,
3835 .func_is_naked = false,
3836 .fn_ret_ty = Type.void,
3837 .fn_ret_ty_ies = null,
3838 .comptime_err_ret_trace = &comptime_err_ret_trace,
3839 };
3840 defer sema.deinit();
3841
3842 (switch (resolution) {
3843 .fields => sema.resolveStructFieldTypes(ty.toIntern(), struct_obj),
3844 .inits => sema.resolveStructFieldInits(ty),
3845 .alignment => sema.resolveStructAlignment(ty.toIntern(), struct_obj),
3846 .layout => sema.resolveStructLayout(ty),
3847 .full => sema.resolveStructFully(ty),
3848 }) catch |err| switch (err) {
3849 error.AnalysisFail => {
3850 if (!zcu.failed_analysis.contains(owner)) {
3851 try zcu.transitive_failed_analysis.put(gpa, owner, {});
3852 }
3853 return error.AnalysisFail;
3854 },
3855 error.OutOfMemory, error.Canceled => |e| return e,
3856 };
3857}
3858
3859/// `ty` must be a union.
3860fn resolveUnionInner(
3861 ty: Type,
3862 pt: Zcu.PerThread,
3863 resolution: enum { fields, alignment, layout, full },
3864) SemaError!void {
3865 const zcu = pt.zcu;
3866 const gpa = zcu.gpa;
3867
3868 const union_obj = zcu.typeToUnion(ty).?;
3869 const owner: InternPool.AnalUnit = .wrap(.{ .type = ty.toIntern() });
3870
3871 if (zcu.failed_analysis.contains(owner) or zcu.transitive_failed_analysis.contains(owner)) {
3872 return error.AnalysisFail;
3873 }
3874
3875 if (zcu.comp.debugIncremental()) {
3876 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, owner);
3877 info.last_update_gen = zcu.generation;
3878 }
3879
3880 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3881 defer analysis_arena.deinit();
3882
3883 var comptime_err_ret_trace = std.array_list.Managed(Zcu.LazySrcLoc).init(gpa);
3884 defer comptime_err_ret_trace.deinit();
3885
3886 const zir = zcu.namespacePtr(union_obj.namespace).fileScope(zcu).zir.?;
3887 var sema: Sema = .{
3888 .pt = pt,
3889 .gpa = gpa,
3890 .arena = analysis_arena.allocator(),
3891 .code = zir,
3892 .owner = owner,
3893 .func_index = .none,
3894 .func_is_naked = false,
3895 .fn_ret_ty = Type.void,
3896 .fn_ret_ty_ies = null,
3897 .comptime_err_ret_trace = &comptime_err_ret_trace,
3898 };
3899 defer sema.deinit();
3900
3901 (switch (resolution) {
3902 .fields => sema.resolveUnionFieldTypes(ty, union_obj),
3903 .alignment => sema.resolveUnionAlignment(ty, union_obj),
3904 .layout => sema.resolveUnionLayout(ty),
3905 .full => sema.resolveUnionFully(ty),
3906 }) catch |err| switch (err) {
3907 error.AnalysisFail => {
3908 if (!zcu.failed_analysis.contains(owner)) {
3909 try zcu.transitive_failed_analysis.put(gpa, owner, {});
3910 }
3911 return error.AnalysisFail;
3912 },
3913 error.OutOfMemory => |e| return e,
3914 error.Canceled => |e| return e,
3915 };
3916}
3917
39182685pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu) Zcu.UnionLayout {
39192686 const ip = &zcu.intern_pool;
3920 assert(loaded_union.haveLayout(ip));
39212687 var most_aligned_field: u32 = 0;
39222688 var most_aligned_field_align: InternPool.Alignment = .@"1";
39232689 var most_aligned_field_size: u64 = 0;
......@@ -3928,11 +2694,14 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
39282694 const field_ty: Type = .fromInterned(field_ty_ip_index);
39292695 if (field_ty.isNoReturn(zcu)) continue;
39302696
3931 const explicit_align = loaded_union.fieldAlign(ip, field_index);
3932 const field_align = if (explicit_align != .none)
3933 explicit_align
3934 else
3935 field_ty.abiAlignment(zcu);
2697 const field_align: InternPool.Alignment = a: {
2698 const explicit_aligns = loaded_union.field_aligns.get(ip);
2699 if (explicit_aligns.len > 0) {
2700 const a = explicit_aligns[field_index];
2701 if (a != .none) break :a a;
2702 }
2703 break :a field_ty.abiAlignment(zcu);
2704 };
39362705 if (field_ty.hasRuntimeBits(zcu)) {
39372706 const field_size = field_ty.abiSize(zcu);
39382707 if (field_size > payload_size) {
......@@ -3947,8 +2716,9 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
39472716 }
39482717 payload_align = payload_align.max(field_align);
39492718 }
3950 const have_tag = loaded_union.flagsUnordered(ip).runtime_tag.hasTag();
3951 if (!have_tag or !Type.fromInterned(loaded_union.enum_tag_ty).hasRuntimeBits(zcu)) {
2719 if (loaded_union.runtime_tag == .none or
2720 !Type.fromInterned(loaded_union.enum_tag_type).hasRuntimeBits(zcu))
2721 {
39522722 return .{
39532723 .abi_size = payload_align.forward(payload_size),
39542724 .abi_align = payload_align,
......@@ -3963,10 +2733,10 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
39632733 };
39642734 }
39652735
3966 const tag_size = Type.fromInterned(loaded_union.enum_tag_ty).abiSize(zcu);
3967 const tag_align = Type.fromInterned(loaded_union.enum_tag_ty).abiAlignment(zcu).max(.@"1");
2736 const tag_size = Type.fromInterned(loaded_union.enum_tag_type).abiSize(zcu);
2737 const tag_align = Type.fromInterned(loaded_union.enum_tag_type).abiAlignment(zcu).max(.@"1");
39682738 return .{
3969 .abi_size = loaded_union.sizeUnordered(ip),
2739 .abi_size = loaded_union.size,
39702740 .abi_align = tag_align.max(payload_align),
39712741 .most_aligned_field = most_aligned_field,
39722742 .most_aligned_field_size = most_aligned_field_size,
......@@ -3975,7 +2745,7 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
39752745 .payload_align = payload_align,
39762746 .tag_align = tag_align,
39772747 .tag_size = tag_size,
3978 .padding = loaded_union.paddingUnordered(ip),
2748 .padding = loaded_union.padding,
39792749 };
39802750}
39812751
......@@ -3989,10 +2759,17 @@ pub fn getUnionLayout(loaded_union: InternPool.LoadedUnionType, zcu: *const Zcu)
39892759/// Handles const-ness and address spaces in particular.
39902760/// This code is duplicated in `Sema.analyzePtrArithmetic`.
39912761/// May perform type resolution and return a transitive `error.AnalysisFail`.
2762/// MLUGG TODO audit this shit
39922763pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type {
39932764 const zcu = pt.zcu;
39942765 const ptr_info = ptr_ty.ptrInfo(zcu);
3995 const elem_ty = ptr_ty.elemType2(zcu);
2766 const elem_ty: Type = switch (ptr_info.flags.size) {
2767 .one => switch (Type.fromInterned(ptr_info.child).zigTypeTag(zcu)) {
2768 .array, .vector => Type.fromInterned(ptr_info.child).childType(zcu),
2769 else => .fromInterned(ptr_info.child),
2770 },
2771 .many, .c, .slice => .fromInterned(ptr_info.child),
2772 };
39962773 const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0;
39972774 const parent_ty = ptr_ty.childType(zcu);
39982775
......@@ -4024,7 +2801,7 @@ pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type {
40242801 }
40252802 // If the addend is not a comptime-known value we can still count on
40262803 // it being a multiple of the type size.
4027 const elem_size = (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar;
2804 const elem_size = elem_ty.abiSize(zcu);
40282805 const addend = if (offset) |off| elem_size * off else elem_size;
40292806
40302807 // The resulting pointer is aligned to the lcd between the offset (an
......@@ -4037,7 +2814,7 @@ pub fn elemPtrType(ptr_ty: Type, offset: ?usize, pt: Zcu.PerThread) !Type {
40372814 assert(new_align != .none);
40382815 break :a new_align;
40392816 };
4040 return pt.ptrTypeSema(.{
2817 return pt.ptrType(.{
40412818 .child = elem_ty.toIntern(),
40422819 .flags = .{
40432820 .alignment = alignment,
......@@ -4069,11 +2846,107 @@ pub fn containerTypeName(ty: Type, ip: *const InternPool) InternPool.NullTermina
40692846/// Returns `null` otherwise.
40702847pub fn isNullFromType(ty: Type, zcu: *const Zcu) ?bool {
40712848 if (ty.zigTypeTag(zcu) != .optional and !ty.isCPtr(zcu)) return false;
4072 const child = ty.optionalChild(zcu);
4073 if (child.zigTypeTag(zcu) == .noreturn) return true; // `?noreturn` is always null
2849 if (ty.optionalChild(zcu).isNoReturn(zcu)) return true; // `?noreturn` is always null
40742850 return null;
40752851}
40762852
2853/// Returns true if `ty` is allowed in packed types.
2854pub fn packable(ty: Type, zcu: *const Zcu) bool {
2855 return switch (ty.zigTypeTag(zcu)) {
2856 .type,
2857 .comptime_float,
2858 .comptime_int,
2859 .enum_literal,
2860 .undefined,
2861 .null,
2862 .error_union,
2863 .error_set,
2864 .frame,
2865 .noreturn,
2866 .@"opaque",
2867 .@"anyframe",
2868 .@"fn",
2869 .array,
2870 => false,
2871 .optional => return ty.isPtrLikeOptional(zcu),
2872 .void,
2873 .bool,
2874 .float,
2875 .int,
2876 .vector,
2877 => true,
2878 .@"enum" => zcu.intern_pool.loadEnumType(ty.toIntern()).int_tag_is_explicit,
2879 .pointer => !ty.isSlice(zcu),
2880 .@"struct", .@"union" => ty.containerLayout(zcu) == .@"packed",
2881 };
2882}
2883
2884/// Asserts that `ty` has resolved layout.
2885pub fn assertHasLayout(ty: Type, zcu: *const Zcu) void {
2886 switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
2887 .int_type,
2888 .ptr_type,
2889 .anyframe_type,
2890 .simple_type,
2891 .opaque_type,
2892 .enum_type,
2893 .error_set_type,
2894 .inferred_error_set_type,
2895 => {},
2896 .func_type => |func_type| {
2897 for (func_type.param_types.get(&zcu.intern_pool)) |param_ty| {
2898 assertHasLayout(.fromInterned(param_ty), zcu);
2899 }
2900 assertHasLayout(.fromInterned(func_type.return_type), zcu);
2901 },
2902 .array_type => |arr| assertHasLayout(.fromInterned(arr.child), zcu),
2903 .vector_type => |vec| assertHasLayout(.fromInterned(vec.child), zcu),
2904 .opt_type => |child| assertHasLayout(.fromInterned(child), zcu),
2905 .error_union_type => |eu| assertHasLayout(.fromInterned(eu.payload_type), zcu),
2906 .tuple_type => |tuple| for (tuple.types.get(&zcu.intern_pool)) |field_ty| {
2907 assertHasLayout(.fromInterned(field_ty), zcu);
2908 },
2909 .struct_type, .union_type => {
2910 const unit: InternPool.AnalUnit = .wrap(.{ .type_layout = ty.toIntern() });
2911 assert(!zcu.outdated.contains(unit));
2912 assert(!zcu.potentially_outdated.contains(unit));
2913 },
2914 else => unreachable, // assertion failure; not a struct or union
2915
2916 // values, not types
2917 .simple_value,
2918 .variable,
2919 .@"extern",
2920 .func,
2921 .int,
2922 .err,
2923 .error_union,
2924 .enum_literal,
2925 .enum_tag,
2926 .empty_enum_value,
2927 .float,
2928 .ptr,
2929 .slice,
2930 .opt,
2931 .aggregate,
2932 .un,
2933 // memoization, not types
2934 .memoized_call,
2935 => unreachable,
2936 }
2937}
2938
2939/// Asserts that `ty` is an enum or struct type whose field values/defaults are resolved.
2940pub fn assertHasInits(ty: Type, zcu: *const Zcu) void {
2941 switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
2942 .struct_type, .enum_type => {},
2943 else => unreachable,
2944 }
2945 const unit: InternPool.AnalUnit = .wrap(.{ .type_inits = ty.toIntern() });
2946 assert(!zcu.outdated.contains(unit));
2947 assert(!zcu.potentially_outdated.contains(unit));
2948}
2949
40772950/// Recursively walks the type and marks for each subtype how many times it has been seen
40782951fn collectSubtypes(ty: Type, pt: Zcu.PerThread, visited: *std.AutoArrayHashMapUnmanaged(Type, u16)) error{OutOfMemory}!void {
40792952 const zcu = pt.zcu;
src/Value.zig+145-642
......@@ -146,80 +146,22 @@ pub fn toType(self: Value) Type {
146146 return Type.fromInterned(self.toIntern());
147147}
148148
149pub fn intFromEnum(val: Value, ty: Type, pt: Zcu.PerThread) Allocator.Error!Value {
150 const ip = &pt.zcu.intern_pool;
151 const enum_ty = ip.typeOf(val.toIntern());
152 return switch (ip.indexToKey(enum_ty)) {
153 // Assume it is already an integer and return it directly.
154 .simple_type, .int_type => val,
155 .enum_literal => |enum_literal| {
156 const field_index = ty.enumFieldIndex(enum_literal, pt.zcu).?;
157 switch (ip.indexToKey(ty.toIntern())) {
158 // Assume it is already an integer and return it directly.
159 .simple_type, .int_type => return val,
160 .enum_type => {
161 const enum_type = ip.loadEnumType(ty.toIntern());
162 if (enum_type.values.len != 0) {
163 return Value.fromInterned(enum_type.values.get(ip)[field_index]);
164 } else {
165 // Field index and integer values are the same.
166 return pt.intValue(Type.fromInterned(enum_type.tag_ty), field_index);
167 }
168 },
169 else => unreachable,
170 }
171 },
172 .enum_type => try pt.getCoerced(val, Type.fromInterned(ip.loadEnumType(enum_ty).tag_ty)),
173 else => unreachable,
174 };
149pub fn intFromEnum(val: Value, zcu: *const Zcu) Value {
150 return .fromInterned(zcu.intern_pool.indexToKey(val.toIntern()).enum_tag.int);
175151}
176152
177pub const ResolveStrat = Type.ResolveStrat;
178
179/// Asserts the value is an integer.
153/// Asserts that `val` is an integer.
180154pub fn toBigInt(val: Value, space: *BigIntSpace, zcu: *Zcu) BigIntConst {
181 return val.toBigIntAdvanced(space, .normal, zcu, {}) catch unreachable;
182}
183
184pub fn toBigIntSema(val: Value, space: *BigIntSpace, pt: Zcu.PerThread) !BigIntConst {
185 return try val.toBigIntAdvanced(space, .sema, pt.zcu, pt.tid);
186}
187
188/// Asserts the value is an integer.
189pub fn toBigIntAdvanced(
190 val: Value,
191 space: *BigIntSpace,
192 comptime strat: ResolveStrat,
193 zcu: *Zcu,
194 tid: strat.Tid(),
195) Zcu.SemaError!BigIntConst {
155 if (val.getUnsignedInt(zcu)) |x| {
156 return BigIntMutable.init(&space.limbs, x).toConst();
157 }
196158 const ip = &zcu.intern_pool;
197 return switch (val.toIntern()) {
198 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
199 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
200 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
201 else => switch (ip.indexToKey(val.toIntern())) {
202 .int => |int| switch (int.storage) {
203 .u64, .i64, .big_int => int.storage.toBigInt(space),
204 .lazy_align, .lazy_size => |ty| {
205 if (strat == .sema) try Type.fromInterned(ty).resolveLayout(strat.pt(zcu, tid));
206 const x = switch (int.storage) {
207 else => unreachable,
208 .lazy_align => Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0,
209 .lazy_size => Type.fromInterned(ty).abiSize(zcu),
210 };
211 return BigIntMutable.init(&space.limbs, x).toConst();
212 },
213 },
214 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).toBigIntAdvanced(space, strat, zcu, tid),
215 .opt, .ptr => BigIntMutable.init(
216 &space.limbs,
217 (try val.getUnsignedIntInner(strat, zcu, tid)).?,
218 ).toConst(),
219 .err => |err| BigIntMutable.init(&space.limbs, ip.getErrorValueIfExists(err.name).?).toConst(),
220 else => unreachable,
221 },
159 const int_key = switch (ip.indexToKey(val.toIntern())) {
160 .enum_tag => |enum_tag| ip.indexToKey(enum_tag.int).int,
161 .int => |int| int,
162 else => unreachable,
222163 };
164 return int_key.storage.toBigInt(space);
223165}
224166
225167pub fn isFuncBody(val: Value, zcu: *Zcu) bool {
......@@ -240,31 +182,17 @@ pub fn getVariable(val: Value, mod: *Zcu) ?InternPool.Key.Variable {
240182 };
241183}
242184
243/// If the value fits in a u64, return it, otherwise null.
244/// Asserts not undefined.
245pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 {
246 return getUnsignedIntInner(val, .normal, zcu, {}) catch unreachable;
247}
248
249/// Asserts the value is an integer and it fits in a u64
185/// Asserts the value is a (defined) integer and it fits in a u64.
250186pub fn toUnsignedInt(val: Value, zcu: *const Zcu) u64 {
251187 return getUnsignedInt(val, zcu).?;
252188}
253189
254pub fn getUnsignedIntSema(val: Value, pt: Zcu.PerThread) !?u64 {
255 return try val.getUnsignedIntInner(.sema, pt.zcu, pt.tid);
256}
257
258190/// If the value fits in a u64, return it, otherwise null.
259191/// Asserts not undefined.
260pub fn getUnsignedIntInner(
261 val: Value,
262 comptime strat: ResolveStrat,
263 zcu: strat.ZcuPtr(),
264 tid: strat.Tid(),
265) !?u64 {
192pub fn getUnsignedInt(val: Value, zcu: *const Zcu) ?u64 {
266193 return switch (val.toIntern()) {
267194 .undef => unreachable,
195 .null_value => 0,
268196 .bool_false => 0,
269197 .bool_true => 1,
270198 else => switch (zcu.intern_pool.indexToKey(val.toIntern())) {
......@@ -273,37 +201,27 @@ pub fn getUnsignedIntInner(
273201 .big_int => |big_int| big_int.toInt(u64) catch null,
274202 .u64 => |x| x,
275203 .i64 => |x| std.math.cast(u64, x),
276 .lazy_align => |ty| (try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), zcu, tid)).scalar.toByteUnits() orelse 0,
277 .lazy_size => |ty| (try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), zcu, tid)).scalar,
278204 },
279205 .ptr => |ptr| switch (ptr.base_addr) {
280206 .int => ptr.byte_offset,
281207 .field => |field| {
282 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntInner(strat, zcu, tid)) orelse return null;
208 const base_addr = Value.fromInterned(field.base).getUnsignedInt(zcu) orelse return null;
283209 const struct_ty = Value.fromInterned(field.base).typeOf(zcu).childType(zcu);
284 if (strat == .sema) {
285 const pt = strat.pt(zcu, tid);
286 try struct_ty.resolveLayout(pt);
287 }
288210 return base_addr + struct_ty.structFieldOffset(@intCast(field.index), zcu) + ptr.byte_offset;
289211 },
290212 else => null,
291213 },
292214 .opt => |opt| switch (opt.val) {
293215 .none => 0,
294 else => |payload| Value.fromInterned(payload).getUnsignedIntInner(strat, zcu, tid),
216 else => |payload| Value.fromInterned(payload).getUnsignedInt(zcu),
295217 },
296 .enum_tag => |enum_tag| return Value.fromInterned(enum_tag.int).getUnsignedIntInner(strat, zcu, tid),
218 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).getUnsignedInt(zcu),
219 .err => |err| zcu.intern_pool.getErrorValueIfExists(err.name).?,
297220 else => null,
298221 },
299222 };
300223}
301224
302/// Asserts the value is an integer and it fits in a u64
303pub fn toUnsignedIntSema(val: Value, pt: Zcu.PerThread) !u64 {
304 return (try getUnsignedIntInner(val, .sema, pt.zcu, pt.tid)).?;
305}
306
307225/// Asserts the value is an integer and it fits in a i64
308226pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 {
309227 return switch (val.toIntern()) {
......@@ -314,8 +232,6 @@ pub fn toSignedInt(val: Value, zcu: *const Zcu) i64 {
314232 .big_int => |big_int| big_int.toInt(i64) catch unreachable,
315233 .i64 => |x| x,
316234 .u64 => |x| @intCast(x),
317 .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0),
318 .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(zcu)),
319235 },
320236 else => unreachable,
321237 },
......@@ -487,22 +403,16 @@ pub fn writeToPackedMemory(
487403 buffer[byte_index] &= ~(@as(u8, 1) << @as(u3, @intCast(bit_offset % 8)));
488404 }
489405 },
490 .int, .@"enum" => {
491 if (buffer.len == 0) return;
406 .@"enum" => {
407 const int_val = val.intFromEnum(zcu);
408 return int_val.writeToPackedMemory(int_val.typeOf(zcu), pt, buffer, bit_offset);
409 },
410 .int => {
492411 const bits = ty.intInfo(zcu).bits;
493 if (bits == 0) return;
494
495 switch (ip.indexToKey((try val.intFromEnum(ty, pt)).toIntern()).int.storage) {
412 if (bits == 0 or buffer.len == 0) return;
413 switch (ip.indexToKey(val.toIntern()).int.storage) {
496414 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
497415 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
498 .lazy_align => |lazy_align| {
499 const num = Type.fromInterned(lazy_align).abiAlignment(zcu).toByteUnits() orelse 0;
500 std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian);
501 },
502 .lazy_size => |lazy_size| {
503 const num = Type.fromInterned(lazy_size).abiSize(zcu);
504 std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian);
505 },
506416 }
507417 },
508418 .float => switch (ty.floatBits(target)) {
......@@ -548,19 +458,15 @@ pub fn writeToPackedMemory(
548458 },
549459 .@"union" => {
550460 const union_obj = zcu.typeToUnion(ty).?;
551 switch (union_obj.flagsUnordered(ip).layout) {
552 .auto, .@"extern" => unreachable, // Handled in non-packed writeToMemory
553 .@"packed" => {
554 if (val.unionTag(zcu)) |union_tag| {
555 const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?;
556 const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
557 const field_val = try val.fieldValue(pt, field_index);
558 return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset);
559 } else {
560 const backing_ty = try ty.unionBackingType(pt);
561 return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset);
562 }
563 },
461 assert(union_obj.layout == .@"packed");
462 if (val.unionTag(zcu)) |union_tag| {
463 const field_index = zcu.unionTagFieldIndex(union_obj, union_tag).?;
464 const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
465 const field_val = try val.fieldValue(pt, field_index);
466 return field_val.writeToPackedMemory(field_type, pt, buffer, bit_offset);
467 } else {
468 const backing_ty = try ty.unionBackingType(pt);
469 return val.unionValue(zcu).writeToPackedMemory(backing_ty, pt, buffer, bit_offset);
564470 }
565471 },
566472 .pointer => {
......@@ -729,24 +635,15 @@ pub fn readFromPackedMemory(
729635 },
730636 .pointer => {
731637 assert(!ty.isSlice(zcu)); // No well defined layout.
732 const int_val = try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena);
733 return Value.fromInterned(try pt.intern(.{ .ptr = .{
734 .ty = ty.toIntern(),
735 .base_addr = .int,
736 .byte_offset = int_val.toUnsignedInt(zcu),
737 } }));
638 const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu);
639 return pt.ptrIntValue(ty, addr);
738640 },
739641 .optional => {
740642 assert(ty.isPtrLikeOptional(zcu));
741 const child_ty = ty.optionalChild(zcu);
742 const child_val = try readFromPackedMemory(child_ty, pt, buffer, bit_offset, arena);
643 const addr = (try readFromPackedMemory(Type.usize, pt, buffer, bit_offset, arena)).toUnsignedInt(zcu);
743644 return Value.fromInterned(try pt.intern(.{ .opt = .{
744645 .ty = ty.toIntern(),
745 .val = switch (child_val.orderAgainstZero(zcu)) {
746 .lt => unreachable,
747 .eq => .none,
748 .gt => child_val.toIntern(),
749 },
646 .val = (try pt.ptrIntValue(ty.childType(zcu), addr)).toIntern(),
750647 } }));
751648 },
752649 else => @panic("TODO implement readFromPackedMemory for more types"),
......@@ -764,8 +661,6 @@ pub fn toFloat(val: Value, comptime T: type, zcu: *const Zcu) T {
764661 }
765662 return @floatFromInt(x);
766663 },
767 .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(zcu).toByteUnits() orelse 0),
768 .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(zcu)),
769664 },
770665 .float => |float| switch (float.storage) {
771666 inline else => |x| @floatCast(x),
......@@ -819,110 +714,8 @@ pub fn floatCast(val: Value, dest_ty: Type, pt: Zcu.PerThread) !Value {
819714 } }));
820715}
821716
822pub fn orderAgainstZero(lhs: Value, zcu: *Zcu) std.math.Order {
823 return orderAgainstZeroInner(lhs, .normal, zcu, {}) catch unreachable;
824}
825
826pub fn orderAgainstZeroSema(lhs: Value, pt: Zcu.PerThread) !std.math.Order {
827 return try orderAgainstZeroInner(lhs, .sema, pt.zcu, pt.tid);
828}
829
830pub fn orderAgainstZeroInner(
831 lhs: Value,
832 comptime strat: ResolveStrat,
833 zcu: *Zcu,
834 tid: strat.Tid(),
835) Zcu.SemaError!std.math.Order {
836 return switch (lhs.toIntern()) {
837 .bool_false => .eq,
838 .bool_true => .gt,
839 else => switch (zcu.intern_pool.indexToKey(lhs.toIntern())) {
840 .ptr => |ptr| if (ptr.byte_offset > 0) .gt else switch (ptr.base_addr) {
841 .nav, .comptime_alloc, .comptime_field => .gt,
842 .int => .eq,
843 else => unreachable,
844 },
845 .int => |int| switch (int.storage) {
846 .big_int => |big_int| big_int.orderAgainstScalar(0),
847 inline .u64, .i64 => |x| std.math.order(x, 0),
848 .lazy_align => .gt, // alignment is never 0
849 .lazy_size => |ty| return if (Type.fromInterned(ty).hasRuntimeBitsInner(
850 false,
851 strat.toLazy(),
852 zcu,
853 tid,
854 ) catch |err| switch (err) {
855 error.NeedLazy => unreachable,
856 else => |e| return e,
857 }) .gt else .eq,
858 },
859 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).orderAgainstZeroInner(strat, zcu, tid),
860 .float => |float| switch (float.storage) {
861 inline else => |x| std.math.order(x, 0),
862 },
863 .err => .gt, // error values cannot be 0
864 else => unreachable,
865 },
866 };
867}
868
869/// Asserts the value is comparable.
870pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order {
871 return orderAdvanced(lhs, rhs, .normal, zcu, {}) catch unreachable;
872}
873
874/// Asserts the value is comparable.
875pub fn orderAdvanced(
876 lhs: Value,
877 rhs: Value,
878 comptime strat: ResolveStrat,
879 zcu: *Zcu,
880 tid: strat.Tid(),
881) !std.math.Order {
882 const lhs_against_zero = try lhs.orderAgainstZeroInner(strat, zcu, tid);
883 const rhs_against_zero = try rhs.orderAgainstZeroInner(strat, zcu, tid);
884 switch (lhs_against_zero) {
885 .lt => if (rhs_against_zero != .lt) return .lt,
886 .eq => return rhs_against_zero.invert(),
887 .gt => {},
888 }
889 switch (rhs_against_zero) {
890 .lt => if (lhs_against_zero != .lt) return .gt,
891 .eq => return lhs_against_zero,
892 .gt => {},
893 }
894
895 if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) {
896 const lhs_f128 = lhs.toFloat(f128, zcu);
897 const rhs_f128 = rhs.toFloat(f128, zcu);
898 return std.math.order(lhs_f128, rhs_f128);
899 }
900
901 var lhs_bigint_space: BigIntSpace = undefined;
902 var rhs_bigint_space: BigIntSpace = undefined;
903 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, strat, zcu, tid);
904 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, strat, zcu, tid);
905 return lhs_bigint.order(rhs_bigint);
906}
907
908/// Asserts the value is comparable. Does not take a type parameter because it supports
909/// comparisons between heterogeneous types.
717/// Asserts the value is comparable. Supports comparisons between heterogeneous types.
910718pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, zcu: *Zcu) bool {
911 return compareHeteroAdvanced(lhs, op, rhs, .normal, zcu, {}) catch unreachable;
912}
913
914pub fn compareHeteroSema(lhs: Value, op: std.math.CompareOperator, rhs: Value, pt: Zcu.PerThread) !bool {
915 return try compareHeteroAdvanced(lhs, op, rhs, .sema, pt.zcu, pt.tid);
916}
917
918pub fn compareHeteroAdvanced(
919 lhs: Value,
920 op: std.math.CompareOperator,
921 rhs: Value,
922 comptime strat: ResolveStrat,
923 zcu: *Zcu,
924 tid: strat.Tid(),
925) !bool {
926719 if (lhs.pointerNav(zcu)) |lhs_nav| {
927720 if (rhs.pointerNav(zcu)) |rhs_nav| {
928721 switch (op) {
......@@ -944,9 +737,21 @@ pub fn compareHeteroAdvanced(
944737 else => {},
945738 }
946739 }
947
948740 if (lhs.isNan(zcu) or rhs.isNan(zcu)) return op == .neq;
949 return (try orderAdvanced(lhs, rhs, strat, zcu, tid)).compare(op);
741 return order(lhs, rhs, zcu).compare(op);
742}
743
744pub fn order(lhs: Value, rhs: Value, zcu: *Zcu) std.math.Order {
745 if (lhs.isFloat(zcu) or rhs.isFloat(zcu)) {
746 const lhs_f128 = lhs.toFloat(f128, zcu);
747 const rhs_f128 = rhs.toFloat(f128, zcu);
748 return std.math.order(lhs_f128, rhs_f128);
749 }
750 var lhs_bigint_space: BigIntSpace = undefined;
751 var rhs_bigint_space: BigIntSpace = undefined;
752 const lhs_bigint = lhs.toBigInt(&lhs_bigint_space, zcu);
753 const rhs_bigint = rhs.toBigInt(&rhs_bigint_space, zcu);
754 return lhs_bigint.order(rhs_bigint);
950755}
951756
952757/// Asserts the values are comparable. Both operands have type `ty`.
......@@ -987,56 +792,32 @@ pub fn compareScalar(
987792/// Returns `false` if the value or any vector element is undefined.
988793///
989794/// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
795/// TODO MLUGG: lowkey wanna delete this
990796pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, zcu: *Zcu) bool {
991 return compareAllWithZeroAdvancedExtra(lhs, op, .normal, zcu, {}) catch unreachable;
992}
993
994pub fn compareAllWithZeroSema(
995 lhs: Value,
996 op: std.math.CompareOperator,
997 pt: Zcu.PerThread,
998) Zcu.CompileError!bool {
999 return compareAllWithZeroAdvancedExtra(lhs, op, .sema, pt.zcu, pt.tid);
1000}
1001
1002pub fn compareAllWithZeroAdvancedExtra(
1003 lhs: Value,
1004 op: std.math.CompareOperator,
1005 comptime strat: ResolveStrat,
1006 zcu: *Zcu,
1007 tid: strat.Tid(),
1008) Zcu.CompileError!bool {
1009 if (lhs.isInf(zcu)) {
1010 switch (op) {
1011 .neq => return true,
1012 .eq => return false,
1013 .gt, .gte => return !lhs.isNegativeInf(zcu),
1014 .lt, .lte => return lhs.isNegativeInf(zcu),
1015 }
1016 }
1017
1018 switch (zcu.intern_pool.indexToKey(lhs.toIntern())) {
797 return switch (zcu.intern_pool.indexToKey(lhs.toIntern())) {
1019798 .float => |float| switch (float.storage) {
1020 inline else => |x| if (std.math.isNan(x)) return op == .neq,
799 inline else => |x| std.math.compare(x, op, 0),
1021800 },
1022 .aggregate => |aggregate| return switch (aggregate.storage) {
1023 .bytes => |bytes| for (bytes.toSlice(lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu), &zcu.intern_pool)) |byte| {
1024 if (!std.math.order(byte, 0).compare(op)) break false;
801 .aggregate => |aggregate| switch (aggregate.storage) {
802 .bytes => |bytes| for (bytes.toSlice(
803 lhs.typeOf(zcu).arrayLenIncludingSentinel(zcu),
804 &zcu.intern_pool,
805 )) |byte| {
806 if (!std.math.compare(byte, op, 0)) break false;
1025807 } else true,
1026808 .elems => |elems| for (elems) |elem| {
1027 if (!try Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid)) break false;
809 if (!Value.fromInterned(elem).compareAllWithZero(op, zcu)) break false;
1028810 } else true,
1029 .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, strat, zcu, tid),
811 .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZero(op, zcu),
1030812 },
1031 .undef => return false,
1032 else => {},
1033 }
1034 return (try orderAgainstZeroInner(lhs, strat, zcu, tid)).compare(op);
813 .undef => false,
814 else => order(lhs, .zero_comptime_int, zcu).compare(op),
815 };
1035816}
1036817
1037818pub fn eql(a: Value, b: Value, ty: Type, zcu: *Zcu) bool {
1038 assert(zcu.intern_pool.typeOf(a.toIntern()) == ty.toIntern());
1039 assert(zcu.intern_pool.typeOf(b.toIntern()) == ty.toIntern());
819 assert(a.typeOf(zcu).toIntern() == ty.toIntern());
820 assert(b.typeOf(zcu).toIntern() == ty.toIntern());
1040821 return a.toIntern() == b.toIntern();
1041822}
1042823
......@@ -1088,16 +869,13 @@ pub fn pointerNav(val: Value, zcu: *Zcu) ?InternPool.Nav.Index {
1088869pub const slice_ptr_index = 0;
1089870pub const slice_len_index = 1;
1090871
872pub fn sliceLen(val: Value, zcu: *Zcu) u64 {
873 return Value.fromInterned(zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedInt(zcu);
874}
1091875pub fn slicePtr(val: Value, zcu: *Zcu) Value {
1092876 return Value.fromInterned(zcu.intern_pool.slicePtr(val.toIntern()));
1093877}
1094878
1095/// Gets the `len` field of a slice value as a `u64`.
1096/// Resolves the length using `Sema` if necessary.
1097pub fn sliceLen(val: Value, pt: Zcu.PerThread) !u64 {
1098 return Value.fromInterned(pt.zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedIntSema(pt);
1099}
1100
1101879/// Asserts the value is an aggregate, and returns the element value at the given index.
1102880pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Value {
1103881 const zcu = pt.zcu;
......@@ -1123,62 +901,6 @@ pub fn elemValue(val: Value, pt: Zcu.PerThread, index: usize) Allocator.Error!Va
1123901 }
1124902}
1125903
1126pub fn isLazyAlign(val: Value, zcu: *Zcu) bool {
1127 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1128 .int => |int| int.storage == .lazy_align,
1129 else => false,
1130 };
1131}
1132
1133pub fn isLazySize(val: Value, zcu: *Zcu) bool {
1134 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
1135 .int => |int| int.storage == .lazy_size,
1136 else => false,
1137 };
1138}
1139
1140// Asserts that the provided start/end are in-bounds.
1141pub fn sliceArray(
1142 val: Value,
1143 sema: *Sema,
1144 start: usize,
1145 end: usize,
1146) error{OutOfMemory}!Value {
1147 const pt = sema.pt;
1148 const ip = &pt.zcu.intern_pool;
1149 const io = pt.zcu.comp.io;
1150 return Value.fromInterned(try pt.intern(.{
1151 .aggregate = .{
1152 .ty = switch (pt.zcu.intern_pool.indexToKey(pt.zcu.intern_pool.typeOf(val.toIntern()))) {
1153 .array_type => |array_type| try pt.arrayType(.{
1154 .len = @intCast(end - start),
1155 .child = array_type.child,
1156 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1157 }),
1158 .vector_type => |vector_type| try pt.vectorType(.{
1159 .len = @intCast(end - start),
1160 .child = vector_type.child,
1161 }),
1162 else => unreachable,
1163 }.toIntern(),
1164 .storage = switch (ip.indexToKey(val.toIntern()).aggregate.storage) {
1165 .bytes => |bytes| storage: {
1166 try ip.string_bytes.ensureUnusedCapacity(sema.gpa, end - start + 1);
1167 break :storage .{ .bytes = try ip.getOrPutString(
1168 sema.gpa,
1169 io,
1170 bytes.toSlice(end, ip)[start..],
1171 .maybe_embedded_nulls,
1172 ) };
1173 },
1174 // TODO: write something like getCoercedInts to avoid needing to dupe
1175 .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[start..end]) },
1176 .repeated_elem => |elem| .{ .repeated_elem = elem },
1177 },
1178 },
1179 }));
1180}
1181
1182904pub fn fieldValue(val: Value, pt: Zcu.PerThread, index: usize) !Value {
1183905 const zcu = pt.zcu;
1184906 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
......@@ -1334,63 +1056,6 @@ pub fn isFloat(self: Value, zcu: *const Zcu) bool {
13341056 };
13351057}
13361058
1337pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, zcu: *Zcu) !Value {
1338 return floatFromIntAdvanced(val, arena, int_ty, float_ty, zcu, .normal) catch |err| switch (err) {
1339 error.OutOfMemory => return error.OutOfMemory,
1340 else => unreachable,
1341 };
1342}
1343
1344pub fn floatFromIntAdvanced(
1345 val: Value,
1346 arena: Allocator,
1347 int_ty: Type,
1348 float_ty: Type,
1349 pt: Zcu.PerThread,
1350 comptime strat: ResolveStrat,
1351) !Value {
1352 const zcu = pt.zcu;
1353 if (int_ty.zigTypeTag(zcu) == .vector) {
1354 const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(zcu));
1355 const scalar_ty = float_ty.scalarType(zcu);
1356 for (result_data, 0..) |*scalar, i| {
1357 const elem_val = try val.elemValue(pt, i);
1358 scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, pt, strat)).toIntern();
1359 }
1360 return pt.aggregateValue(float_ty, result_data);
1361 }
1362 return floatFromIntScalar(val, float_ty, pt, strat);
1363}
1364
1365pub fn floatFromIntScalar(val: Value, float_ty: Type, pt: Zcu.PerThread, comptime strat: ResolveStrat) !Value {
1366 return switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) {
1367 .undef => try pt.undefValue(float_ty),
1368 .int => |int| switch (int.storage) {
1369 .big_int => |big_int| pt.floatValue(float_ty, big_int.toFloat(f128, .nearest_even)[0]),
1370 inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, pt),
1371 .lazy_align => |ty| floatFromIntInner((try Type.fromInterned(ty).abiAlignmentInner(strat.toLazy(), pt.zcu, pt.tid)).scalar.toByteUnits() orelse 0, float_ty, pt),
1372 .lazy_size => |ty| floatFromIntInner((try Type.fromInterned(ty).abiSizeInner(strat.toLazy(), pt.zcu, pt.tid)).scalar, float_ty, pt),
1373 },
1374 else => unreachable,
1375 };
1376}
1377
1378fn floatFromIntInner(x: anytype, dest_ty: Type, pt: Zcu.PerThread) !Value {
1379 const target = pt.zcu.getTarget();
1380 const storage: InternPool.Key.Float.Storage = switch (dest_ty.floatBits(target)) {
1381 16 => .{ .f16 = @floatFromInt(x) },
1382 32 => .{ .f32 = @floatFromInt(x) },
1383 64 => .{ .f64 = @floatFromInt(x) },
1384 80 => .{ .f80 = @floatFromInt(x) },
1385 128 => .{ .f128 = @floatFromInt(x) },
1386 else => unreachable,
1387 };
1388 return Value.fromInterned(try pt.intern(.{ .float = .{
1389 .ty = dest_ty.toIntern(),
1390 .storage = storage,
1391 } }));
1392}
1393
13941059fn calcLimbLenFloat(scalar: anytype) usize {
13951060 if (scalar == 0) {
13961061 return 1;
......@@ -1410,11 +1075,11 @@ pub fn numberMax(lhs: Value, rhs: Value, zcu: *Zcu) Value {
14101075 if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef;
14111076 if (lhs.isNan(zcu)) return rhs;
14121077 if (rhs.isNan(zcu)) return lhs;
1413
1414 return switch (order(lhs, rhs, zcu)) {
1415 .lt => rhs,
1416 .gt, .eq => lhs,
1417 };
1078 if (compareHetero(lhs, .gt, rhs, zcu)) {
1079 return lhs;
1080 } else {
1081 return rhs;
1082 }
14181083}
14191084
14201085/// Supports both floats and ints; handles undefined.
......@@ -1422,11 +1087,11 @@ pub fn numberMin(lhs: Value, rhs: Value, zcu: *Zcu) Value {
14221087 if (lhs.isUndef(zcu) or rhs.isUndef(zcu)) return undef;
14231088 if (lhs.isNan(zcu)) return rhs;
14241089 if (rhs.isNan(zcu)) return lhs;
1425
1426 return switch (order(lhs, rhs, zcu)) {
1427 .lt => lhs,
1428 .gt, .eq => rhs,
1429 };
1090 if (compareHetero(lhs, .lt, rhs, zcu)) {
1091 return lhs;
1092 } else {
1093 return rhs;
1094 }
14301095}
14311096
14321097/// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
......@@ -2035,6 +1700,7 @@ pub fn makeBool(x: bool) Value {
20351700/// Returns a pointer to the payload of the optional.
20361701///
20371702/// May perform type resolution.
1703/// MLUGG TODO audit
20381704pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20391705 const zcu = pt.zcu;
20401706 const parent_ptr_ty = parent_ptr.typeOf(zcu);
......@@ -2044,7 +1710,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20441710 assert(ptr_size == .one or ptr_size == .c);
20451711 assert(opt_ty.zigTypeTag(zcu) == .optional);
20461712
2047 const result_ty = try pt.ptrTypeSema(info: {
1713 const result_ty = try pt.ptrType(info: {
20481714 var new = parent_ptr_ty.ptrInfo(zcu);
20491715 // We can correctly preserve alignment `.none`, since an optional has the same
20501716 // natural alignment as its child type.
......@@ -2070,6 +1736,7 @@ pub fn ptrOptPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20701736/// `parent_ptr` must be a single-pointer to some error union.
20711737/// Returns a pointer to the payload of the error union.
20721738/// May perform type resolution.
1739/// MLUGG TODO audit
20731740pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20741741 const zcu = pt.zcu;
20751742 const parent_ptr_ty = parent_ptr.typeOf(zcu);
......@@ -2078,7 +1745,7 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20781745 assert(parent_ptr_ty.ptrSize(zcu) == .one);
20791746 assert(eu_ty.zigTypeTag(zcu) == .error_union);
20801747
2081 const result_ty = try pt.ptrTypeSema(info: {
1748 const result_ty = try pt.ptrType(info: {
20821749 var new = parent_ptr_ty.ptrInfo(zcu);
20831750 // We can correctly preserve alignment `.none`, since an error union has a
20841751 // natural alignment greater than or equal to that of its payload type.
......@@ -2096,6 +1763,8 @@ pub fn ptrEuPayload(parent_ptr: Value, pt: Zcu.PerThread) !Value {
20961763 } }));
20971764}
20981765
1766// MLUGG TODO: audit ptrField etc in terms of resolution, and probably move them under sema
1767
20991768/// `parent_ptr` must be a single-pointer or c pointer to a struct, union, or slice.
21001769///
21011770/// Returns a pointer to the aggregate field at the specified index.
......@@ -2112,23 +1781,34 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
21121781 assert(parent_ptr_info.flags.size == .one or parent_ptr_info.flags.size == .c);
21131782
21141783 // Exiting this `switch` indicates that the `field` pointer representation should be used.
2115 // `field_align` may be `.none` to represent the natural alignment of `field_ty`, but is not necessarily.
2116 const field_ty: Type, const field_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) {
1784 const field_ty: Type, const new_align: InternPool.Alignment = switch (aggregate_ty.zigTypeTag(zcu)) {
21171785 .@"struct" => field: {
21181786 const field_ty = aggregate_ty.fieldType(field_idx, zcu);
21191787 switch (aggregate_ty.containerLayout(zcu)) {
2120 .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) },
1788 .auto => break :field .{ field_ty, a: {
1789 if (parent_ptr_info.flags.alignment == .none) {
1790 break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu);
1791 }
1792 const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu);
1793 break :a field_align.min(parent_ptr_info.flags.alignment);
1794 } },
21211795 .@"extern" => {
21221796 // Well-defined layout, so just offset the pointer appropriately.
2123 try aggregate_ty.resolveLayout(pt);
21241797 const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu);
2125 const field_align = a: {
1798 const field_align: InternPool.Alignment = a: {
1799 if (byte_off == 0) break :a parent_ptr_info.flags.alignment;
1800 const true_field_align: InternPool.Alignment = .fromLog2Units(@ctz(byte_off));
1801 if (parent_ptr_info.flags.alignment == .none and
1802 true_field_align == field_ty.abiAlignment(zcu))
1803 {
1804 break :a .none;
1805 }
21261806 const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: {
2127 break :pa try aggregate_ty.abiAlignmentSema(pt);
1807 break :pa aggregate_ty.abiAlignment(zcu);
21281808 } else parent_ptr_info.flags.alignment;
2129 break :a InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(byte_off)));
1809 break :a .minStrict(true_field_align, parent_align);
21301810 };
2131 const result_ty = try pt.ptrTypeSema(info: {
1811 const result_ty = try pt.ptrType(info: {
21321812 var new = parent_ptr_info;
21331813 new.child = field_ty.toIntern();
21341814 new.flags.alignment = field_align;
......@@ -2143,7 +1823,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
21431823 new.packed_offset = packed_offset;
21441824 new.child = field_ty.toIntern();
21451825 if (new.flags.alignment == .none) {
2146 new.flags.alignment = try aggregate_ty.abiAlignmentSema(pt);
1826 new.flags.alignment = aggregate_ty.abiAlignment(zcu);
21471827 }
21481828 break :info new;
21491829 });
......@@ -2155,10 +1835,16 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
21551835 const union_obj = zcu.typeToUnion(aggregate_ty).?;
21561836 const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]);
21571837 switch (aggregate_ty.containerLayout(zcu)) {
2158 .auto => break :field .{ field_ty, try aggregate_ty.fieldAlignmentSema(field_idx, pt) },
1838 .auto => break :field .{ field_ty, a: {
1839 if (parent_ptr_info.flags.alignment == .none) {
1840 break :a aggregate_ty.explicitFieldAlignment(field_idx, zcu);
1841 }
1842 const field_align = aggregate_ty.resolvedFieldAlignment(field_idx, zcu);
1843 break :a field_align.min(parent_ptr_info.flags.alignment);
1844 } },
21591845 .@"extern" => {
21601846 // Point to the same address.
2161 const result_ty = try pt.ptrTypeSema(info: {
1847 const result_ty = try pt.ptrType(info: {
21621848 var new = parent_ptr_info;
21631849 new.child = field_ty.toIntern();
21641850 break :info new;
......@@ -2166,59 +1852,30 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
21661852 return pt.getCoerced(parent_ptr, result_ty);
21671853 },
21681854 .@"packed" => {
2169 // If the field has an ABI size matching its bit size, then we can continue to use a
2170 // non-bit pointer if the parent pointer is also a non-bit pointer.
2171 if (parent_ptr_info.packed_offset.host_size == 0 and (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar * 8 == try field_ty.bitSizeSema(pt)) {
2172 // We must offset the pointer on big-endian targets, since the bits of packed memory don't align nicely.
2173 const byte_offset = switch (zcu.getTarget().cpu.arch.endian()) {
2174 .little => 0,
2175 .big => (try aggregate_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar - (try field_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar,
2176 };
2177 const result_ty = try pt.ptrTypeSema(info: {
2178 var new = parent_ptr_info;
2179 new.child = field_ty.toIntern();
2180 new.flags.alignment = InternPool.Alignment.fromLog2Units(
2181 @ctz(byte_offset | (try parent_ptr_ty.ptrAlignmentSema(pt)).toByteUnits().?),
2182 );
2183 break :info new;
2184 });
2185 return parent_ptr.getOffsetPtr(byte_offset, result_ty, pt);
2186 } else {
2187 // The result must be a bit-pointer if it is not already.
2188 const result_ty = try pt.ptrTypeSema(info: {
2189 var new = parent_ptr_info;
2190 new.child = field_ty.toIntern();
2191 if (new.packed_offset.host_size == 0) {
2192 new.packed_offset.host_size = @intCast(((try aggregate_ty.bitSizeSema(pt)) + 7) / 8);
2193 assert(new.packed_offset.bit_offset == 0);
2194 }
2195 break :info new;
2196 });
2197 return pt.getCoerced(parent_ptr, result_ty);
2198 }
1855 const result_ty = try pt.ptrType(info: {
1856 var new = parent_ptr_info;
1857 new.child = field_ty.toIntern();
1858 break :info new;
1859 });
1860 return pt.getCoerced(parent_ptr, result_ty);
21991861 },
22001862 }
22011863 },
22021864 .pointer => field_ty: {
22031865 assert(aggregate_ty.isSlice(zcu));
2204 break :field_ty switch (field_idx) {
2205 Value.slice_ptr_index => .{ aggregate_ty.slicePtrFieldType(zcu), Type.usize.abiAlignment(zcu) },
2206 Value.slice_len_index => .{ Type.usize, Type.usize.abiAlignment(zcu) },
1866 break :field_ty .{ switch (field_idx) {
1867 Value.slice_ptr_index => aggregate_ty.slicePtrFieldType(zcu),
1868 Value.slice_len_index => Type.usize,
22071869 else => unreachable,
2208 };
1870 }, switch (parent_ptr_info.flags.alignment) {
1871 .none => .none,
1872 else => Type.usize.abiAlignment(zcu).min(parent_ptr_info.flags.alignment),
1873 } };
22091874 },
22101875 else => unreachable,
22111876 };
22121877
2213 const new_align: InternPool.Alignment = if (parent_ptr_info.flags.alignment != .none) a: {
2214 const ty_align = (try field_ty.abiAlignmentInner(.sema, zcu, pt.tid)).scalar;
2215 const true_field_align = if (field_align == .none) ty_align else field_align;
2216 const new_align = true_field_align.min(parent_ptr_info.flags.alignment);
2217 if (new_align == ty_align) break :a .none;
2218 break :a new_align;
2219 } else field_align;
2220
2221 const result_ty = try pt.ptrTypeSema(info: {
1878 const result_ty = try pt.ptrType(info: {
22221879 var new = parent_ptr_info;
22231880 new.child = field_ty.toIntern();
22241881 new.flags.alignment = new_align;
......@@ -2241,6 +1898,7 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, pt: Zcu.PerThread) !Value {
22411898/// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice.
22421899/// Returns a pointer to the element at the specified index.
22431900/// May perform type resolution.
1901/// MLUGG TODO AUDIT
22441902pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value {
22451903 const zcu = pt.zcu;
22461904 const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) {
......@@ -2267,21 +1925,19 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, pt: Zcu.PerThread) !Value
22671925
22681926 const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) {
22691927 .one => switch (elem_ty.zigTypeTag(zcu)) {
2270 .vector => .{ .offset = field_idx * @divExact(try elem_ty.childType(zcu).bitSizeSema(pt), 8) },
1928 .vector => .{ .offset = field_idx * @divExact(elem_ty.childType(zcu).bitSize(zcu), 8) },
22711929 .array => strat: {
22721930 const arr_elem_ty = elem_ty.childType(zcu);
2273 if (try arr_elem_ty.comptimeOnlySema(pt)) {
2274 break :strat .{ .elem_ptr = arr_elem_ty };
2275 }
2276 break :strat .{ .offset = field_idx * (try arr_elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar };
1931 if (arr_elem_ty.comptimeOnly(zcu)) break :strat .{ .elem_ptr = arr_elem_ty };
1932 break :strat .{ .offset = field_idx * arr_elem_ty.abiSize(zcu) };
22771933 },
22781934 else => unreachable,
22791935 },
22801936
2281 .many, .c => if (try elem_ty.comptimeOnlySema(pt))
1937 .many, .c => if (elem_ty.comptimeOnly(zcu))
22821938 .{ .elem_ptr = elem_ty }
22831939 else
2284 .{ .offset = field_idx * (try elem_ty.abiSizeInner(.sema, zcu, pt.tid)).scalar },
1940 .{ .offset = field_idx * elem_ty.abiSize(zcu) },
22851941
22861942 .slice => unreachable,
22871943 };
......@@ -2430,6 +2086,7 @@ pub fn pointerDerivation(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread) Al
24302086/// which prefer field/elem accesses when lowering constant pointer values.
24312087/// It is also used by the Value printing logic for pointers.
24322088pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerThread, comptime resolve_types: bool, opt_sema: ?*Sema) !PointerDeriveStep {
2089 // MLUGG TODO: audit tf outta this code
24332090 const zcu = pt.zcu;
24342091 const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
24352092 const base_derive: PointerDeriveStep = switch (ptr.base_addr) {
......@@ -2454,7 +2111,7 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh
24542111 .comptime_alloc => |idx| base: {
24552112 const sema = opt_sema.?;
24562113 const alloc = sema.getComptimeAlloc(idx);
2457 const val = try alloc.val.intern(pt, sema.arena);
2114 const val = try alloc.val.intern(pt, arena);
24582115 const ty = val.typeOf(zcu);
24592116 break :base .{ .comptime_alloc_ptr = .{
24602117 .idx = idx,
......@@ -2492,24 +2149,14 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh
24922149 const base_ptr = Value.fromInterned(field.base);
24932150 const base_ptr_ty = base_ptr.typeOf(zcu);
24942151 const agg_ty = base_ptr_ty.childType(zcu);
2495 const field_ty, const field_align = switch (agg_ty.zigTypeTag(zcu)) {
2496 .@"struct" => .{ agg_ty.fieldType(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner(
2497 @intCast(field.index),
2498 if (resolve_types) .sema else .normal,
2499 pt.zcu,
2500 if (resolve_types) pt.tid else {},
2501 ) },
2502 .@"union" => .{ agg_ty.unionFieldTypeByIndex(@intCast(field.index), zcu), try agg_ty.fieldAlignmentInner(
2503 @intCast(field.index),
2504 if (resolve_types) .sema else .normal,
2505 pt.zcu,
2506 if (resolve_types) pt.tid else {},
2507 ) },
2508 .pointer => .{ switch (field.index) {
2509 Value.slice_ptr_index => agg_ty.slicePtrFieldType(zcu),
2510 Value.slice_len_index => Type.usize,
2152 if (resolve_types) try opt_sema.?.ensureLayoutResolved(agg_ty);
2153 const field_ty: Type, const field_align: InternPool.Alignment = switch (agg_ty.zigTypeTag(zcu)) {
2154 .@"struct", .@"union" => .{ agg_ty.fieldType(@intCast(field.index), zcu), agg_ty.resolvedFieldAlignment(@intCast(field.index), pt.zcu) },
2155 .pointer => switch (field.index) {
2156 Value.slice_ptr_index => .{ agg_ty.slicePtrFieldType(zcu), Type.ptrAbiAlignment(zcu.getTarget()) },
2157 Value.slice_len_index => .{ .usize, Type.abiAlignment(.usize, zcu) },
25112158 else => unreachable,
2512 }, Type.usize.abiAlignment(zcu) },
2159 },
25132160 else => unreachable,
25142161 };
25152162 const base_align = base_ptr_ty.ptrAlignment(zcu);
......@@ -2720,148 +2367,6 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, pt: Zcu.PerTh
27202367 } };
27212368}
27222369
2723pub fn resolveLazy(
2724 val: Value,
2725 arena: Allocator,
2726 pt: Zcu.PerThread,
2727) Zcu.SemaError!Value {
2728 switch (pt.zcu.intern_pool.indexToKey(val.toIntern())) {
2729 .int => |int| switch (int.storage) {
2730 .u64, .i64, .big_int => return val,
2731 .lazy_align, .lazy_size => return pt.intValue(
2732 Type.fromInterned(int.ty),
2733 try val.toUnsignedIntSema(pt),
2734 ),
2735 },
2736 .slice => |slice| {
2737 const ptr = try Value.fromInterned(slice.ptr).resolveLazy(arena, pt);
2738 const len = try Value.fromInterned(slice.len).resolveLazy(arena, pt);
2739 if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val;
2740 return Value.fromInterned(try pt.intern(.{ .slice = .{
2741 .ty = slice.ty,
2742 .ptr = ptr.toIntern(),
2743 .len = len.toIntern(),
2744 } }));
2745 },
2746 .ptr => |ptr| {
2747 switch (ptr.base_addr) {
2748 .nav, .comptime_alloc, .uav, .int => return val,
2749 .comptime_field => |field_val| {
2750 const resolved_field_val = (try Value.fromInterned(field_val).resolveLazy(arena, pt)).toIntern();
2751 return if (resolved_field_val == field_val)
2752 val
2753 else
2754 Value.fromInterned(try pt.intern(.{ .ptr = .{
2755 .ty = ptr.ty,
2756 .base_addr = .{ .comptime_field = resolved_field_val },
2757 .byte_offset = ptr.byte_offset,
2758 } }));
2759 },
2760 .eu_payload, .opt_payload => |base| {
2761 const resolved_base = (try Value.fromInterned(base).resolveLazy(arena, pt)).toIntern();
2762 return if (resolved_base == base)
2763 val
2764 else
2765 Value.fromInterned(try pt.intern(.{ .ptr = .{
2766 .ty = ptr.ty,
2767 .base_addr = switch (ptr.base_addr) {
2768 .eu_payload => .{ .eu_payload = resolved_base },
2769 .opt_payload => .{ .opt_payload = resolved_base },
2770 else => unreachable,
2771 },
2772 .byte_offset = ptr.byte_offset,
2773 } }));
2774 },
2775 .arr_elem, .field => |base_index| {
2776 const resolved_base = (try Value.fromInterned(base_index.base).resolveLazy(arena, pt)).toIntern();
2777 return if (resolved_base == base_index.base)
2778 val
2779 else
2780 Value.fromInterned(try pt.intern(.{ .ptr = .{
2781 .ty = ptr.ty,
2782 .base_addr = switch (ptr.base_addr) {
2783 .arr_elem => .{ .arr_elem = .{
2784 .base = resolved_base,
2785 .index = base_index.index,
2786 } },
2787 .field => .{ .field = .{
2788 .base = resolved_base,
2789 .index = base_index.index,
2790 } },
2791 else => unreachable,
2792 },
2793 .byte_offset = ptr.byte_offset,
2794 } }));
2795 },
2796 }
2797 },
2798 .aggregate => |aggregate| switch (aggregate.storage) {
2799 .bytes => return val,
2800 .elems => |elems| {
2801 var resolved_elems: []InternPool.Index = &.{};
2802 for (elems, 0..) |elem, i| {
2803 const resolved_elem = (try Value.fromInterned(elem).resolveLazy(arena, pt)).toIntern();
2804 if (resolved_elems.len == 0 and resolved_elem != elem) {
2805 resolved_elems = try arena.alloc(InternPool.Index, elems.len);
2806 @memcpy(resolved_elems[0..i], elems[0..i]);
2807 }
2808 if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem;
2809 }
2810 return if (resolved_elems.len == 0)
2811 val
2812 else
2813 pt.aggregateValue(.fromInterned(aggregate.ty), resolved_elems);
2814 },
2815 .repeated_elem => |elem| {
2816 const resolved_elem = try Value.fromInterned(elem).resolveLazy(arena, pt);
2817 return if (resolved_elem.toIntern() == elem)
2818 val
2819 else
2820 pt.aggregateSplatValue(.fromInterned(aggregate.ty), resolved_elem);
2821 },
2822 },
2823 .un => |un| {
2824 const resolved_tag = if (un.tag == .none)
2825 .none
2826 else
2827 (try Value.fromInterned(un.tag).resolveLazy(arena, pt)).toIntern();
2828 const resolved_val = (try Value.fromInterned(un.val).resolveLazy(arena, pt)).toIntern();
2829 return if (resolved_tag == un.tag and resolved_val == un.val)
2830 val
2831 else
2832 Value.fromInterned(try pt.internUnion(.{
2833 .ty = un.ty,
2834 .tag = resolved_tag,
2835 .val = resolved_val,
2836 }));
2837 },
2838 .error_union => |eu| switch (eu.val) {
2839 .err_name => return val,
2840 .payload => |payload| {
2841 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2842 if (resolved_payload.toIntern() == payload) return val;
2843 return .fromInterned(try pt.intern(.{ .error_union = .{
2844 .ty = eu.ty,
2845 .val = .{ .payload = resolved_payload.toIntern() },
2846 } }));
2847 },
2848 },
2849 .opt => |opt| switch (opt.val) {
2850 .none => return val,
2851 else => |payload| {
2852 const resolved_payload = try Value.fromInterned(payload).resolveLazy(arena, pt);
2853 if (resolved_payload.toIntern() == payload) return val;
2854 return .fromInterned(try pt.intern(.{ .opt = .{
2855 .ty = opt.ty,
2856 .val = resolved_payload.toIntern(),
2857 } }));
2858 },
2859 },
2860
2861 else => return val,
2862 }
2863}
2864
28652370const InterpretMode = enum {
28662371 /// In this mode, types are assumed to match what the compiler was built with in terms of field
28672372 /// order, field types, etc. This improves compiler performance. However, it means that certain
......@@ -2878,7 +2383,6 @@ const interpret_mode: InterpretMode = @field(InterpretMode, @tagName(build_optio
28782383
28792384/// Given a `Value` representing a comptime-known value of type `T`, unwrap it into an actual `T` known to the compiler.
28802385/// This is useful for accessing `std.builtin` structures received from comptime logic.
2881/// `val` must be fully resolved.
28822386pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMemory, UndefinedValue, TypeMismatch }!T {
28832387 const zcu = pt.zcu;
28842388 const io = zcu.comp.io;
......@@ -2917,7 +2421,6 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe
29172421 },
29182422
29192423 .int => switch (ip.indexToKey(val.toIntern()).int.storage) {
2920 .lazy_align, .lazy_size => unreachable, // `val` is fully resolved
29212424 inline .u64, .i64 => |x| std.math.cast(T, x) orelse return error.TypeMismatch,
29222425 .big_int => |big| big.toInt(T) catch return error.TypeMismatch,
29232426 },
src/Zcu.zig+84-79
......@@ -14,6 +14,8 @@ const mem = std.mem;
1414const Allocator = std.mem.Allocator;
1515const assert = std.debug.assert;
1616const log = std.log.scoped(.zcu);
17const deps_log = std.log.scoped(.zcu_deps);
18const refs_log = std.log.scoped(.zcu_refs);
1719const BigIntConst = std.math.big.int.Const;
1820const BigIntMutable = std.math.big.int.Mutable;
1921const Target = std.Target;
......@@ -2685,10 +2687,10 @@ pub const LazySrcLoc = struct {
26852687 .struct_init, .struct_init_ref => zir.extraData(Zir.Inst.StructInit, inst.data.pl_node.payload_index).data.abs_node,
26862688 .struct_init_anon => zir.extraData(Zir.Inst.StructInitAnon, inst.data.pl_node.payload_index).data.abs_node,
26872689 .extended => switch (inst.data.extended.opcode) {
2688 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_node,
2689 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_node,
2690 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_node,
2691 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_node,
2690 .struct_decl => zir.getStructDecl(zir_inst).src_node,
2691 .union_decl => zir.getUnionDecl(zir_inst).src_node,
2692 .enum_decl => zir.getEnumDecl(zir_inst).src_node,
2693 .opaque_decl => zir.getOpaqueDecl(zir_inst).src_node,
26922694 .reify_enum => zir.extraData(Zir.Inst.ReifyEnum, inst.data.extended.operand).data.node,
26932695 .reify_struct => zir.extraData(Zir.Inst.ReifyStruct, inst.data.extended.operand).data.node,
26942696 .reify_union => zir.extraData(Zir.Inst.ReifyUnion, inst.data.extended.operand).data.node,
......@@ -3063,7 +3065,7 @@ pub fn markDependeeOutdated(
30633065 marked_po: enum { not_marked_po, marked_po },
30643066 dependee: InternPool.Dependee,
30653067) !void {
3066 log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3068 deps_log.debug("outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
30673069 var it = zcu.intern_pool.dependencyIterator(dependee);
30683070 while (it.next()) |depender| {
30693071 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
......@@ -3071,9 +3073,9 @@ pub fn markDependeeOutdated(
30713073 .not_marked_po => {},
30723074 .marked_po => {
30733075 po_dep_count.* -= 1;
3074 log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3076 deps_log.debug("outdated {f} => already outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
30753077 if (po_dep_count.* == 0) {
3076 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3078 deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
30773079 try zcu.outdated_ready.put(zcu.gpa, depender, {});
30783080 }
30793081 },
......@@ -3094,9 +3096,9 @@ pub fn markDependeeOutdated(
30943096 depender,
30953097 new_po_dep_count,
30963098 );
3097 log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });
3099 deps_log.debug("outdated {f} => new outdated {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), new_po_dep_count });
30983100 if (new_po_dep_count == 0) {
3099 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3101 deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
31003102 try zcu.outdated_ready.put(zcu.gpa, depender, {});
31013103 }
31023104 // If this is a Decl and was not previously PO, we must recursively
......@@ -3109,16 +3111,16 @@ pub fn markDependeeOutdated(
31093111}
31103112
31113113pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3112 log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)});
3114 deps_log.debug("up-to-date dependee: {f}", .{zcu.fmtDependee(dependee)});
31133115 var it = zcu.intern_pool.dependencyIterator(dependee);
31143116 while (it.next()) |depender| {
31153117 if (zcu.outdated.getPtr(depender)) |po_dep_count| {
31163118 // This depender is already outdated, but it now has one
31173119 // less PO dependency!
31183120 po_dep_count.* -= 1;
3119 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
3121 deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), po_dep_count.* });
31203122 if (po_dep_count.* == 0) {
3121 log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
3123 deps_log.debug("outdated ready: {f}", .{zcu.fmtAnalUnit(depender)});
31223124 try zcu.outdated_ready.put(zcu.gpa, depender, {});
31233125 }
31243126 continue;
......@@ -3132,11 +3134,11 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
31323134 };
31333135 if (ptr.* > 1) {
31343136 ptr.* -= 1;
3135 log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });
3137 deps_log.debug("up-to-date {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender), ptr.* });
31363138 continue;
31373139 }
31383140
3139 log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });
3141 deps_log.debug("up-to-date {f} => {f} po_deps=0 (up-to-date)", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(depender) });
31403142
31413143 // This dependency is no longer PO, i.e. is known to be up-to-date.
31423144 assert(zcu.potentially_outdated.swapRemove(depender));
......@@ -3146,8 +3148,9 @@ pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
31463148 .@"comptime" => {},
31473149 .nav_val => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_val = nav }),
31483150 .nav_ty => |nav| try zcu.markPoDependeeUpToDate(.{ .nav_ty = nav }),
3149 .type => |ty| try zcu.markPoDependeeUpToDate(.{ .interned = ty }),
3150 .func => |func| try zcu.markPoDependeeUpToDate(.{ .interned = func }),
3151 .type_layout => |ty| try zcu.markPoDependeeUpToDate(.{ .type_layout = ty }),
3152 .type_inits => |ty| try zcu.markPoDependeeUpToDate(.{ .type_inits = ty }),
3153 .func => |func| try zcu.markPoDependeeUpToDate(.{ .func_ies = func }),
31513154 .memoized_state => |stage| try zcu.markPoDependeeUpToDate(.{ .memoized_state = stage }),
31523155 }
31533156 }
......@@ -3161,11 +3164,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
31613164 .@"comptime" => return, // analysis of a comptime decl can't outdate any dependencies
31623165 .nav_val => |nav| .{ .nav_val = nav },
31633166 .nav_ty => |nav| .{ .nav_ty = nav },
3164 .type => |ty| .{ .interned = ty },
3165 .func => |func_index| .{ .interned = func_index }, // IES
3167 .type_layout => |ty| .{ .type_layout = ty },
3168 .type_inits => |ty| .{ .type_inits = ty },
3169 .func => |func_index| .{ .func_ies = func_index },
31663170 .memoized_state => |stage| .{ .memoized_state = stage },
31673171 };
3168 log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
3172 deps_log.debug("potentially outdated dependee: {f}", .{zcu.fmtDependee(dependee)});
31693173 var it = ip.dependencyIterator(dependee);
31703174 while (it.next()) |po| {
31713175 if (zcu.outdated.getPtr(po)) |po_dep_count| {
......@@ -3175,17 +3179,17 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
31753179 _ = zcu.outdated_ready.swapRemove(po);
31763180 }
31773181 po_dep_count.* += 1;
3178 log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });
3182 deps_log.debug("po {f} => {f} [outdated] po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), po_dep_count.* });
31793183 continue;
31803184 }
31813185 if (zcu.potentially_outdated.getPtr(po)) |n| {
31823186 // There is now one more PO dependency.
31833187 n.* += 1;
3184 log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });
3188 deps_log.debug("po {f} => {f} po_deps={}", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po), n.* });
31853189 continue;
31863190 }
31873191 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);
3188 log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });
3192 deps_log.debug("po {f} => {f} po_deps=1", .{ zcu.fmtDependee(dependee), zcu.fmtAnalUnit(po) });
31893193 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.
31903194 try zcu.markTransitiveDependersPotentiallyOutdated(po);
31913195 }
......@@ -3240,13 +3244,15 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
32403244 var chosen_unit: ?AnalUnit = null;
32413245 var chosen_unit_dependers: u32 = undefined;
32423246
3247 // MLUGG TODO: i'm 99% sure this is now impossible. check!!!
32433248 inline for (.{ zcu.outdated.keys(), zcu.potentially_outdated.keys() }) |outdated_units| {
32443249 for (outdated_units) |unit| {
32453250 var n: u32 = 0;
32463251 var it = ip.dependencyIterator(switch (unit.unwrap()) {
32473252 .func => continue, // a `func` definitely can't be causing the loop so it is a bad choice
32483253 .@"comptime" => continue, // a `comptime` block can't even be depended on so it is a terrible choice
3249 .type => |ty| .{ .interned = ty },
3254 .type_layout => |ty| .{ .type_layout = ty },
3255 .type_inits => |ty| .{ .type_inits = ty },
32503256 .nav_val => |nav| .{ .nav_val = nav },
32513257 .nav_ty => |nav| .{ .nav_ty = nav },
32523258 .memoized_state => {
......@@ -3377,25 +3383,21 @@ pub fn mapOldZirToNew(
33773383 var comptime_decls: std.ArrayList(Zir.Inst.Index) = .empty;
33783384 defer comptime_decls.deinit(gpa);
33793385
3380 {
3381 var old_decl_it = old_zir.declIterator(match_item.old_inst);
3382 while (old_decl_it.next()) |old_decl_inst| {
3383 const old_decl = old_zir.getDeclaration(old_decl_inst);
3384 switch (old_decl.kind) {
3385 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
3386 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
3387 .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
3388 .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
3389 .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
3390 }
3386 for (old_zir.typeDecls(match_item.old_inst)) |old_decl_inst| {
3387 const old_decl = old_zir.getDeclaration(old_decl_inst);
3388 switch (old_decl.kind) {
3389 .@"comptime" => try comptime_decls.append(gpa, old_decl_inst),
3390 .unnamed_test => try unnamed_tests.append(gpa, old_decl_inst),
3391 .@"test" => try named_tests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
3392 .decltest => try named_decltests.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
3393 .@"const", .@"var" => try named_decls.put(gpa, old_zir.nullTerminatedString(old_decl.name), old_decl_inst),
33913394 }
33923395 }
33933396
33943397 var unnamed_test_idx: u32 = 0;
33953398 var comptime_decl_idx: u32 = 0;
33963399
3397 var new_decl_it = new_zir.declIterator(match_item.new_inst);
3398 while (new_decl_it.next()) |new_decl_inst| {
3400 for (new_zir.typeDecls(match_item.new_inst)) |new_decl_inst| {
33993401 const new_decl = new_zir.getDeclaration(new_decl_inst);
34003402 // Attempt to match this to a declaration in the old ZIR:
34013403 // * For named declarations (`const`/`var`/`fn`), we match based on name.
......@@ -3494,7 +3496,7 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func_index: InternPool.Index) !vo
34943496 }
34953497
34963498 try zcu.func_body_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1);
3497 try zcu.comp.queueJob(.{ .analyze_func = func_index });
3499 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .func = func_index }) });
34983500 zcu.func_body_analysis_queued.putAssumeCapacityNoClobber(func_index, {});
34993501}
35003502
......@@ -3513,7 +3515,7 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav_id: InternPool.Nav.Index) !void
35133515 }
35143516
35153517 try zcu.nav_val_analysis_queued.ensureUnusedCapacity(zcu.gpa, 1);
3516 try zcu.comp.queueJob(.{ .analyze_comptime_unit = .wrap(.{ .nav_val = nav_id }) });
3518 try zcu.comp.queueJob(.{ .analyze_unit = .wrap(.{ .nav_val = nav_id }) });
35173519 zcu.nav_val_analysis_queued.putAssumeCapacityNoClobber(nav_id, {});
35183520}
35193521
......@@ -3908,8 +3910,7 @@ pub fn atomicPtrAlignment(
39083910 return error.BadType;
39093911}
39103912
3911/// Returns null in the following cases:
3912/// * Not a struct.
3913/// Returns null if `ty` is not a struct.
39133914pub fn typeToStruct(zcu: *const Zcu, ty: Type) ?InternPool.LoadedStructType {
39143915 if (ty.ip_index == .none) return null;
39153916 const ip = &zcu.intern_pool;
......@@ -3936,7 +3937,6 @@ pub fn structPackedFieldBitOffset(
39363937) u16 {
39373938 const ip = &zcu.intern_pool;
39383939 assert(struct_type.layout == .@"packed");
3939 assert(struct_type.haveLayout(ip));
39403940 var bit_sum: u64 = 0;
39413941 for (0..struct_type.field_types.len) |i| {
39423942 if (i == field_index) {
......@@ -3995,8 +3995,10 @@ pub const UnionLayout = struct {
39953995pub fn unionTagFieldIndex(zcu: *const Zcu, loaded_union: InternPool.LoadedUnionType, enum_tag: Value) ?u32 {
39963996 const ip = &zcu.intern_pool;
39973997 if (enum_tag.toIntern() == .none) return null;
3998 assert(ip.typeOf(enum_tag.toIntern()) == loaded_union.enum_tag_ty);
3999 return loaded_union.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());
3998 const enum_tag_key = ip.indexToKey(enum_tag.toIntern()).enum_tag;
3999 assert(enum_tag_key.ty == loaded_union.enum_tag_type);
4000 const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type);
4001 return loaded_enum.tagValueIndex(ip, enum_tag_key.int);
40004002}
40014003
40024004pub const ResolvedReference = struct {
......@@ -4049,31 +4051,36 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
40494051 const referencer = types.values()[type_idx];
40504052 type_idx += 1;
40514053
4052 log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
4054 refs_log.debug("handle type '{f}'", .{Type.fromInterned(ty).containerTypeName(ip).fmt(ip)});
40534055
4054 // If this type undergoes type resolution, the corresponding `AnalUnit` is automatically referenced.
4055 const has_resolution: bool = switch (ip.indexToKey(ty)) {
4056 .struct_type, .union_type => true,
4057 .enum_type => |k| k != .generated_tag,
4058 .opaque_type => false,
4056 // If this type undergoes type resolution, the corresponding `AnalUnit`s are automatically referenced.
4057 const has_layout: bool, const has_inits: bool = switch (ip.indexToKey(ty)) {
4058 .struct_type => .{ true, true },
4059 .union_type => .{ true, false },
4060 .enum_type => .{ false, true },
4061 .opaque_type => .{ false, false },
40594062 else => unreachable,
40604063 };
4061 if (has_resolution) {
4064 if (has_layout) {
4065 // this should only be referenced by the type
4066 const unit: AnalUnit = .wrap(.{ .type_layout = ty });
4067 try units.putNoClobber(gpa, unit, referencer);
4068 }
4069 if (has_inits) {
40624070 // this should only be referenced by the type
4063 const unit: AnalUnit = .wrap(.{ .type = ty });
4071 const unit: AnalUnit = .wrap(.{ .type_inits = ty });
40644072 try units.putNoClobber(gpa, unit, referencer);
40654073 }
40664074
40674075 // If this is a union with a generated tag, its tag type is automatically referenced.
40684076 // We don't add this reference for non-generated tags, as those will already be referenced via the union's type resolution, with a better source location.
4069 if (zcu.typeToUnion(Type.fromInterned(ty))) |union_obj| {
4070 const tag_ty = union_obj.enum_tag_ty;
4071 if (tag_ty != .none) {
4072 if (ip.indexToKey(tag_ty).enum_type == .generated_tag) {
4073 const gop = try types.getOrPut(gpa, tag_ty);
4074 if (!gop.found_existing) gop.value_ptr.* = referencer;
4075 }
4076 }
4077 implicit_tag: {
4078 const loaded_union = zcu.typeToUnion(.fromInterned(ty)) orelse break :implicit_tag;
4079 const tag_ty = loaded_union.enum_tag_type;
4080 if (ip.indexToKey(tag_ty).enum_type != .generated_union_tag) break :implicit_tag;
4081 const gop = try types.getOrPut(gpa, tag_ty);
4082 if (gop.found_existing) break :implicit_tag;
4083 gop.value_ptr.* = referencer;
40774084 }
40784085
40794086 // Queue any decls within this type which would be automatically analyzed.
......@@ -4084,7 +4091,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
40844091 const unit: AnalUnit = .wrap(.{ .@"comptime" = cu });
40854092 const gop = try units.getOrPut(gpa, unit);
40864093 if (!gop.found_existing) {
4087 log.debug("type '{f}': ref comptime %{}", .{
4094 refs_log.debug("type '{f}': ref comptime %{}", .{
40884095 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
40894096 @intFromEnum(ip.getComptimeUnit(cu).zir_index.resolve(ip) orelse continue),
40904097 });
......@@ -4118,7 +4125,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41184125 {
41194126 const gop = try units.getOrPut(gpa, .wrap(.{ .nav_val = nav_id }));
41204127 if (!gop.found_existing) {
4121 log.debug("type '{f}': ref test %{}", .{
4128 refs_log.debug("type '{f}': ref test %{}", .{
41224129 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
41234130 @intFromEnum(inst_info.inst),
41244131 });
......@@ -4141,7 +4148,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41414148 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
41424149 const gop = try units.getOrPut(gpa, unit);
41434150 if (!gop.found_existing) {
4144 log.debug("type '{f}': ref named %{}", .{
4151 refs_log.debug("type '{f}': ref named %{}", .{
41454152 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
41464153 @intFromEnum(inst_info.inst),
41474154 });
......@@ -4158,7 +4165,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41584165 const unit: AnalUnit = .wrap(.{ .nav_val = nav });
41594166 const gop = try units.getOrPut(gpa, unit);
41604167 if (!gop.found_existing) {
4161 log.debug("type '{f}': ref named %{}", .{
4168 refs_log.debug("type '{f}': ref named %{}", .{
41624169 Type.fromInterned(ty).containerTypeName(ip).fmt(ip),
41634170 @intFromEnum(inst_info.inst),
41644171 });
......@@ -4177,14 +4184,14 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41774184 const other: AnalUnit = .wrap(switch (unit.unwrap()) {
41784185 .nav_val => |n| .{ .nav_ty = n },
41794186 .nav_ty => |n| .{ .nav_val = n },
4180 .@"comptime", .type, .func, .memoized_state => break :queue_paired,
4187 .@"comptime", .type_layout, .type_inits, .func, .memoized_state => break :queue_paired,
41814188 });
41824189 const gop = try units.getOrPut(gpa, other);
41834190 if (gop.found_existing) break :queue_paired;
41844191 gop.value_ptr.* = units.values()[unit_idx]; // same reference location
41854192 }
41864193
4187 log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
4194 refs_log.debug("handle unit '{f}'", .{zcu.fmtAnalUnit(unit)});
41884195
41894196 if (zcu.reference_table.get(unit)) |first_ref_idx| {
41904197 assert(first_ref_idx != std.math.maxInt(u32));
......@@ -4193,7 +4200,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
41934200 const ref = zcu.all_references.items[ref_idx];
41944201 const gop = try units.getOrPut(gpa, ref.referenced);
41954202 if (!gop.found_existing) {
4196 log.debug("unit '{f}': ref unit '{f}'", .{
4203 refs_log.debug("unit '{f}': ref unit '{f}'", .{
41974204 zcu.fmtAnalUnit(unit),
41984205 zcu.fmtAnalUnit(ref.referenced),
41994206 });
......@@ -4213,7 +4220,7 @@ fn resolveReferencesInner(zcu: *Zcu) !std.AutoArrayHashMapUnmanaged(AnalUnit, ?R
42134220 const ref = zcu.all_type_references.items[ref_idx];
42144221 const gop = try types.getOrPut(gpa, ref.referenced);
42154222 if (!gop.found_existing) {
4216 log.debug("unit '{f}': ref type '{f}'", .{
4223 refs_log.debug("unit '{f}': ref type '{f}'", .{
42174224 zcu.fmtAnalUnit(unit),
42184225 Type.fromInterned(ref.referenced).containerTypeName(ip).fmt(ip),
42194226 });
......@@ -4323,9 +4330,8 @@ fn formatAnalUnit(data: FormatAnalUnit, writer: *Io.Writer) Io.Writer.Error!void
43234330 return writer.print("comptime(inst=<lost> [{}])", .{@intFromEnum(cu_id)});
43244331 }
43254332 },
4326 .nav_val => |nav| return writer.print("nav_val('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4327 .nav_ty => |nav| return writer.print("nav_ty('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4328 .type => |ty| return writer.print("ty('{f}' [{}])", .{ Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
4333 .nav_val, .nav_ty => |nav, tag| return writer.print("{t}('{f}' [{}])", .{ tag, ip.getNav(nav).fqn.fmt(ip), @intFromEnum(nav) }),
4334 .type_layout, .type_inits => |ty, tag| return writer.print("{t}('{f}' [{}])", .{ tag, Type.fromInterned(ty).containerTypeName(ip).fmt(ip), @intFromEnum(ty) }),
43294335 .func => |func| {
43304336 const nav = zcu.funcInfo(func).owner_nav;
43314337 return writer.print("func('{f}' [{}])", .{ ip.getNav(nav).fqn.fmt(ip), @intFromEnum(func) });
......@@ -4347,18 +4353,17 @@ fn formatDependee(data: FormatDependee, writer: *Io.Writer) Io.Writer.Error!void
43474353 const file_path = zcu.fileByIndex(info.file).path;
43484354 return writer.print("inst('{f}', %{d})", .{ file_path.fmt(zcu.comp), @intFromEnum(info.inst) });
43494355 },
4350 .nav_val => |nav| {
4356 .nav_val, .nav_ty => |nav, tag| {
43514357 const fqn = ip.getNav(nav).fqn;
4352 return writer.print("nav_val('{f}')", .{fqn.fmt(ip)});
4358 return writer.print("{t}('{f}')", .{ tag, fqn.fmt(ip) });
43534359 },
4354 .nav_ty => |nav| {
4355 const fqn = ip.getNav(nav).fqn;
4356 return writer.print("nav_ty('{f}')", .{fqn.fmt(ip)});
4360 .type_layout, .type_inits => |ip_index, tag| {
4361 const name = Type.fromInterned(ip_index).containerTypeName(ip);
4362 return writer.print("{t}('{f}')", .{ tag, name.fmt(ip) });
43574363 },
4358 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
4359 .struct_type, .union_type, .enum_type => return writer.print("type('{f}')", .{Type.fromInterned(ip_index).containerTypeName(ip).fmt(ip)}),
4360 .func => |f| return writer.print("ies('{f}')", .{ip.getNav(f.owner_nav).fqn.fmt(ip)}),
4361 else => unreachable,
4364 .func_ies => |ip_index| {
4365 const fqn = ip.getNav(ip.indexToKey(ip_index).func.owner_nav).fqn;
4366 return writer.print("func_ies('{f}')", .{fqn.fmt(ip)});
43624367 },
43634368 .zon_file => |file| {
43644369 const file_path = zcu.fileByIndex(file).path;
src/Zcu/PerThread.zig+807-697
......@@ -598,44 +598,38 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
598598 // Value is whether the declaration is `pub`.
599599 var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, bool) = .empty;
600600 defer old_names.deinit(zcu.gpa);
601 {
602 var it = old_zir.declIterator(old_inst);
603 while (it.next()) |decl_inst| {
604 const old_decl = old_zir.getDeclaration(decl_inst);
605 if (old_decl.name == .empty) continue;
606 const name_ip = try zcu.intern_pool.getOrPutString(
607 zcu.gpa,
608 io,
609 pt.tid,
610 old_zir.nullTerminatedString(old_decl.name),
611 .no_embedded_nulls,
612 );
613 try old_names.put(zcu.gpa, name_ip, old_decl.is_pub);
614 }
601 for (old_zir.typeDecls(old_inst)) |decl_inst| {
602 const old_decl = old_zir.getDeclaration(decl_inst);
603 if (old_decl.name == .empty) continue;
604 const name_ip = try zcu.intern_pool.getOrPutString(
605 zcu.gpa,
606 io,
607 pt.tid,
608 old_zir.nullTerminatedString(old_decl.name),
609 .no_embedded_nulls,
610 );
611 try old_names.put(zcu.gpa, name_ip, old_decl.is_pub);
615612 }
616613 var any_change = false;
617 {
618 var it = new_zir.declIterator(new_inst);
619 while (it.next()) |decl_inst| {
620 const new_decl = new_zir.getDeclaration(decl_inst);
621 if (new_decl.name == .empty) continue;
622 const name_ip = try zcu.intern_pool.getOrPutString(
623 zcu.gpa,
624 io,
625 pt.tid,
626 new_zir.nullTerminatedString(new_decl.name),
627 .no_embedded_nulls,
628 );
629 if (old_names.fetchSwapRemove(name_ip)) |kv| {
630 if (kv.value == new_decl.is_pub) continue;
631 }
632 // Name added, or changed whether it's pub
633 any_change = true;
634 try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{
635 .namespace = tracked_inst_index,
636 .name = name_ip,
637 } });
614 for (new_zir.typeDecls(new_inst)) |decl_inst| {
615 const new_decl = new_zir.getDeclaration(decl_inst);
616 if (new_decl.name == .empty) continue;
617 const name_ip = try zcu.intern_pool.getOrPutString(
618 zcu.gpa,
619 io,
620 pt.tid,
621 new_zir.nullTerminatedString(new_decl.name),
622 .no_embedded_nulls,
623 );
624 if (old_names.fetchSwapRemove(name_ip)) |kv| {
625 if (kv.value == new_decl.is_pub) continue;
638626 }
627 // Name added, or changed whether it's pub
628 any_change = true;
629 try zcu.markDependeeOutdated(.not_marked_po, .{ .namespace_name = .{
630 .namespace = tracked_inst_index,
631 .name = name_ip,
632 } });
639633 }
640634 // The only elements remaining in `old_names` now are any names which were removed.
641635 for (old_names.keys()) |name_ip| {
......@@ -674,24 +668,49 @@ pub fn updateZirRefs(pt: Zcu.PerThread) Allocator.Error!void {
674668 }
675669}
676670
677/// Ensures that `zcu.fileRootType` on this `file_index` gives an up-to-date answer.
678/// Returns `error.AnalysisFail` if the file has an error.
679pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
680 const file_root_type = pt.zcu.fileRootType(file_index);
681 if (file_root_type != .none) {
682 if (pt.ensureTypeUpToDate(file_root_type)) |_| {
683 return;
684 } else |err| switch (err) {
685 error.AnalysisFail => {
686 // The file's root `struct_decl` has, at some point, been lost, because the file failed AstGen.
687 // Clear `file_root_type`, and try the `semaFile` call below, in case the instruction has since
688 // been discovered under a new `TrackedInst.Index`.
689 pt.zcu.setFileRootType(file_index, .none);
690 },
691 else => |e| return e,
692 }
693 }
694 return pt.semaFile(file_index);
671/// Ensures that `zcu.fileRootType` on this `file_index` is populated (not `.none`). This implies
672/// that the file's namespace is scanned, discovering declarations.
673///
674/// Typical Zig compilations begin by claling this function on the root source file of the standard
675/// library, `lib/std/std.zig`. The resulting namespace scan discovers a `comptime` declaration in
676/// that file, which is queued for analysis, and everything goes from there.
677pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void {
678 dev.check(.sema);
679
680 const tracy = trace(@src());
681 defer tracy.end();
682
683 const zcu = pt.zcu;
684 const comp = zcu.comp;
685 const io = comp.io;
686 const gpa = comp.gpa;
687 const ip = &zcu.intern_pool;
688
689 if (zcu.fileRootType(file_index) != .none) return; // already good
690
691 const file = zcu.fileByIndex(file_index);
692 assert(file.getMode() == .zig);
693 const struct_decl = file.zir.?.getStructDecl(.main_struct_inst);
694 const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{
695 .file = file_index,
696 .inst = .main_struct_inst,
697 });
698 const file_root_type = try Sema.analyzeStructDecl(
699 pt,
700 file_index,
701 &file.zir.?,
702 .none,
703 tracked_inst,
704 &struct_decl,
705 null,
706 &.{},
707 .{ .exact = .{
708 .name = try file.internFullyQualifiedName(pt),
709 .nav = .none,
710 } },
711 );
712 zcu.setFileRootType(file_index, file_root_type.toIntern());
713 if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1;
695714}
696715
697716/// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary.
......@@ -1012,6 +1031,238 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
10121031 try sema.flushExports();
10131032}
10141033
1034/// Ensures that the layout of the given `struct` or `union` type is fully up-to-date, performing
1035/// re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or union. Returns
1036/// `error.AnalysisFail` if an analysis error is encountered during type resolution; the caller is
1037/// free to ignore this, since the error is already registered.
1038pub fn ensureTypeLayoutUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
1039 const tracy = trace(@src());
1040 defer tracy.end();
1041
1042 const zcu = pt.zcu;
1043 const gpa = zcu.gpa;
1044
1045 const anal_unit: AnalUnit = .wrap(.{ .type_layout = ty.toIntern() });
1046
1047 log.debug("ensureTypeLayoutUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
1048
1049 assert(!zcu.analysis_in_progress.contains(anal_unit));
1050
1051 // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's
1052 // the only indicator as to whether or not analysis is required; when a struct/union is
1053 // first created, it's marked as outdated.
1054 // MLUGG TODO: make that actually true, it's a good strategy here!
1055
1056 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
1057 zcu.potentially_outdated.swapRemove(anal_unit);
1058
1059 if (was_outdated) {
1060 _ = zcu.outdated_ready.swapRemove(anal_unit);
1061 // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.
1062 if (dev.env.supports(.incremental)) {
1063 zcu.deleteUnitExports(anal_unit);
1064 zcu.deleteUnitReferences(anal_unit);
1065 zcu.deleteUnitCompileLogs(anal_unit);
1066 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1067 kv.value.destroy(gpa);
1068 }
1069 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
1070 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
1071 }
1072 // For types, we already know that we have to invalidate all dependees.
1073 // TODO: we actually *could* detect whether everything was the same. should we bother?
1074 try zcu.markDependeeOutdated(.marked_po, .{ .type_layout = ty.toIntern() });
1075 } else {
1076 // We can trust the current information about this unit.
1077 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1078 if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1079 return;
1080 }
1081
1082 if (zcu.comp.debugIncremental()) {
1083 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
1084 info.last_update_gen = zcu.generation;
1085 info.deps.clearRetainingCapacity();
1086 }
1087
1088 const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null);
1089 defer unit_tracking.end(zcu);
1090
1091 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
1092 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1093
1094 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
1095 defer analysis_arena.deinit();
1096
1097 var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa);
1098 defer comptime_err_ret_trace.deinit();
1099
1100 const file = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu);
1101
1102 var sema: Sema = .{
1103 .pt = pt,
1104 .gpa = gpa,
1105 .arena = analysis_arena.allocator(),
1106 .code = file.zir.?,
1107 .owner = anal_unit,
1108 .func_index = .none,
1109 .func_is_naked = false,
1110 .fn_ret_ty = .void,
1111 .fn_ret_ty_ies = null,
1112 .comptime_err_ret_trace = &comptime_err_ret_trace,
1113 };
1114 defer sema.deinit();
1115
1116 const result = switch (ty.containerLayout(zcu)) {
1117 .auto, .@"extern" => switch (ty.zigTypeTag(zcu)) {
1118 .@"struct" => Sema.type_resolution.resolveStructLayout(&sema, ty),
1119 .@"union" => Sema.type_resolution.resolveUnionLayout(&sema, ty),
1120 else => unreachable,
1121 },
1122 .@"packed" => switch (ty.zigTypeTag(zcu)) {
1123 .@"struct" => Sema.type_resolution.resolvePackedStructLayout(&sema, ty),
1124 .@"union" => Sema.type_resolution.resolvePackedUnionLayout(&sema, ty),
1125 else => unreachable,
1126 },
1127 };
1128 result catch |err| switch (err) {
1129 error.AnalysisFail => {
1130 if (!zcu.failed_analysis.contains(anal_unit)) {
1131 // If this unit caused the error, it would have an entry in `failed_analysis`.
1132 // Since it does not, this must be a transitive failure.
1133 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1134 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1135 }
1136 return error.AnalysisFail;
1137 },
1138 error.OutOfMemory,
1139 error.Canceled,
1140 => |e| return e,
1141 error.ComptimeReturn => unreachable,
1142 error.ComptimeBreak => unreachable,
1143 };
1144
1145 sema.flushExports() catch |err| switch (err) {
1146 error.OutOfMemory => |e| return e,
1147 };
1148
1149 codegen_type: {
1150 if (zcu.comp.config.use_llvm) break :codegen_type;
1151 if (file.mod.?.strip) break :codegen_type;
1152 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1153 try zcu.comp.queueJob(.{ .link_type = ty.toIntern() });
1154 }
1155}
1156
1157/// Ensures that the default/tag values of the given `struct` or `enum` type are fully up-to-date,
1158/// performing re-analysis if necessary. Asserts that `ty` is a struct (not a tuple!) or an enum.
1159/// Returns `error.AnalysisFail` if an analysis error is encountered during resolution; the caller
1160/// is free to ignore this, since the error is already registered.
1161pub fn ensureTypeInitsUpToDate(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
1162 const tracy = trace(@src());
1163 defer tracy.end();
1164
1165 const zcu = pt.zcu;
1166 const gpa = zcu.gpa;
1167
1168 const anal_unit: AnalUnit = .wrap(.{ .type_inits = ty.toIntern() });
1169
1170 log.debug("ensureTypeInitsUpToDate {f}", .{zcu.fmtAnalUnit(anal_unit)});
1171
1172 assert(!zcu.analysis_in_progress.contains(anal_unit));
1173
1174 // Determine whether or not this type is outdated. For this kind of `AnalUnit`, that's
1175 // the only indicator as to whether or not analysis is required; when a struct/enum is
1176 // first created, it's marked as outdated.
1177 // MLUGG TODO: make that actually true, it's a good strategy here!
1178
1179 const was_outdated = zcu.outdated.swapRemove(anal_unit) or
1180 zcu.potentially_outdated.swapRemove(anal_unit);
1181
1182 if (was_outdated) {
1183 _ = zcu.outdated_ready.swapRemove(anal_unit);
1184 // `was_outdated` can be true in the initial update for comptime units, so this isn't a `dev.check`.
1185 if (dev.env.supports(.incremental)) {
1186 zcu.deleteUnitExports(anal_unit);
1187 zcu.deleteUnitReferences(anal_unit);
1188 zcu.deleteUnitCompileLogs(anal_unit);
1189 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
1190 kv.value.destroy(gpa);
1191 }
1192 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
1193 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
1194 }
1195 // For types, we already know that we have to invalidate all dependees.
1196 // TODO: we actually *could* detect whether everything was the same. should we bother?
1197 try zcu.markDependeeOutdated(.marked_po, .{ .type_inits = ty.toIntern() });
1198 } else {
1199 // We can trust the current information about this unit.
1200 if (zcu.failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1201 if (zcu.transitive_failed_analysis.contains(anal_unit)) return error.AnalysisFail;
1202 return;
1203 }
1204
1205 if (zcu.comp.debugIncremental()) {
1206 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
1207 info.last_update_gen = zcu.generation;
1208 info.deps.clearRetainingCapacity();
1209 }
1210
1211 const unit_tracking = zcu.trackUnitSema(ty.containerTypeName(&zcu.intern_pool).toSlice(&zcu.intern_pool), null);
1212 defer unit_tracking.end(zcu);
1213
1214 try zcu.analysis_in_progress.put(gpa, anal_unit, {});
1215 defer assert(zcu.analysis_in_progress.swapRemove(anal_unit));
1216
1217 var analysis_arena: std.heap.ArenaAllocator = .init(gpa);
1218 defer analysis_arena.deinit();
1219
1220 var comptime_err_ret_trace: std.array_list.Managed(Zcu.LazySrcLoc) = .init(gpa);
1221 defer comptime_err_ret_trace.deinit();
1222
1223 const zir = zcu.namespacePtr(ty.getNamespaceIndex(zcu)).fileScope(zcu).zir.?;
1224
1225 var sema: Sema = .{
1226 .pt = pt,
1227 .gpa = gpa,
1228 .arena = analysis_arena.allocator(),
1229 .code = zir,
1230 .owner = anal_unit,
1231 .func_index = .none,
1232 .func_is_naked = false,
1233 .fn_ret_ty = .void,
1234 .fn_ret_ty_ies = null,
1235 .comptime_err_ret_trace = &comptime_err_ret_trace,
1236 };
1237 defer sema.deinit();
1238
1239 const result = switch (ty.zigTypeTag(zcu)) {
1240 .@"struct" => Sema.type_resolution.resolveStructDefaults(&sema, ty),
1241 .@"enum" => Sema.type_resolution.resolveEnumValues(&sema, ty),
1242 else => unreachable,
1243 };
1244 result catch |err| switch (err) {
1245 error.AnalysisFail => {
1246 if (!zcu.failed_analysis.contains(anal_unit)) {
1247 // If this unit caused the error, it would have an entry in `failed_analysis`.
1248 // Since it does not, this must be a transitive failure.
1249 try zcu.transitive_failed_analysis.put(gpa, anal_unit, {});
1250 log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)});
1251 }
1252 return error.AnalysisFail;
1253 },
1254 error.OutOfMemory,
1255 error.Canceled,
1256 => |e| return e,
1257 error.ComptimeReturn => unreachable,
1258 error.ComptimeBreak => unreachable,
1259 };
1260
1261 sema.flushExports() catch |err| switch (err) {
1262 error.OutOfMemory => |e| return e,
1263 };
1264}
1265
10151266/// Ensures that the resolved value of the given `Nav` is fully up-to-date, performing re-analysis
10161267/// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is
10171268/// free to ignore this, since the error is already registered.
......@@ -1360,7 +1611,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
13601611
13611612 // This resolves the type of the resolved value, not that value itself. If `nav_val` is a struct type,
13621613 // this resolves the type `type` (which needs no resolution), not the struct itself.
1363 try nav_ty.resolveLayout(pt);
1614 try sema.ensureLayoutResolved(nav_ty);
13641615
13651616 const queue_linker_work, const is_owned_fn = switch (ip.indexToKey(nav_val.toIntern())) {
13661617 .func => |f| .{ true, f.owner_nav == nav_id }, // note that this lets function aliases reach codegen
......@@ -1377,7 +1628,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
13771628 if (zir_decl.align_body != null and !target_util.supportsFunctionAlignment(zcu.getTarget())) {
13781629 return sema.fail(&block, align_src, "target does not support function alignment", .{});
13791630 }
1380 } else if (try nav_ty.comptimeOnlySema(pt)) {
1631 } else if (nav_ty.comptimeOnly(zcu)) {
13811632 // alignment, linksection, addrspace annotations are not allowed for comptime-only types.
13821633 const reason: []const u8 = switch (ip.indexToKey(nav_val.toIntern())) {
13831634 .func => "function alias", // slightly clearer message, since you *can* specify these on function *declarations*
......@@ -1420,12 +1671,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
14201671 queue_codegen: {
14211672 if (!queue_linker_work) break :queue_codegen;
14221673
1423 if (!try nav_ty.hasRuntimeBitsSema(pt)) {
1674 if (!nav_ty.hasRuntimeBits(zcu)) {
14241675 if (zcu.comp.config.use_llvm) break :queue_codegen;
14251676 if (file.mod.?.strip) break :queue_codegen;
14261677 }
14271678
1428 // This job depends on any resolve_type_fully jobs queued up before it.
14291679 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
14301680 try zcu.comp.queueJob(.{ .link_nav = nav_id });
14311681 }
......@@ -1628,7 +1878,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
16281878 break :ty .fromInterned(type_ref.toInterned().?);
16291879 };
16301880
1631 try resolved_ty.resolveLayout(pt);
1881 try sema.ensureLayoutResolved(resolved_ty);
16321882
16331883 // In the case where the type is specified, this function is also responsible for resolving
16341884 // the pointer modifiers, i.e. alignment, linksection, addrspace.
......@@ -1765,9 +2015,9 @@ pub fn ensureFuncBodyUpToDate(pt: Zcu.PerThread, func_index: InternPool.Index) Z
17652015
17662016 if (was_outdated) {
17672017 if (ies_outdated) {
1768 try zcu.markDependeeOutdated(.marked_po, .{ .interned = func_index });
2018 try zcu.markDependeeOutdated(.marked_po, .{ .func_ies = func_index });
17692019 } else {
1770 try zcu.markPoDependeeUpToDate(.{ .interned = func_index });
2020 try zcu.markPoDependeeUpToDate(.{ .func_ies = func_index });
17712021 }
17722022 }
17732023
......@@ -1817,7 +2067,7 @@ fn analyzeFuncBody(
18172067
18182068 log.debug("analyze and generate fn body {f}", .{zcu.fmtAnalUnit(anal_unit)});
18192069
1820 var air = try pt.analyzeFnBodyInner(func_index);
2070 var air = try pt.analyzeFuncBodyInner(func_index);
18212071 errdefer air.deinit(gpa);
18222072
18232073 const ies_outdated = !func.analysisUnordered(ip).inferred_error_set or
......@@ -1833,7 +2083,6 @@ fn analyzeFuncBody(
18332083 return .{ .ies_outdated = ies_outdated };
18342084 }
18352085
1836 // This job depends on any resolve_type_fully jobs queued up before it.
18372086 zcu.codegen_prog_node.increaseEstimatedTotalItems(1);
18382087 comp.link_prog_node.increaseEstimatedTotalItems(1);
18392088 try comp.queueJob(.{ .codegen_func = .{
......@@ -1844,94 +2093,12 @@ fn analyzeFuncBody(
18442093 return .{ .ies_outdated = ies_outdated };
18452094}
18462095
1847pub fn semaMod(pt: Zcu.PerThread, mod: *Module) !void {
1848 dev.check(.sema);
1849 const file_index = pt.zcu.module_roots.get(mod).?.unwrap().?;
1850 const root_type = pt.zcu.fileRootType(file_index);
1851 if (root_type == .none) {
1852 return pt.semaFile(file_index);
1853 }
1854}
1855
1856fn createFileRootStruct(
1857 pt: Zcu.PerThread,
1858 file_index: Zcu.File.Index,
1859 namespace_index: Zcu.Namespace.Index,
1860 replace_existing: bool,
1861) Allocator.Error!InternPool.Index {
1862 const zcu = pt.zcu;
1863 const gpa = zcu.gpa;
1864 const io = zcu.comp.io;
1865 const ip = &zcu.intern_pool;
1866 const file = zcu.fileByIndex(file_index);
1867 const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;
1868 assert(extended.opcode == .struct_decl);
1869 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
1870 assert(!small.has_captures_len);
1871 assert(!small.has_backing_int);
1872 assert(small.layout == .auto);
1873 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
1874 const fields_len = if (small.has_fields_len) blk: {
1875 const fields_len = file.zir.?.extra[extra_index];
1876 extra_index += 1;
1877 break :blk fields_len;
1878 } else 0;
1879 const decls_len = if (small.has_decls_len) blk: {
1880 const decls_len = file.zir.?.extra[extra_index];
1881 extra_index += 1;
1882 break :blk decls_len;
1883 } else 0;
1884 const decls = file.zir.?.bodySlice(extra_index, decls_len);
1885 extra_index += decls_len;
1886
1887 const tracked_inst = try ip.trackZir(gpa, io, pt.tid, .{
1888 .file = file_index,
1889 .inst = .main_struct_inst,
1890 });
1891 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
1892 .layout = .auto,
1893 .fields_len = fields_len,
1894 .known_non_opv = small.known_non_opv,
1895 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
1896 .any_comptime_fields = small.any_comptime_fields,
1897 .any_default_inits = small.any_default_inits,
1898 .inits_resolved = false,
1899 .any_aligned_fields = small.any_aligned_fields,
1900 .key = .{ .declared = .{
1901 .zir_index = tracked_inst,
1902 .captures = &.{},
1903 } },
1904 }, replace_existing)) {
1905 .existing => unreachable, // we wouldn't be analysing the file root if this type existed
1906 .wip => |wip| wip,
1907 };
1908 errdefer wip_ty.cancel(ip, pt.tid);
1909
1910 wip_ty.setName(ip, try file.internFullyQualifiedName(pt), .none);
1911 ip.namespacePtr(namespace_index).owner_type = wip_ty.index;
1912
1913 if (zcu.comp.config.incremental) {
1914 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = tracked_inst });
1915 }
1916
1917 try pt.scanNamespace(namespace_index, decls);
1918 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
1919 codegen_type: {
1920 if (file.mod.?.strip) break :codegen_type;
1921 // This job depends on any resolve_type_fully jobs queued up before it.
1922 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
1923 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
1924 }
1925 zcu.setFileRootType(file_index, wip_ty.index);
1926 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
1927 return wip_ty.finish(ip, namespace_index);
1928}
1929
19302096/// Re-scan the namespace of a file's root struct type on an incremental update.
19312097/// The file must have successfully populated ZIR.
19322098/// If the file's root struct type is not populated (the file is unreferenced), nothing is done.
19332099/// This is called by `updateZirRefs` for all updated files before the main work loop.
19342100/// This function does not perform any semantic analysis.
2101/// MLUGG TODO: mmmmm i have no idea if this makes sense... tbhwy i just want to update all *changed* namespaces at the start of an update or something lol
19352102fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.Error!void {
19362103 const zcu = pt.zcu;
19372104
......@@ -1945,48 +2112,11 @@ fn updateFileNamespace(pt: Zcu.PerThread, file_index: Zcu.File.Index) Allocator.
19452112 });
19462113
19472114 const namespace_index = Type.fromInterned(file_root_type).getNamespaceIndex(zcu);
1948 const decls = decls: {
1949 const extended = file.zir.?.instructions.items(.data)[@intFromEnum(Zir.Inst.Index.main_struct_inst)].extended;
1950 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
1951
1952 var extra_index: usize = extended.operand + @typeInfo(Zir.Inst.StructDecl).@"struct".fields.len;
1953 extra_index += @intFromBool(small.has_fields_len);
1954 const decls_len = if (small.has_decls_len) blk: {
1955 const decls_len = file.zir.?.extra[extra_index];
1956 extra_index += 1;
1957 break :blk decls_len;
1958 } else 0;
1959 break :decls file.zir.?.bodySlice(extra_index, decls_len);
1960 };
2115 const decls = file.zir.?.getStructDecl(.main_struct_inst).decls;
19612116 try pt.scanNamespace(namespace_index, decls);
19622117 zcu.namespacePtr(namespace_index).generation = zcu.generation;
19632118}
19642119
1965fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
1966 const tracy = trace(@src());
1967 defer tracy.end();
1968
1969 const zcu = pt.zcu;
1970 const file = zcu.fileByIndex(file_index);
1971 assert(file.getMode() == .zig);
1972 assert(zcu.fileRootType(file_index) == .none);
1973
1974 assert(file.zir != null);
1975
1976 const new_namespace_index = try pt.createNamespace(.{
1977 .parent = .none,
1978 .owner_type = undefined, // set in `createFileRootStruct`
1979 .file_scope = file_index,
1980 .generation = zcu.generation,
1981 });
1982 const struct_ty = try pt.createFileRootStruct(file_index, new_namespace_index, false);
1983 errdefer zcu.intern_pool.remove(pt.tid, struct_ty);
1984
1985 if (zcu.comp.time_report) |*tr| {
1986 tr.stats.n_imported_files += 1;
1987 }
1988}
1989
19902120/// Called by AstGen worker threads when an import is seen. If `new_file` is returned, the caller is
19912121/// then responsible for queueing a new AstGen job for the new file.
19922122/// Assumes that `comp.mutex` is NOT locked. It will be locked by this function where necessary.
......@@ -2878,15 +3008,15 @@ const ScanDeclIter = struct {
28783008
28793009 if (existing_unit == null and (want_analysis or decl.linkage == .@"export")) {
28803010 log.debug(
2881 "scanDecl queue analyze_comptime_unit file='{s}' unit={f}",
3011 "scanDecl queue analyze_unit file='{s}' unit={f}",
28823012 .{ namespace.fileScope(zcu).sub_file_path, zcu.fmtAnalUnit(unit) },
28833013 );
2884 try comp.queueJob(.{ .analyze_comptime_unit = unit });
3014 try comp.queueJob(.{ .analyze_unit = unit });
28853015 }
28863016 }
28873017};
28883018
2889fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {
3019fn analyzeFuncBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaError!Air {
28903020 const tracy = trace(@src());
28913021 defer tracy.end();
28923022
......@@ -3020,16 +3150,12 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
30203150 const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
30213151 if (gop.found_existing) continue; // provided above by comptime arg
30223152
3023 const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
3153 const param_ty: Type = .fromInterned(fn_ty_info.param_types.get(ip)[runtime_param_index]);
30243154 runtime_param_index += 1;
30253155
3026 const opt_opv = sema.typeHasOnePossibleValue(Type.fromInterned(param_ty)) catch |err| switch (err) {
3027 error.ComptimeReturn => unreachable,
3028 error.ComptimeBreak => unreachable,
3029 else => |e| return e,
3030 };
3031 if (opt_opv) |opv| {
3032 gop.value_ptr.* = Air.internedToRef(opv.toIntern());
3156 try sema.ensureLayoutResolved(param_ty);
3157 if (try param_ty.onePossibleValue(pt)) |opv| {
3158 gop.value_ptr.* = .fromValue(opv);
30333159 continue;
30343160 }
30353161 const arg_index: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
......@@ -3038,12 +3164,14 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
30383164 sema.air_instructions.appendAssumeCapacity(.{
30393165 .tag = .arg,
30403166 .data = .{ .arg = .{
3041 .ty = Air.internedToRef(param_ty),
3167 .ty = .fromIntern(param_ty.toIntern()),
30423168 .zir_param_index = @intCast(zir_param_index),
30433169 } },
30443170 });
30453171 }
30463172
3173 try sema.ensureLayoutResolved(sema.fn_ret_ty);
3174
30473175 const last_arg_index = inner_block.instructions.items.len;
30483176
30493177 // Save the error trace as our first action in the function.
......@@ -3103,21 +3231,9 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
31033231 func.setResolvedErrorSet(ip, io, ies.resolved);
31043232 }
31053233
3234 // MLUGG TODO: i think this can go away and the assert move to the defer?
31063235 assert(zcu.analysis_in_progress.swapRemove(anal_unit));
31073236
3108 // Finally we must resolve the return type and parameter types so that backends
3109 // have full access to type information.
3110 // Crucially, this happens *after* we set the function state to success above,
3111 // so that dependencies on the function body will now be satisfied rather than
3112 // result in circular dependency errors.
3113 // TODO: this can go away once we fix backends having to resolve `StackTrace`.
3114 // The codegen timing guarantees that the parameter types will be populated.
3115 sema.resolveFnTypes(fn_ty, inner_block.nodeOffset(.zero)) catch |err| switch (err) {
3116 error.ComptimeReturn => unreachable,
3117 error.ComptimeBreak => unreachable,
3118 else => |e| return e,
3119 };
3120
31213237 try sema.flushExports();
31223238
31233239 defer {
......@@ -3605,16 +3721,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error!
36053721
36063722 if (info.flags.size == .c) canon_info.flags.is_allowzero = true;
36073723
3608 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
3609 // type, we change it to 0 here. If this causes an assertion trip because the
3610 // pointee type needs to be resolved more, that needs to be done before calling
3611 // this ptr() function.
3612 if (info.flags.alignment != .none and
3613 info.flags.alignment == Type.fromInterned(info.child).abiAlignment(pt.zcu))
3614 {
3615 canon_info.flags.alignment = .none;
3616 }
3617
36183724 switch (info.flags.vector_index) {
36193725 // Canonicalize host_size. If it matches the bit size of the pointee type,
36203726 // we change it to 0 here. If this causes an assertion trip, the pointee type
......@@ -3632,16 +3738,6 @@ pub fn ptrType(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Allocator.Error!
36323738 return Type.fromInterned(try pt.intern(.{ .ptr_type = canon_info }));
36333739}
36343740
3635/// Like `ptrType`, but if `info` specifies an `alignment`, first ensures the pointer
3636/// child type's alignment is resolved so that an invalid alignment is not used.
3637/// In general, prefer this function during semantic analysis.
3638pub fn ptrTypeSema(pt: Zcu.PerThread, info: InternPool.Key.PtrType) Zcu.SemaError!Type {
3639 if (info.flags.alignment != .none) {
3640 _ = try Type.fromInterned(info.child).abiAlignmentSema(pt);
3641 }
3642 return pt.ptrType(info);
3643}
3644
36453741pub fn singleMutPtrType(pt: Zcu.PerThread, child_type: Type) Allocator.Error!Type {
36463742 return pt.ptrType(.{ .child = child_type.toIntern() });
36473743}
......@@ -3739,31 +3835,37 @@ pub fn enumValue(pt: Zcu.PerThread, ty: Type, tag_int: InternPool.Index) Allocat
37393835/// declaration order.
37403836pub fn enumValueFieldIndex(pt: Zcu.PerThread, ty: Type, field_index: u32) Allocator.Error!Value {
37413837 const ip = &pt.zcu.intern_pool;
3838 ty.assertHasInits(pt.zcu);
37423839 const enum_type = ip.loadEnumType(ty.toIntern());
37433840
3744 if (enum_type.values.len == 0) {
3841 assert(field_index < enum_type.field_names.len);
3842
3843 if (enum_type.field_values.len == 0) {
37453844 // Auto-numbered fields.
37463845 return Value.fromInterned(try pt.intern(.{ .enum_tag = .{
37473846 .ty = ty.toIntern(),
37483847 .int = try pt.intern(.{ .int = .{
3749 .ty = enum_type.tag_ty,
3848 .ty = enum_type.int_tag_type,
37503849 .storage = .{ .u64 = field_index },
37513850 } }),
37523851 } }));
37533852 }
37543853
3755 return Value.fromInterned(try pt.intern(.{ .enum_tag = .{
3854 return .fromInterned(try pt.intern(.{ .enum_tag = .{
37563855 .ty = ty.toIntern(),
3757 .int = enum_type.values.get(ip)[field_index],
3856 .int = enum_type.field_values.get(ip)[field_index],
37583857 } }));
37593858}
37603859
37613860pub fn undefValue(pt: Zcu.PerThread, ty: Type) Allocator.Error!Value {
3762 return Value.fromInterned(try pt.intern(.{ .undef = ty.toIntern() }));
3861 if (std.debug.runtime_safety) {
3862 assert(try ty.onePossibleValue(pt) == null);
3863 }
3864 return .fromInterned(try pt.intern(.{ .undef = ty.toIntern() }));
37633865}
37643866
37653867pub fn undefRef(pt: Zcu.PerThread, ty: Type) Allocator.Error!Air.Inst.Ref {
3766 return Air.internedToRef((try pt.undefValue(ty)).toIntern());
3868 return .fromValue(try pt.undefValue(ty));
37673869}
37683870
37693871pub fn intValue(pt: Zcu.PerThread, ty: Type, x: anytype) Allocator.Error!Value {
......@@ -3916,7 +4018,7 @@ pub fn intFittingRange(pt: Zcu.PerThread, min: Value, max: Value) !Type {
39164018 assert(Value.order(min, max, zcu).compare(.lte));
39174019 }
39184020
3919 const sign = min.orderAgainstZero(zcu) == .lt;
4021 const sign = min.compareHetero(.lt, .zero_comptime_int, zcu);
39204022
39214023 const min_val_bits = pt.intBitsForValue(min, sign);
39224024 const max_val_bits = pt.intBitsForValue(max, sign);
......@@ -3955,12 +4057,6 @@ pub fn intBitsForValue(pt: Zcu.PerThread, val: Value, sign: bool) u16 {
39554057
39564058 return @as(u16, @intCast(big.bitCountTwosComp()));
39574059 },
3958 .lazy_align => |lazy_ty| {
3959 return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(pt.zcu).toByteUnits() orelse 0) + @intFromBool(sign);
3960 },
3961 .lazy_size => |lazy_ty| {
3962 return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(pt.zcu)) + @intFromBool(sign);
3963 },
39644060 }
39654061}
39664062
......@@ -3993,7 +4089,6 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!
39934089 const comp = zcu.comp;
39944090 const result = try zcu.intern_pool.getExtern(comp.gpa, comp.io, pt.tid, key);
39954091 if (result.new_nav.unwrap()) |nav| {
3996 // This job depends on any resolve_type_fully jobs queued up before it.
39974092 comp.link_prog_node.increaseEstimatedTotalItems(1);
39984093 try comp.queueJob(.{ .link_nav = nav });
39994094 if (comp.debugIncremental()) try zcu.incremental_debug_state.newNav(zcu, nav);
......@@ -4013,367 +4108,6 @@ pub fn navAlignment(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) InternPo
40134108 return ty.abiAlignment(zcu);
40144109}
40154110
4016/// `ty` is a container type requiring resolution (struct, union, or enum).
4017/// If `ty` is outdated, it is recreated at a new `InternPool.Index`, which is returned.
4018/// If the type cannot be recreated because it has been lost, `error.AnalysisFail` is returned.
4019/// If `ty` is not outdated, that same `InternPool.Index` is returned.
4020/// If `ty` has already been replaced by this function, the new index will not be returned again.
4021/// Also, if `ty` is an enum, this function will resolve the new type if needed, and the call site
4022/// is responsible for checking `[transitive_]failed_analysis` to detect resolution failures.
4023pub fn ensureTypeUpToDate(pt: Zcu.PerThread, ty: InternPool.Index) Zcu.SemaError!InternPool.Index {
4024 const zcu = pt.zcu;
4025 const gpa = zcu.gpa;
4026 const ip = &zcu.intern_pool;
4027
4028 const anal_unit: AnalUnit = .wrap(.{ .type = ty });
4029 const outdated = zcu.outdated.swapRemove(anal_unit) or
4030 zcu.potentially_outdated.swapRemove(anal_unit);
4031
4032 if (outdated) {
4033 _ = zcu.outdated_ready.swapRemove(anal_unit);
4034 try zcu.markDependeeOutdated(.marked_po, .{ .interned = ty });
4035 }
4036
4037 const ty_key = switch (ip.indexToKey(ty)) {
4038 .struct_type, .union_type, .enum_type => |key| key,
4039 else => unreachable,
4040 };
4041 const declared_ty_key = switch (ty_key) {
4042 .reified => unreachable, // never outdated
4043 .generated_tag => unreachable, // never outdated
4044 .declared => |d| d,
4045 };
4046
4047 if (declared_ty_key.zir_index.resolve(ip) == null) {
4048 // The instruction has been lost -- this type is dead.
4049 return error.AnalysisFail;
4050 }
4051
4052 if (!outdated) return ty;
4053
4054 // We will recreate the type at a new `InternPool.Index`.
4055
4056 // Delete old state which is no longer in use. Technically, this is not necessary: these exports,
4057 // references, etc, will be ignored because the type itself is unreferenced. However, it allows
4058 // reusing the memory which is currently being used to track this state.
4059 zcu.deleteUnitExports(anal_unit);
4060 zcu.deleteUnitReferences(anal_unit);
4061 zcu.deleteUnitCompileLogs(anal_unit);
4062 if (zcu.failed_analysis.fetchSwapRemove(anal_unit)) |kv| {
4063 kv.value.destroy(gpa);
4064 }
4065 _ = zcu.transitive_failed_analysis.swapRemove(anal_unit);
4066 zcu.intern_pool.removeDependenciesForDepender(gpa, anal_unit);
4067
4068 if (zcu.comp.debugIncremental()) {
4069 const info = try zcu.incremental_debug_state.getUnitInfo(gpa, anal_unit);
4070 info.last_update_gen = zcu.generation;
4071 info.deps.clearRetainingCapacity();
4072 }
4073
4074 switch (ip.indexToKey(ty)) {
4075 .struct_type => return pt.recreateStructType(ty, declared_ty_key),
4076 .union_type => return pt.recreateUnionType(ty, declared_ty_key),
4077 .enum_type => return pt.recreateEnumType(ty, declared_ty_key),
4078 else => unreachable,
4079 }
4080}
4081
4082fn recreateStructType(
4083 pt: Zcu.PerThread,
4084 old_ty: InternPool.Index,
4085 key: InternPool.Key.NamespaceType.Declared,
4086) Allocator.Error!InternPool.Index {
4087 const zcu = pt.zcu;
4088 const comp = zcu.comp;
4089 const gpa = comp.gpa;
4090 const io = comp.io;
4091 const ip = &zcu.intern_pool;
4092
4093 const inst_info = key.zir_index.resolveFull(ip).?;
4094 const file = zcu.fileByIndex(inst_info.file);
4095 const zir = file.zir.?;
4096
4097 assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended);
4098 const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended;
4099 assert(extended.opcode == .struct_decl);
4100 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
4101 const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand);
4102 var extra_index = extra.end;
4103
4104 const captures_len = if (small.has_captures_len) blk: {
4105 const captures_len = zir.extra[extra_index];
4106 extra_index += 1;
4107 break :blk captures_len;
4108 } else 0;
4109 const fields_len = if (small.has_fields_len) blk: {
4110 const fields_len = zir.extra[extra_index];
4111 extra_index += 1;
4112 break :blk fields_len;
4113 } else 0;
4114
4115 assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew`
4116
4117 const struct_obj = ip.loadStructType(old_ty);
4118
4119 const wip_ty = switch (try ip.getStructType(gpa, io, pt.tid, .{
4120 .layout = small.layout,
4121 .fields_len = fields_len,
4122 .known_non_opv = small.known_non_opv,
4123 .requires_comptime = if (small.known_comptime_only) .yes else .unknown,
4124 .any_comptime_fields = small.any_comptime_fields,
4125 .any_default_inits = small.any_default_inits,
4126 .inits_resolved = false,
4127 .any_aligned_fields = small.any_aligned_fields,
4128 .key = .{ .declared_owned_captures = .{
4129 .zir_index = key.zir_index,
4130 .captures = key.captures.owned,
4131 } },
4132 }, true)) {
4133 .wip => |wip| wip,
4134 .existing => unreachable, // we passed `replace_existing`
4135 };
4136 errdefer wip_ty.cancel(ip, pt.tid);
4137
4138 wip_ty.setName(ip, struct_obj.name, struct_obj.name_nav);
4139 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
4140 zcu.namespacePtr(struct_obj.namespace).owner_type = wip_ty.index;
4141 // No need to re-scan the namespace -- `zirStructDecl` will ultimately do that if the type is still alive.
4142 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
4143
4144 codegen_type: {
4145 if (file.mod.?.strip) break :codegen_type;
4146 // This job depends on any resolve_type_fully jobs queued up before it.
4147 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
4148 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
4149 }
4150
4151 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
4152 const new_ty = wip_ty.finish(ip, struct_obj.namespace);
4153 if (inst_info.inst == .main_struct_inst) {
4154 // This is the root type of a file! Update the reference.
4155 zcu.setFileRootType(inst_info.file, new_ty);
4156 }
4157 return new_ty;
4158}
4159
4160fn recreateUnionType(
4161 pt: Zcu.PerThread,
4162 old_ty: InternPool.Index,
4163 key: InternPool.Key.NamespaceType.Declared,
4164) Allocator.Error!InternPool.Index {
4165 const zcu = pt.zcu;
4166 const comp = zcu.comp;
4167 const gpa = comp.gpa;
4168 const io = comp.io;
4169 const ip = &zcu.intern_pool;
4170
4171 const inst_info = key.zir_index.resolveFull(ip).?;
4172 const file = zcu.fileByIndex(inst_info.file);
4173 const zir = file.zir.?;
4174
4175 assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended);
4176 const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended;
4177 assert(extended.opcode == .union_decl);
4178 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
4179 const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand);
4180 var extra_index = extra.end;
4181
4182 extra_index += @intFromBool(small.has_tag_type);
4183 const captures_len = if (small.has_captures_len) blk: {
4184 const captures_len = zir.extra[extra_index];
4185 extra_index += 1;
4186 break :blk captures_len;
4187 } else 0;
4188 extra_index += @intFromBool(small.has_body_len);
4189 const fields_len = if (small.has_fields_len) blk: {
4190 const fields_len = zir.extra[extra_index];
4191 extra_index += 1;
4192 break :blk fields_len;
4193 } else 0;
4194
4195 assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew`
4196
4197 const union_obj = ip.loadUnionType(old_ty);
4198
4199 const namespace_index = union_obj.namespace;
4200
4201 const wip_ty = switch (try ip.getUnionType(gpa, io, pt.tid, .{
4202 .flags = .{
4203 .layout = small.layout,
4204 .status = .none,
4205 .runtime_tag = if (small.has_tag_type or small.auto_enum_tag)
4206 .tagged
4207 else if (small.layout != .auto)
4208 .none
4209 else switch (true) { // TODO
4210 true => .safety,
4211 false => .none,
4212 },
4213 .any_aligned_fields = small.any_aligned_fields,
4214 .requires_comptime = .unknown,
4215 .assumed_runtime_bits = false,
4216 .assumed_pointer_aligned = false,
4217 .alignment = .none,
4218 },
4219 .fields_len = fields_len,
4220 .enum_tag_ty = .none, // set later
4221 .field_types = &.{}, // set later
4222 .field_aligns = &.{}, // set later
4223 .key = .{ .declared_owned_captures = .{
4224 .zir_index = key.zir_index,
4225 .captures = key.captures.owned,
4226 } },
4227 }, true)) {
4228 .wip => |wip| wip,
4229 .existing => unreachable, // we passed `replace_existing`
4230 };
4231 errdefer wip_ty.cancel(ip, pt.tid);
4232
4233 wip_ty.setName(ip, union_obj.name, union_obj.name_nav);
4234 try pt.addDependency(.wrap(.{ .type = wip_ty.index }), .{ .src_hash = key.zir_index });
4235 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
4236 // No need to re-scan the namespace -- `zirUnionDecl` will ultimately do that if the type is still alive.
4237 try zcu.comp.queueJob(.{ .resolve_type_fully = wip_ty.index });
4238
4239 codegen_type: {
4240 if (file.mod.?.strip) break :codegen_type;
4241 // This job depends on any resolve_type_fully jobs queued up before it.
4242 zcu.comp.link_prog_node.increaseEstimatedTotalItems(1);
4243 try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
4244 }
4245
4246 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
4247 return wip_ty.finish(ip, namespace_index);
4248}
4249
4250/// This *does* call `Sema.resolveDeclaredEnum`, but errors from it are not propagated.
4251/// Call sites are resposible for checking `[transitive_]failed_analysis` after `ensureTypeUpToDate`
4252/// returns in order to detect resolution failures.
4253fn recreateEnumType(
4254 pt: Zcu.PerThread,
4255 old_ty: InternPool.Index,
4256 key: InternPool.Key.NamespaceType.Declared,
4257) (Allocator.Error || Io.Cancelable)!InternPool.Index {
4258 const zcu = pt.zcu;
4259 const comp = zcu.comp;
4260 const gpa = comp.gpa;
4261 const io = comp.io;
4262 const ip = &zcu.intern_pool;
4263
4264 const inst_info = key.zir_index.resolveFull(ip).?;
4265 const file = zcu.fileByIndex(inst_info.file);
4266 const zir = file.zir.?;
4267
4268 assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended);
4269 const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended;
4270 assert(extended.opcode == .enum_decl);
4271 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
4272 const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand);
4273 var extra_index = extra.end;
4274
4275 const tag_type_ref = if (small.has_tag_type) blk: {
4276 const tag_type_ref: Zir.Inst.Ref = @enumFromInt(zir.extra[extra_index]);
4277 extra_index += 1;
4278 break :blk tag_type_ref;
4279 } else .none;
4280
4281 const captures_len = if (small.has_captures_len) blk: {
4282 const captures_len = zir.extra[extra_index];
4283 extra_index += 1;
4284 break :blk captures_len;
4285 } else 0;
4286
4287 const body_len = if (small.has_body_len) blk: {
4288 const body_len = zir.extra[extra_index];
4289 extra_index += 1;
4290 break :blk body_len;
4291 } else 0;
4292
4293 const fields_len = if (small.has_fields_len) blk: {
4294 const fields_len = zir.extra[extra_index];
4295 extra_index += 1;
4296 break :blk fields_len;
4297 } else 0;
4298
4299 const decls_len = if (small.has_decls_len) blk: {
4300 const decls_len = zir.extra[extra_index];
4301 extra_index += 1;
4302 break :blk decls_len;
4303 } else 0;
4304
4305 assert(captures_len == key.captures.owned.len); // synchronises with logic in `Zcu.mapOldZirToNew`
4306
4307 extra_index += captures_len * 2;
4308 extra_index += decls_len;
4309
4310 const body = zir.bodySlice(extra_index, body_len);
4311 extra_index += body.len;
4312
4313 const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
4314 const body_end = extra_index;
4315 extra_index += bit_bags_count;
4316
4317 const any_values = for (zir.extra[body_end..][0..bit_bags_count]) |bag| {
4318 if (bag != 0) break true;
4319 } else false;
4320
4321 const enum_obj = ip.loadEnumType(old_ty);
4322
4323 const namespace_index = enum_obj.namespace;
4324
4325 const wip_ty = switch (try ip.getEnumType(gpa, io, pt.tid, .{
4326 .has_values = any_values,
4327 .tag_mode = if (small.nonexhaustive)
4328 .nonexhaustive
4329 else if (tag_type_ref == .none)
4330 .auto
4331 else
4332 .explicit,
4333 .fields_len = fields_len,
4334 .key = .{ .declared_owned_captures = .{
4335 .zir_index = key.zir_index,
4336 .captures = key.captures.owned,
4337 } },
4338 }, true)) {
4339 .wip => |wip| wip,
4340 .existing => unreachable, // we passed `replace_existing`
4341 };
4342 var done = true;
4343 errdefer if (!done) wip_ty.cancel(ip, pt.tid);
4344
4345 wip_ty.setName(ip, enum_obj.name, enum_obj.name_nav);
4346
4347 zcu.namespacePtr(namespace_index).owner_type = wip_ty.index;
4348 // No need to re-scan the namespace -- `zirEnumDecl` will ultimately do that if the type is still alive.
4349
4350 if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
4351 wip_ty.prepare(ip, namespace_index);
4352 done = true;
4353
4354 Sema.resolveDeclaredEnum(
4355 pt,
4356 wip_ty,
4357 inst_info.inst,
4358 key.zir_index,
4359 namespace_index,
4360 enum_obj.name,
4361 small,
4362 body,
4363 tag_type_ref,
4364 any_values,
4365 fields_len,
4366 zir,
4367 body_end,
4368 ) catch |err| switch (err) {
4369 error.OutOfMemory => |e| return e,
4370 error.Canceled => |e| return e,
4371 error.AnalysisFail => {}, // call sites are responsible for checking `[transitive_]failed_analysis` to detect this
4372 };
4373
4374 return wip_ty.index;
4375}
4376
43774111/// Given a namespace, re-scan its declarations from the type definition if they have not
43784112/// yet been re-scanned on this update.
43794113/// If the type declaration instruction has been lost, returns `error.AnalysisFail`.
......@@ -4396,7 +4130,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
43964130 };
43974131
43984132 const key = switch (full_key) {
4399 .reified, .generated_tag => {
4133 .reified, .generated_union_tag => {
44004134 // Namespace always empty, so up-to-date.
44014135 namespace.generation = zcu.generation;
44024136 return;
......@@ -4408,100 +4142,13 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
44084142
44094143 const inst_info = key.zir_index.resolveFull(ip) orelse return error.AnalysisFail;
44104144 const file = zcu.fileByIndex(inst_info.file);
4411 const zir = file.zir.?;
4412
4413 assert(zir.instructions.items(.tag)[@intFromEnum(inst_info.inst)] == .extended);
4414 const extended = zir.instructions.items(.data)[@intFromEnum(inst_info.inst)].extended;
4145 const zir = &file.zir.?;
44154146
44164147 const decls = switch (container) {
4417 .@"struct" => decls: {
4418 assert(extended.opcode == .struct_decl);
4419 const small: Zir.Inst.StructDecl.Small = @bitCast(extended.small);
4420 const extra = zir.extraData(Zir.Inst.StructDecl, extended.operand);
4421 var extra_index = extra.end;
4422 const captures_len = if (small.has_captures_len) blk: {
4423 const captures_len = zir.extra[extra_index];
4424 extra_index += 1;
4425 break :blk captures_len;
4426 } else 0;
4427 extra_index += @intFromBool(small.has_fields_len);
4428 const decls_len = if (small.has_decls_len) blk: {
4429 const decls_len = zir.extra[extra_index];
4430 extra_index += 1;
4431 break :blk decls_len;
4432 } else 0;
4433 extra_index += captures_len * 2;
4434 if (small.has_backing_int) {
4435 const backing_int_body_len = zir.extra[extra_index];
4436 extra_index += 1; // backing_int_body_len
4437 if (backing_int_body_len == 0) {
4438 extra_index += 1; // backing_int_ref
4439 } else {
4440 extra_index += backing_int_body_len; // backing_int_body_inst
4441 }
4442 }
4443 break :decls zir.bodySlice(extra_index, decls_len);
4444 },
4445 .@"union" => decls: {
4446 assert(extended.opcode == .union_decl);
4447 const small: Zir.Inst.UnionDecl.Small = @bitCast(extended.small);
4448 const extra = zir.extraData(Zir.Inst.UnionDecl, extended.operand);
4449 var extra_index = extra.end;
4450 extra_index += @intFromBool(small.has_tag_type);
4451 const captures_len = if (small.has_captures_len) blk: {
4452 const captures_len = zir.extra[extra_index];
4453 extra_index += 1;
4454 break :blk captures_len;
4455 } else 0;
4456 extra_index += @intFromBool(small.has_body_len);
4457 extra_index += @intFromBool(small.has_fields_len);
4458 const decls_len = if (small.has_decls_len) blk: {
4459 const decls_len = zir.extra[extra_index];
4460 extra_index += 1;
4461 break :blk decls_len;
4462 } else 0;
4463 extra_index += captures_len * 2;
4464 break :decls zir.bodySlice(extra_index, decls_len);
4465 },
4466 .@"enum" => decls: {
4467 assert(extended.opcode == .enum_decl);
4468 const small: Zir.Inst.EnumDecl.Small = @bitCast(extended.small);
4469 const extra = zir.extraData(Zir.Inst.EnumDecl, extended.operand);
4470 var extra_index = extra.end;
4471 extra_index += @intFromBool(small.has_tag_type);
4472 const captures_len = if (small.has_captures_len) blk: {
4473 const captures_len = zir.extra[extra_index];
4474 extra_index += 1;
4475 break :blk captures_len;
4476 } else 0;
4477 extra_index += @intFromBool(small.has_body_len);
4478 extra_index += @intFromBool(small.has_fields_len);
4479 const decls_len = if (small.has_decls_len) blk: {
4480 const decls_len = zir.extra[extra_index];
4481 extra_index += 1;
4482 break :blk decls_len;
4483 } else 0;
4484 extra_index += captures_len * 2;
4485 break :decls zir.bodySlice(extra_index, decls_len);
4486 },
4487 .@"opaque" => decls: {
4488 assert(extended.opcode == .opaque_decl);
4489 const small: Zir.Inst.OpaqueDecl.Small = @bitCast(extended.small);
4490 const extra = zir.extraData(Zir.Inst.OpaqueDecl, extended.operand);
4491 var extra_index = extra.end;
4492 const captures_len = if (small.has_captures_len) blk: {
4493 const captures_len = zir.extra[extra_index];
4494 extra_index += 1;
4495 break :blk captures_len;
4496 } else 0;
4497 const decls_len = if (small.has_decls_len) blk: {
4498 const decls_len = zir.extra[extra_index];
4499 extra_index += 1;
4500 break :blk decls_len;
4501 } else 0;
4502 extra_index += captures_len * 2;
4503 break :decls zir.bodySlice(extra_index, decls_len);
4504 },
4148 .@"struct" => zir.getStructDecl(inst_info.inst).decls,
4149 .@"union" => zir.getUnionDecl(inst_info.inst).decls,
4150 .@"enum" => zir.getEnumDecl(inst_info.inst).decls,
4151 .@"opaque" => zir.getOpaqueDecl(inst_info.inst).decls,
45054152 };
45064153
45074154 try pt.scanNamespace(namespace_index, decls);
......@@ -4509,7 +4156,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace
45094156}
45104157
45114158pub fn refValue(pt: Zcu.PerThread, val: InternPool.Index) Zcu.SemaError!InternPool.Index {
4512 const ptr_ty = (try pt.ptrTypeSema(.{
4159 const ptr_ty = (try pt.ptrType(.{
45134160 .child = pt.zcu.intern_pool.typeOf(val),
45144161 .flags = .{
45154162 .alignment = .none,
......@@ -4703,3 +4350,466 @@ fn printVerboseAir(
47034350 try air.write(w, pt, liveness);
47044351 try w.print("# End Function AIR: {f}\n\n", .{fqn.fmt(ip)});
47054352}
4353
4354// MLUGG TODO: these functions are all blatant hacks. See if I can remove them!
4355pub fn resolveTypeForCodegen(pt: Zcu.PerThread, ty: Type) Zcu.SemaError!void {
4356 const zcu = pt.zcu;
4357 const ip = &zcu.intern_pool;
4358 if (ty.isGenericPoison()) return;
4359 switch (ty.zigTypeTag(zcu)) {
4360 .type,
4361 .void,
4362 .bool,
4363 .noreturn,
4364 .int,
4365 .float,
4366 .error_set,
4367 .@"opaque",
4368 .comptime_float,
4369 .comptime_int,
4370 .undefined,
4371 .null,
4372 .enum_literal,
4373 => {},
4374
4375 .frame, .@"anyframe" => @panic("TODO resolveTypeForCodegen async frames"),
4376
4377 .optional => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4378 .error_union => try pt.resolveTypeForCodegen(ty.errorUnionPayload(zcu)),
4379 .pointer => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4380 .array => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4381 .vector => try pt.resolveTypeForCodegen(ty.childType(zcu)),
4382
4383 .@"fn" => {
4384 const info = zcu.typeToFunc(ty).?;
4385 for (0..info.param_types.len) |i| {
4386 const param_ty = info.param_types.get(ip)[i];
4387 try pt.resolveTypeForCodegen(.fromInterned(param_ty));
4388 }
4389 try pt.resolveTypeForCodegen(.fromInterned(info.return_type));
4390 },
4391
4392 .@"struct" => switch (ip.indexToKey(ty.toIntern())) {
4393 .struct_type => {
4394 try pt.ensureTypeLayoutUpToDate(ty);
4395 try pt.ensureTypeInitsUpToDate(ty);
4396 },
4397 .tuple_type => |tuple| for (0..tuple.types.len) |i| {
4398 const field_is_comptime = tuple.values.get(ip)[i] != .none;
4399 if (field_is_comptime) continue;
4400 const field_ty = tuple.types.get(ip)[i];
4401 try pt.resolveTypeForCodegen(.fromInterned(field_ty));
4402 },
4403 else => unreachable,
4404 },
4405
4406 .@"union" => try pt.ensureTypeLayoutUpToDate(ty),
4407 .@"enum" => try pt.ensureTypeInitsUpToDate(ty),
4408 }
4409}
4410pub fn resolveValueTypesForCodegen(pt: Zcu.PerThread, val: Value) Zcu.SemaError!void {
4411 const zcu = pt.zcu;
4412 const ty: Type = switch (val.typeOf(zcu).toIntern()) {
4413 .type_type => if (val.isUndef(zcu)) {
4414 return;
4415 } else val.toType(),
4416 else => |ty| .fromInterned(ty),
4417 };
4418 return pt.resolveTypeForCodegen(ty);
4419}
4420pub fn resolveAirTypesForCodegen(pt: Zcu.PerThread, air: *const Air) Zcu.SemaError!void {
4421 return pt.resolveBodyTypesForCodegen(air, air.getMainBody());
4422}
4423fn resolveBodyTypesForCodegen(pt: Zcu.PerThread, air: *const Air, body: []const Air.Inst.Index) Zcu.SemaError!void {
4424 const zcu = pt.zcu;
4425 const tags = air.instructions.items(.tag);
4426 const datas = air.instructions.items(.data);
4427 for (body) |inst| {
4428 const data = datas[@intFromEnum(inst)];
4429 switch (tags[@intFromEnum(inst)]) {
4430 .inferred_alloc, .inferred_alloc_comptime => unreachable,
4431
4432 .arg => try pt.resolveTypeForCodegen(data.arg.ty.toType()),
4433
4434 .add,
4435 .add_safe,
4436 .add_optimized,
4437 .add_wrap,
4438 .add_sat,
4439 .sub,
4440 .sub_safe,
4441 .sub_optimized,
4442 .sub_wrap,
4443 .sub_sat,
4444 .mul,
4445 .mul_safe,
4446 .mul_optimized,
4447 .mul_wrap,
4448 .mul_sat,
4449 .div_float,
4450 .div_float_optimized,
4451 .div_trunc,
4452 .div_trunc_optimized,
4453 .div_floor,
4454 .div_floor_optimized,
4455 .div_exact,
4456 .div_exact_optimized,
4457 .rem,
4458 .rem_optimized,
4459 .mod,
4460 .mod_optimized,
4461 .max,
4462 .min,
4463 .bit_and,
4464 .bit_or,
4465 .shr,
4466 .shr_exact,
4467 .shl,
4468 .shl_exact,
4469 .shl_sat,
4470 .xor,
4471 .cmp_lt,
4472 .cmp_lt_optimized,
4473 .cmp_lte,
4474 .cmp_lte_optimized,
4475 .cmp_eq,
4476 .cmp_eq_optimized,
4477 .cmp_gte,
4478 .cmp_gte_optimized,
4479 .cmp_gt,
4480 .cmp_gt_optimized,
4481 .cmp_neq,
4482 .cmp_neq_optimized,
4483 .bool_and,
4484 .bool_or,
4485 .store,
4486 .store_safe,
4487 .set_union_tag,
4488 .array_elem_val,
4489 .slice_elem_val,
4490 .ptr_elem_val,
4491 .memset,
4492 .memset_safe,
4493 .memcpy,
4494 .memmove,
4495 .atomic_store_unordered,
4496 .atomic_store_monotonic,
4497 .atomic_store_release,
4498 .atomic_store_seq_cst,
4499 .legalize_vec_elem_val,
4500 => {
4501 try pt.resolveRefTypesForCodegen(data.bin_op.lhs);
4502 try pt.resolveRefTypesForCodegen(data.bin_op.rhs);
4503 },
4504
4505 .not,
4506 .bitcast,
4507 .clz,
4508 .ctz,
4509 .popcount,
4510 .byte_swap,
4511 .bit_reverse,
4512 .abs,
4513 .load,
4514 .fptrunc,
4515 .fpext,
4516 .intcast,
4517 .intcast_safe,
4518 .trunc,
4519 .optional_payload,
4520 .optional_payload_ptr,
4521 .optional_payload_ptr_set,
4522 .wrap_optional,
4523 .unwrap_errunion_payload,
4524 .unwrap_errunion_err,
4525 .unwrap_errunion_payload_ptr,
4526 .unwrap_errunion_err_ptr,
4527 .errunion_payload_ptr_set,
4528 .wrap_errunion_payload,
4529 .wrap_errunion_err,
4530 .struct_field_ptr_index_0,
4531 .struct_field_ptr_index_1,
4532 .struct_field_ptr_index_2,
4533 .struct_field_ptr_index_3,
4534 .get_union_tag,
4535 .slice_len,
4536 .slice_ptr,
4537 .ptr_slice_len_ptr,
4538 .ptr_slice_ptr_ptr,
4539 .array_to_slice,
4540 .int_from_float,
4541 .int_from_float_optimized,
4542 .int_from_float_safe,
4543 .int_from_float_optimized_safe,
4544 .float_from_int,
4545 .splat,
4546 .error_set_has_value,
4547 .addrspace_cast,
4548 .c_va_arg,
4549 .c_va_copy,
4550 => {
4551 try pt.resolveTypeForCodegen(data.ty_op.ty.toType());
4552 try pt.resolveRefTypesForCodegen(data.ty_op.operand);
4553 },
4554
4555 .alloc,
4556 .ret_ptr,
4557 .c_va_start,
4558 => try pt.resolveTypeForCodegen(data.ty),
4559
4560 .ptr_add,
4561 .ptr_sub,
4562 .add_with_overflow,
4563 .sub_with_overflow,
4564 .mul_with_overflow,
4565 .shl_with_overflow,
4566 .slice,
4567 .slice_elem_ptr,
4568 .ptr_elem_ptr,
4569 => {
4570 const bin = air.extraData(Air.Bin, data.ty_pl.payload).data;
4571 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4572 try pt.resolveRefTypesForCodegen(bin.lhs);
4573 try pt.resolveRefTypesForCodegen(bin.rhs);
4574 },
4575
4576 .block,
4577 .loop,
4578 => {
4579 const block = air.unwrapBlock(inst);
4580 try pt.resolveTypeForCodegen(block.ty);
4581 try pt.resolveBodyTypesForCodegen(air, block.body);
4582 },
4583
4584 .dbg_inline_block => {
4585 const block = air.unwrapDbgBlock(inst);
4586 try pt.resolveTypeForCodegen(block.ty);
4587 try pt.resolveBodyTypesForCodegen(air, block.body);
4588 },
4589
4590 .sqrt,
4591 .sin,
4592 .cos,
4593 .tan,
4594 .exp,
4595 .exp2,
4596 .log,
4597 .log2,
4598 .log10,
4599 .floor,
4600 .ceil,
4601 .round,
4602 .trunc_float,
4603 .neg,
4604 .neg_optimized,
4605 .is_null,
4606 .is_non_null,
4607 .is_null_ptr,
4608 .is_non_null_ptr,
4609 .is_err,
4610 .is_non_err,
4611 .is_err_ptr,
4612 .is_non_err_ptr,
4613 .ret,
4614 .ret_safe,
4615 .ret_load,
4616 .is_named_enum_value,
4617 .tag_name,
4618 .error_name,
4619 .cmp_lt_errors_len,
4620 .c_va_end,
4621 .set_err_return_trace,
4622 => try pt.resolveRefTypesForCodegen(data.un_op),
4623
4624 .br, .switch_dispatch => try pt.resolveRefTypesForCodegen(data.br.operand),
4625
4626 .cmp_vector,
4627 .cmp_vector_optimized,
4628 => {
4629 const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data;
4630 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4631 try pt.resolveRefTypesForCodegen(extra.lhs);
4632 try pt.resolveRefTypesForCodegen(extra.rhs);
4633 },
4634
4635 .reduce,
4636 .reduce_optimized,
4637 => try pt.resolveRefTypesForCodegen(data.reduce.operand),
4638
4639 .struct_field_ptr,
4640 .struct_field_val,
4641 => {
4642 const extra = air.extraData(Air.StructField, data.ty_pl.payload).data;
4643 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4644 try pt.resolveRefTypesForCodegen(extra.struct_operand);
4645 },
4646
4647 .shuffle_one => {
4648 const unwrapped = air.unwrapShuffleOne(zcu, inst);
4649 try pt.resolveTypeForCodegen(unwrapped.result_ty);
4650 try pt.resolveRefTypesForCodegen(unwrapped.operand);
4651 for (unwrapped.mask) |m| switch (m.unwrap()) {
4652 .elem => {},
4653 .value => |val| try pt.resolveValueTypesForCodegen(.fromInterned(val)),
4654 };
4655 },
4656
4657 .shuffle_two => {
4658 const unwrapped = air.unwrapShuffleTwo(zcu, inst);
4659 try pt.resolveTypeForCodegen(unwrapped.result_ty);
4660 try pt.resolveRefTypesForCodegen(unwrapped.operand_a);
4661 try pt.resolveRefTypesForCodegen(unwrapped.operand_b);
4662 // No values to check because there are no comptime-known values other than undef
4663 },
4664
4665 .cmpxchg_weak,
4666 .cmpxchg_strong,
4667 => {
4668 const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data;
4669 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4670 try pt.resolveRefTypesForCodegen(extra.ptr);
4671 try pt.resolveRefTypesForCodegen(extra.expected_value);
4672 try pt.resolveRefTypesForCodegen(extra.new_value);
4673 },
4674
4675 .aggregate_init => {
4676 const ty = data.ty_pl.ty.toType();
4677 const elems_len: usize = @intCast(ty.arrayLen(zcu));
4678 const elems: []const Air.Inst.Ref = @ptrCast(air.extra.items[data.ty_pl.payload..][0..elems_len]);
4679 try pt.resolveTypeForCodegen(ty);
4680 if (ty.zigTypeTag(zcu) == .@"struct") {
4681 for (elems, 0..) |elem, elem_idx| {
4682 if (ty.structFieldIsComptime(elem_idx, zcu)) continue;
4683 try pt.resolveRefTypesForCodegen(elem);
4684 }
4685 } else {
4686 for (elems) |elem| {
4687 try pt.resolveRefTypesForCodegen(elem);
4688 }
4689 }
4690 },
4691
4692 .union_init => {
4693 const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data;
4694 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4695 try pt.resolveRefTypesForCodegen(extra.init);
4696 },
4697
4698 .field_parent_ptr => {
4699 const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data;
4700 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4701 try pt.resolveRefTypesForCodegen(extra.field_ptr);
4702 },
4703
4704 .atomic_load => try pt.resolveRefTypesForCodegen(data.atomic_load.ptr),
4705
4706 .prefetch => try pt.resolveRefTypesForCodegen(data.prefetch.ptr),
4707
4708 .runtime_nav_ptr => try pt.resolveTypeForCodegen(.fromInterned(data.ty_nav.ty)),
4709
4710 .select,
4711 .mul_add,
4712 .legalize_vec_store_elem,
4713 => {
4714 const bin = air.extraData(Air.Bin, data.pl_op.payload).data;
4715 try pt.resolveRefTypesForCodegen(data.pl_op.operand);
4716 try pt.resolveRefTypesForCodegen(bin.lhs);
4717 try pt.resolveRefTypesForCodegen(bin.rhs);
4718 },
4719
4720 .atomic_rmw => {
4721 const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data;
4722 try pt.resolveRefTypesForCodegen(data.pl_op.operand);
4723 try pt.resolveRefTypesForCodegen(extra.operand);
4724 },
4725
4726 .call,
4727 .call_always_tail,
4728 .call_never_tail,
4729 .call_never_inline,
4730 => {
4731 const call = air.unwrapCall(inst);
4732 try pt.resolveRefTypesForCodegen(call.callee);
4733 for (call.args) |arg| try pt.resolveRefTypesForCodegen(arg);
4734 },
4735
4736 .dbg_var_ptr,
4737 .dbg_var_val,
4738 .dbg_arg_inline,
4739 => try pt.resolveRefTypesForCodegen(data.pl_op.operand),
4740
4741 .@"try", .try_cold => {
4742 const @"try" = air.unwrapTry(inst);
4743 try pt.resolveRefTypesForCodegen(@"try".error_union);
4744 try pt.resolveBodyTypesForCodegen(air, @"try".else_body);
4745 },
4746
4747 .try_ptr, .try_ptr_cold => {
4748 const try_ptr = air.unwrapTryPtr(inst);
4749 try pt.resolveTypeForCodegen(try_ptr.error_union_payload_ptr_ty.toType());
4750 try pt.resolveRefTypesForCodegen(try_ptr.error_union_ptr);
4751 try pt.resolveBodyTypesForCodegen(air, try_ptr.else_body);
4752 },
4753
4754 .cond_br => {
4755 const cond_br = air.unwrapCondBr(inst);
4756 try pt.resolveRefTypesForCodegen(cond_br.condition);
4757 try pt.resolveBodyTypesForCodegen(air, cond_br.then_body);
4758 try pt.resolveBodyTypesForCodegen(air, cond_br.else_body);
4759 },
4760
4761 .switch_br, .loop_switch_br => {
4762 const switch_br = air.unwrapSwitch(inst);
4763 try pt.resolveRefTypesForCodegen(switch_br.operand);
4764 var it = switch_br.iterateCases();
4765 while (it.next()) |case| {
4766 for (case.items) |item| {
4767 try pt.resolveRefTypesForCodegen(item);
4768 }
4769 for (case.ranges) |range| {
4770 try pt.resolveRefTypesForCodegen(range[0]);
4771 try pt.resolveRefTypesForCodegen(range[1]);
4772 }
4773 try pt.resolveBodyTypesForCodegen(air, case.body);
4774 }
4775 try pt.resolveBodyTypesForCodegen(air, it.elseBody());
4776 },
4777
4778 .assembly => {
4779 const @"asm" = air.unwrapAsm(inst);
4780 try pt.resolveTypeForCodegen(data.ty_pl.ty.toType());
4781 for (@"asm".outputs) |output| if (output != .none) try pt.resolveRefTypesForCodegen(output);
4782 for (@"asm".inputs) |input| if (input != .none) try pt.resolveRefTypesForCodegen(input);
4783 },
4784
4785 .legalize_compiler_rt_call => {
4786 const compiler_rt_call = air.unwrapCompilerRtCall(inst);
4787 for (compiler_rt_call.args) |arg| try pt.resolveRefTypesForCodegen(arg);
4788 },
4789
4790 .trap,
4791 .breakpoint,
4792 .ret_addr,
4793 .frame_addr,
4794 .unreach,
4795 .wasm_memory_size,
4796 .wasm_memory_grow,
4797 .work_item_id,
4798 .work_group_size,
4799 .work_group_id,
4800 .dbg_stmt,
4801 .dbg_empty_stmt,
4802 .err_return_trace,
4803 .save_err_return_trace_index,
4804 .repeat,
4805 => {},
4806 }
4807 }
4808}
4809fn resolveRefTypesForCodegen(pt: Zcu.PerThread, ref: Air.Inst.Ref) Zcu.SemaError!void {
4810 const ip_index = ref.toInterned() orelse {
4811 // `ref` refers to a prior instruction, which we already did the resolution for.
4812 return;
4813 };
4814 return pt.resolveValueTypesForCodegen(.fromInterned(ip_index));
4815}
src/codegen.zig+1-1
......@@ -1088,7 +1088,7 @@ pub fn lowerValue(pt: Zcu.PerThread, val: Value, target: *const std.Target) Allo
10881088 return .{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? };
10891089 }
10901090 } else if (ty.zigTypeTag(zcu) == .pointer) {
1091 const elem_ty = ty.elemType2(zcu);
1091 const elem_ty = ty.childType(zcu);
10921092 if (!elem_ty.hasRuntimeBits(zcu)) {
10931093 return .{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? };
10941094 }
src/codegen/aarch64/Select.zig+4-4
......@@ -2464,7 +2464,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
24642464
24652465 const ty_pl = air.data(air.inst_index).ty_pl;
24662466 const bin_op = isel.air.extraData(Air.Bin, ty_pl.payload).data;
2467 const elem_size = ty_pl.ty.toType().elemType2(zcu).abiSize(zcu);
2467 const elem_size = ty_pl.ty.toType().childType(zcu).abiSize(zcu);
24682468
24692469 const base_vi = try isel.use(bin_op.lhs);
24702470 var base_part_it = base_vi.field(ty_pl.ty.toType(), 0, 8);
......@@ -6145,7 +6145,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
61456145 } else {
61466146 const elem_ptr_ra = try isel.allocIntReg();
61476147 defer isel.freeReg(elem_ptr_ra);
6148 if (!try elem_vi.value.load(isel, slice_ty.elemType2(zcu), elem_ptr_ra, .{
6148 if (!try elem_vi.value.load(isel, slice_ty.childType(zcu), elem_ptr_ra, .{
61496149 .@"volatile" = ptr_info.flags.is_volatile,
61506150 })) break :unused;
61516151 const slice_vi = try isel.use(bin_op.lhs);
......@@ -6253,7 +6253,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
62536253 } else {
62546254 const elem_ptr_ra = try isel.allocIntReg();
62556255 defer isel.freeReg(elem_ptr_ra);
6256 if (!try elem_vi.value.load(isel, ptr_ty.elemType2(zcu), elem_ptr_ra, .{
6256 if (!try elem_vi.value.load(isel, ptr_ty.childType(zcu), elem_ptr_ra, .{
62576257 .@"volatile" = ptr_info.flags.is_volatile,
62586258 })) break :unused;
62596259 const base_vi = try isel.use(bin_op.lhs);
......@@ -6594,7 +6594,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory,
65946594 if (try isel.hasRepeatedByteRepr(.fromInterned(fill_val))) |fill_byte|
65956595 break :fill_byte .{ .constant = fill_byte };
65966596 }
6597 switch (dst_ty.elemType2(zcu).abiSize(zcu)) {
6597 switch (dst_ty.indexablePtrElem(zcu).abiSize(zcu)) {
65986598 0 => unreachable,
65996599 1 => break :fill_byte .{ .value = bin_op.rhs },
66006600 2, 4, 8 => |size| {
src/codegen/c.zig+4-4
......@@ -3676,7 +3676,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
36763676
36773677 const inst_ty = f.typeOfIndex(inst);
36783678 const ptr_ty = f.typeOf(bin_op.lhs);
3679 const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu);
3679 const elem_has_bits = ptr_ty.indexablePtrElem(zcu).hasRuntimeBitsIgnoreComptime(zcu);
36803680
36813681 const ptr = try f.resolveInst(bin_op.lhs);
36823682 const index = try f.resolveInst(bin_op.rhs);
......@@ -3738,7 +3738,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
37383738
37393739 const inst_ty = f.typeOfIndex(inst);
37403740 const slice_ty = f.typeOf(bin_op.lhs);
3741 const elem_ty = slice_ty.elemType2(zcu);
3741 const elem_ty = slice_ty.childType(zcu);
37423742 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu);
37433743
37443744 const slice = try f.resolveInst(bin_op.lhs);
......@@ -4502,7 +4502,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
45024502
45034503 const inst_ty = f.typeOfIndex(inst);
45044504 const inst_scalar_ty = inst_ty.scalarType(zcu);
4505 const elem_ty = inst_scalar_ty.elemType2(zcu);
4505 const elem_ty = inst_scalar_ty.indexablePtrElem(zcu);
45064506 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs);
45074507 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
45084508
......@@ -7037,7 +7037,7 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index, function_paren: []const u8) !CV
70377037 try w.writeAll(", ");
70387038 try writeArrayLen(f, dest_ptr, dest_ty);
70397039 try w.writeAll(" * sizeof(");
7040 try f.renderType(w, dest_ty.elemType2(zcu));
7040 try f.renderType(w, dest_ty.indexablePtrElem(zcu));
70417041 try w.writeAll("));");
70427042 try f.object.newline();
70437043
src/codegen/llvm.zig+1-1
......@@ -2112,7 +2112,7 @@ pub const Object = struct {
21122112 return debug_array_type;
21132113 },
21142114 .vector => {
2115 const elem_ty = ty.elemType2(zcu);
2115 const elem_ty = ty.childType(zcu);
21162116 // Vector elements cannot be padded since that would make
21172117 // @bitSizOf(elem) * len > @bitSizOf(vec).
21182118 // Neither gdb nor lldb seem to be able to display non-byte sized
src/codegen/mips/abi.zig+1-1
......@@ -44,7 +44,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class {
4444 return .byval;
4545 },
4646 .vector => {
47 const elem_type = ty.elemType2(zcu);
47 const elem_type = ty.childType(zcu);
4848 switch (elem_type.zigTypeTag(zcu)) {
4949 .bool, .int => {
5050 const bit_size = ty.bitSize(zcu);
src/codegen/riscv64/CodeGen.zig+2-3
......@@ -2673,7 +2673,7 @@ fn genBinOp(
26732673 defer func.register_manager.unlockReg(tmp_lock);
26742674
26752675 // RISC-V has no immediate mul, so we copy the size to a temporary register
2676 const elem_size = lhs_ty.elemType2(zcu).abiSize(zcu);
2676 const elem_size = lhs_ty.indexablePtrElem(zcu).abiSize(zcu);
26772677 const elem_size_reg = try func.copyToTmpRegister(Type.u64, .{ .immediate = elem_size });
26782678
26792679 try func.genBinOp(
......@@ -3913,9 +3913,8 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void {
39133913 const base_ptr_ty = func.typeOf(bin_op.lhs);
39143914
39153915 const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: {
3916 const elem_ty = base_ptr_ty.elemType2(zcu);
3916 const elem_ty = base_ptr_ty.indexablePtrElem(zcu);
39173917 if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none;
3918
39193918 const base_ptr_mcv = try func.resolveInst(bin_op.lhs);
39203919 const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) {
39213920 .register => |reg| func.register_manager.lockRegAssumeUnused(reg),
src/codegen/spirv/CodeGen.zig+1-1
......@@ -4381,7 +4381,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id {
43814381fn ptrElemPtr(cg: *CodeGen, ptr_ty: Type, ptr_id: Id, index_id: Id) !Id {
43824382 const zcu = cg.module.zcu;
43834383 // Construct new pointer type for the resulting pointer
4384 const elem_ty = ptr_ty.elemType2(zcu); // use elemType() so that we get T for *[N]T.
4384 const elem_ty = ptr_ty.indexablePtrElem(zcu);
43854385 const elem_ty_id = try cg.resolveType(elem_ty, .indirect);
43864386 const elem_ptr_ty_id = try cg.module.ptrType(elem_ty_id, cg.module.storageClass(ptr_ty.ptrAddressSpace(zcu)));
43874387 if (ptr_ty.isSinglePointer(zcu)) {
src/codegen/x86_64/CodeGen.zig+16-21
......@@ -43261,7 +43261,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4326143261 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
4326243262 try ops[0].toSlicePtr(cg);
4326343263 var res: [1]Temp = undefined;
43264 if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
43264 if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
4326543265 .patterns = &.{
4326643266 .{ .src = .{ .to_gpr, .simm32, .none } },
4326743267 },
......@@ -43375,7 +43375,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
4337543375 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
4337643376 try ops[0].toSlicePtr(cg);
4337743377 var res: [1]Temp = undefined;
43378 if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
43378 if (!hack_around_sema_opv_bugs or ty_pl.ty.toType().childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) cg.select(&res, &.{ty_pl.ty.toType()}, &ops, comptime &.{ .{
4337943379 .patterns = &.{
4338043380 .{ .src = .{ .to_gpr, .simm32, .none } },
4338143381 },
......@@ -103926,7 +103926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
103926103926 .array_elem_val, .legalize_vec_elem_val => {
103927103927 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
103928103928 const array_ty = cg.typeOf(bin_op.lhs);
103929 const res_ty = array_ty.elemType2(zcu);
103929 const res_ty = array_ty.childType(zcu);
103930103930 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
103931103931 var res: [1]Temp = undefined;
103932103932 cg.select(&res, &.{res_ty}, &ops, comptime &.{ .{
......@@ -104121,7 +104121,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
104121104121 },
104122104122 .slice_elem_val, .ptr_elem_val => {
104123104123 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
104124 const res_ty = cg.typeOf(bin_op.lhs).elemType2(zcu);
104124 const res_ty = cg.typeOf(bin_op.lhs).indexablePtrElem(zcu);
104125104125 var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs });
104126104126 try ops[0].toSlicePtr(cg);
104127104127 var res: [1]Temp = undefined;
......@@ -187919,7 +187919,6 @@ const Select = struct {
187919187919 unsigned_int: Memory.Size,
187920187920 elem_size_is: u8,
187921187921 po2_elem_size,
187922 elem_int: Memory.Size,
187923187922
187924187923 const OfIsSizes = struct { of: Memory.Size, is: Memory.Size };
187925187924
......@@ -188178,12 +188177,8 @@ const Select = struct {
188178188177 .signed => false,
188179188178 .unsigned => size.bitSize(cg.target) >= int_info.bits,
188180188179 } else false,
188181 .elem_size_is => |size| size == ty.elemType2(zcu).abiSize(zcu),
188182 .po2_elem_size => std.math.isPowerOfTwo(ty.elemType2(zcu).abiSize(zcu)),
188183 .elem_int => |size| if (cg.intInfo(ty.elemType2(zcu))) |elem_int_info|
188184 size.bitSize(cg.target) >= elem_int_info.bits
188185 else
188186 false,
188180 .elem_size_is => |size| size == ty.indexablePtrElem(zcu).abiSize(zcu),
188181 .po2_elem_size => std.math.isPowerOfTwo(ty.indexablePtrElem(zcu).abiSize(zcu)),
188187188182 };
188188188183 }
188189188184 };
......@@ -189918,20 +189913,20 @@ const Select = struct {
189918189913 .dst0_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).abiSize(s.cg.pt.zcu)),
189919189914 .delta_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).abiSize(s.cg.pt.zcu))) -
189920189915 @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).abiSize(s.cg.pt.zcu)))),
189921 .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) -
189922 @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))),
189916 .delta_elem_size => @intCast(@as(SignedImm, @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))) -
189917 @as(SignedImm, @intCast(op.flags.index.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)))),
189923189918 .unaligned_size => @intCast(s.cg.unalignedSize(op.flags.base.ref.typeOf(s))),
189924189919 .unaligned_size_add_elem_size => {
189925189920 const ty = op.flags.base.ref.typeOf(s);
189926 break :lhs @intCast(s.cg.unalignedSize(ty) + ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu));
189921 break :lhs @intCast(s.cg.unalignedSize(ty) + ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu));
189927189922 },
189928189923 .unaligned_size_sub_elem_size => {
189929189924 const ty = op.flags.base.ref.typeOf(s);
189930 break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu));
189925 break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu));
189931189926 },
189932189927 .unaligned_size_sub_2_elem_size => {
189933189928 const ty = op.flags.base.ref.typeOf(s);
189934 break :lhs @intCast(s.cg.unalignedSize(ty) - ty.elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2);
189929 break :lhs @intCast(s.cg.unalignedSize(ty) - ty.scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) * 2);
189935189930 },
189936189931 .bit_size => @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s))),
189937189932 .src0_bit_size => @intCast(s.cg.nonBoolScalarBitSize(Select.Operand.Ref.src0.typeOf(s))),
......@@ -189944,10 +189939,10 @@ const Select = struct {
189944189939 op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu),
189945189940 @divExact(op.flags.base.size.bitSize(s.cg.target), 8),
189946189941 )),
189947 .elem_size => @intCast(op.flags.base.ref.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189948 .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189949 .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189950 .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) *
189942 .elem_size => @intCast(op.flags.base.ref.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189943 .src0_elem_size => @intCast(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189944 .dst0_elem_size => @intCast(Select.Operand.Ref.dst0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu)),
189945 .src0_elem_size_mul_src1 => @intCast(Select.Operand.Ref.src0.typeOf(s).indexableElem(s.cg.pt.zcu).abiSize(s.cg.pt.zcu) *
189951189946 Select.Operand.Ref.src1.valueOf(s).immediate),
189952189947 .vector_index => switch (op.flags.base.ref.typeOf(s).ptrInfo(s.cg.pt.zcu).flags.vector_index) {
189953189948 .none => unreachable,
......@@ -189956,7 +189951,7 @@ const Select = struct {
189956189951 .src1 => @intCast(Select.Operand.Ref.src1.valueOf(s).immediate),
189957189952 .src1_sub_bit_size => @as(SignedImm, @intCast(Select.Operand.Ref.src1.valueOf(s).immediate)) -
189958189953 @as(SignedImm, @intCast(s.cg.nonBoolScalarBitSize(op.flags.base.ref.typeOf(s)))),
189959 .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).elemType2(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))),
189954 .log2_src0_elem_size => @intCast(std.math.log2(Select.Operand.Ref.src0.typeOf(s).scalarType(s.cg.pt.zcu).abiSize(s.cg.pt.zcu))),
189960189955 .elem_mask => @as(u8, std.math.maxInt(u8)) >> @intCast(
189961189956 8 - ((s.cg.unalignedSize(op.flags.base.ref.typeOf(s)) - 1) %
189962189957 @divExact(op.flags.base.size.bitSize(s.cg.target), 8) + 1 >>
src/link/Dwarf.zig+4-4
......@@ -4575,10 +4575,10 @@ fn updateContainerTypeWriterError(
45754575 const name_strat: Zir.Inst.NameStrategy = switch (decl_inst.tag) {
45764576 .struct_init, .struct_init_ref, .struct_init_anon => .anon,
45774577 .extended => switch (decl_inst.data.extended.opcode) {
4578 .struct_decl => @as(Zir.Inst.StructDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4579 .enum_decl => @as(Zir.Inst.EnumDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4580 .union_decl => @as(Zir.Inst.UnionDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4581 .opaque_decl => @as(Zir.Inst.OpaqueDecl.Small, @bitCast(decl_inst.data.extended.small)).name_strategy,
4578 .struct_decl => file.zir.?.getStructDecl(inst_info.inst).name_strategy,
4579 .union_decl => file.zir.?.getUnionDecl(inst_info.inst).name_strategy,
4580 .enum_decl => file.zir.?.getEnumDecl(inst_info.inst).name_strategy,
4581 .opaque_decl => file.zir.?.getOpaqueDecl(inst_info.inst).name_strategy,
45824582
45834583 .reify_enum,
45844584 .reify_struct,
src/mutable_value.zig+3-15
......@@ -18,7 +18,7 @@ pub const MutableValue = union(enum) {
1818 opt_payload: SubValue,
1919 /// An aggregate consisting of a single repeated value.
2020 repeated: SubValue,
21 /// An aggregate of `u8` consisting of "plain" bytes (no lazy or undefined elements).
21 /// An aggregate of `u8` consisting of "plain" bytes (no undefined elements).
2222 bytes: Bytes,
2323 /// An aggregate with arbitrary sub-values.
2424 aggregate: Aggregate,
......@@ -415,16 +415,7 @@ pub const MutableValue = union(enum) {
415415 } else if (!is_struct and is_trivial_int and Type.fromInterned(a.ty).childType(zcu).toIntern() == .u8_type) {
416416 // See if we can switch to `bytes` repr
417417 for (a.elems) |e| {
418 switch (e) {
419 else => break,
420 .interned => |ip_index| switch (ip.indexToKey(ip_index)) {
421 else => break,
422 .int => |int| switch (int.storage) {
423 .u64, .i64, .big_int => {},
424 .lazy_align, .lazy_size => break,
425 },
426 },
427 }
418 if (!e.isTrivialInt(zcu)) break;
428419 } else {
429420 const bytes = try arena.alloc(u8, a.elems.len);
430421 for (a.elems, bytes) |elem_val, *b| {
......@@ -494,10 +485,7 @@ pub const MutableValue = union(enum) {
494485 else => false,
495486 .interned => |ip_index| switch (zcu.intern_pool.indexToKey(ip_index)) {
496487 else => false,
497 .int => |int| switch (int.storage) {
498 .u64, .i64, .big_int => true,
499 .lazy_align, .lazy_size => false,
500 },
488 .int => true,
501489 },
502490 };
503491 }
src/print_value.zig+2-10
......@@ -81,14 +81,6 @@ pub fn print(
8181 .int => |int| switch (int.storage) {
8282 inline .u64, .i64 => |x| try writer.print("{d}", .{x}),
8383 .big_int => |x| try writer.print("{d}", .{x}),
84 .lazy_align => |ty| if (opt_sema != null) {
85 const a = try Type.fromInterned(ty).abiAlignmentSema(pt);
86 try writer.print("{d}", .{a.toByteUnits() orelse 0});
87 } else try writer.print("@alignOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
88 .lazy_size => |ty| if (opt_sema != null) {
89 const s = try Type.fromInterned(ty).abiSizeSema(pt);
90 try writer.print("{d}", .{s});
91 } else try writer.print("@sizeOf({f})", .{Type.fromInterned(ty).fmt(pt)}),
9284 },
9385 .err => |err| try writer.print("error.{f}", .{
9486 err.name.fmt(ip),
......@@ -104,8 +96,8 @@ pub fn print(
10496 }),
10597 .enum_tag => |enum_tag| {
10698 const enum_type = ip.loadEnumType(val.typeOf(zcu).toIntern());
107 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
108 return writer.print(".{f}", .{enum_type.names.get(ip)[tag_index].fmt(ip)});
99 if (enum_type.tagValueIndex(ip, enum_tag.int)) |tag_index| {
100 return writer.print(".{f}", .{enum_type.field_names.get(ip)[tag_index].fmt(ip)});
109101 }
110102 if (level == 0) {
111103 return writer.writeAll("@enumFromInt(...)");