authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-04 20:12:05-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-04 20:12:05-04:00
log790b8428a26457e7ed9ea20485b9d3085011b989
tree3d27f81e31d73af526e8a972504325fa1cb0d9e1
parentde61540c2d049b0774dd9c5e14aa8f65ed1c25ed
parentcda6f552d5d4a996df69981dac7c9d9b3c066537
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20494 from mlugg/the-great-decl-split

refactors ad infinitum

71 files changed, 6753 insertions(+), 6819 deletions(-)

CMakeLists.txt+1-1
...@@ -522,6 +522,7 @@ set(ZIG_STAGE2_SOURCES...@@ -522,6 +522,7 @@ set(ZIG_STAGE2_SOURCES
522 src/Sema.zig522 src/Sema.zig
523 src/Sema/bitcast.zig523 src/Sema/bitcast.zig
524 src/Sema/comptime_ptr_access.zig524 src/Sema/comptime_ptr_access.zig
525 src/Type.zig
525 src/Value.zig526 src/Value.zig
526 src/Zcu.zig527 src/Zcu.zig
527 src/arch/aarch64/CodeGen.zig528 src/arch/aarch64/CodeGen.zig
...@@ -673,7 +674,6 @@ set(ZIG_STAGE2_SOURCES...@@ -673,7 +674,6 @@ set(ZIG_STAGE2_SOURCES
673 src/target.zig674 src/target.zig
674 src/tracy.zig675 src/tracy.zig
675 src/translate_c.zig676 src/translate_c.zig
676 src/type.zig
677 src/wasi_libc.zig677 src/wasi_libc.zig
678)678)
679679
build.zig+6-22
...@@ -82,15 +82,6 @@ pub fn build(b: *std.Build) !void {...@@ -82,15 +82,6 @@ pub fn build(b: *std.Build) !void {
82 docs_step.dependOn(langref_step);82 docs_step.dependOn(langref_step);
83 docs_step.dependOn(std_docs_step);83 docs_step.dependOn(std_docs_step);
8484
85 const check_case_exe = b.addExecutable(.{
86 .name = "check-case",
87 .root_source_file = b.path("test/src/Cases.zig"),
88 .target = b.graph.host,
89 .optimize = optimize,
90 .single_threaded = single_threaded,
91 });
92 check_case_exe.stack_size = stack_size;
93
94 const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;85 const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;
95 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;86 const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
96 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;87 const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release;
...@@ -222,7 +213,6 @@ pub fn build(b: *std.Build) !void {...@@ -222,7 +213,6 @@ pub fn build(b: *std.Build) !void {
222 if (target.result.os.tag == .windows and target.result.abi == .gnu) {213 if (target.result.os.tag == .windows and target.result.abi == .gnu) {
223 // LTO is currently broken on mingw, this can be removed when it's fixed.214 // LTO is currently broken on mingw, this can be removed when it's fixed.
224 exe.want_lto = false;215 exe.want_lto = false;
225 check_case_exe.want_lto = false;
226 }216 }
227217
228 const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");218 const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
...@@ -245,7 +235,6 @@ pub fn build(b: *std.Build) !void {...@@ -245,7 +235,6 @@ pub fn build(b: *std.Build) !void {
245235
246 if (link_libc) {236 if (link_libc) {
247 exe.linkLibC();237 exe.linkLibC();
248 check_case_exe.linkLibC();
249 }238 }
250239
251 const is_debug = optimize == .Debug;240 const is_debug = optimize == .Debug;
...@@ -339,21 +328,17 @@ pub fn build(b: *std.Build) !void {...@@ -339,21 +328,17 @@ pub fn build(b: *std.Build) !void {
339 }328 }
340329
341 try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);330 try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
342 try addCmakeCfgOptionsToExe(b, cfg, check_case_exe, use_zig_libcxx);
343 } else {331 } else {
344 // Here we are -Denable-llvm but no cmake integration.332 // Here we are -Denable-llvm but no cmake integration.
345 try addStaticLlvmOptionsToExe(exe);333 try addStaticLlvmOptionsToExe(exe);
346 try addStaticLlvmOptionsToExe(check_case_exe);
347 }334 }
348 if (target.result.os.tag == .windows) {335 if (target.result.os.tag == .windows) {
349 inline for (.{ exe, check_case_exe }) |artifact| {336 // LLVM depends on networking as of version 18.
350 // LLVM depends on networking as of version 18.337 exe.linkSystemLibrary("ws2_32");
351 artifact.linkSystemLibrary("ws2_32");
352338
353 artifact.linkSystemLibrary("version");339 exe.linkSystemLibrary("version");
354 artifact.linkSystemLibrary("uuid");340 exe.linkSystemLibrary("uuid");
355 artifact.linkSystemLibrary("ole32");341 exe.linkSystemLibrary("ole32");
356 }
357 }342 }
358 }343 }
359344
...@@ -394,7 +379,6 @@ pub fn build(b: *std.Build) !void {...@@ -394,7 +379,6 @@ pub fn build(b: *std.Build) !void {
394 const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{};379 const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{};
395380
396 const test_cases_options = b.addOptions();381 const test_cases_options = b.addOptions();
397 check_case_exe.root_module.addOptions("build_options", test_cases_options);
398382
399 test_cases_options.addOption(bool, "enable_tracy", false);383 test_cases_options.addOption(bool, "enable_tracy", false);
400 test_cases_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions);384 test_cases_options.addOption(bool, "enable_debug_extensions", enable_debug_extensions);
...@@ -458,7 +442,7 @@ pub fn build(b: *std.Build) !void {...@@ -458,7 +442,7 @@ pub fn build(b: *std.Build) !void {
458 test_step.dependOn(check_fmt);442 test_step.dependOn(check_fmt);
459443
460 const test_cases_step = b.step("test-cases", "Run the main compiler test cases");444 const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
461 try tests.addCases(b, test_cases_step, test_filters, check_case_exe, target, .{445 try tests.addCases(b, test_cases_step, test_filters, target, .{
462 .skip_translate_c = skip_translate_c,446 .skip_translate_c = skip_translate_c,
463 .skip_run_translated_c = skip_run_translated_c,447 .skip_run_translated_c = skip_run_translated_c,
464 }, .{448 }, .{
lib/std/dynamic_library.zig+31-16
...@@ -17,12 +17,15 @@ pub const DynLib = struct {...@@ -17,12 +17,15 @@ pub const DynLib = struct {
17 DlDynLib,17 DlDynLib,
18 .windows => WindowsDynLib,18 .windows => WindowsDynLib,
19 .macos, .tvos, .watchos, .ios, .visionos, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris, .illumos => DlDynLib,19 .macos, .tvos, .watchos, .ios, .visionos, .freebsd, .netbsd, .openbsd, .dragonfly, .solaris, .illumos => DlDynLib,
20 else => @compileError("unsupported platform"),20 else => struct {
21 const open = @compileError("unsupported platform");
22 const openZ = @compileError("unsupported platform");
23 },
21 };24 };
2225
23 inner: InnerType,26 inner: InnerType,
2427
25 pub const Error = ElfDynLib.Error || DlDynLib.Error || WindowsDynLib.Error;28 pub const Error = ElfDynLibError || DlDynLibError || WindowsDynLibError;
2629
27 /// Trusts the file. Malicious file will be able to execute arbitrary code.30 /// Trusts the file. Malicious file will be able to execute arbitrary code.
28 pub fn open(path: []const u8) Error!DynLib {31 pub fn open(path: []const u8) Error!DynLib {
...@@ -122,6 +125,18 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) error{InvalidExe}!LinkMap.Iterator {...@@ -122,6 +125,18 @@ pub fn linkmap_iterator(phdrs: []elf.Phdr) error{InvalidExe}!LinkMap.Iterator {
122 return .{ .current = link_map_ptr };125 return .{ .current = link_map_ptr };
123}126}
124127
128/// Separated to avoid referencing `ElfDynLib`, because its field types may not
129/// be valid on other targets.
130const ElfDynLibError = error{
131 FileTooBig,
132 NotElfFile,
133 NotDynamicLibrary,
134 MissingDynamicLinkingInformation,
135 ElfStringSectionNotFound,
136 ElfSymSectionNotFound,
137 ElfHashTableNotFound,
138} || posix.OpenError || posix.MMapError;
139
125pub const ElfDynLib = struct {140pub const ElfDynLib = struct {
126 strings: [*:0]u8,141 strings: [*:0]u8,
127 syms: [*]elf.Sym,142 syms: [*]elf.Sym,
...@@ -130,15 +145,7 @@ pub const ElfDynLib = struct {...@@ -130,15 +145,7 @@ pub const ElfDynLib = struct {
130 verdef: ?*elf.Verdef,145 verdef: ?*elf.Verdef,
131 memory: []align(mem.page_size) u8,146 memory: []align(mem.page_size) u8,
132147
133 pub const Error = error{148 pub const Error = ElfDynLibError;
134 FileTooBig,
135 NotElfFile,
136 NotDynamicLibrary,
137 MissingDynamicLinkingInformation,
138 ElfStringSectionNotFound,
139 ElfSymSectionNotFound,
140 ElfHashTableNotFound,
141 } || posix.OpenError || posix.MMapError;
142149
143 /// Trusts the file. Malicious file will be able to execute arbitrary code.150 /// Trusts the file. Malicious file will be able to execute arbitrary code.
144 pub fn open(path: []const u8) Error!ElfDynLib {151 pub fn open(path: []const u8) Error!ElfDynLib {
...@@ -350,11 +357,15 @@ test "ElfDynLib" {...@@ -350,11 +357,15 @@ test "ElfDynLib" {
350 try testing.expectError(error.FileNotFound, ElfDynLib.open("invalid_so.so"));357 try testing.expectError(error.FileNotFound, ElfDynLib.open("invalid_so.so"));
351}358}
352359
360/// Separated to avoid referencing `WindowsDynLib`, because its field types may not
361/// be valid on other targets.
362const WindowsDynLibError = error{
363 FileNotFound,
364 InvalidPath,
365} || windows.LoadLibraryError;
366
353pub const WindowsDynLib = struct {367pub const WindowsDynLib = struct {
354 pub const Error = error{368 pub const Error = WindowsDynLibError;
355 FileNotFound,
356 InvalidPath,
357 } || windows.LoadLibraryError;
358369
359 dll: windows.HMODULE,370 dll: windows.HMODULE,
360371
...@@ -413,8 +424,12 @@ pub const WindowsDynLib = struct {...@@ -413,8 +424,12 @@ pub const WindowsDynLib = struct {
413 }424 }
414};425};
415426
427/// Separated to avoid referencing `DlDynLib`, because its field types may not
428/// be valid on other targets.
429const DlDynLibError = error{ FileNotFound, NameTooLong };
430
416pub const DlDynLib = struct {431pub const DlDynLib = struct {
417 pub const Error = error{ FileNotFound, NameTooLong };432 pub const Error = DlDynLibError;
418433
419 handle: *anyopaque,434 handle: *anyopaque,
420435
lib/std/http.zig+6-6
...@@ -311,13 +311,13 @@ const builtin = @import("builtin");...@@ -311,13 +311,13 @@ const builtin = @import("builtin");
311const std = @import("std.zig");311const std = @import("std.zig");
312312
313test {313test {
314 _ = Client;
315 _ = Method;
316 _ = Server;
317 _ = Status;
318 _ = HeadParser;
319 _ = ChunkParser;
320 if (builtin.os.tag != .wasi) {314 if (builtin.os.tag != .wasi) {
315 _ = Client;
316 _ = Method;
317 _ = Server;
318 _ = Status;
319 _ = HeadParser;
320 _ = ChunkParser;
321 _ = @import("http/test.zig");321 _ = @import("http/test.zig");
322 }322 }
323}323}
lib/std/net.zig+6-4
...@@ -1930,8 +1930,10 @@ pub const Server = struct {...@@ -1930,8 +1930,10 @@ pub const Server = struct {
1930};1930};
19311931
1932test {1932test {
1933 _ = @import("net/test.zig");1933 if (builtin.os.tag != .wasi) {
1934 _ = Server;1934 _ = Server;
1935 _ = Stream;1935 _ = Stream;
1936 _ = Address;1936 _ = Address;
1937 _ = @import("net/test.zig");
1938 }
1937}1939}
lib/zig.h+4-4
...@@ -207,16 +207,16 @@ typedef char bool;...@@ -207,16 +207,16 @@ typedef char bool;
207 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))207 __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
208#endif208#endif
209209
210#define zig_mangled_tentative zig_mangled
211#define zig_mangled_final zig_mangled
210#if _MSC_VER212#if _MSC_VER
211#define zig_mangled_tentative(mangled, unmangled)213#define zig_mangled(mangled, unmangled) ; \
212#define zig_mangled_final(mangled, unmangled) ; \
213 zig_export(#mangled, unmangled)214 zig_export(#mangled, unmangled)
214#define zig_mangled_export(mangled, unmangled, symbol) \215#define zig_mangled_export(mangled, unmangled, symbol) \
215 zig_export(unmangled, #mangled) \216 zig_export(unmangled, #mangled) \
216 zig_export(symbol, unmangled)217 zig_export(symbol, unmangled)
217#else /* _MSC_VER */218#else /* _MSC_VER */
218#define zig_mangled_tentative(mangled, unmangled) __asm(zig_mangle_c(unmangled))219#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
219#define zig_mangled_final(mangled, unmangled) zig_mangled_tentative(mangled, unmangled)
220#define zig_mangled_export(mangled, unmangled, symbol) \220#define zig_mangled_export(mangled, unmangled, symbol) \
221 zig_mangled_final(mangled, unmangled) \221 zig_mangled_final(mangled, unmangled) \
222 zig_export(symbol, unmangled)222 zig_export(symbol, unmangled)
src/Air.zig+3-1
...@@ -9,7 +9,7 @@ const assert = std.debug.assert;...@@ -9,7 +9,7 @@ const assert = std.debug.assert;
99
10const Air = @This();10const Air = @This();
11const Value = @import("Value.zig");11const Value = @import("Value.zig");
12const Type = @import("type.zig").Type;12const Type = @import("Type.zig");
13const InternPool = @import("InternPool.zig");13const InternPool = @import("InternPool.zig");
14const Zcu = @import("Zcu.zig");14const Zcu = @import("Zcu.zig");
15/// Deprecated.15/// Deprecated.
...@@ -1801,3 +1801,5 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {...@@ -1801,3 +1801,5 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
1801 .atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip),1801 .atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip),
1802 };1802 };
1803}1803}
1804
1805pub const typesFullyResolved = @import("Air/types_resolved.zig").typesFullyResolved;
src/Air/types_resolved.zig created+521
...@@ -0,0 +1,521 @@
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 .atomic_store_unordered,
87 .atomic_store_monotonic,
88 .atomic_store_release,
89 .atomic_store_seq_cst,
90 => {
91 if (!checkRef(data.bin_op.lhs, zcu)) return false;
92 if (!checkRef(data.bin_op.rhs, zcu)) return false;
93 },
94
95 .not,
96 .bitcast,
97 .clz,
98 .ctz,
99 .popcount,
100 .byte_swap,
101 .bit_reverse,
102 .abs,
103 .load,
104 .fptrunc,
105 .fpext,
106 .intcast,
107 .trunc,
108 .optional_payload,
109 .optional_payload_ptr,
110 .optional_payload_ptr_set,
111 .wrap_optional,
112 .unwrap_errunion_payload,
113 .unwrap_errunion_err,
114 .unwrap_errunion_payload_ptr,
115 .unwrap_errunion_err_ptr,
116 .errunion_payload_ptr_set,
117 .wrap_errunion_payload,
118 .wrap_errunion_err,
119 .struct_field_ptr_index_0,
120 .struct_field_ptr_index_1,
121 .struct_field_ptr_index_2,
122 .struct_field_ptr_index_3,
123 .get_union_tag,
124 .slice_len,
125 .slice_ptr,
126 .ptr_slice_len_ptr,
127 .ptr_slice_ptr_ptr,
128 .array_to_slice,
129 .int_from_float,
130 .int_from_float_optimized,
131 .float_from_int,
132 .splat,
133 .error_set_has_value,
134 .addrspace_cast,
135 .c_va_arg,
136 .c_va_copy,
137 => {
138 if (!checkType(data.ty_op.ty.toType(), zcu)) return false;
139 if (!checkRef(data.ty_op.operand, zcu)) return false;
140 },
141
142 .alloc,
143 .ret_ptr,
144 .c_va_start,
145 => {
146 if (!checkType(data.ty, zcu)) return false;
147 },
148
149 .ptr_add,
150 .ptr_sub,
151 .add_with_overflow,
152 .sub_with_overflow,
153 .mul_with_overflow,
154 .shl_with_overflow,
155 .slice,
156 .slice_elem_ptr,
157 .ptr_elem_ptr,
158 => {
159 const bin = air.extraData(Air.Bin, data.ty_pl.payload).data;
160 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
161 if (!checkRef(bin.lhs, zcu)) return false;
162 if (!checkRef(bin.rhs, zcu)) return false;
163 },
164
165 .block,
166 .loop,
167 => {
168 const extra = air.extraData(Air.Block, data.ty_pl.payload);
169 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
170 if (!checkBody(
171 air,
172 @ptrCast(air.extra[extra.end..][0..extra.data.body_len]),
173 zcu,
174 )) return false;
175 },
176
177 .dbg_inline_block => {
178 const extra = air.extraData(Air.DbgInlineBlock, data.ty_pl.payload);
179 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
180 if (!checkBody(
181 air,
182 @ptrCast(air.extra[extra.end..][0..extra.data.body_len]),
183 zcu,
184 )) return false;
185 },
186
187 .sqrt,
188 .sin,
189 .cos,
190 .tan,
191 .exp,
192 .exp2,
193 .log,
194 .log2,
195 .log10,
196 .floor,
197 .ceil,
198 .round,
199 .trunc_float,
200 .neg,
201 .neg_optimized,
202 .is_null,
203 .is_non_null,
204 .is_null_ptr,
205 .is_non_null_ptr,
206 .is_err,
207 .is_non_err,
208 .is_err_ptr,
209 .is_non_err_ptr,
210 .int_from_ptr,
211 .int_from_bool,
212 .ret,
213 .ret_safe,
214 .ret_load,
215 .is_named_enum_value,
216 .tag_name,
217 .error_name,
218 .cmp_lt_errors_len,
219 .c_va_end,
220 .set_err_return_trace,
221 => {
222 if (!checkRef(data.un_op, zcu)) return false;
223 },
224
225 .br => {
226 if (!checkRef(data.br.operand, zcu)) return false;
227 },
228
229 .cmp_vector,
230 .cmp_vector_optimized,
231 => {
232 const extra = air.extraData(Air.VectorCmp, data.ty_pl.payload).data;
233 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
234 if (!checkRef(extra.lhs, zcu)) return false;
235 if (!checkRef(extra.rhs, zcu)) return false;
236 },
237
238 .reduce,
239 .reduce_optimized,
240 => {
241 if (!checkRef(data.reduce.operand, zcu)) return false;
242 },
243
244 .struct_field_ptr,
245 .struct_field_val,
246 => {
247 const extra = air.extraData(Air.StructField, data.ty_pl.payload).data;
248 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
249 if (!checkRef(extra.struct_operand, zcu)) return false;
250 },
251
252 .shuffle => {
253 const extra = air.extraData(Air.Shuffle, data.ty_pl.payload).data;
254 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
255 if (!checkRef(extra.a, zcu)) return false;
256 if (!checkRef(extra.b, zcu)) return false;
257 if (!checkVal(Value.fromInterned(extra.mask), zcu)) return false;
258 },
259
260 .cmpxchg_weak,
261 .cmpxchg_strong,
262 => {
263 const extra = air.extraData(Air.Cmpxchg, data.ty_pl.payload).data;
264 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
265 if (!checkRef(extra.ptr, zcu)) return false;
266 if (!checkRef(extra.expected_value, zcu)) return false;
267 if (!checkRef(extra.new_value, zcu)) return false;
268 },
269
270 .aggregate_init => {
271 const ty = data.ty_pl.ty.toType();
272 const elems_len: usize = @intCast(ty.arrayLen(zcu));
273 const elems: []const Air.Inst.Ref = @ptrCast(air.extra[data.ty_pl.payload..][0..elems_len]);
274 if (!checkType(ty, zcu)) return false;
275 if (ty.zigTypeTag(zcu) == .Struct) {
276 for (elems, 0..) |elem, elem_idx| {
277 if (ty.structFieldIsComptime(elem_idx, zcu)) continue;
278 if (!checkRef(elem, zcu)) return false;
279 }
280 } else {
281 for (elems) |elem| {
282 if (!checkRef(elem, zcu)) return false;
283 }
284 }
285 },
286
287 .union_init => {
288 const extra = air.extraData(Air.UnionInit, data.ty_pl.payload).data;
289 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
290 if (!checkRef(extra.init, zcu)) return false;
291 },
292
293 .field_parent_ptr => {
294 const extra = air.extraData(Air.FieldParentPtr, data.ty_pl.payload).data;
295 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
296 if (!checkRef(extra.field_ptr, zcu)) return false;
297 },
298
299 .atomic_load => {
300 if (!checkRef(data.atomic_load.ptr, zcu)) return false;
301 },
302
303 .prefetch => {
304 if (!checkRef(data.prefetch.ptr, zcu)) return false;
305 },
306
307 .vector_store_elem => {
308 const bin = air.extraData(Air.Bin, data.vector_store_elem.payload).data;
309 if (!checkRef(data.vector_store_elem.vector_ptr, zcu)) return false;
310 if (!checkRef(bin.lhs, zcu)) return false;
311 if (!checkRef(bin.rhs, zcu)) return false;
312 },
313
314 .select,
315 .mul_add,
316 => {
317 const bin = air.extraData(Air.Bin, data.pl_op.payload).data;
318 if (!checkRef(data.pl_op.operand, zcu)) return false;
319 if (!checkRef(bin.lhs, zcu)) return false;
320 if (!checkRef(bin.rhs, zcu)) return false;
321 },
322
323 .atomic_rmw => {
324 const extra = air.extraData(Air.AtomicRmw, data.pl_op.payload).data;
325 if (!checkRef(data.pl_op.operand, zcu)) return false;
326 if (!checkRef(extra.operand, zcu)) return false;
327 },
328
329 .call,
330 .call_always_tail,
331 .call_never_tail,
332 .call_never_inline,
333 => {
334 const extra = air.extraData(Air.Call, data.pl_op.payload);
335 const args: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.args_len]);
336 if (!checkRef(data.pl_op.operand, zcu)) return false;
337 for (args) |arg| if (!checkRef(arg, zcu)) return false;
338 },
339
340 .dbg_var_ptr,
341 .dbg_var_val,
342 => {
343 if (!checkRef(data.pl_op.operand, zcu)) return false;
344 },
345
346 .@"try" => {
347 const extra = air.extraData(Air.Try, data.pl_op.payload);
348 if (!checkRef(data.pl_op.operand, zcu)) return false;
349 if (!checkBody(
350 air,
351 @ptrCast(air.extra[extra.end..][0..extra.data.body_len]),
352 zcu,
353 )) return false;
354 },
355
356 .try_ptr => {
357 const extra = air.extraData(Air.TryPtr, data.ty_pl.payload);
358 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
359 if (!checkRef(extra.data.ptr, zcu)) return false;
360 if (!checkBody(
361 air,
362 @ptrCast(air.extra[extra.end..][0..extra.data.body_len]),
363 zcu,
364 )) return false;
365 },
366
367 .cond_br => {
368 const extra = air.extraData(Air.CondBr, data.pl_op.payload);
369 if (!checkRef(data.pl_op.operand, zcu)) return false;
370 if (!checkBody(
371 air,
372 @ptrCast(air.extra[extra.end..][0..extra.data.then_body_len]),
373 zcu,
374 )) return false;
375 if (!checkBody(
376 air,
377 @ptrCast(air.extra[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len]),
378 zcu,
379 )) return false;
380 },
381
382 .switch_br => {
383 const extra = air.extraData(Air.SwitchBr, data.pl_op.payload);
384 if (!checkRef(data.pl_op.operand, zcu)) return false;
385 var extra_index = extra.end;
386 for (0..extra.data.cases_len) |_| {
387 const case = air.extraData(Air.SwitchBr.Case, extra_index);
388 extra_index = case.end;
389 const items: []const Air.Inst.Ref = @ptrCast(air.extra[extra_index..][0..case.data.items_len]);
390 extra_index += case.data.items_len;
391 for (items) |item| if (!checkRef(item, zcu)) return false;
392 if (!checkBody(
393 air,
394 @ptrCast(air.extra[extra_index..][0..case.data.body_len]),
395 zcu,
396 )) return false;
397 extra_index += case.data.body_len;
398 }
399 if (!checkBody(
400 air,
401 @ptrCast(air.extra[extra_index..][0..extra.data.else_body_len]),
402 zcu,
403 )) return false;
404 },
405
406 .assembly => {
407 const extra = air.extraData(Air.Asm, data.ty_pl.payload);
408 if (!checkType(data.ty_pl.ty.toType(), zcu)) return false;
409 // Luckily, we only care about the inputs and outputs, so we don't have to do
410 // the whole null-terminated string dance.
411 const outputs: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end..][0..extra.data.outputs_len]);
412 const inputs: []const Air.Inst.Ref = @ptrCast(air.extra[extra.end + extra.data.outputs_len ..][0..extra.data.inputs_len]);
413 for (outputs) |output| if (output != .none and !checkRef(output, zcu)) return false;
414 for (inputs) |input| if (input != .none and !checkRef(input, zcu)) return false;
415 },
416
417 .trap,
418 .breakpoint,
419 .ret_addr,
420 .frame_addr,
421 .unreach,
422 .wasm_memory_size,
423 .wasm_memory_grow,
424 .work_item_id,
425 .work_group_size,
426 .work_group_id,
427 .fence,
428 .dbg_stmt,
429 .err_return_trace,
430 .save_err_return_trace_index,
431 => {},
432 }
433 }
434 return true;
435}
436
437fn checkRef(ref: Air.Inst.Ref, zcu: *Zcu) bool {
438 const ip_index = ref.toInterned() orelse {
439 // This operand refers back to a previous instruction.
440 // We have already checked that instruction's type.
441 // So, there's no need to check this operand's type.
442 return true;
443 };
444 return checkVal(Value.fromInterned(ip_index), zcu);
445}
446
447fn checkVal(val: Value, zcu: *Zcu) bool {
448 if (!checkType(val.typeOf(zcu), zcu)) return false;
449 // Check for lazy values
450 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
451 .int => |int| switch (int.storage) {
452 .u64, .i64, .big_int => return true,
453 .lazy_align, .lazy_size => |ty_index| {
454 return checkType(Type.fromInterned(ty_index), zcu);
455 },
456 },
457 else => return true,
458 }
459}
460
461fn checkType(ty: Type, zcu: *Zcu) bool {
462 const ip = &zcu.intern_pool;
463 return switch (ty.zigTypeTag(zcu)) {
464 .Type,
465 .Void,
466 .Bool,
467 .NoReturn,
468 .Int,
469 .Float,
470 .ErrorSet,
471 .Enum,
472 .Opaque,
473 .Vector,
474 // These types can appear due to some dummy instructions Sema introduces and expects to be omitted by Liveness.
475 // It's a little silly -- but fine, we'll return `true`.
476 .ComptimeFloat,
477 .ComptimeInt,
478 .Undefined,
479 .Null,
480 .EnumLiteral,
481 => true,
482
483 .Frame,
484 .AnyFrame,
485 => @panic("TODO Air.types_resolved.checkType async frames"),
486
487 .Optional => checkType(ty.childType(zcu), zcu),
488 .ErrorUnion => checkType(ty.errorUnionPayload(zcu), zcu),
489 .Pointer => checkType(ty.childType(zcu), zcu),
490 .Array => checkType(ty.childType(zcu), zcu),
491
492 .Fn => {
493 const info = zcu.typeToFunc(ty).?;
494 for (0..info.param_types.len) |i| {
495 const param_ty = info.param_types.get(ip)[i];
496 if (!checkType(Type.fromInterned(param_ty), zcu)) return false;
497 }
498 return checkType(Type.fromInterned(info.return_type), zcu);
499 },
500 .Struct => switch (ip.indexToKey(ty.toIntern())) {
501 .struct_type => {
502 const struct_obj = zcu.typeToStruct(ty).?;
503 return switch (struct_obj.layout) {
504 .@"packed" => struct_obj.backingIntType(ip).* != .none,
505 .auto, .@"extern" => struct_obj.flagsPtr(ip).fully_resolved,
506 };
507 },
508 .anon_struct_type => |tuple| {
509 for (0..tuple.types.len) |i| {
510 const field_is_comptime = tuple.values.get(ip)[i] != .none;
511 if (field_is_comptime) continue;
512 const field_ty = tuple.types.get(ip)[i];
513 if (!checkType(Type.fromInterned(field_ty), zcu)) return false;
514 }
515 return true;
516 },
517 else => unreachable,
518 },
519 .Union => return zcu.typeToUnion(ty).?.flagsPtr(ip).status == .fully_resolved,
520 };
521}
src/Compilation.zig+207-137
...@@ -12,7 +12,7 @@ const WaitGroup = std.Thread.WaitGroup;...@@ -12,7 +12,7 @@ const WaitGroup = std.Thread.WaitGroup;
12const ErrorBundle = std.zig.ErrorBundle;12const ErrorBundle = std.zig.ErrorBundle;
1313
14const Value = @import("Value.zig");14const Value = @import("Value.zig");
15const Type = @import("type.zig").Type;15const Type = @import("Type.zig");
16const target_util = @import("target.zig");16const target_util = @import("target.zig");
17const Package = @import("Package.zig");17const Package = @import("Package.zig");
18const link = @import("link.zig");18const link = @import("link.zig");
...@@ -31,11 +31,13 @@ const clangMain = @import("main.zig").clangMain;...@@ -31,11 +31,13 @@ const clangMain = @import("main.zig").clangMain;
31const Zcu = @import("Zcu.zig");31const Zcu = @import("Zcu.zig");
32/// Deprecated; use `Zcu`.32/// Deprecated; use `Zcu`.
33const Module = Zcu;33const Module = Zcu;
34const Sema = @import("Sema.zig");
34const InternPool = @import("InternPool.zig");35const InternPool = @import("InternPool.zig");
35const Cache = std.Build.Cache;36const Cache = std.Build.Cache;
36const c_codegen = @import("codegen/c.zig");37const c_codegen = @import("codegen/c.zig");
37const libtsan = @import("libtsan.zig");38const libtsan = @import("libtsan.zig");
38const Zir = std.zig.Zir;39const Zir = std.zig.Zir;
40const Air = @import("Air.zig");
39const Builtin = @import("Builtin.zig");41const Builtin = @import("Builtin.zig");
40const LlvmObject = @import("codegen/llvm.zig").Object;42const LlvmObject = @import("codegen/llvm.zig").Object;
4143
...@@ -315,18 +317,29 @@ const Job = union(enum) {...@@ -315,18 +317,29 @@ const Job = union(enum) {
315 codegen_decl: InternPool.DeclIndex,317 codegen_decl: InternPool.DeclIndex,
316 /// Write the machine code for a function to the output file.318 /// Write the machine code for a function to the output file.
317 /// This will either be a non-generic `func_decl` or a `func_instance`.319 /// This will either be a non-generic `func_decl` or a `func_instance`.
318 codegen_func: InternPool.Index,320 codegen_func: struct {
321 func: InternPool.Index,
322 /// This `Air` is owned by the `Job` and allocated with `gpa`.
323 /// It must be deinited when the job is processed.
324 air: Air,
325 },
319 /// Render the .h file snippet for the Decl.326 /// Render the .h file snippet for the Decl.
320 emit_h_decl: InternPool.DeclIndex,327 emit_h_decl: InternPool.DeclIndex,
321 /// The Decl needs to be analyzed and possibly export itself.328 /// The Decl needs to be analyzed and possibly export itself.
322 /// It may have already be analyzed, or it may have been determined329 /// It may have already be analyzed, or it may have been determined
323 /// to be outdated; in this case perform semantic analysis again.330 /// to be outdated; in this case perform semantic analysis again.
324 analyze_decl: InternPool.DeclIndex,331 analyze_decl: InternPool.DeclIndex,
332 /// Analyze the body of a runtime function.
333 /// After analysis, a `codegen_func` job will be queued.
334 /// These must be separate jobs to ensure any needed type resolution occurs *before* codegen.
335 analyze_func: InternPool.Index,
325 /// The source file containing the Decl has been updated, and so the336 /// The source file containing the Decl has been updated, and so the
326 /// Decl may need its line number information updated in the debug info.337 /// Decl may need its line number information updated in the debug info.
327 update_line_number: InternPool.DeclIndex,338 update_line_number: InternPool.DeclIndex,
328 /// The main source file for the module needs to be analyzed.339 /// The main source file for the module needs to be analyzed.
329 analyze_mod: *Package.Module,340 analyze_mod: *Package.Module,
341 /// Fully resolve the given `struct` or `union` type.
342 resolve_type_fully: InternPool.Index,
330343
331 /// one of the glibc static objects344 /// one of the glibc static objects
332 glibc_crt_file: glibc.CRTFile,345 glibc_crt_file: glibc.CRTFile,
...@@ -2628,22 +2641,24 @@ fn reportMultiModuleErrors(mod: *Module) !void {...@@ -2628,22 +2641,24 @@ fn reportMultiModuleErrors(mod: *Module) !void {
2628 for (notes[0..num_notes], file.references.items[0..num_notes], 0..) |*note, ref, i| {2641 for (notes[0..num_notes], file.references.items[0..num_notes], 0..) |*note, ref, i| {
2629 errdefer for (notes[0..i]) |*n| n.deinit(mod.gpa);2642 errdefer for (notes[0..i]) |*n| n.deinit(mod.gpa);
2630 note.* = switch (ref) {2643 note.* = switch (ref) {
2631 .import => |loc| blk: {2644 .import => |import| try Module.ErrorMsg.init(
2632 break :blk try Module.ErrorMsg.init(2645 mod.gpa,
2633 mod.gpa,2646 .{
2634 loc,2647 .base_node_inst = try mod.intern_pool.trackZir(mod.gpa, import.file, .main_struct_inst),
2635 "imported from module {s}",2648 .offset = .{ .token_abs = import.token },
2636 .{loc.file_scope.mod.fully_qualified_name},2649 },
2637 );2650 "imported from module {s}",
2638 },2651 .{import.file.mod.fully_qualified_name},
2639 .root => |pkg| blk: {2652 ),
2640 break :blk try Module.ErrorMsg.init(2653 .root => |pkg| try Module.ErrorMsg.init(
2641 mod.gpa,2654 mod.gpa,
2642 .{ .file_scope = file, .base_node = 0, .lazy = .entire_file },2655 .{
2643 "root of module {s}",2656 .base_node_inst = try mod.intern_pool.trackZir(mod.gpa, file, .main_struct_inst),
2644 .{pkg.fully_qualified_name},2657 .offset = .entire_file,
2645 );2658 },
2646 },2659 "root of module {s}",
2660 .{pkg.fully_qualified_name},
2661 ),
2647 };2662 };
2648 }2663 }
2649 errdefer for (notes[0..num_notes]) |*n| n.deinit(mod.gpa);2664 errdefer for (notes[0..num_notes]) |*n| n.deinit(mod.gpa);
...@@ -2651,7 +2666,10 @@ fn reportMultiModuleErrors(mod: *Module) !void {...@@ -2651,7 +2666,10 @@ fn reportMultiModuleErrors(mod: *Module) !void {
2651 if (omitted > 0) {2666 if (omitted > 0) {
2652 notes[num_notes] = try Module.ErrorMsg.init(2667 notes[num_notes] = try Module.ErrorMsg.init(
2653 mod.gpa,2668 mod.gpa,
2654 .{ .file_scope = file, .base_node = 0, .lazy = .entire_file },2669 .{
2670 .base_node_inst = try mod.intern_pool.trackZir(mod.gpa, file, .main_struct_inst),
2671 .offset = .entire_file,
2672 },
2655 "{} more references omitted",2673 "{} more references omitted",
2656 .{omitted},2674 .{omitted},
2657 );2675 );
...@@ -2660,7 +2678,10 @@ fn reportMultiModuleErrors(mod: *Module) !void {...@@ -2660,7 +2678,10 @@ fn reportMultiModuleErrors(mod: *Module) !void {
26602678
2661 const err = try Module.ErrorMsg.create(2679 const err = try Module.ErrorMsg.create(
2662 mod.gpa,2680 mod.gpa,
2663 .{ .file_scope = file, .base_node = 0, .lazy = .entire_file },2681 .{
2682 .base_node_inst = try mod.intern_pool.trackZir(mod.gpa, file, .main_struct_inst),
2683 .offset = .entire_file,
2684 },
2664 "file exists in multiple modules",2685 "file exists in multiple modules",
2665 .{},2686 .{},
2666 );2687 );
...@@ -2831,11 +2852,11 @@ pub fn totalErrorCount(comp: *Compilation) u32 {...@@ -2831,11 +2852,11 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
2831 }2852 }
2832 }2853 }
28332854
2834 if (comp.module) |module| {2855 if (comp.module) |zcu| {
2835 total += module.failed_exports.count();2856 total += zcu.failed_exports.count();
2836 total += module.failed_embed_files.count();2857 total += zcu.failed_embed_files.count();
28372858
2838 for (module.failed_files.keys(), module.failed_files.values()) |file, error_msg| {2859 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
2839 if (error_msg) |_| {2860 if (error_msg) |_| {
2840 total += 1;2861 total += 1;
2841 } else {2862 } else {
...@@ -2851,23 +2872,27 @@ pub fn totalErrorCount(comp: *Compilation) u32 {...@@ -2851,23 +2872,27 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
2851 // When a parse error is introduced, we keep all the semantic analysis for2872 // When a parse error is introduced, we keep all the semantic analysis for
2852 // the previous parse success, including compile errors, but we cannot2873 // the previous parse success, including compile errors, but we cannot
2853 // emit them until the file succeeds parsing.2874 // emit them until the file succeeds parsing.
2854 for (module.failed_decls.keys()) |key| {2875 for (zcu.failed_analysis.keys()) |key| {
2855 if (module.declFileScope(key).okToReportErrors()) {2876 const decl_index = switch (key.unwrap()) {
2877 .decl => |d| d,
2878 .func => |ip_index| zcu.funcInfo(ip_index).owner_decl,
2879 };
2880 if (zcu.declFileScope(decl_index).okToReportErrors()) {
2856 total += 1;2881 total += 1;
2857 if (module.cimport_errors.get(key)) |errors| {2882 if (zcu.cimport_errors.get(key)) |errors| {
2858 total += errors.errorMessageCount();2883 total += errors.errorMessageCount();
2859 }2884 }
2860 }2885 }
2861 }2886 }
2862 if (module.emit_h) |emit_h| {2887 if (zcu.emit_h) |emit_h| {
2863 for (emit_h.failed_decls.keys()) |key| {2888 for (emit_h.failed_decls.keys()) |key| {
2864 if (module.declFileScope(key).okToReportErrors()) {2889 if (zcu.declFileScope(key).okToReportErrors()) {
2865 total += 1;2890 total += 1;
2866 }2891 }
2867 }2892 }
2868 }2893 }
28692894
2870 if (module.global_error_set.entries.len - 1 > module.error_limit) {2895 if (zcu.global_error_set.entries.len - 1 > zcu.error_limit) {
2871 total += 1;2896 total += 1;
2872 }2897 }
2873 }2898 }
...@@ -2882,8 +2907,8 @@ pub fn totalErrorCount(comp: *Compilation) u32 {...@@ -2882,8 +2907,8 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
28822907
2883 // Compile log errors only count if there are no other errors.2908 // Compile log errors only count if there are no other errors.
2884 if (total == 0) {2909 if (total == 0) {
2885 if (comp.module) |module| {2910 if (comp.module) |zcu| {
2886 total += @intFromBool(module.compile_log_decls.count() != 0);2911 total += @intFromBool(zcu.compile_log_sources.count() != 0);
2887 }2912 }
2888 }2913 }
28892914
...@@ -2934,10 +2959,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -2934,10 +2959,13 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
2934 .msg = try bundle.addString("memory allocation failure"),2959 .msg = try bundle.addString("memory allocation failure"),
2935 });2960 });
2936 }2961 }
2937 if (comp.module) |module| {2962 if (comp.module) |zcu| {
2938 for (module.failed_files.keys(), module.failed_files.values()) |file, error_msg| {2963 var all_references = try zcu.resolveReferences();
2964 defer all_references.deinit(gpa);
2965
2966 for (zcu.failed_files.keys(), zcu.failed_files.values()) |file, error_msg| {
2939 if (error_msg) |msg| {2967 if (error_msg) |msg| {
2940 try addModuleErrorMsg(module, &bundle, msg.*);2968 try addModuleErrorMsg(zcu, &bundle, msg.*, &all_references);
2941 } else {2969 } else {
2942 // Must be ZIR errors. Note that this may include AST errors.2970 // Must be ZIR errors. Note that this may include AST errors.
2943 // addZirErrorMessages asserts that the tree is loaded.2971 // addZirErrorMessages asserts that the tree is loaded.
...@@ -2945,54 +2973,59 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -2945,54 +2973,59 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
2945 try addZirErrorMessages(&bundle, file);2973 try addZirErrorMessages(&bundle, file);
2946 }2974 }
2947 }2975 }
2948 for (module.failed_embed_files.values()) |error_msg| {2976 for (zcu.failed_embed_files.values()) |error_msg| {
2949 try addModuleErrorMsg(module, &bundle, error_msg.*);2977 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
2950 }2978 }
2951 for (module.failed_decls.keys(), module.failed_decls.values()) |decl_index, error_msg| {2979 for (zcu.failed_analysis.keys(), zcu.failed_analysis.values()) |anal_unit, error_msg| {
2980 const decl_index = switch (anal_unit.unwrap()) {
2981 .decl => |d| d,
2982 .func => |ip_index| zcu.funcInfo(ip_index).owner_decl,
2983 };
2984
2952 // Skip errors for Decls within files that had a parse failure.2985 // Skip errors for Decls within files that had a parse failure.
2953 // We'll try again once parsing succeeds.2986 // We'll try again once parsing succeeds.
2954 if (module.declFileScope(decl_index).okToReportErrors()) {2987 if (!zcu.declFileScope(decl_index).okToReportErrors()) continue;
2955 try addModuleErrorMsg(module, &bundle, error_msg.*);2988
2956 if (module.cimport_errors.get(decl_index)) |errors| {2989 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
2957 for (errors.getMessages()) |err_msg_index| {2990 if (zcu.cimport_errors.get(anal_unit)) |errors| {
2958 const err_msg = errors.getErrorMessage(err_msg_index);2991 for (errors.getMessages()) |err_msg_index| {
2959 try bundle.addRootErrorMessage(.{2992 const err_msg = errors.getErrorMessage(err_msg_index);
2960 .msg = try bundle.addString(errors.nullTerminatedString(err_msg.msg)),2993 try bundle.addRootErrorMessage(.{
2961 .src_loc = if (err_msg.src_loc != .none) blk: {2994 .msg = try bundle.addString(errors.nullTerminatedString(err_msg.msg)),
2962 const src_loc = errors.getSourceLocation(err_msg.src_loc);2995 .src_loc = if (err_msg.src_loc != .none) blk: {
2963 break :blk try bundle.addSourceLocation(.{2996 const src_loc = errors.getSourceLocation(err_msg.src_loc);
2964 .src_path = try bundle.addString(errors.nullTerminatedString(src_loc.src_path)),2997 break :blk try bundle.addSourceLocation(.{
2965 .span_start = src_loc.span_start,2998 .src_path = try bundle.addString(errors.nullTerminatedString(src_loc.src_path)),
2966 .span_main = src_loc.span_main,2999 .span_start = src_loc.span_start,
2967 .span_end = src_loc.span_end,3000 .span_main = src_loc.span_main,
2968 .line = src_loc.line,3001 .span_end = src_loc.span_end,
2969 .column = src_loc.column,3002 .line = src_loc.line,
2970 .source_line = if (src_loc.source_line != 0) try bundle.addString(errors.nullTerminatedString(src_loc.source_line)) else 0,3003 .column = src_loc.column,
2971 });3004 .source_line = if (src_loc.source_line != 0) try bundle.addString(errors.nullTerminatedString(src_loc.source_line)) else 0,
2972 } else .none,3005 });
2973 });3006 } else .none,
2974 }3007 });
2975 }3008 }
2976 }3009 }
2977 }3010 }
2978 if (module.emit_h) |emit_h| {3011 if (zcu.emit_h) |emit_h| {
2979 for (emit_h.failed_decls.keys(), emit_h.failed_decls.values()) |decl_index, error_msg| {3012 for (emit_h.failed_decls.keys(), emit_h.failed_decls.values()) |decl_index, error_msg| {
2980 // Skip errors for Decls within files that had a parse failure.3013 // Skip errors for Decls within files that had a parse failure.
2981 // We'll try again once parsing succeeds.3014 // We'll try again once parsing succeeds.
2982 if (module.declFileScope(decl_index).okToReportErrors()) {3015 if (zcu.declFileScope(decl_index).okToReportErrors()) {
2983 try addModuleErrorMsg(module, &bundle, error_msg.*);3016 try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
2984 }3017 }
2985 }3018 }
2986 }3019 }
2987 for (module.failed_exports.values()) |value| {3020 for (zcu.failed_exports.values()) |value| {
2988 try addModuleErrorMsg(module, &bundle, value.*);3021 try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
2989 }3022 }
29903023
2991 const actual_error_count = module.global_error_set.entries.len - 1;3024 const actual_error_count = zcu.global_error_set.entries.len - 1;
2992 if (actual_error_count > module.error_limit) {3025 if (actual_error_count > zcu.error_limit) {
2993 try bundle.addRootErrorMessage(.{3026 try bundle.addRootErrorMessage(.{
2994 .msg = try bundle.printString("module used more errors than possible: used {d}, max {d}", .{3027 .msg = try bundle.printString("ZCU used more errors than possible: used {d}, max {d}", .{
2995 actual_error_count, module.error_limit,3028 actual_error_count, zcu.error_limit,
2996 }),3029 }),
2997 .notes_len = 1,3030 .notes_len = 1,
2998 });3031 });
...@@ -3041,25 +3074,28 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3041,25 +3074,28 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3041 }3074 }
30423075
3043 if (comp.module) |zcu| {3076 if (comp.module) |zcu| {
3044 if (bundle.root_list.items.len == 0 and zcu.compile_log_decls.count() != 0) {3077 if (bundle.root_list.items.len == 0 and zcu.compile_log_sources.count() != 0) {
3045 const values = zcu.compile_log_decls.values();3078 var all_references = try zcu.resolveReferences();
3079 defer all_references.deinit(gpa);
3080
3081 const values = zcu.compile_log_sources.values();
3046 // First one will be the error; subsequent ones will be notes.3082 // First one will be the error; subsequent ones will be notes.
3047 const src_loc = values[0].src().upgrade(zcu);3083 const src_loc = values[0].src();
3048 const err_msg: Module.ErrorMsg = .{3084 const err_msg: Module.ErrorMsg = .{
3049 .src_loc = src_loc,3085 .src_loc = src_loc,
3050 .msg = "found compile log statement",3086 .msg = "found compile log statement",
3051 .notes = try gpa.alloc(Module.ErrorMsg, zcu.compile_log_decls.count() - 1),3087 .notes = try gpa.alloc(Module.ErrorMsg, zcu.compile_log_sources.count() - 1),
3052 };3088 };
3053 defer gpa.free(err_msg.notes);3089 defer gpa.free(err_msg.notes);
30543090
3055 for (values[1..], err_msg.notes) |src_info, *note| {3091 for (values[1..], err_msg.notes) |src_info, *note| {
3056 note.* = .{3092 note.* = .{
3057 .src_loc = src_info.src().upgrade(zcu),3093 .src_loc = src_info.src(),
3058 .msg = "also here",3094 .msg = "also here",
3059 };3095 };
3060 }3096 }
30613097
3062 try addModuleErrorMsg(zcu, &bundle, err_msg);3098 try addModuleErrorMsg(zcu, &bundle, err_msg, &all_references);
3063 }3099 }
3064 }3100 }
30653101
...@@ -3115,11 +3151,17 @@ pub const ErrorNoteHashContext = struct {...@@ -3115,11 +3151,17 @@ pub const ErrorNoteHashContext = struct {
3115 }3151 }
3116};3152};
31173153
3118pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void {3154pub fn addModuleErrorMsg(
3155 mod: *Module,
3156 eb: *ErrorBundle.Wip,
3157 module_err_msg: Module.ErrorMsg,
3158 all_references: *const std.AutoHashMapUnmanaged(InternPool.AnalUnit, Zcu.ResolvedReference),
3159) !void {
3119 const gpa = eb.gpa;3160 const gpa = eb.gpa;
3120 const ip = &mod.intern_pool;3161 const ip = &mod.intern_pool;
3121 const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| {3162 const err_src_loc = module_err_msg.src_loc.upgrade(mod);
3122 const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa);3163 const err_source = err_src_loc.file_scope.getSource(gpa) catch |err| {
3164 const file_path = try err_src_loc.file_scope.fullPath(gpa);
3123 defer gpa.free(file_path);3165 defer gpa.free(file_path);
3124 try eb.addRootErrorMessage(.{3166 try eb.addRootErrorMessage(.{
3125 .msg = try eb.printString("unable to load '{s}': {s}", .{3167 .msg = try eb.printString("unable to load '{s}': {s}", .{
...@@ -3128,47 +3170,57 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod...@@ -3128,47 +3170,57 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod
3128 });3170 });
3129 return;3171 return;
3130 };3172 };
3131 const err_span = try module_err_msg.src_loc.span(gpa);3173 const err_span = try err_src_loc.span(gpa);
3132 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main);3174 const err_loc = std.zig.findLineColumn(err_source.bytes, err_span.main);
3133 const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa);3175 const file_path = try err_src_loc.file_scope.fullPath(gpa);
3134 defer gpa.free(file_path);3176 defer gpa.free(file_path);
31353177
3136 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .{};3178 var ref_traces: std.ArrayListUnmanaged(ErrorBundle.ReferenceTrace) = .{};
3137 defer ref_traces.deinit(gpa);3179 defer ref_traces.deinit(gpa);
31383180
3139 const remaining_references: ?u32 = remaining: {3181 if (module_err_msg.reference_trace_root.unwrap()) |rt_root| {
3140 if (mod.comp.reference_trace) |_| {3182 var seen: std.AutoHashMapUnmanaged(InternPool.AnalUnit, void) = .{};
3141 if (module_err_msg.hidden_references > 0) break :remaining module_err_msg.hidden_references;3183 defer seen.deinit(gpa);
3142 } else {3184
3143 if (module_err_msg.reference_trace.len > 0) break :remaining 0;3185 const max_references = mod.comp.reference_trace orelse Sema.default_reference_trace_len;
3186
3187 var referenced_by = rt_root;
3188 while (all_references.get(referenced_by)) |ref| {
3189 const gop = try seen.getOrPut(gpa, ref.referencer);
3190 if (gop.found_existing) break;
3191 if (ref_traces.items.len < max_references) {
3192 const src = ref.src.upgrade(mod);
3193 const source = try src.file_scope.getSource(gpa);
3194 const span = try src.span(gpa);
3195 const loc = std.zig.findLineColumn(source.bytes, span.main);
3196 const rt_file_path = try src.file_scope.fullPath(gpa);
3197 const name = switch (ref.referencer.unwrap()) {
3198 .decl => |d| mod.declPtr(d).name,
3199 .func => |f| mod.funcOwnerDeclPtr(f).name,
3200 };
3201 try ref_traces.append(gpa, .{
3202 .decl_name = try eb.addString(name.toSlice(ip)),
3203 .src_loc = try eb.addSourceLocation(.{
3204 .src_path = try eb.addString(rt_file_path),
3205 .span_start = span.start,
3206 .span_main = span.main,
3207 .span_end = span.end,
3208 .line = @intCast(loc.line),
3209 .column = @intCast(loc.column),
3210 .source_line = 0,
3211 }),
3212 });
3213 }
3214 referenced_by = ref.referencer;
3144 }3215 }
3145 break :remaining null;
3146 };
3147 try ref_traces.ensureTotalCapacityPrecise(gpa, module_err_msg.reference_trace.len +
3148 @intFromBool(remaining_references != null));
31493216
3150 for (module_err_msg.reference_trace) |module_reference| {3217 if (seen.count() > ref_traces.items.len) {
3151 const source = try module_reference.src_loc.file_scope.getSource(gpa);3218 try ref_traces.append(gpa, .{
3152 const span = try module_reference.src_loc.span(gpa);3219 .decl_name = @intCast(seen.count() - ref_traces.items.len),
3153 const loc = std.zig.findLineColumn(source.bytes, span.main);3220 .src_loc = .none,
3154 const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa);3221 });
3155 defer gpa.free(rt_file_path);3222 }
3156 ref_traces.appendAssumeCapacity(.{
3157 .decl_name = try eb.addString(module_reference.decl.toSlice(ip)),
3158 .src_loc = try eb.addSourceLocation(.{
3159 .src_path = try eb.addString(rt_file_path),
3160 .span_start = span.start,
3161 .span_main = span.main,
3162 .span_end = span.end,
3163 .line = @intCast(loc.line),
3164 .column = @intCast(loc.column),
3165 .source_line = 0,
3166 }),
3167 });
3168 }3223 }
3169 if (remaining_references) |remaining| ref_traces.appendAssumeCapacity(
3170 .{ .decl_name = remaining, .src_loc = .none },
3171 );
31723224
3173 const src_loc = try eb.addSourceLocation(.{3225 const src_loc = try eb.addSourceLocation(.{
3174 .src_path = try eb.addString(file_path),3226 .src_path = try eb.addString(file_path),
...@@ -3177,7 +3229,7 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod...@@ -3177,7 +3229,7 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod
3177 .span_end = err_span.end,3229 .span_end = err_span.end,
3178 .line = @intCast(err_loc.line),3230 .line = @intCast(err_loc.line),
3179 .column = @intCast(err_loc.column),3231 .column = @intCast(err_loc.column),
3180 .source_line = if (module_err_msg.src_loc.lazy == .entire_file)3232 .source_line = if (err_src_loc.lazy == .entire_file)
3181 03233 0
3182 else3234 else
3183 try eb.addString(err_loc.source_line),3235 try eb.addString(err_loc.source_line),
...@@ -3194,10 +3246,11 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod...@@ -3194,10 +3246,11 @@ pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Mod
3194 defer notes.deinit(gpa);3246 defer notes.deinit(gpa);
31953247
3196 for (module_err_msg.notes) |module_note| {3248 for (module_err_msg.notes) |module_note| {
3197 const source = try module_note.src_loc.file_scope.getSource(gpa);3249 const note_src_loc = module_note.src_loc.upgrade(mod);
3198 const span = try module_note.src_loc.span(gpa);3250 const source = try note_src_loc.file_scope.getSource(gpa);
3251 const span = try note_src_loc.span(gpa);
3199 const loc = std.zig.findLineColumn(source.bytes, span.main);3252 const loc = std.zig.findLineColumn(source.bytes, span.main);
3200 const note_file_path = try module_note.src_loc.file_scope.fullPath(gpa);3253 const note_file_path = try note_src_loc.file_scope.fullPath(gpa);
3201 defer gpa.free(note_file_path);3254 defer gpa.free(note_file_path);
32023255
3203 const gop = try notes.getOrPutContext(gpa, .{3256 const gop = try notes.getOrPutContext(gpa, .{
...@@ -3348,7 +3401,7 @@ pub fn performAllTheWork(...@@ -3348,7 +3401,7 @@ pub fn performAllTheWork(
3348 if (try zcu.findOutdatedToAnalyze()) |outdated| {3401 if (try zcu.findOutdatedToAnalyze()) |outdated| {
3349 switch (outdated.unwrap()) {3402 switch (outdated.unwrap()) {
3350 .decl => |decl| try comp.work_queue.writeItem(.{ .analyze_decl = decl }),3403 .decl => |decl| try comp.work_queue.writeItem(.{ .analyze_decl = decl }),
3351 .func => |func| try comp.work_queue.writeItem(.{ .codegen_func = func }),3404 .func => |func| try comp.work_queue.writeItem(.{ .analyze_func = func }),
3352 }3405 }
3353 continue;3406 continue;
3354 }3407 }
...@@ -3398,6 +3451,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo...@@ -3398,6 +3451,14 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
3398 const named_frame = tracy.namedFrame("codegen_func");3451 const named_frame = tracy.namedFrame("codegen_func");
3399 defer named_frame.end();3452 defer named_frame.end();
34003453
3454 const module = comp.module.?;
3455 // This call takes ownership of `func.air`.
3456 try module.linkerUpdateFunc(func.func, func.air);
3457 },
3458 .analyze_func => |func| {
3459 const named_frame = tracy.namedFrame("analyze_func");
3460 defer named_frame.end();
3461
3401 const module = comp.module.?;3462 const module = comp.module.?;
3402 module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {3463 module.ensureFuncBodyAnalyzed(func) catch |err| switch (err) {
3403 error.OutOfMemory => return error.OutOfMemory,3464 error.OutOfMemory => return error.OutOfMemory,
...@@ -3405,6 +3466,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo...@@ -3405,6 +3466,9 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
3405 };3466 };
3406 },3467 },
3407 .emit_h_decl => |decl_index| {3468 .emit_h_decl => |decl_index| {
3469 if (true) @panic("regressed compiler feature: emit-h should hook into updateExports, " ++
3470 "not decl analysis, which is too early to know about @export calls");
3471
3408 const module = comp.module.?;3472 const module = comp.module.?;
3409 const decl = module.declPtr(decl_index);3473 const decl = module.declPtr(decl_index);
34103474
...@@ -3477,6 +3541,16 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo...@@ -3477,6 +3541,16 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
3477 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());3541 try module.ensureFuncBodyAnalysisQueued(decl.val.toIntern());
3478 }3542 }
3479 },3543 },
3544 .resolve_type_fully => |ty| {
3545 const named_frame = tracy.namedFrame("resolve_type_fully");
3546 defer named_frame.end();
3547
3548 const zcu = comp.module.?;
3549 Type.fromInterned(ty).resolveFully(zcu) catch |err| switch (err) {
3550 error.OutOfMemory => return error.OutOfMemory,
3551 error.AnalysisFail => return,
3552 };
3553 },
3480 .update_line_number => |decl_index| {3554 .update_line_number => |decl_index| {
3481 const named_frame = tracy.namedFrame("update_line_number");3555 const named_frame = tracy.namedFrame("update_line_number");
3482 defer named_frame.end();3556 defer named_frame.end();
...@@ -3486,15 +3560,18 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo...@@ -3486,15 +3560,18 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: std.Progress.Node) !vo
3486 const decl = module.declPtr(decl_index);3560 const decl = module.declPtr(decl_index);
3487 const lf = comp.bin_file.?;3561 const lf = comp.bin_file.?;
3488 lf.updateDeclLineNumber(module, decl_index) catch |err| {3562 lf.updateDeclLineNumber(module, decl_index) catch |err| {
3489 try module.failed_decls.ensureUnusedCapacity(gpa, 1);3563 try module.failed_analysis.ensureUnusedCapacity(gpa, 1);
3490 module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(3564 module.failed_analysis.putAssumeCapacityNoClobber(
3491 gpa,3565 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
3492 decl.navSrcLoc(module).upgrade(module),3566 try Module.ErrorMsg.create(
3493 "unable to update line number: {s}",3567 gpa,
3494 .{@errorName(err)},3568 decl.navSrcLoc(module),
3495 ));3569 "unable to update line number: {s}",
3570 .{@errorName(err)},
3571 ),
3572 );
3496 decl.analysis = .codegen_failure;3573 decl.analysis = .codegen_failure;
3497 try module.retryable_failures.append(gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));3574 try module.retryable_failures.append(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }));
3498 };3575 };
3499 },3576 },
3500 .analyze_mod => |pkg| {3577 .analyze_mod => |pkg| {
...@@ -3989,9 +4066,8 @@ fn workerAstGenFile(...@@ -3989,9 +4066,8 @@ fn workerAstGenFile(
3989 const res = mod.importFile(file, import_path) catch continue;4066 const res = mod.importFile(file, import_path) catch continue;
3990 if (!res.is_pkg) {4067 if (!res.is_pkg) {
3991 res.file.addReference(mod.*, .{ .import = .{4068 res.file.addReference(mod.*, .{ .import = .{
3992 .file_scope = file,4069 .file = file,
3993 .base_node = 0,4070 .token = item.data.token,
3994 .lazy = .{ .token_abs = item.data.token },
3995 } }) catch continue;4071 } }) catch continue;
3996 }4072 }
3997 break :blk res;4073 break :blk res;
...@@ -4364,20 +4440,14 @@ fn reportRetryableAstGenError(...@@ -4364,20 +4440,14 @@ fn reportRetryableAstGenError(
43644440
4365 file.status = .retryable_failure;4441 file.status = .retryable_failure;
43664442
4367 const src_loc: Module.SrcLoc = switch (src) {4443 const src_loc: Module.LazySrcLoc = switch (src) {
4368 .root => .{4444 .root => .{
4369 .file_scope = file,4445 .base_node_inst = try mod.intern_pool.trackZir(gpa, file, .main_struct_inst),
4370 .base_node = 0,4446 .offset = .entire_file,
4371 .lazy = .entire_file,
4372 },4447 },
4373 .import => |info| blk: {4448 .import => |info| .{
4374 const importing_file = info.importing_file;4449 .base_node_inst = try mod.intern_pool.trackZir(gpa, info.importing_file, .main_struct_inst),
43754450 .offset = .{ .token_abs = info.import_tok },
4376 break :blk .{
4377 .file_scope = importing_file,
4378 .base_node = 0,
4379 .lazy = .{ .token_abs = info.import_tok },
4380 };
4381 },4451 },
4382 };4452 };
43834453
src/InternPool.zig+11-11
...@@ -81,7 +81,7 @@ namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.In...@@ -81,7 +81,7 @@ namespace_name_deps: std.AutoArrayHashMapUnmanaged(NamespaceNameKey, DepEntry.In
81/// Given a `Depender`, points to an entry in `dep_entries` whose `depender`81/// Given a `Depender`, points to an entry in `dep_entries` whose `depender`
82/// matches. The `next_dependee` field can be used to iterate all such entries82/// matches. The `next_dependee` field can be used to iterate all such entries
83/// and remove them from the corresponding lists.83/// and remove them from the corresponding lists.
84first_dependency: std.AutoArrayHashMapUnmanaged(AnalSubject, DepEntry.Index) = .{},84first_dependency: std.AutoArrayHashMapUnmanaged(AnalUnit, DepEntry.Index) = .{},
8585
86/// Stores dependency information. The hashmaps declared above are used to look86/// Stores dependency information. The hashmaps declared above are used to look
87/// up entries in this list as required. This is not stored in `extra` so that87/// up entries in this list as required. This is not stored in `extra` so that
...@@ -132,36 +132,36 @@ pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.I...@@ -132,36 +132,36 @@ pub fn trackZir(ip: *InternPool, gpa: Allocator, file: *Module.File, inst: Zir.I
132 return @enumFromInt(gop.index);132 return @enumFromInt(gop.index);
133}133}
134134
135/// Analysis Subject. Represents a single entity which undergoes semantic analysis.135/// Analysis Unit. Represents a single entity which undergoes semantic analysis.
136/// This is either a `Decl` (in future `Cau`) or a runtime function.136/// This is either a `Decl` (in future `Cau`) or a runtime function.
137/// The LSB is used as a tag bit.137/// The LSB is used as a tag bit.
138/// This is the "source" of an incremental dependency edge.138/// This is the "source" of an incremental dependency edge.
139pub const AnalSubject = packed struct(u32) {139pub const AnalUnit = packed struct(u32) {
140 kind: enum(u1) { decl, func },140 kind: enum(u1) { decl, func },
141 index: u31,141 index: u31,
142 pub const Unwrapped = union(enum) {142 pub const Unwrapped = union(enum) {
143 decl: DeclIndex,143 decl: DeclIndex,
144 func: InternPool.Index,144 func: InternPool.Index,
145 };145 };
146 pub fn unwrap(as: AnalSubject) Unwrapped {146 pub fn unwrap(as: AnalUnit) Unwrapped {
147 return switch (as.kind) {147 return switch (as.kind) {
148 .decl => .{ .decl = @enumFromInt(as.index) },148 .decl => .{ .decl = @enumFromInt(as.index) },
149 .func => .{ .func = @enumFromInt(as.index) },149 .func => .{ .func = @enumFromInt(as.index) },
150 };150 };
151 }151 }
152 pub fn wrap(raw: Unwrapped) AnalSubject {152 pub fn wrap(raw: Unwrapped) AnalUnit {
153 return switch (raw) {153 return switch (raw) {
154 .decl => |decl| .{ .kind = .decl, .index = @intCast(@intFromEnum(decl)) },154 .decl => |decl| .{ .kind = .decl, .index = @intCast(@intFromEnum(decl)) },
155 .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) },155 .func => |func| .{ .kind = .func, .index = @intCast(@intFromEnum(func)) },
156 };156 };
157 }157 }
158 pub fn toOptional(as: AnalSubject) Optional {158 pub fn toOptional(as: AnalUnit) Optional {
159 return @enumFromInt(@as(u32, @bitCast(as)));159 return @enumFromInt(@as(u32, @bitCast(as)));
160 }160 }
161 pub const Optional = enum(u32) {161 pub const Optional = enum(u32) {
162 none = std.math.maxInt(u32),162 none = std.math.maxInt(u32),
163 _,163 _,
164 pub fn unwrap(opt: Optional) ?AnalSubject {164 pub fn unwrap(opt: Optional) ?AnalUnit {
165 return switch (opt) {165 return switch (opt) {
166 .none => null,166 .none => null,
167 _ => @bitCast(@intFromEnum(opt)),167 _ => @bitCast(@intFromEnum(opt)),
...@@ -178,7 +178,7 @@ pub const Dependee = union(enum) {...@@ -178,7 +178,7 @@ pub const Dependee = union(enum) {
178 namespace_name: NamespaceNameKey,178 namespace_name: NamespaceNameKey,
179};179};
180180
181pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalSubject) void {181pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalUnit) void {
182 var opt_idx = (ip.first_dependency.fetchSwapRemove(depender) orelse return).value.toOptional();182 var opt_idx = (ip.first_dependency.fetchSwapRemove(depender) orelse return).value.toOptional();
183183
184 while (opt_idx.unwrap()) |idx| {184 while (opt_idx.unwrap()) |idx| {
...@@ -207,7 +207,7 @@ pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender:...@@ -207,7 +207,7 @@ pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender:
207pub const DependencyIterator = struct {207pub const DependencyIterator = struct {
208 ip: *const InternPool,208 ip: *const InternPool,
209 next_entry: DepEntry.Index.Optional,209 next_entry: DepEntry.Index.Optional,
210 pub fn next(it: *DependencyIterator) ?AnalSubject {210 pub fn next(it: *DependencyIterator) ?AnalUnit {
211 const idx = it.next_entry.unwrap() orelse return null;211 const idx = it.next_entry.unwrap() orelse return null;
212 const entry = it.ip.dep_entries.items[@intFromEnum(idx)];212 const entry = it.ip.dep_entries.items[@intFromEnum(idx)];
213 it.next_entry = entry.next;213 it.next_entry = entry.next;
...@@ -236,7 +236,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI...@@ -236,7 +236,7 @@ pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyI
236 };236 };
237}237}
238238
239pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalSubject, dependee: Dependee) Allocator.Error!void {239pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, dependee: Dependee) Allocator.Error!void {
240 const first_depender_dep: DepEntry.Index.Optional = if (ip.first_dependency.get(depender)) |idx| dep: {240 const first_depender_dep: DepEntry.Index.Optional = if (ip.first_dependency.get(depender)) |idx| dep: {
241 // The entry already exists, so there is capacity to overwrite it later.241 // The entry already exists, so there is capacity to overwrite it later.
242 break :dep idx.toOptional();242 break :dep idx.toOptional();
...@@ -300,7 +300,7 @@ pub const DepEntry = extern struct {...@@ -300,7 +300,7 @@ pub const DepEntry = extern struct {
300 /// the first and only entry in one of `intern_pool.*_deps`, and does not300 /// the first and only entry in one of `intern_pool.*_deps`, and does not
301 /// appear in any list by `first_dependency`, but is not in301 /// appear in any list by `first_dependency`, but is not in
302 /// `free_dep_entries` since `*_deps` stores a reference to it.302 /// `free_dep_entries` since `*_deps` stores a reference to it.
303 depender: AnalSubject.Optional,303 depender: AnalUnit.Optional,
304 /// Index into `dep_entries` forming a doubly linked list of all dependencies on this dependee.304 /// Index into `dep_entries` forming a doubly linked list of all dependencies on this dependee.
305 /// Used to iterate all dependers for a given dependee during an update.305 /// Used to iterate all dependers for a given dependee during an update.
306 /// null if this is the end of the list.306 /// null if this is the end of the list.
src/RangeSet.zig+1-1
...@@ -3,7 +3,7 @@ const assert = std.debug.assert;...@@ -3,7 +3,7 @@ const assert = std.debug.assert;
3const Order = std.math.Order;3const Order = std.math.Order;
44
5const InternPool = @import("InternPool.zig");5const InternPool = @import("InternPool.zig");
6const Type = @import("type.zig").Type;6const Type = @import("Type.zig");
7const Value = @import("Value.zig");7const Value = @import("Value.zig");
8const Zcu = @import("Zcu.zig");8const Zcu = @import("Zcu.zig");
9/// Deprecated.9/// Deprecated.
src/Sema.zig+591-1178
...@@ -64,14 +64,6 @@ generic_owner: InternPool.Index = .none,...@@ -64,14 +64,6 @@ generic_owner: InternPool.Index = .none,
64/// instantiation can point back to the instantiation site in addition to the64/// instantiation can point back to the instantiation site in addition to the
65/// declaration site.65/// declaration site.
66generic_call_src: LazySrcLoc = LazySrcLoc.unneeded,66generic_call_src: LazySrcLoc = LazySrcLoc.unneeded,
67/// The key is types that must be fully resolved prior to machine code
68/// generation pass. Types are added to this set when resolving them
69/// immediately could cause a dependency loop, but they do need to be resolved
70/// before machine code generation passes process the AIR.
71/// It would work fine if this were an array list instead of an array hash map.
72/// I chose array hash map with the intention to save time by omitting
73/// duplicates.
74types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
75/// These are lazily created runtime blocks from block_inline instructions.67/// These are lazily created runtime blocks from block_inline instructions.
76/// They are created when an break_inline passes through a runtime condition, because68/// They are created when an break_inline passes through a runtime condition, because
77/// Sema must convert comptime control flow to runtime control flow, which means69/// Sema must convert comptime control flow to runtime control flow, which means
...@@ -117,6 +109,15 @@ maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAll...@@ -117,6 +109,15 @@ maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAll
117/// Backed by gpa.109/// Backed by gpa.
118comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{},110comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{},
119111
112/// A list of exports performed by this analysis. After this `Sema` terminates,
113/// these are flushed to `Zcu.single_exports` or `Zcu.multi_exports`.
114exports: std.ArrayListUnmanaged(Zcu.Export) = .{},
115
116/// All references registered so far by this `Sema`. This is a temporary duplicate
117/// of data stored in `Zcu.all_references`. It exists to avoid adding references to
118/// a given `AnalUnit` multiple times.
119references: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{},
120
120const MaybeComptimeAlloc = struct {121const MaybeComptimeAlloc = struct {
121 /// The runtime index of the `alloc` instruction.122 /// The runtime index of the `alloc` instruction.
122 runtime_index: Value.RuntimeIndex,123 runtime_index: Value.RuntimeIndex,
...@@ -167,7 +168,7 @@ const log = std.log.scoped(.sema);...@@ -167,7 +168,7 @@ const log = std.log.scoped(.sema);
167const Sema = @This();168const Sema = @This();
168const Value = @import("Value.zig");169const Value = @import("Value.zig");
169const MutableValue = @import("mutable_value.zig").MutableValue;170const MutableValue = @import("mutable_value.zig").MutableValue;
170const Type = @import("type.zig").Type;171const Type = @import("Type.zig");
171const Air = @import("Air.zig");172const Air = @import("Air.zig");
172const Zir = std.zig.Zir;173const Zir = std.zig.Zir;
173const Zcu = @import("Zcu.zig");174const Zcu = @import("Zcu.zig");
...@@ -186,6 +187,7 @@ const build_options = @import("build_options");...@@ -186,6 +187,7 @@ const build_options = @import("build_options");
186const Compilation = @import("Compilation.zig");187const Compilation = @import("Compilation.zig");
187const InternPool = @import("InternPool.zig");188const InternPool = @import("InternPool.zig");
188const Alignment = InternPool.Alignment;189const Alignment = InternPool.Alignment;
190const AnalUnit = InternPool.AnalUnit;
189const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;191const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;
190192
191pub const default_branch_quota = 1000;193pub const default_branch_quota = 1000;
...@@ -862,7 +864,6 @@ pub fn deinit(sema: *Sema) void {...@@ -862,7 +864,6 @@ pub fn deinit(sema: *Sema) void {
862 sema.air_extra.deinit(gpa);864 sema.air_extra.deinit(gpa);
863 sema.inst_map.deinit(gpa);865 sema.inst_map.deinit(gpa);
864 sema.decl_val_table.deinit(gpa);866 sema.decl_val_table.deinit(gpa);
865 sema.types_to_resolve.deinit(gpa);
866 {867 {
867 var it = sema.post_hoc_blocks.iterator();868 var it = sema.post_hoc_blocks.iterator();
868 while (it.next()) |entry| {869 while (it.next()) |entry| {
...@@ -875,6 +876,8 @@ pub fn deinit(sema: *Sema) void {...@@ -875,6 +876,8 @@ pub fn deinit(sema: *Sema) void {
875 sema.base_allocs.deinit(gpa);876 sema.base_allocs.deinit(gpa);
876 sema.maybe_comptime_allocs.deinit(gpa);877 sema.maybe_comptime_allocs.deinit(gpa);
877 sema.comptime_allocs.deinit(gpa);878 sema.comptime_allocs.deinit(gpa);
879 sema.exports.deinit(gpa);
880 sema.references.deinit(gpa);
878 sema.* = undefined;881 sema.* = undefined;
879}882}
880883
...@@ -2067,8 +2070,8 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)...@@ -2067,8 +2070,8 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
2067 const addrs_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(addr_arr_ty));2070 const addrs_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(addr_arr_ty));
20682071
2069 // var st: StackTrace = undefined;2072 // var st: StackTrace = undefined;
2070 const stack_trace_ty = try sema.getBuiltinType("StackTrace");2073 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
2071 try sema.resolveTypeFields(stack_trace_ty);2074 try stack_trace_ty.resolveFields(mod);
2072 const st_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(stack_trace_ty));2075 const st_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(stack_trace_ty));
20732076
2074 // st.instruction_addresses = &addrs;2077 // st.instruction_addresses = &addrs;
...@@ -2414,8 +2417,7 @@ pub fn errNote(...@@ -2414,8 +2417,7 @@ pub fn errNote(
2414 comptime format: []const u8,2417 comptime format: []const u8,
2415 args: anytype,2418 args: anytype,
2416) error{OutOfMemory}!void {2419) error{OutOfMemory}!void {
2417 const zcu = sema.mod;2420 return sema.mod.errNote(src, parent, format, args);
2418 return zcu.errNoteNonLazy(src.upgrade(zcu), parent, format, args);
2419}2421}
24202422
2421fn addFieldErrNote(2423fn addFieldErrNote(
...@@ -2443,7 +2445,7 @@ pub fn errMsg(...@@ -2443,7 +2445,7 @@ pub fn errMsg(
2443 args: anytype,2445 args: anytype,
2444) Allocator.Error!*Module.ErrorMsg {2446) Allocator.Error!*Module.ErrorMsg {
2445 assert(src.offset != .unneeded);2447 assert(src.offset != .unneeded);
2446 return Module.ErrorMsg.create(sema.gpa, src.upgrade(sema.mod), format, args);2448 return Module.ErrorMsg.create(sema.gpa, src, format, args);
2447}2449}
24482450
2449pub fn fail(2451pub fn fail(
...@@ -2466,87 +2468,57 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error...@@ -2466,87 +2468,57 @@ pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.Error
2466 @setCold(true);2468 @setCold(true);
2467 const gpa = sema.gpa;2469 const gpa = sema.gpa;
2468 const mod = sema.mod;2470 const mod = sema.mod;
2471 const ip = &mod.intern_pool;
24692472
2470 ref: {2473 if (build_options.enable_debug_extensions and mod.comp.debug_compile_errors) {
2471 errdefer err_msg.destroy(gpa);2474 var all_references = mod.resolveReferences() catch @panic("out of memory");
2475 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
2476 wip_errors.init(gpa) catch @panic("out of memory");
2477 Compilation.addModuleErrorMsg(mod, &wip_errors, err_msg.*, &all_references) catch unreachable;
2478 std.debug.print("compile error during Sema:\n", .{});
2479 var error_bundle = wip_errors.toOwnedBundle("") catch unreachable;
2480 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
2481 crash_report.compilerPanic("unexpected compile error occurred", null, null);
2482 }
24722483
2473 if (build_options.enable_debug_extensions and mod.comp.debug_compile_errors) {2484 if (block) |start_block| {
2474 var wip_errors: std.zig.ErrorBundle.Wip = undefined;2485 var block_it = start_block;
2475 wip_errors.init(gpa) catch unreachable;2486 while (block_it.inlining) |inlining| {
2476 Compilation.addModuleErrorMsg(mod, &wip_errors, err_msg.*) catch unreachable;2487 try sema.errNote(
2477 std.debug.print("compile error during Sema:\n", .{});2488 inlining.call_src,
2478 var error_bundle = wip_errors.toOwnedBundle("") catch unreachable;2489 err_msg,
2479 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });2490 "called from here",
2480 crash_report.compilerPanic("unexpected compile error occurred", null, null);2491 .{},
2492 );
2493 block_it = inlining.call_block;
2481 }2494 }
2495 }
24822496
2483 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);2497 const use_ref_trace = if (mod.comp.reference_trace) |n| n > 0 else mod.failed_analysis.count() == 0;
2484 try mod.failed_files.ensureUnusedCapacity(gpa, 1);2498 if (use_ref_trace) {
24852499 err_msg.reference_trace_root = sema.ownerUnit().toOptional();
2486 if (block) |start_block| {2500 }
2487 var block_it = start_block;
2488 while (block_it.inlining) |inlining| {
2489 try sema.errNote(
2490 inlining.call_src,
2491 err_msg,
2492 "called from here",
2493 .{},
2494 );
2495 block_it = inlining.call_block;
2496 }
2497
2498 const max_references = refs: {
2499 if (mod.comp.reference_trace) |num| break :refs num;
2500 // Do not add multiple traces without explicit request.
2501 if (mod.failed_decls.count() > 0) break :ref;
2502 break :refs default_reference_trace_len;
2503 };
25042501
2505 var referenced_by = if (sema.owner_func_index != .none)2502 const gop = try mod.failed_analysis.getOrPut(gpa, sema.ownerUnit());
2506 mod.funcOwnerDeclIndex(sema.owner_func_index)2503 if (gop.found_existing) {
2507 else2504 // If there are multiple errors for the same Decl, prefer the first one added.
2508 sema.owner_decl_index;2505 sema.err = null;
2509 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(gpa);2506 err_msg.destroy(gpa);
2510 defer reference_stack.deinit();2507 } else {
25112508 sema.err = err_msg;
2512 // Avoid infinite loops.2509 gop.value_ptr.* = err_msg;
2513 var seen = std.AutoHashMap(InternPool.DeclIndex, void).init(gpa);
2514 defer seen.deinit();
2515
2516 while (mod.reference_table.get(referenced_by)) |ref| {
2517 const gop = try seen.getOrPut(ref.referencer);
2518 if (gop.found_existing) break;
2519 if (reference_stack.items.len < max_references) {
2520 const decl = mod.declPtr(ref.referencer);
2521 try reference_stack.append(.{
2522 .decl = decl.name,
2523 .src_loc = ref.src.upgrade(mod),
2524 });
2525 }
2526 referenced_by = ref.referencer;
2527 }
2528 err_msg.reference_trace = try reference_stack.toOwnedSlice();
2529 err_msg.hidden_references = @intCast(seen.count() -| max_references);
2530 }
2531 }2510 }
2532 const ip = &mod.intern_pool;2511
2533 if (sema.owner_func_index != .none) {2512 if (sema.owner_func_index != .none) {
2534 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;2513 ip.funcAnalysis(sema.owner_func_index).state = .sema_failure;
2535 } else {2514 } else {
2536 sema.owner_decl.analysis = .sema_failure;2515 sema.owner_decl.analysis = .sema_failure;
2537 }2516 }
2517
2538 if (sema.func_index != .none) {2518 if (sema.func_index != .none) {
2539 ip.funcAnalysis(sema.func_index).state = .sema_failure;2519 ip.funcAnalysis(sema.func_index).state = .sema_failure;
2540 }2520 }
2541 const gop = mod.failed_decls.getOrPutAssumeCapacity(sema.owner_decl_index);2521
2542 if (gop.found_existing) {
2543 // If there are multiple errors for the same Decl, prefer the first one added.
2544 sema.err = null;
2545 err_msg.destroy(gpa);
2546 } else {
2547 sema.err = err_msg;
2548 gop.value_ptr.* = err_msg;
2549 }
2550 return error.AnalysisFail;2522 return error.AnalysisFail;
2551}2523}
25522524
...@@ -2561,7 +2533,6 @@ fn reparentOwnedErrorMsg(...@@ -2561,7 +2533,6 @@ fn reparentOwnedErrorMsg(
2561 args: anytype,2533 args: anytype,
2562) !void {2534) !void {
2563 const mod = sema.mod;2535 const mod = sema.mod;
2564 const resolved_src = src.upgrade(mod);
2565 const msg_str = try std.fmt.allocPrint(mod.gpa, format, args);2536 const msg_str = try std.fmt.allocPrint(mod.gpa, format, args);
25662537
2567 const orig_notes = msg.notes.len;2538 const orig_notes = msg.notes.len;
...@@ -2572,7 +2543,7 @@ fn reparentOwnedErrorMsg(...@@ -2572,7 +2543,7 @@ fn reparentOwnedErrorMsg(
2572 .msg = msg.msg,2543 .msg = msg.msg,
2573 };2544 };
25742545
2575 msg.src_loc = resolved_src;2546 msg.src_loc = src;
2576 msg.msg = msg_str;2547 msg.msg = msg_str;
2577}2548}
25782549
...@@ -2649,7 +2620,7 @@ fn analyzeAsInt(...@@ -2649,7 +2620,7 @@ fn analyzeAsInt(
2649 const mod = sema.mod;2620 const mod = sema.mod;
2650 const coerced = try sema.coerce(block, dest_ty, air_ref, src);2621 const coerced = try sema.coerce(block, dest_ty, air_ref, src);
2651 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);2622 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);
2652 return (try val.getUnsignedIntAdvanced(mod, sema)).?;2623 return (try val.getUnsignedIntAdvanced(mod, .sema)).?;
2653}2624}
26542625
2655/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,2626/// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`,
...@@ -2735,12 +2706,12 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {...@@ -2735,12 +2706,12 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {
2735 if (!zcu.comp.debug_incremental) return false;2706 if (!zcu.comp.debug_incremental) return false;
27362707
2737 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);2708 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);
2738 const decl_as_depender = InternPool.AnalSubject.wrap(.{ .decl = decl_index });2709 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });
2739 const was_outdated = zcu.outdated.swapRemove(decl_as_depender) or2710 const was_outdated = zcu.outdated.swapRemove(decl_as_depender) or
2740 zcu.potentially_outdated.swapRemove(decl_as_depender);2711 zcu.potentially_outdated.swapRemove(decl_as_depender);
2741 if (!was_outdated) return false;2712 if (!was_outdated) return false;
2742 _ = zcu.outdated_ready.swapRemove(decl_as_depender);2713 _ = zcu.outdated_ready.swapRemove(decl_as_depender);
2743 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));2714 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
2744 zcu.intern_pool.remove(ty);2715 zcu.intern_pool.remove(ty);
2745 zcu.declPtr(decl_index).analysis = .dependency_failure;2716 zcu.declPtr(decl_index).analysis = .dependency_failure;
2746 try zcu.markDependeeOutdated(.{ .decl_val = decl_index });2717 try zcu.markDependeeOutdated(.{ .decl_val = decl_index });
...@@ -2834,7 +2805,7 @@ fn zirStructDecl(...@@ -2834,7 +2805,7 @@ fn zirStructDecl(
2834 if (sema.mod.comp.debug_incremental) {2805 if (sema.mod.comp.debug_incremental) {
2835 try ip.addDependency(2806 try ip.addDependency(
2836 sema.gpa,2807 sema.gpa,
2837 InternPool.AnalSubject.wrap(.{ .decl = new_decl_index }),2808 AnalUnit.wrap(.{ .decl = new_decl_index }),
2838 .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) },2809 .{ .src_hash = try ip.trackZir(sema.gpa, block.getFileScope(mod), inst) },
2839 );2810 );
2840 }2811 }
...@@ -2853,6 +2824,8 @@ fn zirStructDecl(...@@ -2853,6 +2824,8 @@ fn zirStructDecl(
2853 }2824 }
28542825
2855 try mod.finalizeAnonDecl(new_decl_index);2826 try mod.finalizeAnonDecl(new_decl_index);
2827 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
2828 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
2856 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));2829 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
2857}2830}
28582831
...@@ -3068,7 +3041,7 @@ fn zirEnumDecl(...@@ -3068,7 +3041,7 @@ fn zirEnumDecl(
3068 if (sema.mod.comp.debug_incremental) {3041 if (sema.mod.comp.debug_incremental) {
3069 try mod.intern_pool.addDependency(3042 try mod.intern_pool.addDependency(
3070 sema.gpa,3043 sema.gpa,
3071 InternPool.AnalSubject.wrap(.{ .decl = new_decl_index }),3044 AnalUnit.wrap(.{ .decl = new_decl_index }),
3072 .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) },3045 .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) },
3073 );3046 );
3074 }3047 }
...@@ -3334,7 +3307,7 @@ fn zirUnionDecl(...@@ -3334,7 +3307,7 @@ fn zirUnionDecl(
3334 if (sema.mod.comp.debug_incremental) {3307 if (sema.mod.comp.debug_incremental) {
3335 try mod.intern_pool.addDependency(3308 try mod.intern_pool.addDependency(
3336 sema.gpa,3309 sema.gpa,
3337 InternPool.AnalSubject.wrap(.{ .decl = new_decl_index }),3310 AnalUnit.wrap(.{ .decl = new_decl_index }),
3338 .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) },3311 .{ .src_hash = try mod.intern_pool.trackZir(sema.gpa, block.getFileScope(mod), inst) },
3339 );3312 );
3340 }3313 }
...@@ -3353,7 +3326,8 @@ fn zirUnionDecl(...@@ -3353,7 +3326,8 @@ fn zirUnionDecl(
3353 }3326 }
33543327
3355 try mod.finalizeAnonDecl(new_decl_index);3328 try mod.finalizeAnonDecl(new_decl_index);
33563329 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
3330 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
3357 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));3331 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, new_namespace_index));
3358}3332}
33593333
...@@ -3422,7 +3396,7 @@ fn zirOpaqueDecl(...@@ -3422,7 +3396,7 @@ fn zirOpaqueDecl(
3422 if (sema.mod.comp.debug_incremental) {3396 if (sema.mod.comp.debug_incremental) {
3423 try ip.addDependency(3397 try ip.addDependency(
3424 gpa,3398 gpa,
3425 InternPool.AnalSubject.wrap(.{ .decl = new_decl_index }),3399 AnalUnit.wrap(.{ .decl = new_decl_index }),
3426 .{ .src_hash = try ip.trackZir(gpa, block.getFileScope(mod), inst) },3400 .{ .src_hash = try ip.trackZir(gpa, block.getFileScope(mod), inst) },
3427 );3401 );
3428 }3402 }
...@@ -3478,12 +3452,12 @@ fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -3478,12 +3452,12 @@ fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
3478 defer tracy.end();3452 defer tracy.end();
34793453
3480 if (block.is_comptime or try sema.typeRequiresComptime(sema.fn_ret_ty)) {3454 if (block.is_comptime or try sema.typeRequiresComptime(sema.fn_ret_ty)) {
3481 try sema.resolveTypeFields(sema.fn_ret_ty);3455 try sema.fn_ret_ty.resolveFields(sema.mod);
3482 return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty, .none);3456 return sema.analyzeComptimeAlloc(block, sema.fn_ret_ty, .none);
3483 }3457 }
34843458
3485 const target = sema.mod.getTarget();3459 const target = sema.mod.getTarget();
3486 const ptr_type = try sema.ptrType(.{3460 const ptr_type = try sema.mod.ptrTypeSema(.{
3487 .child = sema.fn_ret_ty.toIntern(),3461 .child = sema.fn_ret_ty.toIntern(),
3488 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },3462 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
3489 });3463 });
...@@ -3492,7 +3466,6 @@ fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -3492,7 +3466,6 @@ fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
3492 // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr.3466 // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr.
3493 // TODO when functions gain result location support, the inlining struct in3467 // TODO when functions gain result location support, the inlining struct in
3494 // Block should contain the return pointer, and we would pass that through here.3468 // Block should contain the return pointer, and we would pass that through here.
3495 try sema.queueFullTypeResolution(sema.fn_ret_ty);
3496 return block.addTy(.alloc, ptr_type);3469 return block.addTy(.alloc, ptr_type);
3497 }3470 }
34983471
...@@ -3688,8 +3661,8 @@ fn zirAllocExtended(...@@ -3688,8 +3661,8 @@ fn zirAllocExtended(
3688 try sema.validateVarType(block, ty_src, var_ty, false);3661 try sema.validateVarType(block, ty_src, var_ty, false);
3689 }3662 }
3690 const target = sema.mod.getTarget();3663 const target = sema.mod.getTarget();
3691 try sema.resolveTypeLayout(var_ty);3664 try var_ty.resolveLayout(sema.mod);
3692 const ptr_type = try sema.ptrType(.{3665 const ptr_type = try sema.mod.ptrTypeSema(.{
3693 .child = var_ty.toIntern(),3666 .child = var_ty.toIntern(),
3694 .flags = .{3667 .flags = .{
3695 .alignment = alignment,3668 .alignment = alignment,
...@@ -3923,7 +3896,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,...@@ -3923,7 +3896,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
3923 const idx_val = (try sema.resolveValue(data.rhs)).?;3896 const idx_val = (try sema.resolveValue(data.rhs)).?;
3924 break :blk .{3897 break :blk .{
3925 data.lhs,3898 data.lhs,
3926 .{ .elem = try idx_val.toUnsignedIntAdvanced(sema) },3899 .{ .elem = try idx_val.toUnsignedIntSema(zcu) },
3927 };3900 };
3928 },3901 },
3929 .bitcast => .{3902 .bitcast => .{
...@@ -3961,7 +3934,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,...@@ -3961,7 +3934,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
3961 .val = payload_val.toIntern(),3934 .val = payload_val.toIntern(),
3962 } });3935 } });
3963 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(opt_val), opt_ty);3936 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(opt_val), opt_ty);
3964 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrOptPayload(sema)).toIntern();3937 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrOptPayload(zcu)).toIntern();
3965 },3938 },
3966 .eu_payload => ptr: {3939 .eu_payload => ptr: {
3967 // Set the error union to non-error at comptime.3940 // Set the error union to non-error at comptime.
...@@ -3974,7 +3947,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,...@@ -3974,7 +3947,7 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
3974 .val = .{ .payload = payload_val.toIntern() },3947 .val = .{ .payload = payload_val.toIntern() },
3975 } });3948 } });
3976 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(eu_val), eu_ty);3949 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(eu_val), eu_ty);
3977 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrEuPayload(sema)).toIntern();3950 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrEuPayload(zcu)).toIntern();
3978 },3951 },
3979 .field => |idx| ptr: {3952 .field => |idx| ptr: {
3980 const maybe_union_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu);3953 const maybe_union_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu);
...@@ -3988,9 +3961,9 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,...@@ -3988,9 +3961,9 @@ fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref,
3988 const store_val = try zcu.unionValue(maybe_union_ty, tag_val, payload_val);3961 const store_val = try zcu.unionValue(maybe_union_ty, tag_val, payload_val);
3989 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), store_val, maybe_union_ty);3962 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), store_val, maybe_union_ty);
3990 }3963 }
3991 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, sema)).toIntern();3964 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, zcu)).toIntern();
3992 },3965 },
3993 .elem => |idx| (try Value.fromInterned(decl_parent_ptr).ptrElem(idx, sema)).toIntern(),3966 .elem => |idx| (try Value.fromInterned(decl_parent_ptr).ptrElem(idx, zcu)).toIntern(),
3994 };3967 };
3995 try ptr_mapping.put(air_ptr, new_ptr);3968 try ptr_mapping.put(air_ptr, new_ptr);
3996 }3969 }
...@@ -4081,7 +4054,7 @@ fn finishResolveComptimeKnownAllocPtr(...@@ -4081,7 +4054,7 @@ fn finishResolveComptimeKnownAllocPtr(
4081fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type {4054fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type {
4082 var ptr_info = ptr_ty.ptrInfo(sema.mod);4055 var ptr_info = ptr_ty.ptrInfo(sema.mod);
4083 ptr_info.flags.is_const = true;4056 ptr_info.flags.is_const = true;
4084 return sema.ptrType(ptr_info);4057 return sema.mod.ptrTypeSema(ptr_info);
4085}4058}
40864059
4087fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {4060fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {
...@@ -4124,11 +4097,10 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -4124,11 +4097,10 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
4124 return sema.analyzeComptimeAlloc(block, var_ty, .none);4097 return sema.analyzeComptimeAlloc(block, var_ty, .none);
4125 }4098 }
4126 const target = sema.mod.getTarget();4099 const target = sema.mod.getTarget();
4127 const ptr_type = try sema.ptrType(.{4100 const ptr_type = try sema.mod.ptrTypeSema(.{
4128 .child = var_ty.toIntern(),4101 .child = var_ty.toIntern(),
4129 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },4102 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
4130 });4103 });
4131 try sema.queueFullTypeResolution(var_ty);
4132 const ptr = try block.addTy(.alloc, ptr_type);4104 const ptr = try block.addTy(.alloc, ptr_type);
4133 const ptr_inst = ptr.toIndex().?;4105 const ptr_inst = ptr.toIndex().?;
4134 try sema.maybe_comptime_allocs.put(sema.gpa, ptr_inst, .{ .runtime_index = block.runtime_index });4106 try sema.maybe_comptime_allocs.put(sema.gpa, ptr_inst, .{ .runtime_index = block.runtime_index });
...@@ -4148,11 +4120,10 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -4148,11 +4120,10 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
4148 }4120 }
4149 try sema.validateVarType(block, ty_src, var_ty, false);4121 try sema.validateVarType(block, ty_src, var_ty, false);
4150 const target = sema.mod.getTarget();4122 const target = sema.mod.getTarget();
4151 const ptr_type = try sema.ptrType(.{4123 const ptr_type = try sema.mod.ptrTypeSema(.{
4152 .child = var_ty.toIntern(),4124 .child = var_ty.toIntern(),
4153 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },4125 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
4154 });4126 });
4155 try sema.queueFullTypeResolution(var_ty);
4156 return block.addTy(.alloc, ptr_type);4127 return block.addTy(.alloc, ptr_type);
4157}4128}
41584129
...@@ -4229,6 +4200,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4229,6 +4200,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4229 if (mod.intern_pool.isFuncBody(val)) {4200 if (mod.intern_pool.isFuncBody(val)) {
4230 const ty = Type.fromInterned(mod.intern_pool.typeOf(val));4201 const ty = Type.fromInterned(mod.intern_pool.typeOf(val));
4231 if (try sema.fnHasRuntimeBits(ty)) {4202 if (try sema.fnHasRuntimeBits(ty)) {
4203 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = val }));
4232 try mod.ensureFuncBodyAnalysisQueued(val);4204 try mod.ensureFuncBodyAnalysisQueued(val);
4233 }4205 }
4234 }4206 }
...@@ -4247,7 +4219,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4247,7 +4219,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4247 }4219 }
4248 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none);4220 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none);
42494221
4250 const final_ptr_ty = try sema.ptrType(.{4222 const final_ptr_ty = try mod.ptrTypeSema(.{
4251 .child = final_elem_ty.toIntern(),4223 .child = final_elem_ty.toIntern(),
4252 .flags = .{4224 .flags = .{
4253 .alignment = ia1.alignment,4225 .alignment = ia1.alignment,
...@@ -4267,7 +4239,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4267,7 +4239,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4267 // Unless the block is comptime, `alloc_inferred` always produces4239 // Unless the block is comptime, `alloc_inferred` always produces
4268 // a runtime constant. The final inferred type needs to be4240 // a runtime constant. The final inferred type needs to be
4269 // fully resolved so it can be lowered in codegen.4241 // fully resolved so it can be lowered in codegen.
4270 try sema.resolveTypeFully(final_elem_ty);4242 try final_elem_ty.resolveFully(mod);
42714243
4272 return;4244 return;
4273 }4245 }
...@@ -4279,8 +4251,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com...@@ -4279,8 +4251,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
4279 return sema.fail(block, src, "value with comptime-only type '{}' depends on runtime control flow", .{final_elem_ty.fmt(mod)});4251 return sema.fail(block, src, "value with comptime-only type '{}' depends on runtime control flow", .{final_elem_ty.fmt(mod)});
4280 }4252 }
42814253
4282 try sema.queueFullTypeResolution(final_elem_ty);
4283
4284 // Change it to a normal alloc.4254 // Change it to a normal alloc.
4285 sema.air_instructions.set(@intFromEnum(ptr_inst), .{4255 sema.air_instructions.set(@intFromEnum(ptr_inst), .{
4286 .tag = .alloc,4256 .tag = .alloc,
...@@ -4653,7 +4623,7 @@ fn validateArrayInitTy(...@@ -4653,7 +4623,7 @@ fn validateArrayInitTy(
4653 return;4623 return;
4654 },4624 },
4655 .Struct => if (ty.isTuple(mod)) {4625 .Struct => if (ty.isTuple(mod)) {
4656 try sema.resolveTypeFields(ty);4626 try ty.resolveFields(mod);
4657 const array_len = ty.arrayLen(mod);4627 const array_len = ty.arrayLen(mod);
4658 if (init_count > array_len) {4628 if (init_count > array_len) {
4659 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{4629 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
...@@ -4931,7 +4901,7 @@ fn validateStructInit(...@@ -4931,7 +4901,7 @@ fn validateStructInit(
4931 if (block.is_comptime and4901 if (block.is_comptime and
4932 (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null)4902 (try sema.resolveDefinedValue(block, init_src, struct_ptr)) != null)
4933 {4903 {
4934 try sema.resolveStructLayout(struct_ty);4904 try struct_ty.resolveLayout(mod);
4935 // In this case the only thing we need to do is evaluate the implicit4905 // In this case the only thing we need to do is evaluate the implicit
4936 // store instructions for default field values, and report any missing fields.4906 // store instructions for default field values, and report any missing fields.
4937 // Avoid the cost of the extra machinery for detecting a comptime struct init value.4907 // Avoid the cost of the extra machinery for detecting a comptime struct init value.
...@@ -4939,7 +4909,7 @@ fn validateStructInit(...@@ -4939,7 +4909,7 @@ fn validateStructInit(
4939 const i: u32 = @intCast(i_usize);4909 const i: u32 = @intCast(i_usize);
4940 if (field_ptr != .none) continue;4910 if (field_ptr != .none) continue;
49414911
4942 try sema.resolveStructFieldInits(struct_ty);4912 try struct_ty.resolveStructFieldInits(mod);
4943 const default_val = struct_ty.structFieldDefaultValue(i, mod);4913 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4944 if (default_val.toIntern() == .unreachable_value) {4914 if (default_val.toIntern() == .unreachable_value) {
4945 const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse {4915 const field_name = struct_ty.structFieldName(i, mod).unwrap() orelse {
...@@ -4988,7 +4958,7 @@ fn validateStructInit(...@@ -4988,7 +4958,7 @@ fn validateStructInit(
4988 const air_tags = sema.air_instructions.items(.tag);4958 const air_tags = sema.air_instructions.items(.tag);
4989 const air_datas = sema.air_instructions.items(.data);4959 const air_datas = sema.air_instructions.items(.data);
49904960
4991 try sema.resolveStructFieldInits(struct_ty);4961 try struct_ty.resolveStructFieldInits(mod);
49924962
4993 // We collect the comptime field values in case the struct initialization4963 // We collect the comptime field values in case the struct initialization
4994 // ends up being comptime-known.4964 // ends up being comptime-known.
...@@ -5147,7 +5117,7 @@ fn validateStructInit(...@@ -5147,7 +5117,7 @@ fn validateStructInit(
5147 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);5117 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
5148 return;5118 return;
5149 }5119 }
5150 try sema.resolveStructLayout(struct_ty);5120 try struct_ty.resolveLayout(mod);
51515121
5152 // Our task is to insert `store` instructions for all the default field values.5122 // Our task is to insert `store` instructions for all the default field values.
5153 for (found_fields, 0..) |field_ptr, i| {5123 for (found_fields, 0..) |field_ptr, i| {
...@@ -5192,7 +5162,7 @@ fn zirValidatePtrArrayInit(...@@ -5192,7 +5162,7 @@ fn zirValidatePtrArrayInit(
5192 var root_msg: ?*Module.ErrorMsg = null;5162 var root_msg: ?*Module.ErrorMsg = null;
5193 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);5163 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
51945164
5195 try sema.resolveStructFieldInits(array_ty);5165 try array_ty.resolveStructFieldInits(mod);
5196 var i = instrs.len;5166 var i = instrs.len;
5197 while (i < array_len) : (i += 1) {5167 while (i < array_len) : (i += 1) {
5198 const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern();5168 const default_val = array_ty.structFieldDefaultValue(i, mod).toIntern();
...@@ -5261,7 +5231,7 @@ fn zirValidatePtrArrayInit(...@@ -5261,7 +5231,7 @@ fn zirValidatePtrArrayInit(
52615231
5262 if (array_ty.isTuple(mod)) {5232 if (array_ty.isTuple(mod)) {
5263 if (array_ty.structFieldIsComptime(i, mod))5233 if (array_ty.structFieldIsComptime(i, mod))
5264 try sema.resolveStructFieldInits(array_ty);5234 try array_ty.resolveStructFieldInits(mod);
5265 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {5235 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
5266 element_vals[i] = opv.toIntern();5236 element_vals[i] = opv.toIntern();
5267 continue;5237 continue;
...@@ -5601,7 +5571,7 @@ fn storeToInferredAllocComptime(...@@ -5601,7 +5571,7 @@ fn storeToInferredAllocComptime(
5601 .needed_comptime_reason = "value being stored to a comptime variable must be comptime-known",5571 .needed_comptime_reason = "value being stored to a comptime variable must be comptime-known",
5602 });5572 });
5603 };5573 };
5604 const alloc_ty = try sema.ptrType(.{5574 const alloc_ty = try zcu.ptrTypeSema(.{
5605 .child = operand_ty.toIntern(),5575 .child = operand_ty.toIntern(),
5606 .flags = .{5576 .flags = .{
5607 .alignment = iac.alignment,5577 .alignment = iac.alignment,
...@@ -5708,7 +5678,7 @@ fn anonDeclRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {...@@ -5708,7 +5678,7 @@ fn anonDeclRef(sema: *Sema, val: InternPool.Index) CompileError!Air.Inst.Ref {
57085678
5709fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {5679fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index {
5710 const mod = sema.mod;5680 const mod = sema.mod;
5711 const ptr_ty = (try sema.ptrType(.{5681 const ptr_ty = (try mod.ptrTypeSema(.{
5712 .child = mod.intern_pool.typeOf(val),5682 .child = mod.intern_pool.typeOf(val),
5713 .flags = .{5683 .flags = .{
5714 .alignment = .none,5684 .alignment = .none,
...@@ -5817,11 +5787,7 @@ fn zirCompileLog(...@@ -5817,11 +5787,7 @@ fn zirCompileLog(
5817 }5787 }
5818 try writer.print("\n", .{});5788 try writer.print("\n", .{});
58195789
5820 const decl_index = if (sema.func_index != .none)5790 const gop = try mod.compile_log_sources.getOrPut(sema.gpa, sema.ownerUnit());
5821 mod.funcOwnerDeclIndex(sema.func_index)
5822 else
5823 sema.owner_decl_index;
5824 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
5825 if (!gop.found_existing) gop.value_ptr.* = .{5791 if (!gop.found_existing) gop.value_ptr.* = .{
5826 .base_node_inst = block.src_base_inst,5792 .base_node_inst = block.src_base_inst,
5827 .node_offset = src_node,5793 .node_offset = src_node,
...@@ -5974,7 +5940,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -5974,7 +5940,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
5974 if (!comp.config.link_libc)5940 if (!comp.config.link_libc)
5975 try sema.errNote(src, msg, "libc headers not available; compilation does not link against libc", .{});5941 try sema.errNote(src, msg, "libc headers not available; compilation does not link against libc", .{});
59765942
5977 const gop = try mod.cimport_errors.getOrPut(gpa, sema.owner_decl_index);5943 const gop = try mod.cimport_errors.getOrPut(gpa, sema.ownerUnit());
5978 if (!gop.found_existing) {5944 if (!gop.found_existing) {
5979 gop.value_ptr.* = c_import_res.errors;5945 gop.value_ptr.* = c_import_res.errors;
5980 c_import_res.errors = std.zig.ErrorBundle.empty;5946 c_import_res.errors = std.zig.ErrorBundle.empty;
...@@ -6393,6 +6359,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -6393,6 +6359,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
6393 } else try sema.lookupIdentifier(block, operand_src, decl_name);6359 } else try sema.lookupIdentifier(block, operand_src, decl_name);
6394 const options = try sema.resolveExportOptions(block, options_src, extra.options);6360 const options = try sema.resolveExportOptions(block, options_src, extra.options);
6395 {6361 {
6362 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = decl_index }));
6396 try sema.ensureDeclAnalyzed(decl_index);6363 try sema.ensureDeclAnalyzed(decl_index);
6397 const exported_decl = mod.declPtr(decl_index);6364 const exported_decl = mod.declPtr(decl_index);
6398 if (exported_decl.val.getFunction(mod)) |function| {6365 if (exported_decl.val.getFunction(mod)) |function| {
...@@ -6423,10 +6390,9 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -6423,10 +6390,9 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
6423 return sema.analyzeExport(block, src, options, decl_index);6390 return sema.analyzeExport(block, src, options, decl_index);
6424 }6391 }
64256392
6426 try addExport(mod, .{6393 try sema.exports.append(mod.gpa, .{
6427 .opts = options,6394 .opts = options,
6428 .src = src,6395 .src = src,
6429 .owner_decl = sema.owner_decl_index,
6430 .exported = .{ .value = operand.toIntern() },6396 .exported = .{ .value = operand.toIntern() },
6431 .status = .in_progress,6397 .status = .in_progress,
6432 });6398 });
...@@ -6445,6 +6411,7 @@ pub fn analyzeExport(...@@ -6445,6 +6411,7 @@ pub fn analyzeExport(
6445 if (options.linkage == .internal)6411 if (options.linkage == .internal)
6446 return;6412 return;
64476413
6414 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = exported_decl_index }));
6448 try sema.ensureDeclAnalyzed(exported_decl_index);6415 try sema.ensureDeclAnalyzed(exported_decl_index);
6449 const exported_decl = mod.declPtr(exported_decl_index);6416 const exported_decl = mod.declPtr(exported_decl_index);
6450 const export_ty = exported_decl.typeOf(mod);6417 const export_ty = exported_decl.typeOf(mod);
...@@ -6467,48 +6434,16 @@ pub fn analyzeExport(...@@ -6467,48 +6434,16 @@ pub fn analyzeExport(
6467 return sema.fail(block, src, "export target cannot be extern", .{});6434 return sema.fail(block, src, "export target cannot be extern", .{});
6468 }6435 }
64696436
6470 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);6437 try sema.maybeQueueFuncBodyAnalysis(src, exported_decl_index);
64716438
6472 try addExport(mod, .{6439 try sema.exports.append(gpa, .{
6473 .opts = options,6440 .opts = options,
6474 .src = src,6441 .src = src,
6475 .owner_decl = sema.owner_decl_index,
6476 .exported = .{ .decl_index = exported_decl_index },6442 .exported = .{ .decl_index = exported_decl_index },
6477 .status = .in_progress,6443 .status = .in_progress,
6478 });6444 });
6479}6445}
64806446
6481fn addExport(mod: *Module, export_init: Module.Export) error{OutOfMemory}!void {
6482 const gpa = mod.gpa;
6483
6484 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
6485 try mod.value_exports.ensureUnusedCapacity(gpa, 1);
6486 try mod.export_owners.ensureUnusedCapacity(gpa, 1);
6487
6488 const new_export = try gpa.create(Module.Export);
6489 errdefer gpa.destroy(new_export);
6490
6491 new_export.* = export_init;
6492
6493 const eo_gop = mod.export_owners.getOrPutAssumeCapacity(export_init.owner_decl);
6494 if (!eo_gop.found_existing) eo_gop.value_ptr.* = .{};
6495 try eo_gop.value_ptr.append(gpa, new_export);
6496 errdefer _ = eo_gop.value_ptr.pop();
6497
6498 switch (export_init.exported) {
6499 .decl_index => |decl_index| {
6500 const de_gop = mod.decl_exports.getOrPutAssumeCapacity(decl_index);
6501 if (!de_gop.found_existing) de_gop.value_ptr.* = .{};
6502 try de_gop.value_ptr.append(gpa, new_export);
6503 },
6504 .value => |value| {
6505 const ve_gop = mod.value_exports.getOrPutAssumeCapacity(value);
6506 if (!ve_gop.found_existing) ve_gop.value_ptr.* = .{};
6507 try ve_gop.value_ptr.append(gpa, new_export);
6508 },
6509 }
6510}
6511
6512fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {6447fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
6513 const mod = sema.mod;6448 const mod = sema.mod;
6514 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;6449 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
...@@ -6700,8 +6635,6 @@ fn addDbgVar(...@@ -6700,8 +6635,6 @@ fn addDbgVar(
6700 // real `block` instruction.6635 // real `block` instruction.
6701 if (block.need_debug_scope) |ptr| ptr.* = true;6636 if (block.need_debug_scope) |ptr| ptr.* = true;
67026637
6703 try sema.queueFullTypeResolution(operand_ty);
6704
6705 // Add the name to the AIR.6638 // Add the name to the AIR.
6706 const name_extra_index: u32 = @intCast(sema.air_extra.items.len);6639 const name_extra_index: u32 = @intCast(sema.air_extra.items.len);
6707 const elements_used = name.len / 4 + 1;6640 const elements_used = name.len / 4 + 1;
...@@ -6730,8 +6663,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -6730,8 +6663,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
6730 .no_embedded_nulls,6663 .no_embedded_nulls,
6731 );6664 );
6732 const decl_index = try sema.lookupIdentifier(block, src, decl_name);6665 const decl_index = try sema.lookupIdentifier(block, src, decl_name);
6733 try sema.addReferencedBy(src, decl_index);6666 return sema.analyzeDeclRef(src, decl_index);
6734 return sema.analyzeDeclRef(decl_index);
6735}6667}
67366668
6737fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6669fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -6888,14 +6820,8 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref...@@ -6888,14 +6820,8 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
68886820
6889 if (!block.ownerModule().error_tracing) return .none;6821 if (!block.ownerModule().error_tracing) return .none;
68906822
6891 const stack_trace_ty = sema.getBuiltinType("StackTrace") catch |err| switch (err) {6823 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
6892 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,6824 try stack_trace_ty.resolveFields(mod);
6893 else => |e| return e,
6894 };
6895 sema.resolveTypeFields(stack_trace_ty) catch |err| switch (err) {
6896 error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
6897 else => |e| return e,
6898 };
6899 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);6825 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
6900 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {6826 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
6901 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),6827 error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
...@@ -6935,8 +6861,8 @@ fn popErrorReturnTrace(...@@ -6935,8 +6861,8 @@ fn popErrorReturnTrace(
6935 // AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or6861 // AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or
6936 // the result is comptime-known to be a non-error. Either way, pop unconditionally.6862 // the result is comptime-known to be a non-error. Either way, pop unconditionally.
69376863
6938 const stack_trace_ty = try sema.getBuiltinType("StackTrace");6864 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
6939 try sema.resolveTypeFields(stack_trace_ty);6865 try stack_trace_ty.resolveFields(mod);
6940 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);6866 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
6941 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);6867 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
6942 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);6868 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
...@@ -6961,8 +6887,8 @@ fn popErrorReturnTrace(...@@ -6961,8 +6887,8 @@ fn popErrorReturnTrace(
6961 defer then_block.instructions.deinit(gpa);6887 defer then_block.instructions.deinit(gpa);
69626888
6963 // If non-error, then pop the error return trace by restoring the index.6889 // If non-error, then pop the error return trace by restoring the index.
6964 const stack_trace_ty = try sema.getBuiltinType("StackTrace");6890 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
6965 try sema.resolveTypeFields(stack_trace_ty);6891 try stack_trace_ty.resolveFields(mod);
6966 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);6892 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
6967 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);6893 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
6968 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);6894 const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
...@@ -7088,8 +7014,8 @@ fn zirCall(...@@ -7088,8 +7014,8 @@ fn zirCall(
7088 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only7014 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
7089 // need to clean-up our own trace if we were passed to a non-error-handling expression.7015 // need to clean-up our own trace if we were passed to a non-error-handling expression.
7090 if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) {7016 if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) {
7091 const stack_trace_ty = try sema.getBuiltinType("StackTrace");7017 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
7092 try sema.resolveTypeFields(stack_trace_ty);7018 try stack_trace_ty.resolveFields(mod);
7093 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index", .no_embedded_nulls);7019 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index", .no_embedded_nulls);
7094 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);7020 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
70957021
...@@ -7320,10 +7246,6 @@ const CallArgsInfo = union(enum) {...@@ -7320,10 +7246,6 @@ const CallArgsInfo = union(enum) {
7320 ) CompileError!Air.Inst.Ref {7246 ) CompileError!Air.Inst.Ref {
7321 const mod = sema.mod;7247 const mod = sema.mod;
7322 const param_count = func_ty_info.param_types.len;7248 const param_count = func_ty_info.param_types.len;
7323 if (maybe_param_ty) |param_ty| switch (param_ty.toIntern()) {
7324 .generic_poison_type => {},
7325 else => try sema.queueFullTypeResolution(param_ty),
7326 };
7327 const uncoerced_arg: Air.Inst.Ref = switch (cai) {7249 const uncoerced_arg: Air.Inst.Ref = switch (cai) {
7328 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],7250 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index],
7329 .zir_call => |zir_call| arg_val: {7251 .zir_call => |zir_call| arg_val: {
...@@ -7550,24 +7472,19 @@ fn analyzeCall(...@@ -7550,24 +7472,19 @@ fn analyzeCall(
75507472
7551 const gpa = sema.gpa;7473 const gpa = sema.gpa;
75527474
7553 var is_generic_call = func_ty_info.is_generic;7475 const is_generic_call = func_ty_info.is_generic;
7554 var is_comptime_call = block.is_comptime or modifier == .compile_time;7476 var is_comptime_call = block.is_comptime or modifier == .compile_time;
7555 var is_inline_call = is_comptime_call or modifier == .always_inline or func_ty_info.cc == .Inline;7477 var is_inline_call = is_comptime_call or modifier == .always_inline or func_ty_info.cc == .Inline;
7556 var comptime_reason: ?*const Block.ComptimeReason = null;7478 var comptime_reason: ?*const Block.ComptimeReason = null;
7557 if (!is_inline_call and !is_comptime_call) {7479 if (!is_inline_call and !is_comptime_call) {
7558 if (sema.typeRequiresComptime(Type.fromInterned(func_ty_info.return_type))) |ct| {7480 if (try sema.typeRequiresComptime(Type.fromInterned(func_ty_info.return_type))) {
7559 is_comptime_call = ct;7481 is_comptime_call = true;
7560 is_inline_call = ct;7482 is_inline_call = true;
7561 if (ct) {7483 comptime_reason = &.{ .comptime_ret_ty = .{
7562 comptime_reason = &.{ .comptime_ret_ty = .{7484 .func = func,
7563 .func = func,7485 .func_src = func_src,
7564 .func_src = func_src,7486 .return_ty = Type.fromInterned(func_ty_info.return_type),
7565 .return_ty = Type.fromInterned(func_ty_info.return_type),7487 } };
7566 } };
7567 }
7568 } else |err| switch (err) {
7569 error.GenericPoison => is_generic_call = true,
7570 else => |e| return e,
7571 }7488 }
7572 }7489 }
75737490
...@@ -7927,13 +7844,13 @@ fn analyzeCall(...@@ -7927,13 +7844,13 @@ fn analyzeCall(
79277844
7928 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);7845 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
79297846
7930 try sema.queueFullTypeResolution(Type.fromInterned(func_ty_info.return_type));
7931 if (sema.owner_func_index != .none and Type.fromInterned(func_ty_info.return_type).isError(mod)) {7847 if (sema.owner_func_index != .none and Type.fromInterned(func_ty_info.return_type).isError(mod)) {
7932 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;7848 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
7933 }7849 }
79347850
7935 if (try sema.resolveValue(func)) |func_val| {7851 if (try sema.resolveValue(func)) |func_val| {
7936 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {7852 if (mod.intern_pool.isFuncBody(func_val.toIntern())) {
7853 try sema.addReferenceEntry(call_src, AnalUnit.wrap(.{ .func = func_val.toIntern() }));
7937 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());7854 try mod.ensureFuncBodyAnalysisQueued(func_val.toIntern());
7938 }7855 }
7939 }7856 }
...@@ -8336,7 +8253,6 @@ fn instantiateGenericCall(...@@ -8336,7 +8253,6 @@ fn instantiateGenericCall(
8336 }8253 }
8337 } else {8254 } else {
8338 // The parameter is runtime-known.8255 // The parameter is runtime-known.
8339 try sema.queueFullTypeResolution(arg_ty);
8340 child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{8256 child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{
8341 .tag = .arg,8257 .tag = .arg,
8342 .data = .{ .arg = .{8258 .data = .{ .arg = .{
...@@ -8370,8 +8286,6 @@ fn instantiateGenericCall(...@@ -8370,8 +8286,6 @@ fn instantiateGenericCall(
8370 const callee = mod.funcInfo(callee_index);8286 const callee = mod.funcInfo(callee_index);
8371 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);8287 callee.branchQuota(ip).* = @max(callee.branchQuota(ip).*, sema.branch_quota);
83728288
8373 try sema.addReferencedBy(call_src, callee.owner_decl);
8374
8375 // Make a runtime call to the new function, making sure to omit the comptime args.8289 // Make a runtime call to the new function, making sure to omit the comptime args.
8376 const func_ty = Type.fromInterned(callee.ty);8290 const func_ty = Type.fromInterned(callee.ty);
8377 const func_ty_info = mod.typeToFunc(func_ty).?;8291 const func_ty_info = mod.typeToFunc(func_ty).?;
...@@ -8387,8 +8301,6 @@ fn instantiateGenericCall(...@@ -8387,8 +8301,6 @@ fn instantiateGenericCall(
8387 return error.GenericPoison;8301 return error.GenericPoison;
8388 }8302 }
83898303
8390 try sema.queueFullTypeResolution(Type.fromInterned(func_ty_info.return_type));
8391
8392 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);8304 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
83938305
8394 if (sema.owner_func_index != .none and8306 if (sema.owner_func_index != .none and
...@@ -8397,6 +8309,7 @@ fn instantiateGenericCall(...@@ -8397,6 +8309,7 @@ fn instantiateGenericCall(
8397 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;8309 ip.funcAnalysis(sema.owner_func_index).calls_or_awaits_errorable_fn = true;
8398 }8310 }
83998311
8312 try sema.addReferenceEntry(call_src, AnalUnit.wrap(.{ .func = callee_index }));
8400 try mod.ensureFuncBodyAnalysisQueued(callee_index);8313 try mod.ensureFuncBodyAnalysisQueued(callee_index);
84018314
8402 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + runtime_args.items.len);8315 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len + runtime_args.items.len);
...@@ -8411,6 +8324,9 @@ fn instantiateGenericCall(...@@ -8411,6 +8324,9 @@ fn instantiateGenericCall(
8411 });8324 });
8412 sema.appendRefsAssumeCapacity(runtime_args.items);8325 sema.appendRefsAssumeCapacity(runtime_args.items);
84138326
8327 // `child_sema` is owned by us, so just take its exports.
8328 try sema.exports.appendSlice(sema.gpa, child_sema.exports.items);
8329
8414 if (ensure_result_used) {8330 if (ensure_result_used) {
8415 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);8331 try sema.ensureResultUsed(block, sema.typeOf(result), call_src);
8416 }8332 }
...@@ -8476,7 +8392,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil...@@ -8476,7 +8392,7 @@ fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
8476 else => |e| return e,8392 else => |e| return e,
8477 };8393 };
8478 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(mod);8394 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(mod);
8479 try sema.resolveTypeFields(indexable_ty);8395 try indexable_ty.resolveFields(mod);
8480 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction8396 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
8481 if (indexable_ty.zigTypeTag(mod) == .Struct) {8397 if (indexable_ty.zigTypeTag(mod) == .Struct) {
8482 const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);8398 const elem_type = indexable_ty.structFieldType(@intFromEnum(bin.rhs), mod);
...@@ -8740,7 +8656,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD...@@ -8740,7 +8656,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
8740 const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src);8656 const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src);
87418657
8742 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {8658 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8743 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntAdvanced(sema));8659 const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(mod));
8744 if (int > mod.global_error_set.count() or int == 0)8660 if (int > mod.global_error_set.count() or int == 0)
8745 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});8661 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8746 return Air.internedToRef((try mod.intern(.{ .err = .{8662 return Air.internedToRef((try mod.intern(.{ .err = .{
...@@ -8844,7 +8760,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -8844,7 +8760,7 @@ fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
8844 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(mod)) {8760 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(mod)) {
8845 .Enum => operand,8761 .Enum => operand,
8846 .Union => blk: {8762 .Union => blk: {
8847 try sema.resolveTypeFields(operand_ty);8763 try operand_ty.resolveFields(mod);
8848 const tag_ty = operand_ty.unionTagType(mod) orelse {8764 const tag_ty = operand_ty.unionTagType(mod) orelse {
8849 return sema.fail(8765 return sema.fail(
8850 block,8766 block,
...@@ -8986,7 +8902,7 @@ fn analyzeOptionalPayloadPtr(...@@ -8986,7 +8902,7 @@ fn analyzeOptionalPayloadPtr(
8986 }8902 }
89878903
8988 const child_type = opt_type.optionalChild(zcu);8904 const child_type = opt_type.optionalChild(zcu);
8989 const child_pointer = try sema.ptrType(.{8905 const child_pointer = try zcu.ptrTypeSema(.{
8990 .child = child_type.toIntern(),8906 .child = child_type.toIntern(),
8991 .flags = .{8907 .flags = .{
8992 .is_const = optional_ptr_ty.isConstPtr(zcu),8908 .is_const = optional_ptr_ty.isConstPtr(zcu),
...@@ -9010,13 +8926,13 @@ fn analyzeOptionalPayloadPtr(...@@ -9010,13 +8926,13 @@ fn analyzeOptionalPayloadPtr(
9010 const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);8926 const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
9011 try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr);8927 try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr);
9012 }8928 }
9013 return Air.internedToRef((try ptr_val.ptrOptPayload(sema)).toIntern());8929 return Air.internedToRef((try ptr_val.ptrOptPayload(zcu)).toIntern());
9014 }8930 }
9015 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {8931 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
9016 if (val.isNull(zcu)) {8932 if (val.isNull(zcu)) {
9017 return sema.fail(block, src, "unable to unwrap null", .{});8933 return sema.fail(block, src, "unable to unwrap null", .{});
9018 }8934 }
9019 return Air.internedToRef((try ptr_val.ptrOptPayload(sema)).toIntern());8935 return Air.internedToRef((try ptr_val.ptrOptPayload(zcu)).toIntern());
9020 }8936 }
9021 }8937 }
90228938
...@@ -9059,7 +8975,7 @@ fn zirOptionalPayload(...@@ -9059,7 +8975,7 @@ fn zirOptionalPayload(
9059 // TODO https://github.com/ziglang/zig/issues/65978975 // TODO https://github.com/ziglang/zig/issues/6597
9060 if (true) break :t operand_ty;8976 if (true) break :t operand_ty;
9061 const ptr_info = operand_ty.ptrInfo(mod);8977 const ptr_info = operand_ty.ptrInfo(mod);
9062 break :t try sema.ptrType(.{8978 break :t try mod.ptrTypeSema(.{
9063 .child = ptr_info.child,8979 .child = ptr_info.child,
9064 .flags = .{8980 .flags = .{
9065 .alignment = ptr_info.flags.alignment,8981 .alignment = ptr_info.flags.alignment,
...@@ -9177,7 +9093,7 @@ fn analyzeErrUnionPayloadPtr(...@@ -9177,7 +9093,7 @@ fn analyzeErrUnionPayloadPtr(
91779093
9178 const err_union_ty = operand_ty.childType(zcu);9094 const err_union_ty = operand_ty.childType(zcu);
9179 const payload_ty = err_union_ty.errorUnionPayload(zcu);9095 const payload_ty = err_union_ty.errorUnionPayload(zcu);
9180 const operand_pointer_ty = try sema.ptrType(.{9096 const operand_pointer_ty = try zcu.ptrTypeSema(.{
9181 .child = payload_ty.toIntern(),9097 .child = payload_ty.toIntern(),
9182 .flags = .{9098 .flags = .{
9183 .is_const = operand_ty.isConstPtr(zcu),9099 .is_const = operand_ty.isConstPtr(zcu),
...@@ -9202,13 +9118,13 @@ fn analyzeErrUnionPayloadPtr(...@@ -9202,13 +9118,13 @@ fn analyzeErrUnionPayloadPtr(
9202 const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);9118 const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
9203 try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr);9119 try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr);
9204 }9120 }
9205 return Air.internedToRef((try ptr_val.ptrEuPayload(sema)).toIntern());9121 return Air.internedToRef((try ptr_val.ptrEuPayload(zcu)).toIntern());
9206 }9122 }
9207 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {9123 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
9208 if (val.getErrorName(zcu).unwrap()) |name| {9124 if (val.getErrorName(zcu).unwrap()) |name| {
9209 return sema.failWithComptimeErrorRetTrace(block, src, name);9125 return sema.failWithComptimeErrorRetTrace(block, src, name);
9210 }9126 }
9211 return Air.internedToRef((try ptr_val.ptrEuPayload(sema)).toIntern());9127 return Air.internedToRef((try ptr_val.ptrEuPayload(zcu)).toIntern());
9212 }9128 }
9213 }9129 }
92149130
...@@ -9656,17 +9572,8 @@ fn funcCommon(...@@ -9656,17 +9572,8 @@ fn funcCommon(
9656 }9572 }
9657 }9573 }
96589574
9659 var ret_ty_requires_comptime = false;9575 const ret_ty_requires_comptime = try sema.typeRequiresComptime(bare_return_type);
9660 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {9576 const ret_poison = bare_return_type.isGenericPoison();
9661 ret_ty_requires_comptime = ret_comptime;
9662 break :rp bare_return_type.isGenericPoison();
9663 } else |err| switch (err) {
9664 error.GenericPoison => rp: {
9665 is_generic = true;
9666 break :rp true;
9667 },
9668 else => |e| return e,
9669 };
9670 const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;9577 const final_is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
96719578
9672 const param_types = block.params.items(.ty);9579 const param_types = block.params.items(.ty);
...@@ -10014,8 +9921,8 @@ fn finishFunc(...@@ -10014,8 +9921,8 @@ fn finishFunc(
10014 if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {9921 if (!final_is_generic and sema.wantErrorReturnTracing(return_type)) {
10015 // Make sure that StackTrace's fields are resolved so that the backend can9922 // Make sure that StackTrace's fields are resolved so that the backend can
10016 // lower this fn type.9923 // lower this fn type.
10017 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");9924 const unresolved_stack_trace_ty = try mod.getBuiltinType("StackTrace");
10018 try sema.resolveTypeFields(unresolved_stack_trace_ty);9925 try unresolved_stack_trace_ty.resolveFields(mod);
10019 }9926 }
100209927
10021 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);9928 return Air.internedToRef(if (opt_func_index != .none) opt_func_index else func_ty);
...@@ -10074,21 +9981,7 @@ fn zirParam(...@@ -10074,21 +9981,7 @@ fn zirParam(
10074 }9981 }
10075 };9982 };
100769983
10077 const is_comptime = sema.typeRequiresComptime(param_ty) catch |err| switch (err) {9984 const is_comptime = try sema.typeRequiresComptime(param_ty) or comptime_syntax;
10078 error.GenericPoison => {
10079 // The type is not available until the generic instantiation.
10080 // We result the param instruction with a poison value and
10081 // insert an anytype parameter.
10082 try block.params.append(sema.arena, .{
10083 .ty = .generic_poison_type,
10084 .is_comptime = comptime_syntax,
10085 .name = param_name,
10086 });
10087 sema.inst_map.putAssumeCapacity(inst, .generic_poison);
10088 return;
10089 },
10090 else => |e| return e,
10091 } or comptime_syntax;
100929985
10093 try block.params.append(sema.arena, .{9986 try block.params.append(sema.arena, .{
10094 .ty = param_ty.toIntern(),9987 .ty = param_ty.toIntern(),
...@@ -10215,7 +10108,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10215,7 +10108,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10215 }10108 }
10216 return Air.internedToRef((try zcu.intValue(10109 return Air.internedToRef((try zcu.intValue(
10217 Type.usize,10110 Type.usize,
10218 (try operand_val.getUnsignedIntAdvanced(zcu, sema)).?,10111 (try operand_val.getUnsignedIntAdvanced(zcu, .sema)).?,
10219 )).toIntern());10112 )).toIntern());
10220 }10113 }
10221 const len = operand_ty.vectorLen(zcu);10114 const len = operand_ty.vectorLen(zcu);
...@@ -10227,7 +10120,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -10227,7 +10120,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
10227 new_elem.* = (try zcu.undefValue(Type.usize)).toIntern();10120 new_elem.* = (try zcu.undefValue(Type.usize)).toIntern();
10228 continue;10121 continue;
10229 }10122 }
10230 const addr = try ptr_val.getUnsignedIntAdvanced(zcu, sema) orelse {10123 const addr = try ptr_val.getUnsignedIntAdvanced(zcu, .sema) orelse {
10231 // A vector element wasn't an integer pointer. This is a runtime operation.10124 // A vector element wasn't an integer pointer. This is a runtime operation.
10232 break :ct;10125 break :ct;
10233 };10126 };
...@@ -11100,7 +10993,7 @@ const SwitchProngAnalysis = struct {...@@ -11100,7 +10993,7 @@ const SwitchProngAnalysis = struct {
11100 const union_obj = zcu.typeToUnion(operand_ty).?;10993 const union_obj = zcu.typeToUnion(operand_ty).?;
11101 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);10994 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
11102 if (capture_byref) {10995 if (capture_byref) {
11103 const ptr_field_ty = try sema.ptrType(.{10996 const ptr_field_ty = try zcu.ptrTypeSema(.{
11104 .child = field_ty.toIntern(),10997 .child = field_ty.toIntern(),
11105 .flags = .{10998 .flags = .{
11106 .is_const = !operand_ptr_ty.ptrIsMutable(zcu),10999 .is_const = !operand_ptr_ty.ptrIsMutable(zcu),
...@@ -11109,7 +11002,7 @@ const SwitchProngAnalysis = struct {...@@ -11109,7 +11002,7 @@ const SwitchProngAnalysis = struct {
11109 },11002 },
11110 });11003 });
11111 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |union_ptr| {11004 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |union_ptr| {
11112 return Air.internedToRef((try union_ptr.ptrField(field_index, sema)).toIntern());11005 return Air.internedToRef((try union_ptr.ptrField(field_index, zcu)).toIntern());
11113 }11006 }
11114 return block.addStructFieldPtr(spa.operand_ptr, field_index, ptr_field_ty);11007 return block.addStructFieldPtr(spa.operand_ptr, field_index, ptr_field_ty);
11115 } else {11008 } else {
...@@ -11203,7 +11096,7 @@ const SwitchProngAnalysis = struct {...@@ -11203,7 +11096,7 @@ const SwitchProngAnalysis = struct {
11203 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len);11096 const dummy_captures = try sema.arena.alloc(Air.Inst.Ref, case_vals.len);
11204 for (field_indices, dummy_captures) |field_idx, *dummy| {11097 for (field_indices, dummy_captures) |field_idx, *dummy| {
11205 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]);11098 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]);
11206 const field_ptr_ty = try sema.ptrType(.{11099 const field_ptr_ty = try zcu.ptrTypeSema(.{
11207 .child = field_ty.toIntern(),11100 .child = field_ty.toIntern(),
11208 .flags = .{11101 .flags = .{
11209 .is_const = operand_ptr_info.flags.is_const,11102 .is_const = operand_ptr_info.flags.is_const,
...@@ -11239,7 +11132,7 @@ const SwitchProngAnalysis = struct {...@@ -11239,7 +11132,7 @@ const SwitchProngAnalysis = struct {
1123911132
11240 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |op_ptr_val| {11133 if (try sema.resolveDefinedValue(block, operand_src, spa.operand_ptr)) |op_ptr_val| {
11241 if (op_ptr_val.isUndef(zcu)) return zcu.undefRef(capture_ptr_ty);11134 if (op_ptr_val.isUndef(zcu)) return zcu.undefRef(capture_ptr_ty);
11242 const field_ptr_val = try op_ptr_val.ptrField(first_field_index, sema);11135 const field_ptr_val = try op_ptr_val.ptrField(first_field_index, zcu);
11243 return Air.internedToRef((try zcu.getCoerced(field_ptr_val, capture_ptr_ty)).toIntern());11136 return Air.internedToRef((try zcu.getCoerced(field_ptr_val, capture_ptr_ty)).toIntern());
11244 }11137 }
1124511138
...@@ -11452,7 +11345,7 @@ fn switchCond(...@@ -11452,7 +11345,7 @@ fn switchCond(
11452 },11345 },
1145311346
11454 .Union => {11347 .Union => {
11455 try sema.resolveTypeFields(operand_ty);11348 try operand_ty.resolveFields(mod);
11456 const enum_ty = operand_ty.unionTagType(mod) orelse {11349 const enum_ty = operand_ty.unionTagType(mod) orelse {
11457 const msg = msg: {11350 const msg = msg: {
11458 const msg = try sema.errMsg(src, "switch on union with no attached enum", .{});11351 const msg = try sema.errMsg(src, "switch on union with no attached enum", .{});
...@@ -13744,7 +13637,7 @@ fn maybeErrorUnwrap(...@@ -13744,7 +13637,7 @@ fn maybeErrorUnwrap(
13744 return true;13637 return true;
13745 }13638 }
1374613639
13747 const panic_fn = try sema.getBuiltin("panicUnwrapError");13640 const panic_fn = try mod.getBuiltin("panicUnwrapError");
13748 const err_return_trace = try sema.getErrorReturnTrace(block);13641 const err_return_trace = try sema.getErrorReturnTrace(block);
13749 const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };13642 const args: [2]Air.Inst.Ref = .{ err_return_trace, operand };
13750 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");13643 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
...@@ -13754,7 +13647,7 @@ fn maybeErrorUnwrap(...@@ -13754,7 +13647,7 @@ fn maybeErrorUnwrap(
13754 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;13647 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
13755 const msg_inst = try sema.resolveInst(inst_data.operand);13648 const msg_inst = try sema.resolveInst(inst_data.operand);
1375613649
13757 const panic_fn = try sema.getBuiltin("panic");13650 const panic_fn = try mod.getBuiltin("panic");
13758 const err_return_trace = try sema.getErrorReturnTrace(block);13651 const err_return_trace = try sema.getErrorReturnTrace(block);
13759 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };13652 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
13760 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");13653 try sema.callBuiltin(block, operand_src, panic_fn, .auto, &args, .@"safety check");
...@@ -13819,7 +13712,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -13819,7 +13712,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
13819 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{13712 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, .{
13820 .needed_comptime_reason = "field name must be comptime-known",13713 .needed_comptime_reason = "field name must be comptime-known",
13821 });13714 });
13822 try sema.resolveTypeFields(ty);13715 try ty.resolveFields(mod);
13823 const ip = &mod.intern_pool;13716 const ip = &mod.intern_pool;
1382413717
13825 const has_field = hf: {13718 const has_field = hf: {
...@@ -13934,7 +13827,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -13934,7 +13827,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
13934 return sema.fail(block, operand_src, "file path name cannot be empty", .{});13827 return sema.fail(block, operand_src, "file path name cannot be empty", .{});
13935 }13828 }
1393613829
13937 const val = mod.embedFile(block.getFileScope(mod), name, operand_src.upgrade(mod)) catch |err| switch (err) {13830 const val = mod.embedFile(block.getFileScope(mod), name, operand_src) catch |err| switch (err) {
13938 error.ImportOutsideModulePath => {13831 error.ImportOutsideModulePath => {
13939 return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name});13832 return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name});
13940 },13833 },
...@@ -13999,7 +13892,7 @@ fn zirShl(...@@ -13999,7 +13892,7 @@ fn zirShl(
13999 return mod.undefRef(sema.typeOf(lhs));13892 return mod.undefRef(sema.typeOf(lhs));
14000 }13893 }
14001 // If rhs is 0, return lhs without doing any calculations.13894 // If rhs is 0, return lhs without doing any calculations.
14002 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {13895 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
14003 return lhs;13896 return lhs;
14004 }13897 }
14005 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt and air_tag != .shl_sat) {13898 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt and air_tag != .shl_sat) {
...@@ -14164,7 +14057,7 @@ fn zirShr(...@@ -14164,7 +14057,7 @@ fn zirShr(
14164 return mod.undefRef(lhs_ty);14057 return mod.undefRef(lhs_ty);
14165 }14058 }
14166 // If rhs is 0, return lhs without doing any calculations.14059 // If rhs is 0, return lhs without doing any calculations.
14167 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {14060 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
14168 return lhs;14061 return lhs;
14169 }14062 }
14170 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt) {14063 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt) {
...@@ -14211,7 +14104,7 @@ fn zirShr(...@@ -14211,7 +14104,7 @@ fn zirShr(
14211 if (air_tag == .shr_exact) {14104 if (air_tag == .shr_exact) {
14212 // Detect if any ones would be shifted out.14105 // Detect if any ones would be shifted out.
14213 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, mod);14106 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, mod);
14214 if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema))) {14107 if (!(try truncated.compareAllWithZeroSema(.eq, mod))) {
14215 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});14108 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});
14216 }14109 }
14217 }14110 }
...@@ -14635,12 +14528,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14635,12 +14528,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14635 try sema.requireRuntimeBlock(block, src, runtime_src);14528 try sema.requireRuntimeBlock(block, src, runtime_src);
1463614529
14637 if (ptr_addrspace) |ptr_as| {14530 if (ptr_addrspace) |ptr_as| {
14638 const alloc_ty = try sema.ptrType(.{14531 const alloc_ty = try mod.ptrTypeSema(.{
14639 .child = result_ty.toIntern(),14532 .child = result_ty.toIntern(),
14640 .flags = .{ .address_space = ptr_as },14533 .flags = .{ .address_space = ptr_as },
14641 });14534 });
14642 const alloc = try block.addTy(.alloc, alloc_ty);14535 const alloc = try block.addTy(.alloc, alloc_ty);
14643 const elem_ptr_ty = try sema.ptrType(.{14536 const elem_ptr_ty = try mod.ptrTypeSema(.{
14644 .child = resolved_elem_ty.toIntern(),14537 .child = resolved_elem_ty.toIntern(),
14645 .flags = .{ .address_space = ptr_as },14538 .flags = .{ .address_space = ptr_as },
14646 });14539 });
...@@ -14723,7 +14616,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins...@@ -14723,7 +14616,7 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
14723 .none => null,14616 .none => null,
14724 else => Value.fromInterned(ptr_info.sentinel),14617 else => Value.fromInterned(ptr_info.sentinel),
14725 },14618 },
14726 .len = try val.sliceLen(sema),14619 .len = try val.sliceLen(mod),
14727 };14620 };
14728 },14621 },
14729 .One => {14622 .One => {
...@@ -14965,12 +14858,12 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -14965,12 +14858,12 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
14965 }14858 }
1496614859
14967 if (ptr_addrspace) |ptr_as| {14860 if (ptr_addrspace) |ptr_as| {
14968 const alloc_ty = try sema.ptrType(.{14861 const alloc_ty = try mod.ptrTypeSema(.{
14969 .child = result_ty.toIntern(),14862 .child = result_ty.toIntern(),
14970 .flags = .{ .address_space = ptr_as },14863 .flags = .{ .address_space = ptr_as },
14971 });14864 });
14972 const alloc = try block.addTy(.alloc, alloc_ty);14865 const alloc = try block.addTy(.alloc, alloc_ty);
14973 const elem_ptr_ty = try sema.ptrType(.{14866 const elem_ptr_ty = try mod.ptrTypeSema(.{
14974 .child = lhs_info.elem_type.toIntern(),14867 .child = lhs_info.elem_type.toIntern(),
14975 .flags = .{ .address_space = ptr_as },14868 .flags = .{ .address_space = ptr_as },
14976 });14869 });
...@@ -15158,7 +15051,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15158,7 +15051,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15158 .Int, .ComptimeInt, .ComptimeFloat => {15051 .Int, .ComptimeInt, .ComptimeFloat => {
15159 if (maybe_lhs_val) |lhs_val| {15052 if (maybe_lhs_val) |lhs_val| {
15160 if (!lhs_val.isUndef(mod)) {15053 if (!lhs_val.isUndef(mod)) {
15161 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {15054 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
15162 const scalar_zero = switch (scalar_tag) {15055 const scalar_zero = switch (scalar_tag) {
15163 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),15056 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
15164 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),15057 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
...@@ -15173,7 +15066,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15173,7 +15066,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15173 if (rhs_val.isUndef(mod)) {15066 if (rhs_val.isUndef(mod)) {
15174 return sema.failWithUseOfUndef(block, rhs_src);15067 return sema.failWithUseOfUndef(block, rhs_src);
15175 }15068 }
15176 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15069 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15177 return sema.failWithDivideByZero(block, rhs_src);15070 return sema.failWithDivideByZero(block, rhs_src);
15178 }15071 }
15179 // TODO: if the RHS is one, return the LHS directly15072 // TODO: if the RHS is one, return the LHS directly
...@@ -15294,7 +15187,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15294,7 +15187,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15294 if (lhs_val.isUndef(mod)) {15187 if (lhs_val.isUndef(mod)) {
15295 return sema.failWithUseOfUndef(block, rhs_src);15188 return sema.failWithUseOfUndef(block, rhs_src);
15296 } else {15189 } else {
15297 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {15190 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
15298 const scalar_zero = switch (scalar_tag) {15191 const scalar_zero = switch (scalar_tag) {
15299 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),15192 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
15300 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),15193 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
...@@ -15309,7 +15202,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15309,7 +15202,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15309 if (rhs_val.isUndef(mod)) {15202 if (rhs_val.isUndef(mod)) {
15310 return sema.failWithUseOfUndef(block, rhs_src);15203 return sema.failWithUseOfUndef(block, rhs_src);
15311 }15204 }
15312 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15205 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15313 return sema.failWithDivideByZero(block, rhs_src);15206 return sema.failWithDivideByZero(block, rhs_src);
15314 }15207 }
15315 // TODO: if the RHS is one, return the LHS directly15208 // TODO: if the RHS is one, return the LHS directly
...@@ -15461,7 +15354,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15461,7 +15354,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15461 // If the lhs is undefined, result is undefined.15354 // If the lhs is undefined, result is undefined.
15462 if (maybe_lhs_val) |lhs_val| {15355 if (maybe_lhs_val) |lhs_val| {
15463 if (!lhs_val.isUndef(mod)) {15356 if (!lhs_val.isUndef(mod)) {
15464 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {15357 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
15465 const scalar_zero = switch (scalar_tag) {15358 const scalar_zero = switch (scalar_tag) {
15466 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),15359 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
15467 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),15360 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
...@@ -15476,7 +15369,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15476,7 +15369,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15476 if (rhs_val.isUndef(mod)) {15369 if (rhs_val.isUndef(mod)) {
15477 return sema.failWithUseOfUndef(block, rhs_src);15370 return sema.failWithUseOfUndef(block, rhs_src);
15478 }15371 }
15479 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15372 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15480 return sema.failWithDivideByZero(block, rhs_src);15373 return sema.failWithDivideByZero(block, rhs_src);
15481 }15374 }
15482 // TODO: if the RHS is one, return the LHS directly15375 // TODO: if the RHS is one, return the LHS directly
...@@ -15571,7 +15464,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15571,7 +15464,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15571 // If the lhs is undefined, result is undefined.15464 // If the lhs is undefined, result is undefined.
15572 if (maybe_lhs_val) |lhs_val| {15465 if (maybe_lhs_val) |lhs_val| {
15573 if (!lhs_val.isUndef(mod)) {15466 if (!lhs_val.isUndef(mod)) {
15574 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {15467 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
15575 const scalar_zero = switch (scalar_tag) {15468 const scalar_zero = switch (scalar_tag) {
15576 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),15469 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
15577 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),15470 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
...@@ -15586,7 +15479,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -15586,7 +15479,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
15586 if (rhs_val.isUndef(mod)) {15479 if (rhs_val.isUndef(mod)) {
15587 return sema.failWithUseOfUndef(block, rhs_src);15480 return sema.failWithUseOfUndef(block, rhs_src);
15588 }15481 }
15589 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15482 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15590 return sema.failWithDivideByZero(block, rhs_src);15483 return sema.failWithDivideByZero(block, rhs_src);
15591 }15484 }
15592 }15485 }
...@@ -15811,7 +15704,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15811,7 +15704,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15811 if (lhs_val.isUndef(mod)) {15704 if (lhs_val.isUndef(mod)) {
15812 return sema.failWithUseOfUndef(block, lhs_src);15705 return sema.failWithUseOfUndef(block, lhs_src);
15813 }15706 }
15814 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {15707 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
15815 const scalar_zero = switch (scalar_tag) {15708 const scalar_zero = switch (scalar_tag) {
15816 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),15709 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
15817 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),15710 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
...@@ -15830,18 +15723,18 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15830,18 +15723,18 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15830 if (rhs_val.isUndef(mod)) {15723 if (rhs_val.isUndef(mod)) {
15831 return sema.failWithUseOfUndef(block, rhs_src);15724 return sema.failWithUseOfUndef(block, rhs_src);
15832 }15725 }
15833 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15726 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15834 return sema.failWithDivideByZero(block, rhs_src);15727 return sema.failWithDivideByZero(block, rhs_src);
15835 }15728 }
15836 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))) {15729 if (!(try rhs_val.compareAllWithZeroSema(.gte, mod))) {
15837 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);15730 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
15838 }15731 }
15839 if (maybe_lhs_val) |lhs_val| {15732 if (maybe_lhs_val) |lhs_val| {
15840 const rem_result = try sema.intRem(resolved_type, lhs_val, rhs_val);15733 const rem_result = try sema.intRem(resolved_type, lhs_val, rhs_val);
15841 // If this answer could possibly be different by doing `intMod`,15734 // If this answer could possibly be different by doing `intMod`,
15842 // we must emit a compile error. Otherwise, it's OK.15735 // we must emit a compile error. Otherwise, it's OK.
15843 if (!(try lhs_val.compareAllWithZeroAdvanced(.gte, sema)) and15736 if (!(try lhs_val.compareAllWithZeroSema(.gte, mod)) and
15844 !(try rem_result.compareAllWithZeroAdvanced(.eq, sema)))15737 !(try rem_result.compareAllWithZeroSema(.eq, mod)))
15845 {15738 {
15846 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);15739 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
15847 }15740 }
...@@ -15859,14 +15752,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -15859,14 +15752,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
15859 if (rhs_val.isUndef(mod)) {15752 if (rhs_val.isUndef(mod)) {
15860 return sema.failWithUseOfUndef(block, rhs_src);15753 return sema.failWithUseOfUndef(block, rhs_src);
15861 }15754 }
15862 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15755 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15863 return sema.failWithDivideByZero(block, rhs_src);15756 return sema.failWithDivideByZero(block, rhs_src);
15864 }15757 }
15865 if (!(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))) {15758 if (!(try rhs_val.compareAllWithZeroSema(.gte, mod))) {
15866 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);15759 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
15867 }15760 }
15868 if (maybe_lhs_val) |lhs_val| {15761 if (maybe_lhs_val) |lhs_val| {
15869 if (lhs_val.isUndef(mod) or !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))) {15762 if (lhs_val.isUndef(mod) or !(try lhs_val.compareAllWithZeroSema(.gte, mod))) {
15870 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);15763 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
15871 }15764 }
15872 return Air.internedToRef((try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod)).toIntern());15765 return Air.internedToRef((try lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod)).toIntern());
...@@ -15917,8 +15810,8 @@ fn intRemScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) CompileErr...@@ -15917,8 +15810,8 @@ fn intRemScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) CompileErr
15917 // resorting to BigInt first.15810 // resorting to BigInt first.
15918 var lhs_space: Value.BigIntSpace = undefined;15811 var lhs_space: Value.BigIntSpace = undefined;
15919 var rhs_space: Value.BigIntSpace = undefined;15812 var rhs_space: Value.BigIntSpace = undefined;
15920 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);15813 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, .sema);
15921 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);15814 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, .sema);
15922 const limbs_q = try sema.arena.alloc(15815 const limbs_q = try sema.arena.alloc(
15923 math.big.Limb,15816 math.big.Limb,
15924 lhs_bigint.limbs.len,15817 lhs_bigint.limbs.len,
...@@ -15994,7 +15887,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -15994,7 +15887,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
15994 if (rhs_val.isUndef(mod)) {15887 if (rhs_val.isUndef(mod)) {
15995 return sema.failWithUseOfUndef(block, rhs_src);15888 return sema.failWithUseOfUndef(block, rhs_src);
15996 }15889 }
15997 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15890 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
15998 return sema.failWithDivideByZero(block, rhs_src);15891 return sema.failWithDivideByZero(block, rhs_src);
15999 }15892 }
16000 if (maybe_lhs_val) |lhs_val| {15893 if (maybe_lhs_val) |lhs_val| {
...@@ -16010,7 +15903,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -16010,7 +15903,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16010 if (rhs_val.isUndef(mod)) {15903 if (rhs_val.isUndef(mod)) {
16011 return sema.failWithUseOfUndef(block, rhs_src);15904 return sema.failWithUseOfUndef(block, rhs_src);
16012 }15905 }
16013 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15906 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
16014 return sema.failWithDivideByZero(block, rhs_src);15907 return sema.failWithDivideByZero(block, rhs_src);
16015 }15908 }
16016 }15909 }
...@@ -16089,7 +15982,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -16089,7 +15982,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16089 if (rhs_val.isUndef(mod)) {15982 if (rhs_val.isUndef(mod)) {
16090 return sema.failWithUseOfUndef(block, rhs_src);15983 return sema.failWithUseOfUndef(block, rhs_src);
16091 }15984 }
16092 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {15985 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
16093 return sema.failWithDivideByZero(block, rhs_src);15986 return sema.failWithDivideByZero(block, rhs_src);
16094 }15987 }
16095 if (maybe_lhs_val) |lhs_val| {15988 if (maybe_lhs_val) |lhs_val| {
...@@ -16105,7 +15998,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins...@@ -16105,7 +15998,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
16105 if (rhs_val.isUndef(mod)) {15998 if (rhs_val.isUndef(mod)) {
16106 return sema.failWithUseOfUndef(block, rhs_src);15999 return sema.failWithUseOfUndef(block, rhs_src);
16107 }16000 }
16108 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {16001 if (!(try rhs_val.compareAllWithZeroSema(.neq, mod))) {
16109 return sema.failWithDivideByZero(block, rhs_src);16002 return sema.failWithDivideByZero(block, rhs_src);
16110 }16003 }
16111 }16004 }
...@@ -16192,12 +16085,12 @@ fn zirOverflowArithmetic(...@@ -16192,12 +16085,12 @@ fn zirOverflowArithmetic(
16192 // to the result, even if it is undefined..16085 // to the result, even if it is undefined..
16193 // Otherwise, if either of the argument is undefined, undefined is returned.16086 // Otherwise, if either of the argument is undefined, undefined is returned.
16194 if (maybe_lhs_val) |lhs_val| {16087 if (maybe_lhs_val) |lhs_val| {
16195 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16088 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroSema(.eq, mod))) {
16196 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };16089 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
16197 }16090 }
16198 }16091 }
16199 if (maybe_rhs_val) |rhs_val| {16092 if (maybe_rhs_val) |rhs_val| {
16200 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16093 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroSema(.eq, mod))) {
16201 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16094 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
16202 }16095 }
16203 }16096 }
...@@ -16218,7 +16111,7 @@ fn zirOverflowArithmetic(...@@ -16218,7 +16111,7 @@ fn zirOverflowArithmetic(
16218 if (maybe_rhs_val) |rhs_val| {16111 if (maybe_rhs_val) |rhs_val| {
16219 if (rhs_val.isUndef(mod)) {16112 if (rhs_val.isUndef(mod)) {
16220 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };16113 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
16221 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16114 } else if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16222 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16115 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
16223 } else if (maybe_lhs_val) |lhs_val| {16116 } else if (maybe_lhs_val) |lhs_val| {
16224 if (lhs_val.isUndef(mod)) {16117 if (lhs_val.isUndef(mod)) {
...@@ -16237,7 +16130,7 @@ fn zirOverflowArithmetic(...@@ -16237,7 +16130,7 @@ fn zirOverflowArithmetic(
16237 const scalar_one = try mod.intValue(dest_ty.scalarType(mod), 1);16130 const scalar_one = try mod.intValue(dest_ty.scalarType(mod), 1);
16238 if (maybe_lhs_val) |lhs_val| {16131 if (maybe_lhs_val) |lhs_val| {
16239 if (!lhs_val.isUndef(mod)) {16132 if (!lhs_val.isUndef(mod)) {
16240 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16133 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
16241 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16134 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
16242 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {16135 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
16243 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };16136 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
...@@ -16247,7 +16140,7 @@ fn zirOverflowArithmetic(...@@ -16247,7 +16140,7 @@ fn zirOverflowArithmetic(
1624716140
16248 if (maybe_rhs_val) |rhs_val| {16141 if (maybe_rhs_val) |rhs_val| {
16249 if (!rhs_val.isUndef(mod)) {16142 if (!rhs_val.isUndef(mod)) {
16250 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16143 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16251 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };16144 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
16252 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {16145 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
16253 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16146 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
...@@ -16271,12 +16164,12 @@ fn zirOverflowArithmetic(...@@ -16271,12 +16164,12 @@ fn zirOverflowArithmetic(
16271 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.16164 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
16272 // Oterhwise if either of the arguments is undefined, both results are undefined.16165 // Oterhwise if either of the arguments is undefined, both results are undefined.
16273 if (maybe_lhs_val) |lhs_val| {16166 if (maybe_lhs_val) |lhs_val| {
16274 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16167 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroSema(.eq, mod))) {
16275 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16168 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
16276 }16169 }
16277 }16170 }
16278 if (maybe_rhs_val) |rhs_val| {16171 if (maybe_rhs_val) |rhs_val| {
16279 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16172 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroSema(.eq, mod))) {
16280 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };16173 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
16281 }16174 }
16282 }16175 }
...@@ -16427,7 +16320,7 @@ fn analyzeArithmetic(...@@ -16427,7 +16320,7 @@ fn analyzeArithmetic(
16427 // overflow (max_int), causing illegal behavior.16320 // overflow (max_int), causing illegal behavior.
16428 // For floats: either operand being undef makes the result undef.16321 // For floats: either operand being undef makes the result undef.
16429 if (maybe_lhs_val) |lhs_val| {16322 if (maybe_lhs_val) |lhs_val| {
16430 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16323 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroSema(.eq, mod))) {
16431 return casted_rhs;16324 return casted_rhs;
16432 }16325 }
16433 }16326 }
...@@ -16439,7 +16332,7 @@ fn analyzeArithmetic(...@@ -16439,7 +16332,7 @@ fn analyzeArithmetic(
16439 return mod.undefRef(resolved_type);16332 return mod.undefRef(resolved_type);
16440 }16333 }
16441 }16334 }
16442 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16335 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16443 return casted_lhs;16336 return casted_lhs;
16444 }16337 }
16445 }16338 }
...@@ -16471,7 +16364,7 @@ fn analyzeArithmetic(...@@ -16471,7 +16364,7 @@ fn analyzeArithmetic(
16471 // If either of the operands are zero, the other operand is returned.16364 // If either of the operands are zero, the other operand is returned.
16472 // If either of the operands are undefined, the result is undefined.16365 // If either of the operands are undefined, the result is undefined.
16473 if (maybe_lhs_val) |lhs_val| {16366 if (maybe_lhs_val) |lhs_val| {
16474 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16367 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroSema(.eq, mod))) {
16475 return casted_rhs;16368 return casted_rhs;
16476 }16369 }
16477 }16370 }
...@@ -16479,7 +16372,7 @@ fn analyzeArithmetic(...@@ -16479,7 +16372,7 @@ fn analyzeArithmetic(
16479 if (rhs_val.isUndef(mod)) {16372 if (rhs_val.isUndef(mod)) {
16480 return mod.undefRef(resolved_type);16373 return mod.undefRef(resolved_type);
16481 }16374 }
16482 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16375 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16483 return casted_lhs;16376 return casted_lhs;
16484 }16377 }
16485 if (maybe_lhs_val) |lhs_val| {16378 if (maybe_lhs_val) |lhs_val| {
...@@ -16492,7 +16385,7 @@ fn analyzeArithmetic(...@@ -16492,7 +16385,7 @@ fn analyzeArithmetic(
16492 // If either of the operands are zero, then the other operand is returned.16385 // If either of the operands are zero, then the other operand is returned.
16493 // If either of the operands are undefined, the result is undefined.16386 // If either of the operands are undefined, the result is undefined.
16494 if (maybe_lhs_val) |lhs_val| {16387 if (maybe_lhs_val) |lhs_val| {
16495 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {16388 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroSema(.eq, mod))) {
16496 return casted_rhs;16389 return casted_rhs;
16497 }16390 }
16498 }16391 }
...@@ -16500,7 +16393,7 @@ fn analyzeArithmetic(...@@ -16500,7 +16393,7 @@ fn analyzeArithmetic(
16500 if (rhs_val.isUndef(mod)) {16393 if (rhs_val.isUndef(mod)) {
16501 return mod.undefRef(resolved_type);16394 return mod.undefRef(resolved_type);
16502 }16395 }
16503 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16396 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16504 return casted_lhs;16397 return casted_lhs;
16505 }16398 }
16506 if (maybe_lhs_val) |lhs_val| {16399 if (maybe_lhs_val) |lhs_val| {
...@@ -16541,7 +16434,7 @@ fn analyzeArithmetic(...@@ -16541,7 +16434,7 @@ fn analyzeArithmetic(
16541 return mod.undefRef(resolved_type);16434 return mod.undefRef(resolved_type);
16542 }16435 }
16543 }16436 }
16544 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16437 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16545 return casted_lhs;16438 return casted_lhs;
16546 }16439 }
16547 }16440 }
...@@ -16576,7 +16469,7 @@ fn analyzeArithmetic(...@@ -16576,7 +16469,7 @@ fn analyzeArithmetic(
16576 if (rhs_val.isUndef(mod)) {16469 if (rhs_val.isUndef(mod)) {
16577 return mod.undefRef(resolved_type);16470 return mod.undefRef(resolved_type);
16578 }16471 }
16579 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16472 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16580 return casted_lhs;16473 return casted_lhs;
16581 }16474 }
16582 }16475 }
...@@ -16597,7 +16490,7 @@ fn analyzeArithmetic(...@@ -16597,7 +16490,7 @@ fn analyzeArithmetic(
16597 if (rhs_val.isUndef(mod)) {16490 if (rhs_val.isUndef(mod)) {
16598 return mod.undefRef(resolved_type);16491 return mod.undefRef(resolved_type);
16599 }16492 }
16600 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16493 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16601 return casted_lhs;16494 return casted_lhs;
16602 }16495 }
16603 }16496 }
...@@ -16644,7 +16537,7 @@ fn analyzeArithmetic(...@@ -16644,7 +16537,7 @@ fn analyzeArithmetic(
16644 if (lhs_val.isNan(mod)) {16537 if (lhs_val.isNan(mod)) {
16645 return Air.internedToRef(lhs_val.toIntern());16538 return Air.internedToRef(lhs_val.toIntern());
16646 }16539 }
16647 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) lz: {16540 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) lz: {
16648 if (maybe_rhs_val) |rhs_val| {16541 if (maybe_rhs_val) |rhs_val| {
16649 if (rhs_val.isNan(mod)) {16542 if (rhs_val.isNan(mod)) {
16650 return Air.internedToRef(rhs_val.toIntern());16543 return Air.internedToRef(rhs_val.toIntern());
...@@ -16675,7 +16568,7 @@ fn analyzeArithmetic(...@@ -16675,7 +16568,7 @@ fn analyzeArithmetic(
16675 if (rhs_val.isNan(mod)) {16568 if (rhs_val.isNan(mod)) {
16676 return Air.internedToRef(rhs_val.toIntern());16569 return Air.internedToRef(rhs_val.toIntern());
16677 }16570 }
16678 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: {16571 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) rz: {
16679 if (maybe_lhs_val) |lhs_val| {16572 if (maybe_lhs_val) |lhs_val| {
16680 if (lhs_val.isInf(mod)) {16573 if (lhs_val.isInf(mod)) {
16681 return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan(f128))).toIntern());16574 return Air.internedToRef((try mod.floatValue(resolved_type, std.math.nan(f128))).toIntern());
...@@ -16727,7 +16620,7 @@ fn analyzeArithmetic(...@@ -16727,7 +16620,7 @@ fn analyzeArithmetic(
16727 };16620 };
16728 if (maybe_lhs_val) |lhs_val| {16621 if (maybe_lhs_val) |lhs_val| {
16729 if (!lhs_val.isUndef(mod)) {16622 if (!lhs_val.isUndef(mod)) {
16730 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16623 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
16731 const zero_val = try sema.splat(resolved_type, scalar_zero);16624 const zero_val = try sema.splat(resolved_type, scalar_zero);
16732 return Air.internedToRef(zero_val.toIntern());16625 return Air.internedToRef(zero_val.toIntern());
16733 }16626 }
...@@ -16740,7 +16633,7 @@ fn analyzeArithmetic(...@@ -16740,7 +16633,7 @@ fn analyzeArithmetic(
16740 if (rhs_val.isUndef(mod)) {16633 if (rhs_val.isUndef(mod)) {
16741 return mod.undefRef(resolved_type);16634 return mod.undefRef(resolved_type);
16742 }16635 }
16743 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16636 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16744 const zero_val = try sema.splat(resolved_type, scalar_zero);16637 const zero_val = try sema.splat(resolved_type, scalar_zero);
16745 return Air.internedToRef(zero_val.toIntern());16638 return Air.internedToRef(zero_val.toIntern());
16746 }16639 }
...@@ -16772,7 +16665,7 @@ fn analyzeArithmetic(...@@ -16772,7 +16665,7 @@ fn analyzeArithmetic(
16772 };16665 };
16773 if (maybe_lhs_val) |lhs_val| {16666 if (maybe_lhs_val) |lhs_val| {
16774 if (!lhs_val.isUndef(mod)) {16667 if (!lhs_val.isUndef(mod)) {
16775 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16668 if (try lhs_val.compareAllWithZeroSema(.eq, mod)) {
16776 const zero_val = try sema.splat(resolved_type, scalar_zero);16669 const zero_val = try sema.splat(resolved_type, scalar_zero);
16777 return Air.internedToRef(zero_val.toIntern());16670 return Air.internedToRef(zero_val.toIntern());
16778 }16671 }
...@@ -16785,7 +16678,7 @@ fn analyzeArithmetic(...@@ -16785,7 +16678,7 @@ fn analyzeArithmetic(
16785 if (rhs_val.isUndef(mod)) {16678 if (rhs_val.isUndef(mod)) {
16786 return mod.undefRef(resolved_type);16679 return mod.undefRef(resolved_type);
16787 }16680 }
16788 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {16681 if (try rhs_val.compareAllWithZeroSema(.eq, mod)) {
16789 const zero_val = try sema.splat(resolved_type, scalar_zero);16682 const zero_val = try sema.splat(resolved_type, scalar_zero);
16790 return Air.internedToRef(zero_val.toIntern());16683 return Air.internedToRef(zero_val.toIntern());
16791 }16684 }
...@@ -16881,7 +16774,7 @@ fn analyzePtrArithmetic(...@@ -16881,7 +16774,7 @@ fn analyzePtrArithmetic(
1688116774
16882 const new_ptr_ty = t: {16775 const new_ptr_ty = t: {
16883 // Calculate the new pointer alignment.16776 // Calculate the new pointer alignment.
16884 // This code is duplicated in `elemPtrType`.16777 // This code is duplicated in `Type.elemPtrType`.
16885 if (ptr_info.flags.alignment == .none) {16778 if (ptr_info.flags.alignment == .none) {
16886 // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.16779 // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.
16887 break :t ptr_ty;16780 break :t ptr_ty;
...@@ -16890,7 +16783,7 @@ fn analyzePtrArithmetic(...@@ -16890,7 +16783,7 @@ fn analyzePtrArithmetic(
16890 // it being a multiple of the type size.16783 // it being a multiple of the type size.
16891 const elem_size = try sema.typeAbiSize(Type.fromInterned(ptr_info.child));16784 const elem_size = try sema.typeAbiSize(Type.fromInterned(ptr_info.child));
16892 const addend = if (opt_off_val) |off_val| a: {16785 const addend = if (opt_off_val) |off_val| a: {
16893 const off_int = try sema.usizeCast(block, offset_src, try off_val.toUnsignedIntAdvanced(sema));16786 const off_int = try sema.usizeCast(block, offset_src, try off_val.toUnsignedIntSema(mod));
16894 break :a elem_size * off_int;16787 break :a elem_size * off_int;
16895 } else elem_size;16788 } else elem_size;
1689616789
...@@ -16903,7 +16796,7 @@ fn analyzePtrArithmetic(...@@ -16903,7 +16796,7 @@ fn analyzePtrArithmetic(
16903 ));16796 ));
16904 assert(new_align != .none);16797 assert(new_align != .none);
1690516798
16906 break :t try sema.ptrType(.{16799 break :t try mod.ptrTypeSema(.{
16907 .child = ptr_info.child,16800 .child = ptr_info.child,
16908 .sentinel = ptr_info.sentinel,16801 .sentinel = ptr_info.sentinel,
16909 .flags = .{16802 .flags = .{
...@@ -16922,14 +16815,14 @@ fn analyzePtrArithmetic(...@@ -16922,14 +16815,14 @@ fn analyzePtrArithmetic(
16922 if (opt_off_val) |offset_val| {16815 if (opt_off_val) |offset_val| {
16923 if (ptr_val.isUndef(mod)) return mod.undefRef(new_ptr_ty);16816 if (ptr_val.isUndef(mod)) return mod.undefRef(new_ptr_ty);
1692416817
16925 const offset_int = try sema.usizeCast(block, offset_src, try offset_val.toUnsignedIntAdvanced(sema));16818 const offset_int = try sema.usizeCast(block, offset_src, try offset_val.toUnsignedIntSema(mod));
16926 if (offset_int == 0) return ptr;16819 if (offset_int == 0) return ptr;
16927 if (air_tag == .ptr_sub) {16820 if (air_tag == .ptr_sub) {
16928 const elem_size = try sema.typeAbiSize(Type.fromInterned(ptr_info.child));16821 const elem_size = try sema.typeAbiSize(Type.fromInterned(ptr_info.child));
16929 const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty);16822 const new_ptr_val = try sema.ptrSubtract(block, op_src, ptr_val, offset_int * elem_size, new_ptr_ty);
16930 return Air.internedToRef(new_ptr_val.toIntern());16823 return Air.internedToRef(new_ptr_val.toIntern());
16931 } else {16824 } else {
16932 const new_ptr_val = try mod.getCoerced(try ptr_val.ptrElem(offset_int, sema), new_ptr_ty);16825 const new_ptr_val = try mod.getCoerced(try ptr_val.ptrElem(offset_int, mod), new_ptr_ty);
16933 return Air.internedToRef(new_ptr_val.toIntern());16826 return Air.internedToRef(new_ptr_val.toIntern());
16934 }16827 }
16935 } else break :rs offset_src;16828 } else break :rs offset_src;
...@@ -17028,7 +16921,6 @@ fn zirAsm(...@@ -17028,7 +16921,6 @@ fn zirAsm(
17028 // Indicate the output is the asm instruction return value.16921 // Indicate the output is the asm instruction return value.
17029 arg.* = .none;16922 arg.* = .none;
17030 const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);16923 const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);
17031 try sema.queueFullTypeResolution(out_ty);
17032 expr_ty = Air.internedToRef(out_ty.toIntern());16924 expr_ty = Air.internedToRef(out_ty.toIntern());
17033 } else {16925 } else {
17034 arg.* = try sema.resolveInst(output.data.operand);16926 arg.* = try sema.resolveInst(output.data.operand);
...@@ -17063,7 +16955,6 @@ fn zirAsm(...@@ -17063,7 +16955,6 @@ fn zirAsm(
17063 .ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),16955 .ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
17064 else => {16956 else => {
17065 arg.* = uncasted_arg;16957 arg.* = uncasted_arg;
17066 try sema.queueFullTypeResolution(uncasted_arg_ty);
17067 },16958 },
17068 }16959 }
1706916960
...@@ -17222,7 +17113,7 @@ fn analyzeCmpUnionTag(...@@ -17222,7 +17113,7 @@ fn analyzeCmpUnionTag(
17222) CompileError!Air.Inst.Ref {17113) CompileError!Air.Inst.Ref {
17223 const mod = sema.mod;17114 const mod = sema.mod;
17224 const union_ty = sema.typeOf(un);17115 const union_ty = sema.typeOf(un);
17225 try sema.resolveTypeFields(union_ty);17116 try union_ty.resolveFields(mod);
17226 const union_tag_ty = union_ty.unionTagType(mod) orelse {17117 const union_tag_ty = union_ty.unionTagType(mod) orelse {
17227 const msg = msg: {17118 const msg = msg: {
17228 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});17119 const msg = try sema.errMsg(un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
...@@ -17438,9 +17329,6 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -17438,9 +17329,6 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
17438 => {},17329 => {},
17439 }17330 }
17440 const val = try ty.lazyAbiSize(mod);17331 const val = try ty.lazyAbiSize(mod);
17441 if (val.isLazySize(mod)) {
17442 try sema.queueFullTypeResolution(ty);
17443 }
17444 return Air.internedToRef(val.toIntern());17332 return Air.internedToRef(val.toIntern());
17445}17333}
1744617334
...@@ -17480,7 +17368,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -17480,7 +17368,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
17480 .AnyFrame,17368 .AnyFrame,
17481 => {},17369 => {},
17482 }17370 }
17483 const bit_size = try operand_ty.bitSizeAdvanced(mod, sema);17371 const bit_size = try operand_ty.bitSizeAdvanced(mod, .sema);
17484 return mod.intRef(Type.comptime_int, bit_size);17372 return mod.intRef(Type.comptime_int, bit_size);
17485}17373}
1748617374
...@@ -17507,7 +17395,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17507,7 +17395,7 @@ fn zirClosureGet(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
17507 .@"comptime" => |index| return Air.internedToRef(index),17395 .@"comptime" => |index| return Air.internedToRef(index),
17508 .runtime => |index| index,17396 .runtime => |index| index,
17509 .decl_val => |decl_index| return sema.analyzeDeclVal(block, src, decl_index),17397 .decl_val => |decl_index| return sema.analyzeDeclVal(block, src, decl_index),
17510 .decl_ref => |decl_index| return sema.analyzeDeclRef(decl_index),17398 .decl_ref => |decl_index| return sema.analyzeDeclRef(src, decl_index),
17511 };17399 };
1751217400
17513 // The comptime case is handled already above. Runtime case below.17401 // The comptime case is handled already above. Runtime case below.
...@@ -17666,7 +17554,7 @@ fn zirBuiltinSrc(...@@ -17666,7 +17554,7 @@ fn zirBuiltinSrc(
17666 } });17554 } });
17667 };17555 };
1766817556
17669 const src_loc_ty = try sema.getBuiltinType("SourceLocation");17557 const src_loc_ty = try mod.getBuiltinType("SourceLocation");
17670 const fields = .{17558 const fields = .{
17671 // file: [:0]const u8,17559 // file: [:0]const u8,
17672 file_name_val,17560 file_name_val,
...@@ -17690,7 +17578,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17690,7 +17578,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17690 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;17578 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
17691 const src = block.nodeOffset(inst_data.src_node);17579 const src = block.nodeOffset(inst_data.src_node);
17692 const ty = try sema.resolveType(block, src, inst_data.operand);17580 const ty = try sema.resolveType(block, src, inst_data.operand);
17693 const type_info_ty = try sema.getBuiltinType("Type");17581 const type_info_ty = try mod.getBuiltinType("Type");
17694 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;17582 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;
1769517583
17696 if (ty.typeDeclInst(mod)) |type_decl_inst| {17584 if (ty.typeDeclInst(mod)) |type_decl_inst| {
...@@ -17771,7 +17659,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17771,7 +17659,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17771 .ty = new_decl_ty.toIntern(),17659 .ty = new_decl_ty.toIntern(),
17772 .storage = .{ .elems = param_vals },17660 .storage = .{ .elems = param_vals },
17773 } });17661 } });
17774 const slice_ty = (try sema.ptrType(.{17662 const slice_ty = (try mod.ptrTypeSema(.{
17775 .child = param_info_ty.toIntern(),17663 .child = param_info_ty.toIntern(),
17776 .flags = .{17664 .flags = .{
17777 .size = .Slice,17665 .size = .Slice,
...@@ -17801,7 +17689,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17801,7 +17689,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17801 func_ty_info.return_type,17689 func_ty_info.return_type,
17802 } });17690 } });
1780317691
17804 const callconv_ty = try sema.getBuiltinType("CallingConvention");17692 const callconv_ty = try mod.getBuiltinType("CallingConvention");
1780517693
17806 const field_values = .{17694 const field_values = .{
17807 // calling_convention: CallingConvention,17695 // calling_convention: CallingConvention,
...@@ -17835,7 +17723,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17835,7 +17723,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17835 const int_info_decl = mod.declPtr(int_info_decl_index);17723 const int_info_decl = mod.declPtr(int_info_decl_index);
17836 const int_info_ty = int_info_decl.val.toType();17724 const int_info_ty = int_info_decl.val.toType();
1783717725
17838 const signedness_ty = try sema.getBuiltinType("Signedness");17726 const signedness_ty = try mod.getBuiltinType("Signedness");
17839 const info = ty.intInfo(mod);17727 const info = ty.intInfo(mod);
17840 const field_values = .{17728 const field_values = .{
17841 // signedness: Signedness,17729 // signedness: Signedness,
...@@ -17883,12 +17771,12 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -17883,12 +17771,12 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
17883 else17771 else
17884 try Type.fromInterned(info.child).lazyAbiAlignment(mod);17772 try Type.fromInterned(info.child).lazyAbiAlignment(mod);
1788517773
17886 const addrspace_ty = try sema.getBuiltinType("AddressSpace");17774 const addrspace_ty = try mod.getBuiltinType("AddressSpace");
17887 const pointer_ty = t: {17775 const pointer_ty = t: {
17888 const decl_index = (try sema.namespaceLookup(17776 const decl_index = (try sema.namespaceLookup(
17889 block,17777 block,
17890 src,17778 src,
17891 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod),17779 (try mod.getBuiltinType("Type")).getNamespaceIndex(mod),
17892 try ip.getOrPutString(gpa, "Pointer", .no_embedded_nulls),17780 try ip.getOrPutString(gpa, "Pointer", .no_embedded_nulls),
17893 )).?;17781 )).?;
17894 try sema.ensureDeclAnalyzed(decl_index);17782 try sema.ensureDeclAnalyzed(decl_index);
...@@ -18037,8 +17925,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18037,8 +17925,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18037 break :t set_field_ty_decl.val.toType();17925 break :t set_field_ty_decl.val.toType();
18038 };17926 };
1803917927
18040 try sema.queueFullTypeResolution(error_field_ty);
18041
18042 // Build our list of Error values17928 // Build our list of Error values
18043 // Optional value is only null if anyerror17929 // Optional value is only null if anyerror
18044 // Value can be zero-length slice otherwise17930 // Value can be zero-length slice otherwise
...@@ -18089,7 +17975,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18089,7 +17975,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18089 };17975 };
1809017976
18091 // Build our ?[]const Error value17977 // Build our ?[]const Error value
18092 const slice_errors_ty = try sema.ptrType(.{17978 const slice_errors_ty = try mod.ptrTypeSema(.{
18093 .child = error_field_ty.toIntern(),17979 .child = error_field_ty.toIntern(),
18094 .flags = .{17980 .flags = .{
18095 .size = .Slice,17981 .size = .Slice,
...@@ -18235,7 +18121,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18235,7 +18121,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18235 .ty = fields_array_ty.toIntern(),18121 .ty = fields_array_ty.toIntern(),
18236 .storage = .{ .elems = enum_field_vals },18122 .storage = .{ .elems = enum_field_vals },
18237 } });18123 } });
18238 const slice_ty = (try sema.ptrType(.{18124 const slice_ty = (try mod.ptrTypeSema(.{
18239 .child = enum_field_ty.toIntern(),18125 .child = enum_field_ty.toIntern(),
18240 .flags = .{18126 .flags = .{
18241 .size = .Slice,18127 .size = .Slice,
...@@ -18315,7 +18201,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18315,7 +18201,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18315 break :t union_field_ty_decl.val.toType();18201 break :t union_field_ty_decl.val.toType();
18316 };18202 };
1831718203
18318 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout18204 try ty.resolveLayout(mod); // Getting alignment requires type layout
18319 const union_obj = mod.typeToUnion(ty).?;18205 const union_obj = mod.typeToUnion(ty).?;
18320 const tag_type = union_obj.loadTagType(ip);18206 const tag_type = union_obj.loadTagType(ip);
18321 const layout = union_obj.getLayout(ip);18207 const layout = union_obj.getLayout(ip);
...@@ -18351,7 +18237,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18351,7 +18237,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18351 };18237 };
1835218238
18353 const alignment = switch (layout) {18239 const alignment = switch (layout) {
18354 .auto, .@"extern" => try sema.unionFieldAlignment(union_obj, @intCast(field_index)),18240 .auto, .@"extern" => try mod.unionFieldNormalAlignmentAdvanced(union_obj, @intCast(field_index), .sema),
18355 .@"packed" => .none,18241 .@"packed" => .none,
18356 };18242 };
1835718243
...@@ -18379,7 +18265,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18379,7 +18265,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18379 .ty = array_fields_ty.toIntern(),18265 .ty = array_fields_ty.toIntern(),
18380 .storage = .{ .elems = union_field_vals },18266 .storage = .{ .elems = union_field_vals },
18381 } });18267 } });
18382 const slice_ty = (try sema.ptrType(.{18268 const slice_ty = (try mod.ptrTypeSema(.{
18383 .child = union_field_ty.toIntern(),18269 .child = union_field_ty.toIntern(),
18384 .flags = .{18270 .flags = .{
18385 .size = .Slice,18271 .size = .Slice,
...@@ -18412,7 +18298,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18412,7 +18298,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18412 const decl_index = (try sema.namespaceLookup(18298 const decl_index = (try sema.namespaceLookup(
18413 block,18299 block,
18414 src,18300 src,
18415 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod),18301 (try mod.getBuiltinType("Type")).getNamespaceIndex(mod),
18416 try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),18302 try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),
18417 )).?;18303 )).?;
18418 try sema.ensureDeclAnalyzed(decl_index);18304 try sema.ensureDeclAnalyzed(decl_index);
...@@ -18465,7 +18351,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18465,7 +18351,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18465 break :t struct_field_ty_decl.val.toType();18351 break :t struct_field_ty_decl.val.toType();
18466 };18352 };
1846718353
18468 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout18354 try ty.resolveLayout(mod); // Getting alignment requires type layout
1846918355
18470 var struct_field_vals: []InternPool.Index = &.{};18356 var struct_field_vals: []InternPool.Index = &.{};
18471 defer gpa.free(struct_field_vals);18357 defer gpa.free(struct_field_vals);
...@@ -18505,7 +18391,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18505,7 +18391,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18505 } });18391 } });
18506 };18392 };
1850718393
18508 try sema.resolveTypeLayout(Type.fromInterned(field_ty));18394 try Type.fromInterned(field_ty).resolveLayout(mod);
1850918395
18510 const is_comptime = field_val != .none;18396 const is_comptime = field_val != .none;
18511 const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null;18397 const opt_default_val = if (is_comptime) Value.fromInterned(field_val) else null;
...@@ -18534,7 +18420,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18534,7 +18420,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18534 };18420 };
18535 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);18421 struct_field_vals = try gpa.alloc(InternPool.Index, struct_type.field_types.len);
1853618422
18537 try sema.resolveStructFieldInits(ty);18423 try ty.resolveStructFieldInits(mod);
1853818424
18539 for (struct_field_vals, 0..) |*field_val, field_index| {18425 for (struct_field_vals, 0..) |*field_val, field_index| {
18540 const field_name = if (struct_type.fieldName(ip, field_index).unwrap()) |field_name|18426 const field_name = if (struct_type.fieldName(ip, field_index).unwrap()) |field_name|
...@@ -18573,10 +18459,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18573,10 +18459,11 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18573 const default_val_ptr = try sema.optRefValue(opt_default_val);18459 const default_val_ptr = try sema.optRefValue(opt_default_val);
18574 const alignment = switch (struct_type.layout) {18460 const alignment = switch (struct_type.layout) {
18575 .@"packed" => .none,18461 .@"packed" => .none,
18576 else => try sema.structFieldAlignment(18462 else => try mod.structFieldAlignmentAdvanced(
18577 struct_type.fieldAlign(ip, field_index),18463 struct_type.fieldAlign(ip, field_index),
18578 field_ty,18464 field_ty,
18579 struct_type.layout,18465 struct_type.layout,
18466 .sema,
18580 ),18467 ),
18581 };18468 };
1858218469
...@@ -18608,7 +18495,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18608,7 +18495,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18608 .ty = array_fields_ty.toIntern(),18495 .ty = array_fields_ty.toIntern(),
18609 .storage = .{ .elems = struct_field_vals },18496 .storage = .{ .elems = struct_field_vals },
18610 } });18497 } });
18611 const slice_ty = (try sema.ptrType(.{18498 const slice_ty = (try mod.ptrTypeSema(.{
18612 .child = struct_field_ty.toIntern(),18499 .child = struct_field_ty.toIntern(),
18613 .flags = .{18500 .flags = .{
18614 .size = .Slice,18501 .size = .Slice,
...@@ -18644,7 +18531,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18644,7 +18531,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18644 const decl_index = (try sema.namespaceLookup(18531 const decl_index = (try sema.namespaceLookup(
18645 block,18532 block,
18646 src,18533 src,
18647 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod),18534 (try mod.getBuiltinType("Type")).getNamespaceIndex(mod),
18648 try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),18535 try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),
18649 )).?;18536 )).?;
18650 try sema.ensureDeclAnalyzed(decl_index);18537 try sema.ensureDeclAnalyzed(decl_index);
...@@ -18688,7 +18575,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -18688,7 +18575,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
18688 break :t type_opaque_ty_decl.val.toType();18575 break :t type_opaque_ty_decl.val.toType();
18689 };18576 };
1869018577
18691 try sema.resolveTypeFields(ty);18578 try ty.resolveFields(mod);
18692 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod));18579 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespaceIndex(mod));
1869318580
18694 const field_values = .{18581 const field_values = .{
...@@ -18730,7 +18617,6 @@ fn typeInfoDecls(...@@ -18730,7 +18617,6 @@ fn typeInfoDecls(
18730 const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index);18617 const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index);
18731 break :t declaration_ty_decl.val.toType();18618 break :t declaration_ty_decl.val.toType();
18732 };18619 };
18733 try sema.queueFullTypeResolution(declaration_ty);
1873418620
18735 var decl_vals = std.ArrayList(InternPool.Index).init(gpa);18621 var decl_vals = std.ArrayList(InternPool.Index).init(gpa);
18736 defer decl_vals.deinit();18622 defer decl_vals.deinit();
...@@ -18748,7 +18634,7 @@ fn typeInfoDecls(...@@ -18748,7 +18634,7 @@ fn typeInfoDecls(
18748 .ty = array_decl_ty.toIntern(),18634 .ty = array_decl_ty.toIntern(),
18749 .storage = .{ .elems = decl_vals.items },18635 .storage = .{ .elems = decl_vals.items },
18750 } });18636 } });
18751 const slice_ty = (try sema.ptrType(.{18637 const slice_ty = (try mod.ptrTypeSema(.{
18752 .child = declaration_ty.toIntern(),18638 .child = declaration_ty.toIntern(),
18753 .flags = .{18639 .flags = .{
18754 .size = .Slice,18640 .size = .Slice,
...@@ -19348,7 +19234,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr...@@ -19348,7 +19234,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1934819234
19349 const operand_ty = sema.typeOf(operand);19235 const operand_ty = sema.typeOf(operand);
19350 const ptr_info = operand_ty.ptrInfo(mod);19236 const ptr_info = operand_ty.ptrInfo(mod);
19351 const res_ty = try sema.ptrType(.{19237 const res_ty = try mod.ptrTypeSema(.{
19352 .child = err_union_ty.errorUnionPayload(mod).toIntern(),19238 .child = err_union_ty.errorUnionPayload(mod).toIntern(),
19353 .flags = .{19239 .flags = .{
19354 .is_const = ptr_info.flags.is_const,19240 .is_const = ptr_info.flags.is_const,
...@@ -19581,11 +19467,11 @@ fn retWithErrTracing(...@@ -19581,11 +19467,11 @@ fn retWithErrTracing(
19581 else => true,19467 else => true,
19582 };19468 };
19583 const gpa = sema.gpa;19469 const gpa = sema.gpa;
19584 const stack_trace_ty = try sema.getBuiltinType("StackTrace");19470 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
19585 try sema.resolveTypeFields(stack_trace_ty);19471 try stack_trace_ty.resolveFields(mod);
19586 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);19472 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
19587 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);19473 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
19588 const return_err_fn = try sema.getBuiltin("returnError");19474 const return_err_fn = try mod.getBuiltin("returnError");
19589 const args: [1]Air.Inst.Ref = .{err_return_trace};19475 const args: [1]Air.Inst.Ref = .{err_return_trace};
1959019476
19591 if (!need_check) {19477 if (!need_check) {
...@@ -19788,7 +19674,7 @@ fn analyzeRet(...@@ -19788,7 +19674,7 @@ fn analyzeRet(
19788 return sema.failWithOwnedErrorMsg(block, msg);19674 return sema.failWithOwnedErrorMsg(block, msg);
19789 }19675 }
1979019676
19791 try sema.resolveTypeLayout(sema.fn_ret_ty);19677 try sema.fn_ret_ty.resolveLayout(mod);
1979219678
19793 try sema.validateRuntimeValue(block, operand_src, operand);19679 try sema.validateRuntimeValue(block, operand_src, operand);
1979419680
...@@ -19870,7 +19756,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19870,7 +19756,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19870 },19756 },
19871 else => {},19757 else => {},
19872 }19758 }
19873 const align_bytes = (try val.getUnsignedIntAdvanced(mod, sema)).?;19759 const align_bytes = (try val.getUnsignedIntAdvanced(mod, .sema)).?;
19874 break :blk try sema.validateAlignAllowZero(block, align_src, align_bytes);19760 break :blk try sema.validateAlignAllowZero(block, align_src, align_bytes);
19875 } else .none;19761 } else .none;
1987619762
...@@ -19904,7 +19790,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19904,7 +19790,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19904 elem_ty.fmt(mod), bit_offset, bit_offset - host_size * 8, host_size,19790 elem_ty.fmt(mod), bit_offset, bit_offset - host_size * 8, host_size,
19905 });19791 });
19906 }19792 }
19907 const elem_bit_size = try elem_ty.bitSizeAdvanced(mod, sema);19793 const elem_bit_size = try elem_ty.bitSizeAdvanced(mod, .sema);
19908 if (elem_bit_size > host_size * 8 - bit_offset) {19794 if (elem_bit_size > host_size * 8 - bit_offset) {
19909 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{19795 return sema.fail(block, bitoffset_src, "packed type '{}' at bit offset {} ends {} bits after the end of a {} byte host integer", .{
19910 elem_ty.fmt(mod), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,19796 elem_ty.fmt(mod), bit_offset, elem_bit_size - (host_size * 8 - bit_offset), host_size,
...@@ -19945,7 +19831,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -19945,7 +19831,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
19945 });19831 });
19946 }19832 }
1994719833
19948 const ty = try sema.ptrType(.{19834 const ty = try mod.ptrTypeSema(.{
19949 .child = elem_ty.toIntern(),19835 .child = elem_ty.toIntern(),
19950 .sentinel = sentinel,19836 .sentinel = sentinel,
19951 .flags = .{19837 .flags = .{
...@@ -20036,7 +19922,7 @@ fn structInitEmpty(...@@ -20036,7 +19922,7 @@ fn structInitEmpty(
20036 const mod = sema.mod;19922 const mod = sema.mod;
20037 const gpa = sema.gpa;19923 const gpa = sema.gpa;
20038 // This logic must be synchronized with that in `zirStructInit`.19924 // This logic must be synchronized with that in `zirStructInit`.
20039 try sema.resolveTypeFields(struct_ty);19925 try struct_ty.resolveFields(mod);
2004019926
20041 // The init values to use for the struct instance.19927 // The init values to use for the struct instance.
20042 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod));19928 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod));
...@@ -20107,7 +19993,6 @@ fn unionInit(...@@ -20107,7 +19993,6 @@ fn unionInit(
2010719993
20108 try sema.requireRuntimeBlock(block, init_src, null);19994 try sema.requireRuntimeBlock(block, init_src, null);
20109 _ = union_ty_src;19995 _ = union_ty_src;
20110 try sema.queueFullTypeResolution(union_ty);
20111 return block.addUnionInit(union_ty, field_index, init);19996 return block.addUnionInit(union_ty, field_index, init);
20112}19997}
2011319998
...@@ -20136,7 +20021,7 @@ fn zirStructInit(...@@ -20136,7 +20021,7 @@ fn zirStructInit(
20136 else => |e| return e,20021 else => |e| return e,
20137 };20022 };
20138 const resolved_ty = result_ty.optEuBaseType(mod);20023 const resolved_ty = result_ty.optEuBaseType(mod);
20139 try sema.resolveTypeLayout(resolved_ty);20024 try resolved_ty.resolveLayout(mod);
2014020025
20141 if (resolved_ty.zigTypeTag(mod) == .Struct) {20026 if (resolved_ty.zigTypeTag(mod) == .Struct) {
20142 // This logic must be synchronized with that in `zirStructInitEmpty`.20027 // This logic must be synchronized with that in `zirStructInitEmpty`.
...@@ -20177,7 +20062,7 @@ fn zirStructInit(...@@ -20177,7 +20062,7 @@ fn zirStructInit(
20177 const field_ty = resolved_ty.structFieldType(field_index, mod);20062 const field_ty = resolved_ty.structFieldType(field_index, mod);
20178 field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src);20063 field_inits[field_index] = try sema.coerce(block, field_ty, uncoerced_init, field_src);
20179 if (!is_packed) {20064 if (!is_packed) {
20180 try sema.resolveStructFieldInits(resolved_ty);20065 try resolved_ty.resolveStructFieldInits(mod);
20181 if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {20066 if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
20182 const init_val = (try sema.resolveValue(field_inits[field_index])) orelse {20067 const init_val = (try sema.resolveValue(field_inits[field_index])) orelse {
20183 return sema.failWithNeededComptime(block, field_src, .{20068 return sema.failWithNeededComptime(block, field_src, .{
...@@ -20250,7 +20135,7 @@ fn zirStructInit(...@@ -20250,7 +20135,7 @@ fn zirStructInit(
2025020135
20251 if (is_ref) {20136 if (is_ref) {
20252 const target = mod.getTarget();20137 const target = mod.getTarget();
20253 const alloc_ty = try sema.ptrType(.{20138 const alloc_ty = try mod.ptrTypeSema(.{
20254 .child = result_ty.toIntern(),20139 .child = result_ty.toIntern(),
20255 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20140 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20256 });20141 });
...@@ -20264,7 +20149,6 @@ fn zirStructInit(...@@ -20264,7 +20149,6 @@ fn zirStructInit(
20264 }20149 }
2026520150
20266 try sema.requireRuntimeBlock(block, src, null);20151 try sema.requireRuntimeBlock(block, src, null);
20267 try sema.queueFullTypeResolution(resolved_ty);
20268 const union_val = try block.addUnionInit(resolved_ty, field_index, init_inst);20152 const union_val = try block.addUnionInit(resolved_ty, field_index, init_inst);
20269 return sema.coerce(block, result_ty, union_val, src);20153 return sema.coerce(block, result_ty, union_val, src);
20270 }20154 }
...@@ -20341,7 +20225,7 @@ fn finishStructInit(...@@ -20341,7 +20225,7 @@ fn finishStructInit(
20341 continue;20225 continue;
20342 }20226 }
2034320227
20344 try sema.resolveStructFieldInits(struct_ty);20228 try struct_ty.resolveStructFieldInits(mod);
2034520229
20346 const field_init = struct_type.fieldInit(ip, i);20230 const field_init = struct_type.fieldInit(ip, i);
20347 if (field_init == .none) {20231 if (field_init == .none) {
...@@ -20411,9 +20295,9 @@ fn finishStructInit(...@@ -20411,9 +20295,9 @@ fn finishStructInit(
20411 }20295 }
2041220296
20413 if (is_ref) {20297 if (is_ref) {
20414 try sema.resolveStructLayout(struct_ty);20298 try struct_ty.resolveLayout(mod);
20415 const target = sema.mod.getTarget();20299 const target = sema.mod.getTarget();
20416 const alloc_ty = try sema.ptrType(.{20300 const alloc_ty = try mod.ptrTypeSema(.{
20417 .child = result_ty.toIntern(),20301 .child = result_ty.toIntern(),
20418 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20302 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20419 });20303 });
...@@ -20433,8 +20317,7 @@ fn finishStructInit(...@@ -20433,8 +20317,7 @@ fn finishStructInit(
20433 .init_node_offset = init_src.offset.node_offset.x,20317 .init_node_offset = init_src.offset.node_offset.x,
20434 .elem_index = @intCast(runtime_index),20318 .elem_index = @intCast(runtime_index),
20435 } }));20319 } }));
20436 try sema.resolveStructFieldInits(struct_ty);20320 try struct_ty.resolveStructFieldInits(mod);
20437 try sema.queueFullTypeResolution(struct_ty);
20438 const struct_val = try block.addAggregateInit(struct_ty, field_inits);20321 const struct_val = try block.addAggregateInit(struct_ty, field_inits);
20439 return sema.coerce(block, result_ty, struct_val, init_src);20322 return sema.coerce(block, result_ty, struct_val, init_src);
20440}20323}
...@@ -20543,7 +20426,7 @@ fn structInitAnon(...@@ -20543,7 +20426,7 @@ fn structInitAnon(
2054320426
20544 if (is_ref) {20427 if (is_ref) {
20545 const target = mod.getTarget();20428 const target = mod.getTarget();
20546 const alloc_ty = try sema.ptrType(.{20429 const alloc_ty = try mod.ptrTypeSema(.{
20547 .child = tuple_ty,20430 .child = tuple_ty,
20548 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20431 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20549 });20432 });
...@@ -20557,7 +20440,7 @@ fn structInitAnon(...@@ -20557,7 +20440,7 @@ fn structInitAnon(
20557 };20440 };
20558 extra_index = item.end;20441 extra_index = item.end;
2055920442
20560 const field_ptr_ty = try sema.ptrType(.{20443 const field_ptr_ty = try mod.ptrTypeSema(.{
20561 .child = field_ty,20444 .child = field_ty,
20562 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20445 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20563 });20446 });
...@@ -20650,7 +20533,7 @@ fn zirArrayInit(...@@ -20650,7 +20533,7 @@ fn zirArrayInit(
20650 dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src);20533 dest.* = try sema.coerce(block, elem_ty, resolved_arg, elem_src);
20651 if (is_tuple) {20534 if (is_tuple) {
20652 if (array_ty.structFieldIsComptime(i, mod))20535 if (array_ty.structFieldIsComptime(i, mod))
20653 try sema.resolveStructFieldInits(array_ty);20536 try array_ty.resolveStructFieldInits(mod);
20654 if (try array_ty.structFieldValueComptime(mod, i)) |field_val| {20537 if (try array_ty.structFieldValueComptime(mod, i)) |field_val| {
20655 const init_val = try sema.resolveValue(dest.*) orelse {20538 const init_val = try sema.resolveValue(dest.*) orelse {
20656 return sema.failWithNeededComptime(block, elem_src, .{20539 return sema.failWithNeededComptime(block, elem_src, .{
...@@ -20694,11 +20577,10 @@ fn zirArrayInit(...@@ -20694,11 +20577,10 @@ fn zirArrayInit(
20694 .init_node_offset = src.offset.node_offset.x,20577 .init_node_offset = src.offset.node_offset.x,
20695 .elem_index = runtime_index,20578 .elem_index = runtime_index,
20696 } }));20579 } }));
20697 try sema.queueFullTypeResolution(array_ty);
2069820580
20699 if (is_ref) {20581 if (is_ref) {
20700 const target = mod.getTarget();20582 const target = mod.getTarget();
20701 const alloc_ty = try sema.ptrType(.{20583 const alloc_ty = try mod.ptrTypeSema(.{
20702 .child = result_ty.toIntern(),20584 .child = result_ty.toIntern(),
20703 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20585 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20704 });20586 });
...@@ -20707,7 +20589,7 @@ fn zirArrayInit(...@@ -20707,7 +20589,7 @@ fn zirArrayInit(
2070720589
20708 if (is_tuple) {20590 if (is_tuple) {
20709 for (resolved_args, 0..) |arg, i| {20591 for (resolved_args, 0..) |arg, i| {
20710 const elem_ptr_ty = try sema.ptrType(.{20592 const elem_ptr_ty = try mod.ptrTypeSema(.{
20711 .child = array_ty.structFieldType(i, mod).toIntern(),20593 .child = array_ty.structFieldType(i, mod).toIntern(),
20712 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20594 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20713 });20595 });
...@@ -20720,7 +20602,7 @@ fn zirArrayInit(...@@ -20720,7 +20602,7 @@ fn zirArrayInit(
20720 return sema.makePtrConst(block, alloc);20602 return sema.makePtrConst(block, alloc);
20721 }20603 }
2072220604
20723 const elem_ptr_ty = try sema.ptrType(.{20605 const elem_ptr_ty = try mod.ptrTypeSema(.{
20724 .child = array_ty.elemType2(mod).toIntern(),20606 .child = array_ty.elemType2(mod).toIntern(),
20725 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20607 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20726 });20608 });
...@@ -20808,14 +20690,14 @@ fn arrayInitAnon(...@@ -20808,14 +20690,14 @@ fn arrayInitAnon(
2080820690
20809 if (is_ref) {20691 if (is_ref) {
20810 const target = sema.mod.getTarget();20692 const target = sema.mod.getTarget();
20811 const alloc_ty = try sema.ptrType(.{20693 const alloc_ty = try mod.ptrTypeSema(.{
20812 .child = tuple_ty,20694 .child = tuple_ty,
20813 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20695 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20814 });20696 });
20815 const alloc = try block.addTy(.alloc, alloc_ty);20697 const alloc = try block.addTy(.alloc, alloc_ty);
20816 for (operands, 0..) |operand, i_usize| {20698 for (operands, 0..) |operand, i_usize| {
20817 const i: u32 = @intCast(i_usize);20699 const i: u32 = @intCast(i_usize);
20818 const field_ptr_ty = try sema.ptrType(.{20700 const field_ptr_ty = try mod.ptrTypeSema(.{
20819 .child = types[i],20701 .child = types[i],
20820 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },20702 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) },
20821 });20703 });
...@@ -20885,7 +20767,7 @@ fn fieldType(...@@ -20885,7 +20767,7 @@ fn fieldType(
20885 const ip = &mod.intern_pool;20767 const ip = &mod.intern_pool;
20886 var cur_ty = aggregate_ty;20768 var cur_ty = aggregate_ty;
20887 while (true) {20769 while (true) {
20888 try sema.resolveTypeFields(cur_ty);20770 try cur_ty.resolveFields(mod);
20889 switch (cur_ty.zigTypeTag(mod)) {20771 switch (cur_ty.zigTypeTag(mod)) {
20890 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {20772 .Struct => switch (ip.indexToKey(cur_ty.toIntern())) {
20891 .anon_struct_type => |anon_struct| {20773 .anon_struct_type => |anon_struct| {
...@@ -20936,8 +20818,8 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {...@@ -20936,8 +20818,8 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
20936fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {20818fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
20937 const mod = sema.mod;20819 const mod = sema.mod;
20938 const ip = &mod.intern_pool;20820 const ip = &mod.intern_pool;
20939 const stack_trace_ty = try sema.getBuiltinType("StackTrace");20821 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
20940 try sema.resolveTypeFields(stack_trace_ty);20822 try stack_trace_ty.resolveFields(mod);
20941 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);20823 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
20942 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());20824 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
2094320825
...@@ -20971,9 +20853,6 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20971,9 +20853,6 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20971 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});20853 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
20972 }20854 }
20973 const val = try ty.lazyAbiAlignment(mod);20855 const val = try ty.lazyAbiAlignment(mod);
20974 if (val.isLazyAlign(mod)) {
20975 try sema.queueFullTypeResolution(ty);
20976 }
20977 return Air.internedToRef(val.toIntern());20856 return Air.internedToRef(val.toIntern());
20978}20857}
2097920858
...@@ -21148,7 +21027,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -21148,7 +21027,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
21148 const mod = sema.mod;21027 const mod = sema.mod;
21149 const ip = &mod.intern_pool;21028 const ip = &mod.intern_pool;
2115021029
21151 try sema.resolveTypeLayout(operand_ty);21030 try operand_ty.resolveLayout(mod);
21152 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {21031 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
21153 .EnumLiteral => {21032 .EnumLiteral => {
21154 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, operand, undefined);21033 const val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, operand, undefined);
...@@ -21224,7 +21103,7 @@ fn zirReify(...@@ -21224,7 +21103,7 @@ fn zirReify(
21224 },21103 },
21225 },21104 },
21226 };21105 };
21227 const type_info_ty = try sema.getBuiltinType("Type");21106 const type_info_ty = try mod.getBuiltinType("Type");
21228 const uncasted_operand = try sema.resolveInst(extra.operand);21107 const uncasted_operand = try sema.resolveInst(extra.operand);
21229 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);21108 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
21230 const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{21109 const val = try sema.resolveConstDefinedValue(block, operand_src, type_info, .{
...@@ -21258,7 +21137,7 @@ fn zirReify(...@@ -21258,7 +21137,7 @@ fn zirReify(
21258 );21137 );
2125921138
21260 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);21139 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
21261 const bits: u16 = @intCast(try bits_val.toUnsignedIntAdvanced(sema));21140 const bits: u16 = @intCast(try bits_val.toUnsignedIntSema(mod));
21262 const ty = try mod.intType(signedness, bits);21141 const ty = try mod.intType(signedness, bits);
21263 return Air.internedToRef(ty.toIntern());21142 return Air.internedToRef(ty.toIntern());
21264 },21143 },
...@@ -21273,7 +21152,7 @@ fn zirReify(...@@ -21273,7 +21152,7 @@ fn zirReify(
21273 try ip.getOrPutString(gpa, "child", .no_embedded_nulls),21152 try ip.getOrPutString(gpa, "child", .no_embedded_nulls),
21274 ).?);21153 ).?);
2127521154
21276 const len: u32 = @intCast(try len_val.toUnsignedIntAdvanced(sema));21155 const len: u32 = @intCast(try len_val.toUnsignedIntSema(mod));
21277 const child_ty = child_val.toType();21156 const child_ty = child_val.toType();
2127821157
21279 try sema.checkVectorElemType(block, src, child_ty);21158 try sema.checkVectorElemType(block, src, child_ty);
...@@ -21291,7 +21170,7 @@ fn zirReify(...@@ -21291,7 +21170,7 @@ fn zirReify(
21291 try ip.getOrPutString(gpa, "bits", .no_embedded_nulls),21170 try ip.getOrPutString(gpa, "bits", .no_embedded_nulls),
21292 ).?);21171 ).?);
2129321172
21294 const bits: u16 = @intCast(try bits_val.toUnsignedIntAdvanced(sema));21173 const bits: u16 = @intCast(try bits_val.toUnsignedIntSema(mod));
21295 const ty = switch (bits) {21174 const ty = switch (bits) {
21296 16 => Type.f16,21175 16 => Type.f16,
21297 32 => Type.f32,21176 32 => Type.f32,
...@@ -21341,7 +21220,7 @@ fn zirReify(...@@ -21341,7 +21220,7 @@ fn zirReify(
21341 return sema.fail(block, src, "alignment must fit in 'u32'", .{});21220 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
21342 }21221 }
2134321222
21344 const alignment_val_int = (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?;21223 const alignment_val_int = (try alignment_val.getUnsignedIntAdvanced(mod, .sema)).?;
21345 if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) {21224 if (alignment_val_int > 0 and !math.isPowerOfTwo(alignment_val_int)) {
21346 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int});21225 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{alignment_val_int});
21347 }21226 }
...@@ -21349,7 +21228,7 @@ fn zirReify(...@@ -21349,7 +21228,7 @@ fn zirReify(
2134921228
21350 const elem_ty = child_val.toType();21229 const elem_ty = child_val.toType();
21351 if (abi_align != .none) {21230 if (abi_align != .none) {
21352 try sema.resolveTypeLayout(elem_ty);21231 try elem_ty.resolveLayout(mod);
21353 }21232 }
2135421233
21355 const ptr_size = mod.toEnum(std.builtin.Type.Pointer.Size, size_val);21234 const ptr_size = mod.toEnum(std.builtin.Type.Pointer.Size, size_val);
...@@ -21393,7 +21272,7 @@ fn zirReify(...@@ -21393,7 +21272,7 @@ fn zirReify(
21393 }21272 }
21394 }21273 }
2139521274
21396 const ty = try sema.ptrType(.{21275 const ty = try mod.ptrTypeSema(.{
21397 .child = elem_ty.toIntern(),21276 .child = elem_ty.toIntern(),
21398 .sentinel = actual_sentinel,21277 .sentinel = actual_sentinel,
21399 .flags = .{21278 .flags = .{
...@@ -21422,7 +21301,7 @@ fn zirReify(...@@ -21422,7 +21301,7 @@ fn zirReify(
21422 try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls),21301 try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls),
21423 ).?);21302 ).?);
2142421303
21425 const len = try len_val.toUnsignedIntAdvanced(sema);21304 const len = try len_val.toUnsignedIntSema(mod);
21426 const child_ty = child_val.toType();21305 const child_ty = child_val.toType();
21427 const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {21306 const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {
21428 const ptr_ty = try mod.singleMutPtrType(child_ty);21307 const ptr_ty = try mod.singleMutPtrType(child_ty);
...@@ -21529,7 +21408,7 @@ fn zirReify(...@@ -21529,7 +21408,7 @@ fn zirReify(
21529 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);21408 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
2153021409
21531 // Decls21410 // Decls
21532 if (try decls_val.sliceLen(sema) > 0) {21411 if (try decls_val.sliceLen(mod) > 0) {
21533 return sema.fail(block, src, "reified structs must have no decls", .{});21412 return sema.fail(block, src, "reified structs must have no decls", .{});
21534 }21413 }
2153521414
...@@ -21562,7 +21441,7 @@ fn zirReify(...@@ -21562,7 +21441,7 @@ fn zirReify(
21562 try ip.getOrPutString(gpa, "is_exhaustive", .no_embedded_nulls),21441 try ip.getOrPutString(gpa, "is_exhaustive", .no_embedded_nulls),
21563 ).?);21442 ).?);
2156421443
21565 if (try decls_val.sliceLen(sema) > 0) {21444 if (try decls_val.sliceLen(mod) > 0) {
21566 return sema.fail(block, src, "reified enums must have no decls", .{});21445 return sema.fail(block, src, "reified enums must have no decls", .{});
21567 }21446 }
2156821447
...@@ -21580,7 +21459,7 @@ fn zirReify(...@@ -21580,7 +21459,7 @@ fn zirReify(
21580 ).?);21459 ).?);
2158121460
21582 // Decls21461 // Decls
21583 if (try decls_val.sliceLen(sema) > 0) {21462 if (try decls_val.sliceLen(mod) > 0) {
21584 return sema.fail(block, src, "reified opaque must have no decls", .{});21463 return sema.fail(block, src, "reified opaque must have no decls", .{});
21585 }21464 }
2158621465
...@@ -21628,7 +21507,7 @@ fn zirReify(...@@ -21628,7 +21507,7 @@ fn zirReify(
21628 try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),21507 try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),
21629 ).?);21508 ).?);
2163021509
21631 if (try decls_val.sliceLen(sema) > 0) {21510 if (try decls_val.sliceLen(mod) > 0) {
21632 return sema.fail(block, src, "reified unions must have no decls", .{});21511 return sema.fail(block, src, "reified unions must have no decls", .{});
21633 }21512 }
21634 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);21513 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
...@@ -21987,7 +21866,7 @@ fn reifyUnion(...@@ -21987,7 +21866,7 @@ fn reifyUnion(
2198721866
21988 field_ty.* = field_type_val.toIntern();21867 field_ty.* = field_type_val.toIntern();
21989 if (any_aligns) {21868 if (any_aligns) {
21990 const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntAdvanced(sema);21869 const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntSema(mod);
21991 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {21870 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
21992 // TODO: better source location21871 // TODO: better source location
21993 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});21872 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
...@@ -22032,7 +21911,7 @@ fn reifyUnion(...@@ -22032,7 +21911,7 @@ fn reifyUnion(
2203221911
22033 field_ty.* = field_type_val.toIntern();21912 field_ty.* = field_type_val.toIntern();
22034 if (any_aligns) {21913 if (any_aligns) {
22035 const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntAdvanced(sema);21914 const byte_align = try (try field_info.fieldValue(mod, 2)).toUnsignedIntSema(mod);
22036 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {21915 if (byte_align > 0 and !math.isPowerOfTwo(byte_align)) {
22037 // TODO: better source location21916 // TODO: better source location
22038 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});21917 return sema.fail(block, src, "alignment value '{d}' is not a power of two or zero", .{byte_align});
...@@ -22089,6 +21968,8 @@ fn reifyUnion(...@@ -22089,6 +21968,8 @@ fn reifyUnion(
22089 loaded_union.flagsPtr(ip).status = .have_field_types;21968 loaded_union.flagsPtr(ip).status = .have_field_types;
2209021969
22091 try mod.finalizeAnonDecl(new_decl_index);21970 try mod.finalizeAnonDecl(new_decl_index);
21971 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
21972 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
22092 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));21973 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
22093}21974}
2209421975
...@@ -22162,7 +22043,7 @@ fn reifyStruct(...@@ -22162,7 +22043,7 @@ fn reifyStruct(
2216222043
22163 if (field_is_comptime) any_comptime_fields = true;22044 if (field_is_comptime) any_comptime_fields = true;
22164 if (field_default_value != .none) any_default_inits = true;22045 if (field_default_value != .none) any_default_inits = true;
22165 switch (try field_alignment_val.orderAgainstZeroAdvanced(mod, sema)) {22046 switch (try field_alignment_val.orderAgainstZeroAdvanced(mod, .sema)) {
22166 .eq => {},22047 .eq => {},
22167 .gt => any_aligned_fields = true,22048 .gt => any_aligned_fields = true,
22168 .lt => unreachable,22049 .lt => unreachable,
...@@ -22245,7 +22126,7 @@ fn reifyStruct(...@@ -22245,7 +22126,7 @@ fn reifyStruct(
22245 return sema.fail(block, src, "alignment must fit in 'u32'", .{});22126 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
22246 }22127 }
2224722128
22248 const byte_align = try field_alignment_val.toUnsignedIntAdvanced(sema);22129 const byte_align = try field_alignment_val.toUnsignedIntSema(mod);
22249 if (byte_align == 0) {22130 if (byte_align == 0) {
22250 if (layout != .@"packed") {22131 if (layout != .@"packed") {
22251 struct_type.field_aligns.get(ip)[field_idx] = .none;22132 struct_type.field_aligns.get(ip)[field_idx] = .none;
...@@ -22331,7 +22212,7 @@ fn reifyStruct(...@@ -22331,7 +22212,7 @@ fn reifyStruct(
22331 var fields_bit_sum: u64 = 0;22212 var fields_bit_sum: u64 = 0;
22332 for (0..struct_type.field_types.len) |field_idx| {22213 for (0..struct_type.field_types.len) |field_idx| {
22333 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_idx]);22214 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_idx]);
22334 sema.resolveTypeLayout(field_ty) catch |err| switch (err) {22215 field_ty.resolveLayout(mod) catch |err| switch (err) {
22335 error.AnalysisFail => {22216 error.AnalysisFail => {
22336 const msg = sema.err orelse return err;22217 const msg = sema.err orelse return err;
22337 try sema.errNote(src, msg, "while checking a field of this struct", .{});22218 try sema.errNote(src, msg, "while checking a field of this struct", .{});
...@@ -22353,11 +22234,13 @@ fn reifyStruct(...@@ -22353,11 +22234,13 @@ fn reifyStruct(
22353 }22234 }
2235422235
22355 try mod.finalizeAnonDecl(new_decl_index);22236 try mod.finalizeAnonDecl(new_decl_index);
22237 try mod.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
22238 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = new_decl_index }));
22356 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));22239 return Air.internedToRef(wip_ty.finish(ip, new_decl_index, .none));
22357}22240}
2235822241
22359fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {22242fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref {
22360 const va_list_ty = try sema.getBuiltinType("VaList");22243 const va_list_ty = try sema.mod.getBuiltinType("VaList");
22361 const va_list_ptr = try sema.mod.singleMutPtrType(va_list_ty);22244 const va_list_ptr = try sema.mod.singleMutPtrType(va_list_ty);
2236222245
22363 const inst = try sema.resolveInst(zir_ref);22246 const inst = try sema.resolveInst(zir_ref);
...@@ -22396,7 +22279,7 @@ fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)...@@ -22396,7 +22279,7 @@ fn zirCVaCopy(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
22396 const va_list_src = block.builtinCallArgSrc(extra.node, 0);22279 const va_list_src = block.builtinCallArgSrc(extra.node, 0);
2239722280
22398 const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand);22281 const va_list_ref = try sema.resolveVaListRef(block, va_list_src, extra.operand);
22399 const va_list_ty = try sema.getBuiltinType("VaList");22282 const va_list_ty = try sema.mod.getBuiltinType("VaList");
2240022283
22401 try sema.requireRuntimeBlock(block, src, null);22284 try sema.requireRuntimeBlock(block, src, null);
22402 return block.addTyOp(.c_va_copy, va_list_ty, va_list_ref);22285 return block.addTyOp(.c_va_copy, va_list_ty, va_list_ref);
...@@ -22416,7 +22299,7 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C...@@ -22416,7 +22299,7 @@ fn zirCVaEnd(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
22416fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {22299fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
22417 const src = block.nodeOffset(@bitCast(extended.operand));22300 const src = block.nodeOffset(@bitCast(extended.operand));
2241822301
22419 const va_list_ty = try sema.getBuiltinType("VaList");22302 const va_list_ty = try sema.mod.getBuiltinType("VaList");
22420 try sema.requireRuntimeBlock(block, src, null);22303 try sema.requireRuntimeBlock(block, src, null);
22421 return block.addInst(.{22304 return block.addInst(.{
22422 .tag = .c_va_start,22305 .tag = .c_va_start,
...@@ -22550,7 +22433,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro...@@ -22550,7 +22433,7 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
22550 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);22433 _ = try sema.checkIntType(block, operand_src, operand_scalar_ty);
2255122434
22552 if (try sema.resolveValue(operand)) |operand_val| {22435 if (try sema.resolveValue(operand)) |operand_val| {
22553 const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, mod, sema);22436 const result_val = try operand_val.floatFromIntAdvanced(sema.arena, operand_ty, dest_ty, mod, .sema);
22554 return Air.internedToRef(result_val.toIntern());22437 return Air.internedToRef(result_val.toIntern());
22555 } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeFloat) {22438 } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeFloat) {
22556 return sema.failWithNeededComptime(block, operand_src, .{22439 return sema.failWithNeededComptime(block, operand_src, .{
...@@ -22598,7 +22481,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -22598,7 +22481,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
22598 try sema.checkPtrType(block, src, ptr_ty, true);22481 try sema.checkPtrType(block, src, ptr_ty, true);
2259922482
22600 const elem_ty = ptr_ty.elemType2(mod);22483 const elem_ty = ptr_ty.elemType2(mod);
22601 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);22484 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, .sema);
2260222485
22603 if (ptr_ty.isSlice(mod)) {22486 if (ptr_ty.isSlice(mod)) {
22604 const msg = msg: {22487 const msg = msg: {
...@@ -22697,7 +22580,7 @@ fn ptrFromIntVal(...@@ -22697,7 +22580,7 @@ fn ptrFromIntVal(
22697 }22580 }
22698 return sema.failWithUseOfUndef(block, operand_src);22581 return sema.failWithUseOfUndef(block, operand_src);
22699 }22582 }
22700 const addr = try operand_val.toUnsignedIntAdvanced(sema);22583 const addr = try operand_val.toUnsignedIntSema(zcu);
22701 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)22584 if (!ptr_ty.isAllowzeroPtr(zcu) and addr == 0)
22702 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(zcu)});22585 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(zcu)});
22703 if (addr != 0 and ptr_align != .none and !ptr_align.check(addr))22586 if (addr != 0 and ptr_align != .none and !ptr_align.check(addr))
...@@ -22895,8 +22778,8 @@ fn ptrCastFull(...@@ -22895,8 +22778,8 @@ fn ptrCastFull(
22895 const src_info = operand_ty.ptrInfo(mod);22778 const src_info = operand_ty.ptrInfo(mod);
22896 const dest_info = dest_ty.ptrInfo(mod);22779 const dest_info = dest_ty.ptrInfo(mod);
2289722780
22898 try sema.resolveTypeLayout(Type.fromInterned(src_info.child));22781 try Type.fromInterned(src_info.child).resolveLayout(mod);
22899 try sema.resolveTypeLayout(Type.fromInterned(dest_info.child));22782 try Type.fromInterned(dest_info.child).resolveLayout(mod);
2290022783
22901 const src_slice_like = src_info.flags.size == .Slice or22784 const src_slice_like = src_info.flags.size == .Slice or
22902 (src_info.flags.size == .One and Type.fromInterned(src_info.child).zigTypeTag(mod) == .Array);22785 (src_info.flags.size == .One and Type.fromInterned(src_info.child).zigTypeTag(mod) == .Array);
...@@ -23144,7 +23027,7 @@ fn ptrCastFull(...@@ -23144,7 +23027,7 @@ fn ptrCastFull(
23144 // Only convert to a many-pointer at first23027 // Only convert to a many-pointer at first
23145 var info = dest_info;23028 var info = dest_info;
23146 info.flags.size = .Many;23029 info.flags.size = .Many;
23147 const ty = try sema.ptrType(info);23030 const ty = try mod.ptrTypeSema(info);
23148 if (dest_ty.zigTypeTag(mod) == .Optional) {23031 if (dest_ty.zigTypeTag(mod) == .Optional) {
23149 break :blk try mod.optionalType(ty.toIntern());23032 break :blk try mod.optionalType(ty.toIntern());
23150 } else {23033 } else {
...@@ -23162,7 +23045,7 @@ fn ptrCastFull(...@@ -23162,7 +23045,7 @@ fn ptrCastFull(
23162 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});23045 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});
23163 }23046 }
23164 if (dest_align.compare(.gt, src_align)) {23047 if (dest_align.compare(.gt, src_align)) {
23165 if (try ptr_val.getUnsignedIntAdvanced(mod, null)) |addr| {23048 if (try ptr_val.getUnsignedIntAdvanced(mod, .sema)) |addr| {
23166 if (!dest_align.check(addr)) {23049 if (!dest_align.check(addr)) {
23167 return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{23050 return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{
23168 addr,23051 addr,
...@@ -23229,7 +23112,7 @@ fn ptrCastFull(...@@ -23229,7 +23112,7 @@ fn ptrCastFull(
23229 // We can't change address spaces with a bitcast, so this requires two instructions23112 // We can't change address spaces with a bitcast, so this requires two instructions
23230 var intermediate_info = src_info;23113 var intermediate_info = src_info;
23231 intermediate_info.flags.address_space = dest_info.flags.address_space;23114 intermediate_info.flags.address_space = dest_info.flags.address_space;
23232 const intermediate_ptr_ty = try sema.ptrType(intermediate_info);23115 const intermediate_ptr_ty = try mod.ptrTypeSema(intermediate_info);
23233 const intermediate_ty = if (dest_ptr_ty.zigTypeTag(mod) == .Optional) blk: {23116 const intermediate_ty = if (dest_ptr_ty.zigTypeTag(mod) == .Optional) blk: {
23234 break :blk try mod.optionalType(intermediate_ptr_ty.toIntern());23117 break :blk try mod.optionalType(intermediate_ptr_ty.toIntern());
23235 } else intermediate_ptr_ty;23118 } else intermediate_ptr_ty;
...@@ -23286,7 +23169,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst...@@ -23286,7 +23169,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
23286 if (flags.volatile_cast) ptr_info.flags.is_volatile = false;23169 if (flags.volatile_cast) ptr_info.flags.is_volatile = false;
2328723170
23288 const dest_ty = blk: {23171 const dest_ty = blk: {
23289 const dest_ty = try sema.ptrType(ptr_info);23172 const dest_ty = try mod.ptrTypeSema(ptr_info);
23290 if (operand_ty.zigTypeTag(mod) == .Optional) {23173 if (operand_ty.zigTypeTag(mod) == .Optional) {
23291 break :blk try mod.optionalType(dest_ty.toIntern());23174 break :blk try mod.optionalType(dest_ty.toIntern());
23292 }23175 }
...@@ -23576,7 +23459,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6...@@ -23576,7 +23459,7 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2357623459
23577 const mod = sema.mod;23460 const mod = sema.mod;
23578 const ip = &mod.intern_pool;23461 const ip = &mod.intern_pool;
23579 try sema.resolveTypeLayout(ty);23462 try ty.resolveLayout(mod);
23580 switch (ty.zigTypeTag(mod)) {23463 switch (ty.zigTypeTag(mod)) {
23581 .Struct => {},23464 .Struct => {},
23582 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(mod)}),23465 else => return sema.fail(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(mod)}),
...@@ -23819,7 +23702,7 @@ fn checkAtomicPtrOperand(...@@ -23819,7 +23702,7 @@ fn checkAtomicPtrOperand(
23819 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(mod)) {23702 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(mod)) {
23820 .Pointer => ptr_ty.ptrInfo(mod),23703 .Pointer => ptr_ty.ptrInfo(mod),
23821 else => {23704 else => {
23822 const wanted_ptr_ty = try sema.ptrType(wanted_ptr_data);23705 const wanted_ptr_ty = try mod.ptrTypeSema(wanted_ptr_data);
23823 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);23706 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
23824 unreachable;23707 unreachable;
23825 },23708 },
...@@ -23829,7 +23712,7 @@ fn checkAtomicPtrOperand(...@@ -23829,7 +23712,7 @@ fn checkAtomicPtrOperand(
23829 wanted_ptr_data.flags.is_allowzero = ptr_data.flags.is_allowzero;23712 wanted_ptr_data.flags.is_allowzero = ptr_data.flags.is_allowzero;
23830 wanted_ptr_data.flags.is_volatile = ptr_data.flags.is_volatile;23713 wanted_ptr_data.flags.is_volatile = ptr_data.flags.is_volatile;
2383123714
23832 const wanted_ptr_ty = try sema.ptrType(wanted_ptr_data);23715 const wanted_ptr_ty = try mod.ptrTypeSema(wanted_ptr_data);
23833 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);23716 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2383423717
23835 return casted_ptr;23718 return casted_ptr;
...@@ -24006,7 +23889,7 @@ fn resolveExportOptions(...@@ -24006,7 +23889,7 @@ fn resolveExportOptions(
24006 const mod = sema.mod;23889 const mod = sema.mod;
24007 const gpa = sema.gpa;23890 const gpa = sema.gpa;
24008 const ip = &mod.intern_pool;23891 const ip = &mod.intern_pool;
24009 const export_options_ty = try sema.getBuiltinType("ExportOptions");23892 const export_options_ty = try mod.getBuiltinType("ExportOptions");
24010 const air_ref = try sema.resolveInst(zir_ref);23893 const air_ref = try sema.resolveInst(zir_ref);
24011 const options = try sema.coerce(block, export_options_ty, air_ref, src);23894 const options = try sema.coerce(block, export_options_ty, air_ref, src);
2401223895
...@@ -24070,7 +23953,7 @@ fn resolveBuiltinEnum(...@@ -24070,7 +23953,7 @@ fn resolveBuiltinEnum(
24070 reason: NeededComptimeReason,23953 reason: NeededComptimeReason,
24071) CompileError!@field(std.builtin, name) {23954) CompileError!@field(std.builtin, name) {
24072 const mod = sema.mod;23955 const mod = sema.mod;
24073 const ty = try sema.getBuiltinType(name);23956 const ty = try mod.getBuiltinType(name);
24074 const air_ref = try sema.resolveInst(zir_ref);23957 const air_ref = try sema.resolveInst(zir_ref);
24075 const coerced = try sema.coerce(block, ty, air_ref, src);23958 const coerced = try sema.coerce(block, ty, air_ref, src);
24076 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);23959 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason);
...@@ -24830,7 +24713,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -24830,7 +24713,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
24830 const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;24713 const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
24831 const func = try sema.resolveInst(extra.callee);24714 const func = try sema.resolveInst(extra.callee);
2483224715
24833 const modifier_ty = try sema.getBuiltinType("CallModifier");24716 const modifier_ty = try mod.getBuiltinType("CallModifier");
24834 const air_ref = try sema.resolveInst(extra.modifier);24717 const air_ref = try sema.resolveInst(extra.modifier);
24835 const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);24718 const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);
24836 const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{24719 const modifier_val = try sema.resolveConstDefinedValue(block, modifier_src, modifier_ref, .{
...@@ -24934,7 +24817,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24934,7 +24817,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24934 .Struct, .Union => {},24817 .Struct, .Union => {},
24935 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(zcu)}),24818 else => return sema.fail(block, inst_src, "expected pointer to struct or union type, found '{}'", .{parent_ptr_ty.fmt(zcu)}),
24936 }24819 }
24937 try sema.resolveTypeLayout(parent_ty);24820 try parent_ty.resolveLayout(zcu);
2493824821
24939 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{24822 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{
24940 .needed_comptime_reason = "field name must be comptime-known",24823 .needed_comptime_reason = "field name must be comptime-known",
...@@ -24965,7 +24848,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24965,7 +24848,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24965 var actual_parent_ptr_info: InternPool.Key.PtrType = .{24848 var actual_parent_ptr_info: InternPool.Key.PtrType = .{
24966 .child = parent_ty.toIntern(),24849 .child = parent_ty.toIntern(),
24967 .flags = .{24850 .flags = .{
24968 .alignment = try parent_ptr_ty.ptrAlignmentAdvanced(zcu, sema),24851 .alignment = try parent_ptr_ty.ptrAlignmentAdvanced(zcu, .sema),
24969 .is_const = field_ptr_info.flags.is_const,24852 .is_const = field_ptr_info.flags.is_const,
24970 .is_volatile = field_ptr_info.flags.is_volatile,24853 .is_volatile = field_ptr_info.flags.is_volatile,
24971 .is_allowzero = field_ptr_info.flags.is_allowzero,24854 .is_allowzero = field_ptr_info.flags.is_allowzero,
...@@ -24977,7 +24860,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24977,7 +24860,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24977 var actual_field_ptr_info: InternPool.Key.PtrType = .{24860 var actual_field_ptr_info: InternPool.Key.PtrType = .{
24978 .child = field_ty.toIntern(),24861 .child = field_ty.toIntern(),
24979 .flags = .{24862 .flags = .{
24980 .alignment = try field_ptr_ty.ptrAlignmentAdvanced(zcu, sema),24863 .alignment = try field_ptr_ty.ptrAlignmentAdvanced(zcu, .sema),
24981 .is_const = field_ptr_info.flags.is_const,24864 .is_const = field_ptr_info.flags.is_const,
24982 .is_volatile = field_ptr_info.flags.is_volatile,24865 .is_volatile = field_ptr_info.flags.is_volatile,
24983 .is_allowzero = field_ptr_info.flags.is_allowzero,24866 .is_allowzero = field_ptr_info.flags.is_allowzero,
...@@ -24988,12 +24871,13 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -24988,12 +24871,13 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
24988 switch (parent_ty.containerLayout(zcu)) {24871 switch (parent_ty.containerLayout(zcu)) {
24989 .auto => {24872 .auto => {
24990 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(24873 actual_parent_ptr_info.flags.alignment = actual_field_ptr_info.flags.alignment.minStrict(
24991 if (zcu.typeToStruct(parent_ty)) |struct_obj| try sema.structFieldAlignment(24874 if (zcu.typeToStruct(parent_ty)) |struct_obj| try zcu.structFieldAlignmentAdvanced(
24992 struct_obj.fieldAlign(ip, field_index),24875 struct_obj.fieldAlign(ip, field_index),
24993 field_ty,24876 field_ty,
24994 struct_obj.layout,24877 struct_obj.layout,
24878 .sema,
24995 ) else if (zcu.typeToUnion(parent_ty)) |union_obj|24879 ) else if (zcu.typeToUnion(parent_ty)) |union_obj|
24996 try sema.unionFieldAlignment(union_obj, field_index)24880 try zcu.unionFieldNormalAlignmentAdvanced(union_obj, field_index, .sema)
24997 else24881 else
24998 actual_field_ptr_info.flags.alignment,24882 actual_field_ptr_info.flags.alignment,
24999 );24883 );
...@@ -25023,9 +24907,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -25023,9 +24907,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
25023 },24907 },
25024 }24908 }
2502524909
25026 const actual_field_ptr_ty = try sema.ptrType(actual_field_ptr_info);24910 const actual_field_ptr_ty = try zcu.ptrTypeSema(actual_field_ptr_info);
25027 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src);24911 const casted_field_ptr = try sema.coerce(block, actual_field_ptr_ty, field_ptr, field_ptr_src);
25028 const actual_parent_ptr_ty = try sema.ptrType(actual_parent_ptr_info);24912 const actual_parent_ptr_ty = try zcu.ptrTypeSema(actual_parent_ptr_info);
2502924913
25030 const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: {24914 const result = if (try sema.resolveDefinedValue(block, field_ptr_src, casted_field_ptr)) |field_ptr_val| result: {
25031 switch (parent_ty.zigTypeTag(zcu)) {24915 switch (parent_ty.zigTypeTag(zcu)) {
...@@ -25085,7 +24969,6 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins...@@ -25085,7 +24969,6 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Ins
25085 break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src);24969 break :result try sema.coerce(block, actual_parent_ptr_ty, Air.internedToRef(field.base), inst_src);
25086 } else result: {24970 } else result: {
25087 try sema.requireRuntimeBlock(block, inst_src, field_ptr_src);24971 try sema.requireRuntimeBlock(block, inst_src, field_ptr_src);
25088 try sema.queueFullTypeResolution(parent_ty);
25089 break :result try block.addInst(.{24972 break :result try block.addInst(.{
25090 .tag = .field_parent_ptr,24973 .tag = .field_parent_ptr,
25091 .data = .{ .ty_pl = .{24974 .data = .{ .ty_pl = .{
...@@ -25398,7 +25281,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A...@@ -25398,7 +25281,7 @@ fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !A
25398 // Already an array pointer.25281 // Already an array pointer.
25399 return ptr;25282 return ptr;
25400 }25283 }
25401 const new_ty = try sema.ptrType(.{25284 const new_ty = try mod.ptrTypeSema(.{
25402 .child = (try mod.arrayType(.{25285 .child = (try mod.arrayType(.{
25403 .len = len,25286 .len = len,
25404 .sentinel = info.sentinel,25287 .sentinel = info.sentinel,
...@@ -25497,7 +25380,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25497,7 +25380,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25497 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {25380 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
25498 if (!sema.isComptimeMutablePtr(dest_ptr_val)) break :rs dest_src;25381 if (!sema.isComptimeMutablePtr(dest_ptr_val)) break :rs dest_src;
25499 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {25382 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
25500 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;25383 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, .sema)).?;
25501 const len = try sema.usizeCast(block, dest_src, len_u64);25384 const len = try sema.usizeCast(block, dest_src, len_u64);
25502 for (0..len) |i| {25385 for (0..len) |i| {
25503 const elem_index = try mod.intRef(Type.usize, i);25386 const elem_index = try mod.intRef(Type.usize, i);
...@@ -25556,7 +25439,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25556,7 +25439,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25556 var new_dest_ptr = dest_ptr;25439 var new_dest_ptr = dest_ptr;
25557 var new_src_ptr = src_ptr;25440 var new_src_ptr = src_ptr;
25558 if (len_val) |val| {25441 if (len_val) |val| {
25559 const len = try val.toUnsignedIntAdvanced(sema);25442 const len = try val.toUnsignedIntSema(mod);
25560 if (len == 0) {25443 if (len == 0) {
25561 // This AIR instruction guarantees length > 0 if it is comptime-known.25444 // This AIR instruction guarantees length > 0 if it is comptime-known.
25562 return;25445 return;
...@@ -25603,7 +25486,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25603,7 +25486,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25603 assert(dest_manyptr_ty_key.flags.size == .One);25486 assert(dest_manyptr_ty_key.flags.size == .One);
25604 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();25487 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();
25605 dest_manyptr_ty_key.flags.size = .Many;25488 dest_manyptr_ty_key.flags.size = .Many;
25606 break :ptr try sema.coerceCompatiblePtrs(block, try sema.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);25489 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrTypeSema(dest_manyptr_ty_key), new_dest_ptr, dest_src);
25607 } else new_dest_ptr;25490 } else new_dest_ptr;
2560825491
25609 const new_src_ptr_ty = sema.typeOf(new_src_ptr);25492 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
...@@ -25614,7 +25497,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25614,7 +25497,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25614 assert(src_manyptr_ty_key.flags.size == .One);25497 assert(src_manyptr_ty_key.flags.size == .One);
25615 src_manyptr_ty_key.child = src_elem_ty.toIntern();25498 src_manyptr_ty_key.child = src_elem_ty.toIntern();
25616 src_manyptr_ty_key.flags.size = .Many;25499 src_manyptr_ty_key.flags.size = .Many;
25617 break :ptr try sema.coerceCompatiblePtrs(block, try sema.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);25500 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrTypeSema(src_manyptr_ty_key), new_src_ptr, src_src);
25618 } else new_src_ptr;25501 } else new_src_ptr;
2561925502
25620 // ok1: dest >= src + len25503 // ok1: dest >= src + len
...@@ -25681,7 +25564,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -25681,7 +25564,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
25681 const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src;25564 const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src;
25682 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), dest_src);25565 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), dest_src);
25683 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;25566 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;
25684 const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?;25567 const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, .sema)).?;
25685 const len = try sema.usizeCast(block, dest_src, len_u64);25568 const len = try sema.usizeCast(block, dest_src, len_u64);
25686 if (len == 0) {25569 if (len == 0) {
25687 // This AIR instruction guarantees length > 0 if it is comptime-known.25570 // This AIR instruction guarantees length > 0 if it is comptime-known.
...@@ -25861,7 +25744,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25861,7 +25744,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25861 if (val.isGenericPoison()) {25744 if (val.isGenericPoison()) {
25862 break :blk null;25745 break :blk null;
25863 }25746 }
25864 const alignment = try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntAdvanced(sema));25747 const alignment = try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(mod));
25865 const default = target_util.defaultFunctionAlignment(target);25748 const default = target_util.defaultFunctionAlignment(target);
25866 break :blk if (alignment == default) .none else alignment;25749 break :blk if (alignment == default) .none else alignment;
25867 } else if (extra.data.bits.has_align_ref) blk: {25750 } else if (extra.data.bits.has_align_ref) blk: {
...@@ -25881,7 +25764,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25881,7 +25764,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25881 error.GenericPoison => break :blk null,25764 error.GenericPoison => break :blk null,
25882 else => |e| return e,25765 else => |e| return e,
25883 };25766 };
25884 const alignment = try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntAdvanced(sema));25767 const alignment = try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(mod));
25885 const default = target_util.defaultFunctionAlignment(target);25768 const default = target_util.defaultFunctionAlignment(target);
25886 break :blk if (alignment == default) .none else alignment;25769 break :blk if (alignment == default) .none else alignment;
25887 } else .none;25770 } else .none;
...@@ -25957,7 +25840,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -25957,7 +25840,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
25957 const body = sema.code.bodySlice(extra_index, body_len);25840 const body = sema.code.bodySlice(extra_index, body_len);
25958 extra_index += body.len;25841 extra_index += body.len;
2595925842
25960 const cc_ty = try sema.getBuiltinType("CallingConvention");25843 const cc_ty = try mod.getBuiltinType("CallingConvention");
25961 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, .{25844 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, .{
25962 .needed_comptime_reason = "calling convention must be comptime-known",25845 .needed_comptime_reason = "calling convention must be comptime-known",
25963 });25846 });
...@@ -26170,7 +26053,7 @@ fn resolvePrefetchOptions(...@@ -26170,7 +26053,7 @@ fn resolvePrefetchOptions(
26170 const mod = sema.mod;26053 const mod = sema.mod;
26171 const gpa = sema.gpa;26054 const gpa = sema.gpa;
26172 const ip = &mod.intern_pool;26055 const ip = &mod.intern_pool;
26173 const options_ty = try sema.getBuiltinType("PrefetchOptions");26056 const options_ty = try mod.getBuiltinType("PrefetchOptions");
26174 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);26057 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
2617526058
26176 const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node });26059 const rw_src = block.src(.{ .init_field_rw = src.offset.node_offset_builtin_call_arg.builtin_call_node });
...@@ -26194,7 +26077,7 @@ fn resolvePrefetchOptions(...@@ -26194,7 +26077,7 @@ fn resolvePrefetchOptions(
2619426077
26195 return std.builtin.PrefetchOptions{26078 return std.builtin.PrefetchOptions{
26196 .rw = mod.toEnum(std.builtin.PrefetchOptions.Rw, rw_val),26079 .rw = mod.toEnum(std.builtin.PrefetchOptions.Rw, rw_val),
26197 .locality = @intCast(try locality_val.toUnsignedIntAdvanced(sema)),26080 .locality = @intCast(try locality_val.toUnsignedIntSema(mod)),
26198 .cache = mod.toEnum(std.builtin.PrefetchOptions.Cache, cache_val),26081 .cache = mod.toEnum(std.builtin.PrefetchOptions.Cache, cache_val),
26199 };26082 };
26200}26083}
...@@ -26242,7 +26125,7 @@ fn resolveExternOptions(...@@ -26242,7 +26125,7 @@ fn resolveExternOptions(
26242 const gpa = sema.gpa;26125 const gpa = sema.gpa;
26243 const ip = &mod.intern_pool;26126 const ip = &mod.intern_pool;
26244 const options_inst = try sema.resolveInst(zir_ref);26127 const options_inst = try sema.resolveInst(zir_ref);
26245 const extern_options_ty = try sema.getBuiltinType("ExternOptions");26128 const extern_options_ty = try mod.getBuiltinType("ExternOptions");
26246 const options = try sema.coerce(block, extern_options_ty, options_inst, src);26129 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
2624726130
26248 const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node });26131 const name_src = block.src(.{ .init_field_name = src.offset.node_offset_builtin_call_arg.builtin_call_node });
...@@ -26493,7 +26376,7 @@ fn explainWhyTypeIsComptime(...@@ -26493,7 +26376,7 @@ fn explainWhyTypeIsComptime(
26493 var type_set = TypeSet{};26376 var type_set = TypeSet{};
26494 defer type_set.deinit(sema.gpa);26377 defer type_set.deinit(sema.gpa);
2649526378
26496 try sema.resolveTypeFully(ty);26379 try ty.resolveFully(sema.mod);
26497 return sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty, &type_set);26380 return sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty, &type_set);
26498}26381}
2649926382
...@@ -26620,7 +26503,7 @@ const ExternPosition = enum {...@@ -26620,7 +26503,7 @@ const ExternPosition = enum {
2662026503
26621/// Returns true if `ty` is allowed in extern types.26504/// Returns true if `ty` is allowed in extern types.
26622/// Does *NOT* require `ty` to be resolved in any way.26505/// Does *NOT* require `ty` to be resolved in any way.
26623/// Calls `resolveTypeLayout` for packed containers.26506/// Calls `resolveLayout` for packed containers.
26624fn validateExternType(26507fn validateExternType(
26625 sema: *Sema,26508 sema: *Sema,
26626 ty: Type,26509 ty: Type,
...@@ -26671,7 +26554,7 @@ fn validateExternType(...@@ -26671,7 +26554,7 @@ fn validateExternType(
26671 .Struct, .Union => switch (ty.containerLayout(mod)) {26554 .Struct, .Union => switch (ty.containerLayout(mod)) {
26672 .@"extern" => return true,26555 .@"extern" => return true,
26673 .@"packed" => {26556 .@"packed" => {
26674 const bit_size = try ty.bitSizeAdvanced(mod, sema);26557 const bit_size = try ty.bitSizeAdvanced(mod, .sema);
26675 switch (bit_size) {26558 switch (bit_size) {
26676 0, 8, 16, 32, 64, 128 => return true,26559 0, 8, 16, 32, 64, 128 => return true,
26677 else => return false,26560 else => return false,
...@@ -26849,11 +26732,11 @@ fn explainWhyTypeIsNotPacked(...@@ -26849,11 +26732,11 @@ fn explainWhyTypeIsNotPacked(
26849 }26732 }
26850}26733}
2685126734
26852fn prepareSimplePanic(sema: *Sema, block: *Block) !void {26735fn prepareSimplePanic(sema: *Sema) !void {
26853 const mod = sema.mod;26736 const mod = sema.mod;
2685426737
26855 if (mod.panic_func_index == .none) {26738 if (mod.panic_func_index == .none) {
26856 const decl_index = (try sema.getBuiltinDecl(block, "panic"));26739 const decl_index = (try mod.getBuiltinDecl("panic"));
26857 // decl_index may be an alias; we must find the decl that actually26740 // decl_index may be an alias; we must find the decl that actually
26858 // owns the function.26741 // owns the function.
26859 try sema.ensureDeclAnalyzed(decl_index);26742 try sema.ensureDeclAnalyzed(decl_index);
...@@ -26866,10 +26749,10 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {...@@ -26866,10 +26749,10 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void {
26866 }26749 }
2686726750
26868 if (mod.null_stack_trace == .none) {26751 if (mod.null_stack_trace == .none) {
26869 const stack_trace_ty = try sema.getBuiltinType("StackTrace");26752 const stack_trace_ty = try mod.getBuiltinType("StackTrace");
26870 try sema.resolveTypeFields(stack_trace_ty);26753 try stack_trace_ty.resolveFields(mod);
26871 const target = mod.getTarget();26754 const target = mod.getTarget();
26872 const ptr_stack_trace_ty = try sema.ptrType(.{26755 const ptr_stack_trace_ty = try mod.ptrTypeSema(.{
26873 .child = stack_trace_ty.toIntern(),26756 .child = stack_trace_ty.toIntern(),
26874 .flags = .{26757 .flags = .{
26875 .address_space = target_util.defaultAddressSpace(target, .global_constant),26758 .address_space = target_util.defaultAddressSpace(target, .global_constant),
...@@ -26891,9 +26774,9 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP...@@ -26891,9 +26774,9 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP
26891 const gpa = sema.gpa;26774 const gpa = sema.gpa;
26892 if (mod.panic_messages[@intFromEnum(panic_id)].unwrap()) |x| return x;26775 if (mod.panic_messages[@intFromEnum(panic_id)].unwrap()) |x| return x;
2689326776
26894 try sema.prepareSimplePanic(block);26777 try sema.prepareSimplePanic();
2689526778
26896 const panic_messages_ty = try sema.getBuiltinType("panic_messages");26779 const panic_messages_ty = try mod.getBuiltinType("panic_messages");
26897 const msg_decl_index = (sema.namespaceLookup(26780 const msg_decl_index = (sema.namespaceLookup(
26898 block,26781 block,
26899 LazySrcLoc.unneeded,26782 LazySrcLoc.unneeded,
...@@ -26999,7 +26882,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst....@@ -26999,7 +26882,7 @@ fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.
26999 return;26882 return;
27000 }26883 }
2700126884
27002 try sema.prepareSimplePanic(block);26885 try sema.prepareSimplePanic();
2700326886
27004 const panic_func = mod.funcInfo(mod.panic_func_index);26887 const panic_func = mod.funcInfo(mod.panic_func_index);
27005 const panic_fn = try sema.analyzeDeclVal(block, src, panic_func.owner_decl);26888 const panic_fn = try sema.analyzeDeclVal(block, src, panic_func.owner_decl);
...@@ -27045,7 +26928,7 @@ fn panicUnwrapError(...@@ -27045,7 +26928,7 @@ fn panicUnwrapError(
27045 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) {26928 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) {
27046 _ = try fail_block.addNoOp(.trap);26929 _ = try fail_block.addNoOp(.trap);
27047 } else {26930 } else {
27048 const panic_fn = try sema.getBuiltin("panicUnwrapError");26931 const panic_fn = try sema.mod.getBuiltin("panicUnwrapError");
27049 const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);26932 const err = try fail_block.addTyOp(unwrap_err_tag, Type.anyerror, operand);
27050 const err_return_trace = try sema.getErrorReturnTrace(&fail_block);26933 const err_return_trace = try sema.getErrorReturnTrace(&fail_block);
27051 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };26934 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
...@@ -27104,7 +26987,7 @@ fn panicSentinelMismatch(...@@ -27104,7 +26987,7 @@ fn panicSentinelMismatch(
27104 const actual_sentinel = if (ptr_ty.isSlice(mod))26987 const actual_sentinel = if (ptr_ty.isSlice(mod))
27105 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)26988 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
27106 else blk: {26989 else blk: {
27107 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);26990 const elem_ptr_ty = try ptr_ty.elemPtrType(null, mod);
27108 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);26991 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);
27109 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);26992 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);
27110 };26993 };
...@@ -27122,7 +27005,7 @@ fn panicSentinelMismatch(...@@ -27122,7 +27005,7 @@ fn panicSentinelMismatch(
27122 } else if (sentinel_ty.isSelfComparable(mod, true))27005 } else if (sentinel_ty.isSelfComparable(mod, true))
27123 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)27006 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)
27124 else {27007 else {
27125 const panic_fn = try sema.getBuiltin("checkNonScalarSentinel");27008 const panic_fn = try mod.getBuiltin("checkNonScalarSentinel");
27126 const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel };27009 const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel };
27127 try sema.callBuiltin(parent_block, src, panic_fn, .auto, &args, .@"safety check");27010 try sema.callBuiltin(parent_block, src, panic_fn, .auto, &args, .@"safety check");
27128 return;27011 return;
...@@ -27161,7 +27044,7 @@ fn safetyCheckFormatted(...@@ -27161,7 +27044,7 @@ fn safetyCheckFormatted(
27161 if (!sema.mod.backendSupportsFeature(.safety_check_formatted)) {27044 if (!sema.mod.backendSupportsFeature(.safety_check_formatted)) {
27162 _ = try fail_block.addNoOp(.trap);27045 _ = try fail_block.addNoOp(.trap);
27163 } else {27046 } else {
27164 const panic_fn = try sema.getBuiltin(func);27047 const panic_fn = try sema.mod.getBuiltin(func);
27165 try sema.callBuiltin(&fail_block, src, panic_fn, .auto, args, .@"safety check");27048 try sema.callBuiltin(&fail_block, src, panic_fn, .auto, args, .@"safety check");
27166 }27049 }
27167 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);27050 try sema.addSafetyCheckExtra(parent_block, ok, &fail_block);
...@@ -27223,7 +27106,7 @@ fn fieldVal(...@@ -27223,7 +27106,7 @@ fn fieldVal(
27223 return Air.internedToRef((try mod.intValue(Type.usize, inner_ty.arrayLen(mod))).toIntern());27106 return Air.internedToRef((try mod.intValue(Type.usize, inner_ty.arrayLen(mod))).toIntern());
27224 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {27107 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {
27225 const ptr_info = object_ty.ptrInfo(mod);27108 const ptr_info = object_ty.ptrInfo(mod);
27226 const result_ty = try sema.ptrType(.{27109 const result_ty = try mod.ptrTypeSema(.{
27227 .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(),27110 .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(),
27228 .sentinel = if (inner_ty.sentinel(mod)) |s| s.toIntern() else .none,27111 .sentinel = if (inner_ty.sentinel(mod)) |s| s.toIntern() else .none,
27229 .flags = .{27112 .flags = .{
...@@ -27320,7 +27203,7 @@ fn fieldVal(...@@ -27320,7 +27203,7 @@ fn fieldVal(
27320 if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| {27203 if (try sema.namespaceLookupVal(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| {
27321 return inst;27204 return inst;
27322 }27205 }
27323 try sema.resolveTypeFields(child_type);27206 try child_type.resolveFields(mod);
27324 if (child_type.unionTagType(mod)) |enum_ty| {27207 if (child_type.unionTagType(mod)) |enum_ty| {
27325 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index_usize| {27208 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index_usize| {
27326 const field_index: u32 = @intCast(field_index_usize);27209 const field_index: u32 = @intCast(field_index_usize);
...@@ -27414,7 +27297,7 @@ fn fieldPtr(...@@ -27414,7 +27297,7 @@ fn fieldPtr(
27414 return anonDeclRef(sema, int_val.toIntern());27297 return anonDeclRef(sema, int_val.toIntern());
27415 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {27298 } else if (field_name.eqlSlice("ptr", ip) and is_pointer_to) {
27416 const ptr_info = object_ty.ptrInfo(mod);27299 const ptr_info = object_ty.ptrInfo(mod);
27417 const new_ptr_ty = try sema.ptrType(.{27300 const new_ptr_ty = try mod.ptrTypeSema(.{
27418 .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(),27301 .child = Type.fromInterned(ptr_info.child).childType(mod).toIntern(),
27419 .sentinel = if (object_ty.sentinel(mod)) |s| s.toIntern() else .none,27302 .sentinel = if (object_ty.sentinel(mod)) |s| s.toIntern() else .none,
27420 .flags = .{27303 .flags = .{
...@@ -27429,7 +27312,7 @@ fn fieldPtr(...@@ -27429,7 +27312,7 @@ fn fieldPtr(
27429 .packed_offset = ptr_info.packed_offset,27312 .packed_offset = ptr_info.packed_offset,
27430 });27313 });
27431 const ptr_ptr_info = object_ptr_ty.ptrInfo(mod);27314 const ptr_ptr_info = object_ptr_ty.ptrInfo(mod);
27432 const result_ty = try sema.ptrType(.{27315 const result_ty = try mod.ptrTypeSema(.{
27433 .child = new_ptr_ty.toIntern(),27316 .child = new_ptr_ty.toIntern(),
27434 .sentinel = if (object_ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,27317 .sentinel = if (object_ptr_ty.sentinel(mod)) |s| s.toIntern() else .none,
27435 .flags = .{27318 .flags = .{
...@@ -27463,7 +27346,7 @@ fn fieldPtr(...@@ -27463,7 +27346,7 @@ fn fieldPtr(
27463 if (field_name.eqlSlice("ptr", ip)) {27346 if (field_name.eqlSlice("ptr", ip)) {
27464 const slice_ptr_ty = inner_ty.slicePtrFieldType(mod);27347 const slice_ptr_ty = inner_ty.slicePtrFieldType(mod);
2746527348
27466 const result_ty = try sema.ptrType(.{27349 const result_ty = try mod.ptrTypeSema(.{
27467 .child = slice_ptr_ty.toIntern(),27350 .child = slice_ptr_ty.toIntern(),
27468 .flags = .{27351 .flags = .{
27469 .is_const = !attr_ptr_ty.ptrIsMutable(mod),27352 .is_const = !attr_ptr_ty.ptrIsMutable(mod),
...@@ -27473,7 +27356,7 @@ fn fieldPtr(...@@ -27473,7 +27356,7 @@ fn fieldPtr(
27473 });27356 });
2747427357
27475 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {27358 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
27476 return Air.internedToRef((try val.ptrField(Value.slice_ptr_index, sema)).toIntern());27359 return Air.internedToRef((try val.ptrField(Value.slice_ptr_index, mod)).toIntern());
27477 }27360 }
27478 try sema.requireRuntimeBlock(block, src, null);27361 try sema.requireRuntimeBlock(block, src, null);
2747927362
...@@ -27481,7 +27364,7 @@ fn fieldPtr(...@@ -27481,7 +27364,7 @@ fn fieldPtr(
27481 try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);27364 try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr);
27482 return field_ptr;27365 return field_ptr;
27483 } else if (field_name.eqlSlice("len", ip)) {27366 } else if (field_name.eqlSlice("len", ip)) {
27484 const result_ty = try sema.ptrType(.{27367 const result_ty = try mod.ptrTypeSema(.{
27485 .child = .usize_type,27368 .child = .usize_type,
27486 .flags = .{27369 .flags = .{
27487 .is_const = !attr_ptr_ty.ptrIsMutable(mod),27370 .is_const = !attr_ptr_ty.ptrIsMutable(mod),
...@@ -27491,7 +27374,7 @@ fn fieldPtr(...@@ -27491,7 +27374,7 @@ fn fieldPtr(
27491 });27374 });
2749227375
27493 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {27376 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
27494 return Air.internedToRef((try val.ptrField(Value.slice_len_index, sema)).toIntern());27377 return Air.internedToRef((try val.ptrField(Value.slice_len_index, mod)).toIntern());
27495 }27378 }
27496 try sema.requireRuntimeBlock(block, src, null);27379 try sema.requireRuntimeBlock(block, src, null);
2749727380
...@@ -27559,7 +27442,7 @@ fn fieldPtr(...@@ -27559,7 +27442,7 @@ fn fieldPtr(
27559 if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| {27442 if (try sema.namespaceLookupRef(block, src, child_type.getNamespaceIndex(mod), field_name)) |inst| {
27560 return inst;27443 return inst;
27561 }27444 }
27562 try sema.resolveTypeFields(child_type);27445 try child_type.resolveFields(mod);
27563 if (child_type.unionTagType(mod)) |enum_ty| {27446 if (child_type.unionTagType(mod)) |enum_ty| {
27564 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {27447 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {
27565 const field_index_u32: u32 = @intCast(field_index);27448 const field_index_u32: u32 = @intCast(field_index);
...@@ -27654,7 +27537,7 @@ fn fieldCallBind(...@@ -27654,7 +27537,7 @@ fn fieldCallBind(
27654 find_field: {27537 find_field: {
27655 switch (concrete_ty.zigTypeTag(mod)) {27538 switch (concrete_ty.zigTypeTag(mod)) {
27656 .Struct => {27539 .Struct => {
27657 try sema.resolveTypeFields(concrete_ty);27540 try concrete_ty.resolveFields(mod);
27658 if (mod.typeToStruct(concrete_ty)) |struct_type| {27541 if (mod.typeToStruct(concrete_ty)) |struct_type| {
27659 const field_index = struct_type.nameIndex(ip, field_name) orelse27542 const field_index = struct_type.nameIndex(ip, field_name) orelse
27660 break :find_field;27543 break :find_field;
...@@ -27680,7 +27563,7 @@ fn fieldCallBind(...@@ -27680,7 +27563,7 @@ fn fieldCallBind(
27680 }27563 }
27681 },27564 },
27682 .Union => {27565 .Union => {
27683 try sema.resolveTypeFields(concrete_ty);27566 try concrete_ty.resolveFields(mod);
27684 const union_obj = mod.typeToUnion(concrete_ty).?;27567 const union_obj = mod.typeToUnion(concrete_ty).?;
27685 _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field;27568 _ = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse break :find_field;
27686 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);27569 const field_ptr = try unionFieldPtr(sema, block, src, object_ptr, field_name, field_name_src, concrete_ty, false);
...@@ -27701,7 +27584,6 @@ fn fieldCallBind(...@@ -27701,7 +27584,6 @@ fn fieldCallBind(
27701 const decl_idx = (try sema.namespaceLookup(block, src, namespace, field_name)) orelse27584 const decl_idx = (try sema.namespaceLookup(block, src, namespace, field_name)) orelse
27702 break :found_decl null;27585 break :found_decl null;
2770327586
27704 try sema.addReferencedBy(src, decl_idx);
27705 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);27587 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
27706 const decl_type = sema.typeOf(decl_val);27588 const decl_type = sema.typeOf(decl_val);
27707 if (mod.typeToFunc(decl_type)) |func_type| f: {27589 if (mod.typeToFunc(decl_type)) |func_type| f: {
...@@ -27791,7 +27673,7 @@ fn finishFieldCallBind(...@@ -27791,7 +27673,7 @@ fn finishFieldCallBind(
27791 object_ptr: Air.Inst.Ref,27673 object_ptr: Air.Inst.Ref,
27792) CompileError!ResolvedFieldCallee {27674) CompileError!ResolvedFieldCallee {
27793 const mod = sema.mod;27675 const mod = sema.mod;
27794 const ptr_field_ty = try sema.ptrType(.{27676 const ptr_field_ty = try mod.ptrTypeSema(.{
27795 .child = field_ty.toIntern(),27677 .child = field_ty.toIntern(),
27796 .flags = .{27678 .flags = .{
27797 .is_const = !ptr_ty.ptrIsMutable(mod),27679 .is_const = !ptr_ty.ptrIsMutable(mod),
...@@ -27802,14 +27684,14 @@ fn finishFieldCallBind(...@@ -27802,14 +27684,14 @@ fn finishFieldCallBind(
27802 const container_ty = ptr_ty.childType(mod);27684 const container_ty = ptr_ty.childType(mod);
27803 if (container_ty.zigTypeTag(mod) == .Struct) {27685 if (container_ty.zigTypeTag(mod) == .Struct) {
27804 if (container_ty.structFieldIsComptime(field_index, mod)) {27686 if (container_ty.structFieldIsComptime(field_index, mod)) {
27805 try sema.resolveStructFieldInits(container_ty);27687 try container_ty.resolveStructFieldInits(mod);
27806 const default_val = (try container_ty.structFieldValueComptime(mod, field_index)).?;27688 const default_val = (try container_ty.structFieldValueComptime(mod, field_index)).?;
27807 return .{ .direct = Air.internedToRef(default_val.toIntern()) };27689 return .{ .direct = Air.internedToRef(default_val.toIntern()) };
27808 }27690 }
27809 }27691 }
2781027692
27811 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {27693 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
27812 const ptr_val = try struct_ptr_val.ptrField(field_index, sema);27694 const ptr_val = try struct_ptr_val.ptrField(field_index, mod);
27813 const pointer = Air.internedToRef(ptr_val.toIntern());27695 const pointer = Air.internedToRef(ptr_val.toIntern());
27814 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };27696 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
27815 }27697 }
...@@ -27857,8 +27739,7 @@ fn namespaceLookupRef(...@@ -27857,8 +27739,7 @@ fn namespaceLookupRef(
27857 decl_name: InternPool.NullTerminatedString,27739 decl_name: InternPool.NullTerminatedString,
27858) CompileError!?Air.Inst.Ref {27740) CompileError!?Air.Inst.Ref {
27859 const decl = (try sema.namespaceLookup(block, src, opt_namespace, decl_name)) orelse return null;27741 const decl = (try sema.namespaceLookup(block, src, opt_namespace, decl_name)) orelse return null;
27860 try sema.addReferencedBy(src, decl);27742 return try sema.analyzeDeclRef(src, decl);
27861 return try sema.analyzeDeclRef(decl);
27862}27743}
2786327744
27864fn namespaceLookupVal(27745fn namespaceLookupVal(
...@@ -27886,8 +27767,8 @@ fn structFieldPtr(...@@ -27886,8 +27767,8 @@ fn structFieldPtr(
27886 const ip = &mod.intern_pool;27767 const ip = &mod.intern_pool;
27887 assert(struct_ty.zigTypeTag(mod) == .Struct);27768 assert(struct_ty.zigTypeTag(mod) == .Struct);
2788827769
27889 try sema.resolveTypeFields(struct_ty);27770 try struct_ty.resolveFields(mod);
27890 try sema.resolveStructLayout(struct_ty);27771 try struct_ty.resolveLayout(mod);
2789127772
27892 if (struct_ty.isTuple(mod)) {27773 if (struct_ty.isTuple(mod)) {
27893 if (field_name.eqlSlice("len", ip)) {27774 if (field_name.eqlSlice("len", ip)) {
...@@ -27926,7 +27807,7 @@ fn structFieldPtrByIndex(...@@ -27926,7 +27807,7 @@ fn structFieldPtrByIndex(
27926 }27807 }
2792727808
27928 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {27809 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
27929 const val = try struct_ptr_val.ptrField(field_index, sema);27810 const val = try struct_ptr_val.ptrField(field_index, mod);
27930 return Air.internedToRef(val.toIntern());27811 return Air.internedToRef(val.toIntern());
27931 }27812 }
2793227813
...@@ -27970,10 +27851,11 @@ fn structFieldPtrByIndex(...@@ -27970,10 +27851,11 @@ fn structFieldPtrByIndex(
27970 @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset)));27851 @enumFromInt(@min(@intFromEnum(parent_align), @ctz(field_offset)));
27971 } else {27852 } else {
27972 // Our alignment is capped at the field alignment.27853 // Our alignment is capped at the field alignment.
27973 const field_align = try sema.structFieldAlignment(27854 const field_align = try mod.structFieldAlignmentAdvanced(
27974 struct_type.fieldAlign(ip, field_index),27855 struct_type.fieldAlign(ip, field_index),
27975 Type.fromInterned(field_ty),27856 Type.fromInterned(field_ty),
27976 struct_type.layout,27857 struct_type.layout,
27858 .sema,
27977 );27859 );
27978 ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none)27860 ptr_ty_data.flags.alignment = if (struct_ptr_ty_info.flags.alignment == .none)
27979 field_align27861 field_align
...@@ -27981,10 +27863,10 @@ fn structFieldPtrByIndex(...@@ -27981,10 +27863,10 @@ fn structFieldPtrByIndex(
27981 field_align.min(parent_align);27863 field_align.min(parent_align);
27982 }27864 }
2798327865
27984 const ptr_field_ty = try sema.ptrType(ptr_ty_data);27866 const ptr_field_ty = try mod.ptrTypeSema(ptr_ty_data);
2798527867
27986 if (struct_type.fieldIsComptime(ip, field_index)) {27868 if (struct_type.fieldIsComptime(ip, field_index)) {
27987 try sema.resolveStructFieldInits(struct_ty);27869 try struct_ty.resolveStructFieldInits(mod);
27988 const val = try mod.intern(.{ .ptr = .{27870 const val = try mod.intern(.{ .ptr = .{
27989 .ty = ptr_field_ty.toIntern(),27871 .ty = ptr_field_ty.toIntern(),
27990 .base_addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] },27872 .base_addr = .{ .comptime_field = struct_type.field_inits.get(ip)[field_index] },
...@@ -28010,7 +27892,7 @@ fn structFieldVal(...@@ -28010,7 +27892,7 @@ fn structFieldVal(
28010 const ip = &mod.intern_pool;27892 const ip = &mod.intern_pool;
28011 assert(struct_ty.zigTypeTag(mod) == .Struct);27893 assert(struct_ty.zigTypeTag(mod) == .Struct);
2801227894
28013 try sema.resolveTypeFields(struct_ty);27895 try struct_ty.resolveFields(mod);
2801427896
28015 switch (ip.indexToKey(struct_ty.toIntern())) {27897 switch (ip.indexToKey(struct_ty.toIntern())) {
28016 .struct_type => {27898 .struct_type => {
...@@ -28021,7 +27903,7 @@ fn structFieldVal(...@@ -28021,7 +27903,7 @@ fn structFieldVal(
28021 const field_index = struct_type.nameIndex(ip, field_name) orelse27903 const field_index = struct_type.nameIndex(ip, field_name) orelse
28022 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);27904 return sema.failWithBadStructFieldAccess(block, struct_ty, struct_type, field_name_src, field_name);
28023 if (struct_type.fieldIsComptime(ip, field_index)) {27905 if (struct_type.fieldIsComptime(ip, field_index)) {
28024 try sema.resolveStructFieldInits(struct_ty);27906 try struct_ty.resolveStructFieldInits(mod);
28025 return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]);27907 return Air.internedToRef(struct_type.field_inits.get(ip)[field_index]);
28026 }27908 }
2802727909
...@@ -28038,7 +27920,7 @@ fn structFieldVal(...@@ -28038,7 +27920,7 @@ fn structFieldVal(
28038 }27920 }
2803927921
28040 try sema.requireRuntimeBlock(block, src, null);27922 try sema.requireRuntimeBlock(block, src, null);
28041 try sema.resolveTypeLayout(field_ty);27923 try field_ty.resolveLayout(mod);
28042 return block.addStructFieldVal(struct_byval, field_index, field_ty);27924 return block.addStructFieldVal(struct_byval, field_index, field_ty);
28043 },27925 },
28044 .anon_struct_type => |anon_struct| {27926 .anon_struct_type => |anon_struct| {
...@@ -28105,7 +27987,7 @@ fn tupleFieldValByIndex(...@@ -28105,7 +27987,7 @@ fn tupleFieldValByIndex(
28105 const field_ty = tuple_ty.structFieldType(field_index, mod);27987 const field_ty = tuple_ty.structFieldType(field_index, mod);
2810627988
28107 if (tuple_ty.structFieldIsComptime(field_index, mod))27989 if (tuple_ty.structFieldIsComptime(field_index, mod))
28108 try sema.resolveStructFieldInits(tuple_ty);27990 try tuple_ty.resolveStructFieldInits(mod);
28109 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {27991 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
28110 return Air.internedToRef(default_value.toIntern());27992 return Air.internedToRef(default_value.toIntern());
28111 }27993 }
...@@ -28126,7 +28008,7 @@ fn tupleFieldValByIndex(...@@ -28126,7 +28008,7 @@ fn tupleFieldValByIndex(
28126 }28008 }
2812728009
28128 try sema.requireRuntimeBlock(block, src, null);28010 try sema.requireRuntimeBlock(block, src, null);
28129 try sema.resolveTypeLayout(field_ty);28011 try field_ty.resolveLayout(mod);
28130 return block.addStructFieldVal(tuple_byval, field_index, field_ty);28012 return block.addStructFieldVal(tuple_byval, field_index, field_ty);
28131}28013}
2813228014
...@@ -28147,11 +28029,11 @@ fn unionFieldPtr(...@@ -28147,11 +28029,11 @@ fn unionFieldPtr(
2814728029
28148 const union_ptr_ty = sema.typeOf(union_ptr);28030 const union_ptr_ty = sema.typeOf(union_ptr);
28149 const union_ptr_info = union_ptr_ty.ptrInfo(mod);28031 const union_ptr_info = union_ptr_ty.ptrInfo(mod);
28150 try sema.resolveTypeFields(union_ty);28032 try union_ty.resolveFields(mod);
28151 const union_obj = mod.typeToUnion(union_ty).?;28033 const union_obj = mod.typeToUnion(union_ty).?;
28152 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);28034 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
28153 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);28035 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
28154 const ptr_field_ty = try sema.ptrType(.{28036 const ptr_field_ty = try mod.ptrTypeSema(.{
28155 .child = field_ty.toIntern(),28037 .child = field_ty.toIntern(),
28156 .flags = .{28038 .flags = .{
28157 .is_const = union_ptr_info.flags.is_const,28039 .is_const = union_ptr_info.flags.is_const,
...@@ -28162,7 +28044,7 @@ fn unionFieldPtr(...@@ -28162,7 +28044,7 @@ fn unionFieldPtr(
28162 union_ptr_info.flags.alignment28044 union_ptr_info.flags.alignment
28163 else28045 else
28164 try sema.typeAbiAlignment(union_ty);28046 try sema.typeAbiAlignment(union_ty);
28165 const field_align = try sema.unionFieldAlignment(union_obj, field_index);28047 const field_align = try mod.unionFieldNormalAlignmentAdvanced(union_obj, field_index, .sema);
28166 break :blk union_align.min(field_align);28048 break :blk union_align.min(field_align);
28167 } else union_ptr_info.flags.alignment,28049 } else union_ptr_info.flags.alignment,
28168 },28050 },
...@@ -28218,7 +28100,7 @@ fn unionFieldPtr(...@@ -28218,7 +28100,7 @@ fn unionFieldPtr(
28218 },28100 },
28219 .@"packed", .@"extern" => {},28101 .@"packed", .@"extern" => {},
28220 }28102 }
28221 const field_ptr_val = try union_ptr_val.ptrField(field_index, sema);28103 const field_ptr_val = try union_ptr_val.ptrField(field_index, mod);
28222 return Air.internedToRef(field_ptr_val.toIntern());28104 return Air.internedToRef(field_ptr_val.toIntern());
28223 }28105 }
2822428106
...@@ -28253,7 +28135,7 @@ fn unionFieldVal(...@@ -28253,7 +28135,7 @@ fn unionFieldVal(
28253 const ip = &zcu.intern_pool;28135 const ip = &zcu.intern_pool;
28254 assert(union_ty.zigTypeTag(zcu) == .Union);28136 assert(union_ty.zigTypeTag(zcu) == .Union);
2825528137
28256 try sema.resolveTypeFields(union_ty);28138 try union_ty.resolveFields(zcu);
28257 const union_obj = zcu.typeToUnion(union_ty).?;28139 const union_obj = zcu.typeToUnion(union_ty).?;
28258 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);28140 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
28259 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);28141 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
...@@ -28292,7 +28174,7 @@ fn unionFieldVal(...@@ -28292,7 +28174,7 @@ fn unionFieldVal(
28292 .@"packed" => if (tag_matches) {28174 .@"packed" => if (tag_matches) {
28293 // Fast path - no need to use bitcast logic.28175 // Fast path - no need to use bitcast logic.
28294 return Air.internedToRef(un.val);28176 return Air.internedToRef(un.val);
28295 } else if (try sema.bitCastVal(union_val, field_ty, 0, try union_ty.bitSizeAdvanced(zcu, sema), 0)) |field_val| {28177 } else if (try sema.bitCastVal(union_val, field_ty, 0, try union_ty.bitSizeAdvanced(zcu, .sema), 0)) |field_val| {
28296 return Air.internedToRef(field_val.toIntern());28178 return Air.internedToRef(field_val.toIntern());
28297 },28179 },
28298 }28180 }
...@@ -28311,7 +28193,7 @@ fn unionFieldVal(...@@ -28311,7 +28193,7 @@ fn unionFieldVal(
28311 _ = try block.addNoOp(.unreach);28193 _ = try block.addNoOp(.unreach);
28312 return .unreachable_value;28194 return .unreachable_value;
28313 }28195 }
28314 try sema.resolveTypeLayout(field_ty);28196 try field_ty.resolveLayout(zcu);
28315 return block.addStructFieldVal(union_byval, field_index, field_ty);28197 return block.addStructFieldVal(union_byval, field_index, field_ty);
28316}28198}
2831728199
...@@ -28342,7 +28224,7 @@ fn elemPtr(...@@ -28342,7 +28224,7 @@ fn elemPtr(
28342 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{28224 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{
28343 .needed_comptime_reason = "tuple field access index must be comptime-known",28225 .needed_comptime_reason = "tuple field access index must be comptime-known",
28344 });28226 });
28345 const index: u32 = @intCast(try index_val.toUnsignedIntAdvanced(sema));28227 const index: u32 = @intCast(try index_val.toUnsignedIntSema(mod));
28346 break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);28228 break :blk try sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);
28347 },28229 },
28348 else => {28230 else => {
...@@ -28380,11 +28262,11 @@ fn elemPtrOneLayerOnly(...@@ -28380,11 +28262,11 @@ fn elemPtrOneLayerOnly(
28380 const runtime_src = rs: {28262 const runtime_src = rs: {
28381 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;28263 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
28382 const index_val = maybe_index_val orelse break :rs elem_index_src;28264 const index_val = maybe_index_val orelse break :rs elem_index_src;
28383 const index: usize = @intCast(try index_val.toUnsignedIntAdvanced(sema));28265 const index: usize = @intCast(try index_val.toUnsignedIntSema(mod));
28384 const elem_ptr = try ptr_val.ptrElem(index, sema);28266 const elem_ptr = try ptr_val.ptrElem(index, mod);
28385 return Air.internedToRef(elem_ptr.toIntern());28267 return Air.internedToRef(elem_ptr.toIntern());
28386 };28268 };
28387 const result_ty = try sema.elemPtrType(indexable_ty, null);28269 const result_ty = try indexable_ty.elemPtrType(null, mod);
2838828270
28389 try sema.requireRuntimeBlock(block, src, runtime_src);28271 try sema.requireRuntimeBlock(block, src, runtime_src);
28390 return block.addPtrElemPtr(indexable, elem_index, result_ty);28272 return block.addPtrElemPtr(indexable, elem_index, result_ty);
...@@ -28398,7 +28280,7 @@ fn elemPtrOneLayerOnly(...@@ -28398,7 +28280,7 @@ fn elemPtrOneLayerOnly(
28398 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{28280 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{
28399 .needed_comptime_reason = "tuple field access index must be comptime-known",28281 .needed_comptime_reason = "tuple field access index must be comptime-known",
28400 });28282 });
28401 const index: u32 = @intCast(try index_val.toUnsignedIntAdvanced(sema));28283 const index: u32 = @intCast(try index_val.toUnsignedIntSema(mod));
28402 break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false);28284 break :blk try sema.tupleFieldPtr(block, indexable_src, indexable, elem_index_src, index, false);
28403 },28285 },
28404 else => unreachable, // Guaranteed by checkIndexable28286 else => unreachable, // Guaranteed by checkIndexable
...@@ -28438,12 +28320,12 @@ fn elemVal(...@@ -28438,12 +28320,12 @@ fn elemVal(
28438 const runtime_src = rs: {28320 const runtime_src = rs: {
28439 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;28321 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
28440 const index_val = maybe_index_val orelse break :rs elem_index_src;28322 const index_val = maybe_index_val orelse break :rs elem_index_src;
28441 const index: usize = @intCast(try index_val.toUnsignedIntAdvanced(sema));28323 const index: usize = @intCast(try index_val.toUnsignedIntSema(mod));
28442 const elem_ty = indexable_ty.elemType2(mod);28324 const elem_ty = indexable_ty.elemType2(mod);
28443 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);28325 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
28444 const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);28326 const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);
28445 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);28327 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
28446 const elem_ptr_val = try many_ptr_val.ptrElem(index, sema);28328 const elem_ptr_val = try many_ptr_val.ptrElem(index, mod);
28447 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {28329 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
28448 return Air.internedToRef((try mod.getCoerced(elem_val, elem_ty)).toIntern());28330 return Air.internedToRef((try mod.getCoerced(elem_val, elem_ty)).toIntern());
28449 }28331 }
...@@ -28459,7 +28341,7 @@ fn elemVal(...@@ -28459,7 +28341,7 @@ fn elemVal(
28459 if (inner_ty.zigTypeTag(mod) != .Array) break :arr_sent;28341 if (inner_ty.zigTypeTag(mod) != .Array) break :arr_sent;
28460 const sentinel = inner_ty.sentinel(mod) orelse break :arr_sent;28342 const sentinel = inner_ty.sentinel(mod) orelse break :arr_sent;
28461 const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent;28343 const index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index) orelse break :arr_sent;
28462 const index = try sema.usizeCast(block, src, try index_val.toUnsignedIntAdvanced(sema));28344 const index = try sema.usizeCast(block, src, try index_val.toUnsignedIntSema(mod));
28463 if (index != inner_ty.arrayLen(mod)) break :arr_sent;28345 if (index != inner_ty.arrayLen(mod)) break :arr_sent;
28464 return Air.internedToRef(sentinel.toIntern());28346 return Air.internedToRef(sentinel.toIntern());
28465 }28347 }
...@@ -28477,7 +28359,7 @@ fn elemVal(...@@ -28477,7 +28359,7 @@ fn elemVal(
28477 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{28359 const index_val = try sema.resolveConstDefinedValue(block, elem_index_src, elem_index, .{
28478 .needed_comptime_reason = "tuple field access index must be comptime-known",28360 .needed_comptime_reason = "tuple field access index must be comptime-known",
28479 });28361 });
28480 const index: u32 = @intCast(try index_val.toUnsignedIntAdvanced(sema));28362 const index: u32 = @intCast(try index_val.toUnsignedIntSema(mod));
28481 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);28363 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);
28482 },28364 },
28483 else => unreachable,28365 else => unreachable,
...@@ -28522,7 +28404,7 @@ fn tupleFieldPtr(...@@ -28522,7 +28404,7 @@ fn tupleFieldPtr(
28522 const mod = sema.mod;28404 const mod = sema.mod;
28523 const tuple_ptr_ty = sema.typeOf(tuple_ptr);28405 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
28524 const tuple_ty = tuple_ptr_ty.childType(mod);28406 const tuple_ty = tuple_ptr_ty.childType(mod);
28525 try sema.resolveTypeFields(tuple_ty);28407 try tuple_ty.resolveFields(mod);
28526 const field_count = tuple_ty.structFieldCount(mod);28408 const field_count = tuple_ty.structFieldCount(mod);
2852728409
28528 if (field_count == 0) {28410 if (field_count == 0) {
...@@ -28536,7 +28418,7 @@ fn tupleFieldPtr(...@@ -28536,7 +28418,7 @@ fn tupleFieldPtr(
28536 }28418 }
2853728419
28538 const field_ty = tuple_ty.structFieldType(field_index, mod);28420 const field_ty = tuple_ty.structFieldType(field_index, mod);
28539 const ptr_field_ty = try sema.ptrType(.{28421 const ptr_field_ty = try mod.ptrTypeSema(.{
28540 .child = field_ty.toIntern(),28422 .child = field_ty.toIntern(),
28541 .flags = .{28423 .flags = .{
28542 .is_const = !tuple_ptr_ty.ptrIsMutable(mod),28424 .is_const = !tuple_ptr_ty.ptrIsMutable(mod),
...@@ -28546,7 +28428,7 @@ fn tupleFieldPtr(...@@ -28546,7 +28428,7 @@ fn tupleFieldPtr(
28546 });28428 });
2854728429
28548 if (tuple_ty.structFieldIsComptime(field_index, mod))28430 if (tuple_ty.structFieldIsComptime(field_index, mod))
28549 try sema.resolveStructFieldInits(tuple_ty);28431 try tuple_ty.resolveStructFieldInits(mod);
2855028432
28551 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {28433 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
28552 return Air.internedToRef((try mod.intern(.{ .ptr = .{28434 return Air.internedToRef((try mod.intern(.{ .ptr = .{
...@@ -28557,7 +28439,7 @@ fn tupleFieldPtr(...@@ -28557,7 +28439,7 @@ fn tupleFieldPtr(
28557 }28439 }
2855828440
28559 if (try sema.resolveValue(tuple_ptr)) |tuple_ptr_val| {28441 if (try sema.resolveValue(tuple_ptr)) |tuple_ptr_val| {
28560 const field_ptr_val = try tuple_ptr_val.ptrField(field_index, sema);28442 const field_ptr_val = try tuple_ptr_val.ptrField(field_index, mod);
28561 return Air.internedToRef(field_ptr_val.toIntern());28443 return Air.internedToRef(field_ptr_val.toIntern());
28562 }28444 }
2856328445
...@@ -28579,7 +28461,7 @@ fn tupleField(...@@ -28579,7 +28461,7 @@ fn tupleField(
28579) CompileError!Air.Inst.Ref {28461) CompileError!Air.Inst.Ref {
28580 const mod = sema.mod;28462 const mod = sema.mod;
28581 const tuple_ty = sema.typeOf(tuple);28463 const tuple_ty = sema.typeOf(tuple);
28582 try sema.resolveTypeFields(tuple_ty);28464 try tuple_ty.resolveFields(mod);
28583 const field_count = tuple_ty.structFieldCount(mod);28465 const field_count = tuple_ty.structFieldCount(mod);
2858428466
28585 if (field_count == 0) {28467 if (field_count == 0) {
...@@ -28595,7 +28477,7 @@ fn tupleField(...@@ -28595,7 +28477,7 @@ fn tupleField(
28595 const field_ty = tuple_ty.structFieldType(field_index, mod);28477 const field_ty = tuple_ty.structFieldType(field_index, mod);
2859628478
28597 if (tuple_ty.structFieldIsComptime(field_index, mod))28479 if (tuple_ty.structFieldIsComptime(field_index, mod))
28598 try sema.resolveStructFieldInits(tuple_ty);28480 try tuple_ty.resolveStructFieldInits(mod);
28599 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {28481 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
28600 return Air.internedToRef(default_value.toIntern()); // comptime field28482 return Air.internedToRef(default_value.toIntern()); // comptime field
28601 }28483 }
...@@ -28608,7 +28490,7 @@ fn tupleField(...@@ -28608,7 +28490,7 @@ fn tupleField(
28608 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);28490 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
2860928491
28610 try sema.requireRuntimeBlock(block, tuple_src, null);28492 try sema.requireRuntimeBlock(block, tuple_src, null);
28611 try sema.resolveTypeLayout(field_ty);28493 try field_ty.resolveLayout(mod);
28612 return block.addStructFieldVal(tuple, field_index, field_ty);28494 return block.addStructFieldVal(tuple, field_index, field_ty);
28613}28495}
2861428496
...@@ -28638,7 +28520,7 @@ fn elemValArray(...@@ -28638,7 +28520,7 @@ fn elemValArray(
28638 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);28520 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
2863928521
28640 if (maybe_index_val) |index_val| {28522 if (maybe_index_val) |index_val| {
28641 const index: usize = @intCast(try index_val.toUnsignedIntAdvanced(sema));28523 const index: usize = @intCast(try index_val.toUnsignedIntSema(mod));
28642 if (array_sent) |s| {28524 if (array_sent) |s| {
28643 if (index == array_len) {28525 if (index == array_len) {
28644 return Air.internedToRef(s.toIntern());28526 return Air.internedToRef(s.toIntern());
...@@ -28654,7 +28536,7 @@ fn elemValArray(...@@ -28654,7 +28536,7 @@ fn elemValArray(
28654 return mod.undefRef(elem_ty);28536 return mod.undefRef(elem_ty);
28655 }28537 }
28656 if (maybe_index_val) |index_val| {28538 if (maybe_index_val) |index_val| {
28657 const index: usize = @intCast(try index_val.toUnsignedIntAdvanced(sema));28539 const index: usize = @intCast(try index_val.toUnsignedIntSema(mod));
28658 const elem_val = try array_val.elemValue(mod, index);28540 const elem_val = try array_val.elemValue(mod, index);
28659 return Air.internedToRef(elem_val.toIntern());28541 return Air.internedToRef(elem_val.toIntern());
28660 }28542 }
...@@ -28676,7 +28558,6 @@ fn elemValArray(...@@ -28676,7 +28558,6 @@ fn elemValArray(
28676 return Air.internedToRef(elem_val.toIntern());28558 return Air.internedToRef(elem_val.toIntern());
2867728559
28678 try sema.requireRuntimeBlock(block, src, runtime_src);28560 try sema.requireRuntimeBlock(block, src, runtime_src);
28679 try sema.queueFullTypeResolution(array_ty);
28680 return block.addBinOp(.array_elem_val, array, elem_index);28561 return block.addBinOp(.array_elem_val, array, elem_index);
28681}28562}
2868228563
...@@ -28705,7 +28586,7 @@ fn elemPtrArray(...@@ -28705,7 +28586,7 @@ fn elemPtrArray(
28705 const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr);28586 const maybe_undef_array_ptr_val = try sema.resolveValue(array_ptr);
28706 // The index must not be undefined since it can be out of bounds.28587 // The index must not be undefined since it can be out of bounds.
28707 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {28588 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
28708 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntAdvanced(sema));28589 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(mod));
28709 if (index >= array_len_s) {28590 if (index >= array_len_s) {
28710 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";28591 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";
28711 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label });28592 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label });
...@@ -28713,14 +28594,14 @@ fn elemPtrArray(...@@ -28713,14 +28594,14 @@ fn elemPtrArray(
28713 break :o index;28594 break :o index;
28714 } else null;28595 } else null;
2871528596
28716 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);28597 const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, mod);
2871728598
28718 if (maybe_undef_array_ptr_val) |array_ptr_val| {28599 if (maybe_undef_array_ptr_val) |array_ptr_val| {
28719 if (array_ptr_val.isUndef(mod)) {28600 if (array_ptr_val.isUndef(mod)) {
28720 return mod.undefRef(elem_ptr_ty);28601 return mod.undefRef(elem_ptr_ty);
28721 }28602 }
28722 if (offset) |index| {28603 if (offset) |index| {
28723 const elem_ptr = try array_ptr_val.ptrElem(index, sema);28604 const elem_ptr = try array_ptr_val.ptrElem(index, mod);
28724 return Air.internedToRef(elem_ptr.toIntern());28605 return Air.internedToRef(elem_ptr.toIntern());
28725 }28606 }
28726 }28607 }
...@@ -28765,19 +28646,19 @@ fn elemValSlice(...@@ -28765,19 +28646,19 @@ fn elemValSlice(
2876528646
28766 if (maybe_slice_val) |slice_val| {28647 if (maybe_slice_val) |slice_val| {
28767 runtime_src = elem_index_src;28648 runtime_src = elem_index_src;
28768 const slice_len = try slice_val.sliceLen(sema);28649 const slice_len = try slice_val.sliceLen(mod);
28769 const slice_len_s = slice_len + @intFromBool(slice_sent);28650 const slice_len_s = slice_len + @intFromBool(slice_sent);
28770 if (slice_len_s == 0) {28651 if (slice_len_s == 0) {
28771 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});28652 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
28772 }28653 }
28773 if (maybe_index_val) |index_val| {28654 if (maybe_index_val) |index_val| {
28774 const index: usize = @intCast(try index_val.toUnsignedIntAdvanced(sema));28655 const index: usize = @intCast(try index_val.toUnsignedIntSema(mod));
28775 if (index >= slice_len_s) {28656 if (index >= slice_len_s) {
28776 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";28657 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
28777 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });28658 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
28778 }28659 }
28779 const elem_ptr_ty = try sema.elemPtrType(slice_ty, index);28660 const elem_ptr_ty = try slice_ty.elemPtrType(index, mod);
28780 const elem_ptr_val = try slice_val.ptrElem(index, sema);28661 const elem_ptr_val = try slice_val.ptrElem(index, mod);
28781 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {28662 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
28782 return Air.internedToRef(elem_val.toIntern());28663 return Air.internedToRef(elem_val.toIntern());
28783 }28664 }
...@@ -28790,13 +28671,12 @@ fn elemValSlice(...@@ -28790,13 +28671,12 @@ fn elemValSlice(
28790 try sema.requireRuntimeBlock(block, src, runtime_src);28671 try sema.requireRuntimeBlock(block, src, runtime_src);
28791 if (oob_safety and block.wantSafety()) {28672 if (oob_safety and block.wantSafety()) {
28792 const len_inst = if (maybe_slice_val) |slice_val|28673 const len_inst = if (maybe_slice_val) |slice_val|
28793 try mod.intRef(Type.usize, try slice_val.sliceLen(sema))28674 try mod.intRef(Type.usize, try slice_val.sliceLen(mod))
28794 else28675 else
28795 try block.addTyOp(.slice_len, Type.usize, slice);28676 try block.addTyOp(.slice_len, Type.usize, slice);
28796 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;28677 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
28797 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);28678 try sema.panicIndexOutOfBounds(block, src, elem_index, len_inst, cmp_op);
28798 }28679 }
28799 try sema.queueFullTypeResolution(sema.typeOf(slice));
28800 return block.addBinOp(.slice_elem_val, slice, elem_index);28680 return block.addBinOp(.slice_elem_val, slice, elem_index);
28801}28681}
2880228682
...@@ -28817,17 +28697,17 @@ fn elemPtrSlice(...@@ -28817,17 +28697,17 @@ fn elemPtrSlice(
28817 const maybe_undef_slice_val = try sema.resolveValue(slice);28697 const maybe_undef_slice_val = try sema.resolveValue(slice);
28818 // The index must not be undefined since it can be out of bounds.28698 // The index must not be undefined since it can be out of bounds.
28819 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {28699 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
28820 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntAdvanced(sema));28700 const index = try sema.usizeCast(block, elem_index_src, try index_val.toUnsignedIntSema(mod));
28821 break :o index;28701 break :o index;
28822 } else null;28702 } else null;
2882328703
28824 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);28704 const elem_ptr_ty = try slice_ty.elemPtrType(offset, mod);
2882528705
28826 if (maybe_undef_slice_val) |slice_val| {28706 if (maybe_undef_slice_val) |slice_val| {
28827 if (slice_val.isUndef(mod)) {28707 if (slice_val.isUndef(mod)) {
28828 return mod.undefRef(elem_ptr_ty);28708 return mod.undefRef(elem_ptr_ty);
28829 }28709 }
28830 const slice_len = try slice_val.sliceLen(sema);28710 const slice_len = try slice_val.sliceLen(mod);
28831 const slice_len_s = slice_len + @intFromBool(slice_sent);28711 const slice_len_s = slice_len + @intFromBool(slice_sent);
28832 if (slice_len_s == 0) {28712 if (slice_len_s == 0) {
28833 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});28713 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
...@@ -28837,7 +28717,7 @@ fn elemPtrSlice(...@@ -28837,7 +28717,7 @@ fn elemPtrSlice(
28837 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";28717 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
28838 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });28718 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
28839 }28719 }
28840 const elem_ptr_val = try slice_val.ptrElem(index, sema);28720 const elem_ptr_val = try slice_val.ptrElem(index, mod);
28841 return Air.internedToRef(elem_ptr_val.toIntern());28721 return Air.internedToRef(elem_ptr_val.toIntern());
28842 }28722 }
28843 }28723 }
...@@ -28850,7 +28730,7 @@ fn elemPtrSlice(...@@ -28850,7 +28730,7 @@ fn elemPtrSlice(
28850 const len_inst = len: {28730 const len_inst = len: {
28851 if (maybe_undef_slice_val) |slice_val|28731 if (maybe_undef_slice_val) |slice_val|
28852 if (!slice_val.isUndef(mod))28732 if (!slice_val.isUndef(mod))
28853 break :len try mod.intRef(Type.usize, try slice_val.sliceLen(sema));28733 break :len try mod.intRef(Type.usize, try slice_val.sliceLen(mod));
28854 break :len try block.addTyOp(.slice_len, Type.usize, slice);28734 break :len try block.addTyOp(.slice_len, Type.usize, slice);
28855 };28735 };
28856 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;28736 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
...@@ -28915,9 +28795,9 @@ fn coerceExtra(...@@ -28915,9 +28795,9 @@ fn coerceExtra(
28915 if (dest_ty.isGenericPoison()) return inst;28795 if (dest_ty.isGenericPoison()) return inst;
28916 const zcu = sema.mod;28796 const zcu = sema.mod;
28917 const dest_ty_src = inst_src; // TODO better source location28797 const dest_ty_src = inst_src; // TODO better source location
28918 try sema.resolveTypeFields(dest_ty);28798 try dest_ty.resolveFields(zcu);
28919 const inst_ty = sema.typeOf(inst);28799 const inst_ty = sema.typeOf(inst);
28920 try sema.resolveTypeFields(inst_ty);28800 try inst_ty.resolveFields(zcu);
28921 const target = zcu.getTarget();28801 const target = zcu.getTarget();
28922 // If the types are the same, we can return the operand.28802 // If the types are the same, we can return the operand.
28923 if (dest_ty.eql(inst_ty, zcu))28803 if (dest_ty.eql(inst_ty, zcu))
...@@ -28931,7 +28811,6 @@ fn coerceExtra(...@@ -28931,7 +28811,6 @@ fn coerceExtra(
28931 return sema.coerceInMemory(val, dest_ty);28811 return sema.coerceInMemory(val, dest_ty);
28932 }28812 }
28933 try sema.requireRuntimeBlock(block, inst_src, null);28813 try sema.requireRuntimeBlock(block, inst_src, null);
28934 try sema.queueFullTypeResolution(dest_ty);
28935 const new_val = try block.addBitCast(dest_ty, inst);28814 const new_val = try block.addBitCast(dest_ty, inst);
28936 try sema.checkKnownAllocPtr(block, inst, new_val);28815 try sema.checkKnownAllocPtr(block, inst, new_val);
28937 return new_val;28816 return new_val;
...@@ -28996,7 +28875,7 @@ fn coerceExtra(...@@ -28996,7 +28875,7 @@ fn coerceExtra(
28996 if (inst_ty.zigTypeTag(zcu) == .Fn) {28875 if (inst_ty.zigTypeTag(zcu) == .Fn) {
28997 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);28876 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
28998 const fn_decl = fn_val.pointerDecl(zcu).?;28877 const fn_decl = fn_val.pointerDecl(zcu).?;
28999 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);28878 const inst_as_ptr = try sema.analyzeDeclRef(inst_src, fn_decl);
29000 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);28879 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
29001 }28880 }
2900228881
...@@ -29227,7 +29106,7 @@ fn coerceExtra(...@@ -29227,7 +29106,7 @@ fn coerceExtra(
29227 // empty tuple to zero-length slice29106 // empty tuple to zero-length slice
29228 // note that this allows coercing to a mutable slice.29107 // note that this allows coercing to a mutable slice.
29229 if (inst_child_ty.structFieldCount(zcu) == 0) {29108 if (inst_child_ty.structFieldCount(zcu) == 0) {
29230 const align_val = try dest_ty.ptrAlignmentAdvanced(zcu, sema);29109 const align_val = try dest_ty.ptrAlignmentAdvanced(zcu, .sema);
29231 return Air.internedToRef(try zcu.intern(.{ .slice = .{29110 return Air.internedToRef(try zcu.intern(.{ .slice = .{
29232 .ty = dest_ty.toIntern(),29111 .ty = dest_ty.toIntern(),
29233 .ptr = try zcu.intern(.{ .ptr = .{29112 .ptr = try zcu.intern(.{ .ptr = .{
...@@ -29372,7 +29251,7 @@ fn coerceExtra(...@@ -29372,7 +29251,7 @@ fn coerceExtra(
29372 }29251 }
29373 break :int;29252 break :int;
29374 };29253 };
29375 const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, zcu, sema);29254 const result_val = try val.floatFromIntAdvanced(sema.arena, inst_ty, dest_ty, zcu, .sema);
29376 // TODO implement this compile error29255 // TODO implement this compile error
29377 //const int_again_val = try result_val.intFromFloat(sema.arena, inst_ty);29256 //const int_again_val = try result_val.intFromFloat(sema.arena, inst_ty);
29378 //if (!int_again_val.eql(val, inst_ty, zcu)) {29257 //if (!int_again_val.eql(val, inst_ty, zcu)) {
...@@ -30549,7 +30428,7 @@ fn coerceVarArgParam(...@@ -30549,7 +30428,7 @@ fn coerceVarArgParam(
30549 .Fn => fn_ptr: {30428 .Fn => fn_ptr: {
30550 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);30429 const fn_val = try sema.resolveConstDefinedValue(block, LazySrcLoc.unneeded, inst, undefined);
30551 const fn_decl = fn_val.pointerDecl(mod).?;30430 const fn_decl = fn_val.pointerDecl(mod).?;
30552 break :fn_ptr try sema.analyzeDeclRef(fn_decl);30431 break :fn_ptr try sema.analyzeDeclRef(inst_src, fn_decl);
30553 },30432 },
30554 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),30433 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
30555 .Float => float: {30434 .Float => float: {
...@@ -30704,7 +30583,6 @@ fn storePtr2(...@@ -30704,7 +30583,6 @@ fn storePtr2(
30704 }30583 }
3070530584
30706 try sema.requireRuntimeBlock(block, src, runtime_src);30585 try sema.requireRuntimeBlock(block, src, runtime_src);
30707 try sema.queueFullTypeResolution(elem_ty);
3070830586
30709 if (ptr_ty.ptrInfo(mod).flags.vector_index == .runtime) {30587 if (ptr_ty.ptrInfo(mod).flags.vector_index == .runtime) {
30710 const ptr_inst = ptr.toIndex().?;30588 const ptr_inst = ptr.toIndex().?;
...@@ -30926,10 +30804,10 @@ fn bitCast(...@@ -30926,10 +30804,10 @@ fn bitCast(
30926 operand_src: ?LazySrcLoc,30804 operand_src: ?LazySrcLoc,
30927) CompileError!Air.Inst.Ref {30805) CompileError!Air.Inst.Ref {
30928 const zcu = sema.mod;30806 const zcu = sema.mod;
30929 try sema.resolveTypeLayout(dest_ty);30807 try dest_ty.resolveLayout(zcu);
3093030808
30931 const old_ty = sema.typeOf(inst);30809 const old_ty = sema.typeOf(inst);
30932 try sema.resolveTypeLayout(old_ty);30810 try old_ty.resolveLayout(zcu);
3093330811
30934 const dest_bits = dest_ty.bitSize(zcu);30812 const dest_bits = dest_ty.bitSize(zcu);
30935 const old_bits = old_ty.bitSize(zcu);30813 const old_bits = old_ty.bitSize(zcu);
...@@ -31111,7 +30989,7 @@ fn coerceEnumToUnion(...@@ -31111,7 +30989,7 @@ fn coerceEnumToUnion(
3111130989
31112 const union_obj = mod.typeToUnion(union_ty).?;30990 const union_obj = mod.typeToUnion(union_ty).?;
31113 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);30991 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
31114 try sema.resolveTypeFields(field_ty);30992 try field_ty.resolveFields(mod);
31115 if (field_ty.zigTypeTag(mod) == .NoReturn) {30993 if (field_ty.zigTypeTag(mod) == .NoReturn) {
31116 const msg = msg: {30994 const msg = msg: {
31117 const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{});30995 const msg = try sema.errMsg(inst_src, "cannot initialize 'noreturn' field of union", .{});
...@@ -31524,8 +31402,8 @@ fn coerceTupleToStruct(...@@ -31524,8 +31402,8 @@ fn coerceTupleToStruct(
31524) !Air.Inst.Ref {31402) !Air.Inst.Ref {
31525 const mod = sema.mod;31403 const mod = sema.mod;
31526 const ip = &mod.intern_pool;31404 const ip = &mod.intern_pool;
31527 try sema.resolveTypeFields(struct_ty);31405 try struct_ty.resolveFields(mod);
31528 try sema.resolveStructFieldInits(struct_ty);31406 try struct_ty.resolveStructFieldInits(mod);
3152931407
31530 if (struct_ty.isTupleOrAnonStruct(mod)) {31408 if (struct_ty.isTupleOrAnonStruct(mod)) {
31531 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);31409 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
...@@ -31776,11 +31654,10 @@ fn analyzeDeclVal(...@@ -31776,11 +31654,10 @@ fn analyzeDeclVal(
31776 src: LazySrcLoc,31654 src: LazySrcLoc,
31777 decl_index: InternPool.DeclIndex,31655 decl_index: InternPool.DeclIndex,
31778) CompileError!Air.Inst.Ref {31656) CompileError!Air.Inst.Ref {
31779 try sema.addReferencedBy(src, decl_index);
31780 if (sema.decl_val_table.get(decl_index)) |result| {31657 if (sema.decl_val_table.get(decl_index)) |result| {
31781 return result;31658 return result;
31782 }31659 }
31783 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);31660 const decl_ref = try sema.analyzeDeclRefInner(src, decl_index, false);
31784 const result = try sema.analyzeLoad(block, src, decl_ref, src);31661 const result = try sema.analyzeLoad(block, src, decl_ref, src);
31785 if (result.toInterned() != null) {31662 if (result.toInterned() != null) {
31786 if (!block.is_typeof) {31663 if (!block.is_typeof) {
...@@ -31790,18 +31667,18 @@ fn analyzeDeclVal(...@@ -31790,18 +31667,18 @@ fn analyzeDeclVal(
31790 return result;31667 return result;
31791}31668}
3179231669
31793fn addReferencedBy(31670fn addReferenceEntry(
31794 sema: *Sema,31671 sema: *Sema,
31795 src: LazySrcLoc,31672 src: LazySrcLoc,
31796 decl_index: InternPool.DeclIndex,31673 referenced_unit: AnalUnit,
31797) !void {31674) !void {
31798 if (sema.mod.comp.reference_trace == 0) return;31675 if (sema.mod.comp.reference_trace == 0) return;
31799 try sema.mod.reference_table.put(sema.gpa, decl_index, .{31676 const gop = try sema.references.getOrPut(sema.gpa, referenced_unit);
31800 // TODO: this can make the reference trace suboptimal. This will be fixed31677 if (gop.found_existing) return;
31801 // once the reference table is reworked for incremental compilation.31678 // TODO: we need to figure out how to model inline calls here.
31802 .referencer = sema.owner_decl_index,31679 // They aren't references in the analysis sense, but ought to show up in the reference trace!
31803 .src = src,31680 // Would representing inline calls in the reference table cause excessive memory usage?
31804 });31681 try sema.mod.addUnitReference(sema.ownerUnit(), referenced_unit, src);
31805}31682}
3180631683
31807pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!void {31684pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!void {
...@@ -31851,16 +31728,17 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {...@@ -31851,16 +31728,17 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value {
31851 } })));31728 } })));
31852}31729}
3185331730
31854fn analyzeDeclRef(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!Air.Inst.Ref {31731fn analyzeDeclRef(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex) CompileError!Air.Inst.Ref {
31855 return sema.analyzeDeclRefInner(decl_index, true);31732 return sema.analyzeDeclRefInner(src, decl_index, true);
31856}31733}
3185731734
31858/// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but31735/// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but
31859/// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a31736/// only triggers analysis for function bodies if `analyze_fn_body` is true. If it's possible for a
31860/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps31737/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps
31861/// this function with `analyze_fn_body` set to true.31738/// this function with `analyze_fn_body` set to true.
31862fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn_body: bool) CompileError!Air.Inst.Ref {31739fn analyzeDeclRefInner(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex, analyze_fn_body: bool) CompileError!Air.Inst.Ref {
31863 const mod = sema.mod;31740 const mod = sema.mod;
31741 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .decl = decl_index }));
31864 try sema.ensureDeclAnalyzed(decl_index);31742 try sema.ensureDeclAnalyzed(decl_index);
3186531743
31866 const decl_val = try mod.declPtr(decl_index).valueOrFail();31744 const decl_val = try mod.declPtr(decl_index).valueOrFail();
...@@ -31872,7 +31750,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -31872,7 +31750,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
31872 });31750 });
31873 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type31751 // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type
31874 try sema.declareDependency(.{ .decl_val = decl_index });31752 try sema.declareDependency(.{ .decl_val = decl_index });
31875 const ptr_ty = try sema.ptrType(.{31753 const ptr_ty = try mod.ptrTypeSema(.{
31876 .child = decl_val.typeOf(mod).toIntern(),31754 .child = decl_val.typeOf(mod).toIntern(),
31877 .flags = .{31755 .flags = .{
31878 .alignment = owner_decl.alignment,31756 .alignment = owner_decl.alignment,
...@@ -31881,7 +31759,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -31881,7 +31759,7 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
31881 },31759 },
31882 });31760 });
31883 if (analyze_fn_body) {31761 if (analyze_fn_body) {
31884 try sema.maybeQueueFuncBodyAnalysis(decl_index);31762 try sema.maybeQueueFuncBodyAnalysis(src, decl_index);
31885 }31763 }
31886 return Air.internedToRef((try mod.intern(.{ .ptr = .{31764 return Air.internedToRef((try mod.intern(.{ .ptr = .{
31887 .ty = ptr_ty.toIntern(),31765 .ty = ptr_ty.toIntern(),
...@@ -31890,12 +31768,13 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn...@@ -31890,12 +31768,13 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn
31890 } })));31768 } })));
31891}31769}
3189231770
31893fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void {31771fn maybeQueueFuncBodyAnalysis(sema: *Sema, src: LazySrcLoc, decl_index: InternPool.DeclIndex) !void {
31894 const mod = sema.mod;31772 const mod = sema.mod;
31895 const decl = mod.declPtr(decl_index);31773 const decl = mod.declPtr(decl_index);
31896 const decl_val = try decl.valueOrFail();31774 const decl_val = try decl.valueOrFail();
31897 if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return;31775 if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return;
31898 if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return;31776 if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return;
31777 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = decl_val.toIntern() }));
31899 try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern());31778 try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern());
31900}31779}
3190131780
...@@ -31910,22 +31789,22 @@ fn analyzeRef(...@@ -31910,22 +31789,22 @@ fn analyzeRef(
3191031789
31911 if (try sema.resolveValue(operand)) |val| {31790 if (try sema.resolveValue(operand)) |val| {
31912 switch (mod.intern_pool.indexToKey(val.toIntern())) {31791 switch (mod.intern_pool.indexToKey(val.toIntern())) {
31913 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),31792 .extern_func => |extern_func| return sema.analyzeDeclRef(src, extern_func.decl),
31914 .func => |func| return sema.analyzeDeclRef(func.owner_decl),31793 .func => |func| return sema.analyzeDeclRef(src, func.owner_decl),
31915 else => return anonDeclRef(sema, val.toIntern()),31794 else => return anonDeclRef(sema, val.toIntern()),
31916 }31795 }
31917 }31796 }
3191831797
31919 try sema.requireRuntimeBlock(block, src, null);31798 try sema.requireRuntimeBlock(block, src, null);
31920 const address_space = target_util.defaultAddressSpace(mod.getTarget(), .local);31799 const address_space = target_util.defaultAddressSpace(mod.getTarget(), .local);
31921 const ptr_type = try sema.ptrType(.{31800 const ptr_type = try mod.ptrTypeSema(.{
31922 .child = operand_ty.toIntern(),31801 .child = operand_ty.toIntern(),
31923 .flags = .{31802 .flags = .{
31924 .is_const = true,31803 .is_const = true,
31925 .address_space = address_space,31804 .address_space = address_space,
31926 },31805 },
31927 });31806 });
31928 const mut_ptr_type = try sema.ptrType(.{31807 const mut_ptr_type = try mod.ptrTypeSema(.{
31929 .child = operand_ty.toIntern(),31808 .child = operand_ty.toIntern(),
31930 .flags = .{ .address_space = address_space },31809 .flags = .{ .address_space = address_space },
31931 });31810 });
...@@ -32033,7 +31912,7 @@ fn analyzeSliceLen(...@@ -32033,7 +31912,7 @@ fn analyzeSliceLen(
32033 if (slice_val.isUndef(mod)) {31912 if (slice_val.isUndef(mod)) {
32034 return mod.undefRef(Type.usize);31913 return mod.undefRef(Type.usize);
32035 }31914 }
32036 return mod.intRef(Type.usize, try slice_val.sliceLen(sema));31915 return mod.intRef(Type.usize, try slice_val.sliceLen(mod));
32037 }31916 }
32038 try sema.requireRuntimeBlock(block, src, null);31917 try sema.requireRuntimeBlock(block, src, null);
32039 return block.addTyOp(.slice_len, Type.usize, slice_inst);31918 return block.addTyOp(.slice_len, Type.usize, slice_inst);
...@@ -32401,7 +32280,7 @@ fn analyzeSlice(...@@ -32401,7 +32280,7 @@ fn analyzeSlice(
32401 assert(manyptr_ty_key.flags.size == .One);32280 assert(manyptr_ty_key.flags.size == .One);
32402 manyptr_ty_key.child = elem_ty.toIntern();32281 manyptr_ty_key.child = elem_ty.toIntern();
32403 manyptr_ty_key.flags.size = .Many;32282 manyptr_ty_key.flags.size = .Many;
32404 break :ptr try sema.coerceCompatiblePtrs(block, try sema.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);32283 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrTypeSema(manyptr_ty_key), ptr_or_slice, ptr_src);
32405 } else ptr_or_slice;32284 } else ptr_or_slice;
3240632285
32407 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);32286 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);
...@@ -32470,7 +32349,7 @@ fn analyzeSlice(...@@ -32470,7 +32349,7 @@ fn analyzeSlice(
32470 return sema.fail(block, src, "slice of undefined", .{});32349 return sema.fail(block, src, "slice of undefined", .{});
32471 }32350 }
32472 const has_sentinel = slice_ty.sentinel(mod) != null;32351 const has_sentinel = slice_ty.sentinel(mod) != null;
32473 const slice_len = try slice_val.sliceLen(sema);32352 const slice_len = try slice_val.sliceLen(mod);
32474 const len_plus_sent = slice_len + @intFromBool(has_sentinel);32353 const len_plus_sent = slice_len + @intFromBool(has_sentinel);
32475 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);32354 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);
32476 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {32355 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {
...@@ -32485,7 +32364,7 @@ fn analyzeSlice(...@@ -32485,7 +32364,7 @@ fn analyzeSlice(
32485 "end index {} out of bounds for slice of length {d}{s}",32364 "end index {} out of bounds for slice of length {d}{s}",
32486 .{32365 .{
32487 end_val.fmtValue(mod, sema),32366 end_val.fmtValue(mod, sema),
32488 try slice_val.sliceLen(sema),32367 try slice_val.sliceLen(mod),
32489 sentinel_label,32368 sentinel_label,
32490 },32369 },
32491 );32370 );
...@@ -32558,7 +32437,7 @@ fn analyzeSlice(...@@ -32558,7 +32437,7 @@ fn analyzeSlice(
3255832437
32559 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);32438 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
32560 const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);32439 const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);
32561 const elem_ptr = try many_ptr_val.ptrElem(sentinel_index, sema);32440 const elem_ptr = try many_ptr_val.ptrElem(sentinel_index, mod);
32562 const res = try sema.pointerDerefExtra(block, src, elem_ptr);32441 const res = try sema.pointerDerefExtra(block, src, elem_ptr);
32563 const actual_sentinel = switch (res) {32442 const actual_sentinel = switch (res) {
32564 .runtime_load => break :sentinel_check,32443 .runtime_load => break :sentinel_check,
...@@ -32621,9 +32500,9 @@ fn analyzeSlice(...@@ -32621,9 +32500,9 @@ fn analyzeSlice(
32621 const new_allowzero = new_ptr_ty_info.flags.is_allowzero and sema.typeOf(ptr).ptrSize(mod) != .C;32500 const new_allowzero = new_ptr_ty_info.flags.is_allowzero and sema.typeOf(ptr).ptrSize(mod) != .C;
3262232501
32623 if (opt_new_len_val) |new_len_val| {32502 if (opt_new_len_val) |new_len_val| {
32624 const new_len_int = try new_len_val.toUnsignedIntAdvanced(sema);32503 const new_len_int = try new_len_val.toUnsignedIntSema(mod);
3262532504
32626 const return_ty = try sema.ptrType(.{32505 const return_ty = try mod.ptrTypeSema(.{
32627 .child = (try mod.arrayType(.{32506 .child = (try mod.arrayType(.{
32628 .len = new_len_int,32507 .len = new_len_int,
32629 .sentinel = if (sentinel) |s| s.toIntern() else .none,32508 .sentinel = if (sentinel) |s| s.toIntern() else .none,
...@@ -32685,7 +32564,7 @@ fn analyzeSlice(...@@ -32685,7 +32564,7 @@ fn analyzeSlice(
32685 return sema.fail(block, src, "non-zero length slice of undefined pointer", .{});32564 return sema.fail(block, src, "non-zero length slice of undefined pointer", .{});
32686 }32565 }
3268732566
32688 const return_ty = try sema.ptrType(.{32567 const return_ty = try mod.ptrTypeSema(.{
32689 .child = elem_ty.toIntern(),32568 .child = elem_ty.toIntern(),
32690 .sentinel = if (sentinel) |s| s.toIntern() else .none,32569 .sentinel = if (sentinel) |s| s.toIntern() else .none,
32691 .flags = .{32570 .flags = .{
...@@ -32713,7 +32592,7 @@ fn analyzeSlice(...@@ -32713,7 +32592,7 @@ fn analyzeSlice(
32713 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {32592 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
32714 // we don't need to add one for sentinels because the32593 // we don't need to add one for sentinels because the
32715 // underlying value data includes the sentinel32594 // underlying value data includes the sentinel
32716 break :blk try mod.intRef(Type.usize, try slice_val.sliceLen(sema));32595 break :blk try mod.intRef(Type.usize, try slice_val.sliceLen(mod));
32717 }32596 }
3271832597
32719 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);32598 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
...@@ -32805,7 +32684,7 @@ fn cmpNumeric(...@@ -32805,7 +32684,7 @@ fn cmpNumeric(
32805 if (lhs_val.isNan(mod) or rhs_val.isNan(mod)) {32684 if (lhs_val.isNan(mod) or rhs_val.isNan(mod)) {
32806 return if (op == std.math.CompareOperator.neq) .bool_true else .bool_false;32685 return if (op == std.math.CompareOperator.neq) .bool_true else .bool_false;
32807 }32686 }
32808 return if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, mod, sema))32687 return if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, mod, .sema))
32809 .bool_true32688 .bool_true
32810 else32689 else
32811 .bool_false;32690 .bool_false;
...@@ -32874,11 +32753,11 @@ fn cmpNumeric(...@@ -32874,11 +32753,11 @@ fn cmpNumeric(
32874 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,32753 // a signed integer with mantissa bits + 1, and if there was any non-integral part of the float,
32875 // add/subtract 1.32754 // add/subtract 1.
32876 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|32755 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|
32877 !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))32756 !(try lhs_val.compareAllWithZeroSema(.gte, mod))
32878 else32757 else
32879 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(mod));32758 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(mod));
32880 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|32759 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|
32881 !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))32760 !(try rhs_val.compareAllWithZeroSema(.gte, mod))
32882 else32761 else
32883 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(mod));32762 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(mod));
32884 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;32763 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
...@@ -33026,7 +32905,7 @@ fn compareIntsOnlyPossibleResult(...@@ -33026,7 +32905,7 @@ fn compareIntsOnlyPossibleResult(
33026) Allocator.Error!?bool {32905) Allocator.Error!?bool {
33027 const mod = sema.mod;32906 const mod = sema.mod;
33028 const rhs_info = rhs_ty.intInfo(mod);32907 const rhs_info = rhs_ty.intInfo(mod);
33029 const vs_zero = lhs_val.orderAgainstZeroAdvanced(mod, sema) catch unreachable;32908 const vs_zero = lhs_val.orderAgainstZeroAdvanced(mod, .sema) catch unreachable;
33030 const is_zero = vs_zero == .eq;32909 const is_zero = vs_zero == .eq;
33031 const is_negative = vs_zero == .lt;32910 const is_negative = vs_zero == .lt;
33032 const is_positive = vs_zero == .gt;32911 const is_positive = vs_zero == .gt;
...@@ -33190,7 +33069,6 @@ fn wrapErrorUnionPayload(...@@ -33190,7 +33069,6 @@ fn wrapErrorUnionPayload(
33190 } })));33069 } })));
33191 }33070 }
33192 try sema.requireRuntimeBlock(block, inst_src, null);33071 try sema.requireRuntimeBlock(block, inst_src, null);
33193 try sema.queueFullTypeResolution(dest_payload_ty);
33194 return block.addTyOp(.wrap_errunion_payload, dest_ty, coerced);33072 return block.addTyOp(.wrap_errunion_payload, dest_ty, coerced);
33195}33073}
3319633074
...@@ -33993,7 +33871,7 @@ fn resolvePeerTypesInner(...@@ -33993,7 +33871,7 @@ fn resolvePeerTypesInner(
3399333871
33994 opt_ptr_info = ptr_info;33872 opt_ptr_info = ptr_info;
33995 }33873 }
33996 return .{ .success = try sema.ptrType(opt_ptr_info.?) };33874 return .{ .success = try mod.ptrTypeSema(opt_ptr_info.?) };
33997 },33875 },
3399833876
33999 .ptr => {33877 .ptr => {
...@@ -34303,7 +34181,7 @@ fn resolvePeerTypesInner(...@@ -34303,7 +34181,7 @@ fn resolvePeerTypesInner(
34303 },34181 },
34304 }34182 }
3430534183
34306 return .{ .success = try sema.ptrType(opt_ptr_info.?) };34184 return .{ .success = try mod.ptrTypeSema(opt_ptr_info.?) };
34307 },34185 },
3430834186
34309 .func => {34187 .func => {
...@@ -34660,7 +34538,7 @@ fn resolvePeerTypesInner(...@@ -34660,7 +34538,7 @@ fn resolvePeerTypesInner(
34660 var comptime_val: ?Value = null;34538 var comptime_val: ?Value = null;
34661 for (peer_tys) |opt_ty| {34539 for (peer_tys) |opt_ty| {
34662 const struct_ty = opt_ty orelse continue;34540 const struct_ty = opt_ty orelse continue;
34663 try sema.resolveStructFieldInits(struct_ty);34541 try struct_ty.resolveStructFieldInits(mod);
3466434542
34665 const uncoerced_field_val = try struct_ty.structFieldValueComptime(mod, field_index) orelse {34543 const uncoerced_field_val = try struct_ty.structFieldValueComptime(mod, field_index) orelse {
34666 comptime_val = null;34544 comptime_val = null;
...@@ -34796,181 +34674,22 @@ pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {...@@ -34796,181 +34674,22 @@ pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
34796 const ip = &mod.intern_pool;34674 const ip = &mod.intern_pool;
34797 const fn_ty_info = mod.typeToFunc(fn_ty).?;34675 const fn_ty_info = mod.typeToFunc(fn_ty).?;
3479834676
34799 try sema.resolveTypeFully(Type.fromInterned(fn_ty_info.return_type));34677 try Type.fromInterned(fn_ty_info.return_type).resolveFully(mod);
3480034678
34801 if (mod.comp.config.any_error_tracing and34679 if (mod.comp.config.any_error_tracing and
34802 Type.fromInterned(fn_ty_info.return_type).isError(mod))34680 Type.fromInterned(fn_ty_info.return_type).isError(mod))
34803 {34681 {
34804 // Ensure the type exists so that backends can assume that.34682 // Ensure the type exists so that backends can assume that.
34805 _ = try sema.getBuiltinType("StackTrace");34683 _ = try mod.getBuiltinType("StackTrace");
34806 }34684 }
3480734685
34808 for (0..fn_ty_info.param_types.len) |i| {34686 for (0..fn_ty_info.param_types.len) |i| {
34809 try sema.resolveTypeFully(Type.fromInterned(fn_ty_info.param_types.get(ip)[i]));34687 try Type.fromInterned(fn_ty_info.param_types.get(ip)[i]).resolveFully(mod);
34810 }34688 }
34811}34689}
3481234690
34813/// Make it so that calling hash() and eql() on `val` will not assert due
34814/// to a type not having its layout resolved.
34815fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {34691fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
34816 const mod = sema.mod;34692 return val.resolveLazy(sema.arena, sema.mod);
34817 switch (mod.intern_pool.indexToKey(val.toIntern())) {
34818 .int => |int| switch (int.storage) {
34819 .u64, .i64, .big_int => return val,
34820 .lazy_align, .lazy_size => return mod.intValue(
34821 Type.fromInterned(int.ty),
34822 (try val.getUnsignedIntAdvanced(mod, sema)).?,
34823 ),
34824 },
34825 .slice => |slice| {
34826 const ptr = try sema.resolveLazyValue(Value.fromInterned(slice.ptr));
34827 const len = try sema.resolveLazyValue(Value.fromInterned(slice.len));
34828 if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val;
34829 return Value.fromInterned(try mod.intern(.{ .slice = .{
34830 .ty = slice.ty,
34831 .ptr = ptr.toIntern(),
34832 .len = len.toIntern(),
34833 } }));
34834 },
34835 .ptr => |ptr| {
34836 switch (ptr.base_addr) {
34837 .decl, .comptime_alloc, .anon_decl, .int => return val,
34838 .comptime_field => |field_val| {
34839 const resolved_field_val =
34840 (try sema.resolveLazyValue(Value.fromInterned(field_val))).toIntern();
34841 return if (resolved_field_val == field_val)
34842 val
34843 else
34844 Value.fromInterned((try mod.intern(.{ .ptr = .{
34845 .ty = ptr.ty,
34846 .base_addr = .{ .comptime_field = resolved_field_val },
34847 .byte_offset = ptr.byte_offset,
34848 } })));
34849 },
34850 .eu_payload, .opt_payload => |base| {
34851 const resolved_base = (try sema.resolveLazyValue(Value.fromInterned(base))).toIntern();
34852 return if (resolved_base == base)
34853 val
34854 else
34855 Value.fromInterned((try mod.intern(.{ .ptr = .{
34856 .ty = ptr.ty,
34857 .base_addr = switch (ptr.base_addr) {
34858 .eu_payload => .{ .eu_payload = resolved_base },
34859 .opt_payload => .{ .opt_payload = resolved_base },
34860 else => unreachable,
34861 },
34862 .byte_offset = ptr.byte_offset,
34863 } })));
34864 },
34865 .arr_elem, .field => |base_index| {
34866 const resolved_base = (try sema.resolveLazyValue(Value.fromInterned(base_index.base))).toIntern();
34867 return if (resolved_base == base_index.base)
34868 val
34869 else
34870 Value.fromInterned((try mod.intern(.{ .ptr = .{
34871 .ty = ptr.ty,
34872 .base_addr = switch (ptr.base_addr) {
34873 .arr_elem => .{ .arr_elem = .{
34874 .base = resolved_base,
34875 .index = base_index.index,
34876 } },
34877 .field => .{ .field = .{
34878 .base = resolved_base,
34879 .index = base_index.index,
34880 } },
34881 else => unreachable,
34882 },
34883 .byte_offset = ptr.byte_offset,
34884 } })));
34885 },
34886 }
34887 },
34888 .aggregate => |aggregate| switch (aggregate.storage) {
34889 .bytes => return val,
34890 .elems => |elems| {
34891 var resolved_elems: []InternPool.Index = &.{};
34892 for (elems, 0..) |elem, i| {
34893 const resolved_elem = (try sema.resolveLazyValue(Value.fromInterned(elem))).toIntern();
34894 if (resolved_elems.len == 0 and resolved_elem != elem) {
34895 resolved_elems = try sema.arena.alloc(InternPool.Index, elems.len);
34896 @memcpy(resolved_elems[0..i], elems[0..i]);
34897 }
34898 if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem;
34899 }
34900 return if (resolved_elems.len == 0) val else Value.fromInterned((try mod.intern(.{ .aggregate = .{
34901 .ty = aggregate.ty,
34902 .storage = .{ .elems = resolved_elems },
34903 } })));
34904 },
34905 .repeated_elem => |elem| {
34906 const resolved_elem = (try sema.resolveLazyValue(Value.fromInterned(elem))).toIntern();
34907 return if (resolved_elem == elem) val else Value.fromInterned((try mod.intern(.{ .aggregate = .{
34908 .ty = aggregate.ty,
34909 .storage = .{ .repeated_elem = resolved_elem },
34910 } })));
34911 },
34912 },
34913 .un => |un| {
34914 const resolved_tag = if (un.tag == .none)
34915 .none
34916 else
34917 (try sema.resolveLazyValue(Value.fromInterned(un.tag))).toIntern();
34918 const resolved_val = (try sema.resolveLazyValue(Value.fromInterned(un.val))).toIntern();
34919 return if (resolved_tag == un.tag and resolved_val == un.val)
34920 val
34921 else
34922 Value.fromInterned((try mod.intern(.{ .un = .{
34923 .ty = un.ty,
34924 .tag = resolved_tag,
34925 .val = resolved_val,
34926 } })));
34927 },
34928 else => return val,
34929 }
34930}
34931
34932pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
34933 const mod = sema.mod;
34934 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
34935 .simple_type => |simple_type| return sema.resolveSimpleType(simple_type),
34936 else => {},
34937 }
34938 switch (ty.zigTypeTag(mod)) {
34939 .Struct => return sema.resolveStructLayout(ty),
34940 .Union => return sema.resolveUnionLayout(ty),
34941 .Array => {
34942 if (ty.arrayLenIncludingSentinel(mod) == 0) return;
34943 const elem_ty = ty.childType(mod);
34944 return sema.resolveTypeLayout(elem_ty);
34945 },
34946 .Optional => {
34947 const payload_ty = ty.optionalChild(mod);
34948 // In case of querying the ABI alignment of this optional, we will ask
34949 // for hasRuntimeBits() of the payload type, so we need "requires comptime"
34950 // to be known already before this function returns.
34951 _ = try sema.typeRequiresComptime(payload_ty);
34952 return sema.resolveTypeLayout(payload_ty);
34953 },
34954 .ErrorUnion => {
34955 const payload_ty = ty.errorUnionPayload(mod);
34956 return sema.resolveTypeLayout(payload_ty);
34957 },
34958 .Fn => {
34959 const info = mod.typeToFunc(ty).?;
34960 if (info.is_generic) {
34961 // Resolving of generic function types is deferred to when
34962 // the function is instantiated.
34963 return;
34964 }
34965 const ip = &mod.intern_pool;
34966 for (0..info.param_types.len) |i| {
34967 const param_ty = info.param_types.get(ip)[i];
34968 try sema.resolveTypeLayout(Type.fromInterned(param_ty));
34969 }
34970 try sema.resolveTypeLayout(Type.fromInterned(info.return_type));
34971 },
34972 else => {},
34973 }
34974}34693}
3497534694
34976/// Resolve a struct's alignment only without triggering resolution of its layout.34695/// Resolve a struct's alignment only without triggering resolution of its layout.
...@@ -34979,11 +34698,13 @@ pub fn resolveStructAlignment(...@@ -34979,11 +34698,13 @@ pub fn resolveStructAlignment(
34979 sema: *Sema,34698 sema: *Sema,
34980 ty: InternPool.Index,34699 ty: InternPool.Index,
34981 struct_type: InternPool.LoadedStructType,34700 struct_type: InternPool.LoadedStructType,
34982) CompileError!Alignment {34701) SemaError!void {
34983 const mod = sema.mod;34702 const mod = sema.mod;
34984 const ip = &mod.intern_pool;34703 const ip = &mod.intern_pool;
34985 const target = mod.getTarget();34704 const target = mod.getTarget();
3498634705
34706 assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?);
34707
34987 assert(struct_type.flagsPtr(ip).alignment == .none);34708 assert(struct_type.flagsPtr(ip).alignment == .none);
34988 assert(struct_type.layout != .@"packed");34709 assert(struct_type.layout != .@"packed");
3498934710
...@@ -34994,7 +34715,7 @@ pub fn resolveStructAlignment(...@@ -34994,7 +34715,7 @@ pub fn resolveStructAlignment(
34994 struct_type.flagsPtr(ip).assumed_pointer_aligned = true;34715 struct_type.flagsPtr(ip).assumed_pointer_aligned = true;
34995 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));34716 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
34996 struct_type.flagsPtr(ip).alignment = result;34717 struct_type.flagsPtr(ip).alignment = result;
34997 return result;34718 return;
34998 }34719 }
3499934720
35000 try sema.resolveTypeFieldsStruct(ty, struct_type);34721 try sema.resolveTypeFieldsStruct(ty, struct_type);
...@@ -35006,7 +34727,7 @@ pub fn resolveStructAlignment(...@@ -35006,7 +34727,7 @@ pub fn resolveStructAlignment(
35006 struct_type.flagsPtr(ip).assumed_pointer_aligned = true;34727 struct_type.flagsPtr(ip).assumed_pointer_aligned = true;
35007 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));34728 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
35008 struct_type.flagsPtr(ip).alignment = result;34729 struct_type.flagsPtr(ip).alignment = result;
35009 return result;34730 return;
35010 }34731 }
35011 defer struct_type.clearAlignmentWip(ip);34732 defer struct_type.clearAlignmentWip(ip);
3501234733
...@@ -35016,30 +34737,35 @@ pub fn resolveStructAlignment(...@@ -35016,30 +34737,35 @@ pub fn resolveStructAlignment(
35016 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);34737 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
35017 if (struct_type.fieldIsComptime(ip, i) or try sema.typeRequiresComptime(field_ty))34738 if (struct_type.fieldIsComptime(ip, i) or try sema.typeRequiresComptime(field_ty))
35018 continue;34739 continue;
35019 const field_align = try sema.structFieldAlignment(34740 const field_align = try mod.structFieldAlignmentAdvanced(
35020 struct_type.fieldAlign(ip, i),34741 struct_type.fieldAlign(ip, i),
35021 field_ty,34742 field_ty,
35022 struct_type.layout,34743 struct_type.layout,
34744 .sema,
35023 );34745 );
35024 result = result.maxStrict(field_align);34746 result = result.maxStrict(field_align);
35025 }34747 }
3502634748
35027 struct_type.flagsPtr(ip).alignment = result;34749 struct_type.flagsPtr(ip).alignment = result;
35028 return result;
35029}34750}
3503034751
35031fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {34752pub fn resolveStructLayout(sema: *Sema, ty: Type) SemaError!void {
35032 const zcu = sema.mod;34753 const zcu = sema.mod;
35033 const ip = &zcu.intern_pool;34754 const ip = &zcu.intern_pool;
35034 const struct_type = zcu.typeToStruct(ty) orelse return;34755 const struct_type = zcu.typeToStruct(ty) orelse return;
3503534756
34757 assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?);
34758
35036 if (struct_type.haveLayout(ip))34759 if (struct_type.haveLayout(ip))
35037 return;34760 return;
3503834761
35039 try sema.resolveTypeFields(ty);34762 try ty.resolveFields(zcu);
3504034763
35041 if (struct_type.layout == .@"packed") {34764 if (struct_type.layout == .@"packed") {
35042 try semaBackingIntType(zcu, struct_type);34765 semaBackingIntType(zcu, struct_type) catch |err| switch (err) {
34766 error.OutOfMemory, error.AnalysisFail => |e| return e,
34767 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
34768 };
35043 return;34769 return;
35044 }34770 }
3504534771
...@@ -35075,10 +34801,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35075,10 +34801,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
35075 },34801 },
35076 else => return err,34802 else => return err,
35077 };34803 };
35078 field_align.* = try sema.structFieldAlignment(34804 field_align.* = try zcu.structFieldAlignmentAdvanced(
35079 struct_type.fieldAlign(ip, i),34805 struct_type.fieldAlign(ip, i),
35080 field_ty,34806 field_ty,
35081 struct_type.layout,34807 struct_type.layout,
34808 .sema,
35082 );34809 );
35083 big_align = big_align.maxStrict(field_align.*);34810 big_align = big_align.maxStrict(field_align.*);
35084 }34811 }
...@@ -35214,7 +34941,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co...@@ -35214,7 +34941,7 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co
35214 var accumulator: u64 = 0;34941 var accumulator: u64 = 0;
35215 for (0..struct_type.field_types.len) |i| {34942 for (0..struct_type.field_types.len) |i| {
35216 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);34943 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
35217 accumulator += try field_ty.bitSizeAdvanced(mod, &sema);34944 accumulator += try field_ty.bitSizeAdvanced(mod, .sema);
35218 }34945 }
35219 break :blk accumulator;34946 break :blk accumulator;
35220 };34947 };
...@@ -35263,6 +34990,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co...@@ -35263,6 +34990,8 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co
35263 const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum));34990 const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum));
35264 struct_type.backingIntType(ip).* = backing_int_ty.toIntern();34991 struct_type.backingIntType(ip).* = backing_int_ty.toIntern();
35265 }34992 }
34993
34994 try sema.flushExports();
35266}34995}
3526734996
35268fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void {34997fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void {
...@@ -35322,11 +35051,13 @@ pub fn resolveUnionAlignment(...@@ -35322,11 +35051,13 @@ pub fn resolveUnionAlignment(
35322 sema: *Sema,35051 sema: *Sema,
35323 ty: Type,35052 ty: Type,
35324 union_type: InternPool.LoadedUnionType,35053 union_type: InternPool.LoadedUnionType,
35325) CompileError!Alignment {35054) SemaError!void {
35326 const mod = sema.mod;35055 const mod = sema.mod;
35327 const ip = &mod.intern_pool;35056 const ip = &mod.intern_pool;
35328 const target = mod.getTarget();35057 const target = mod.getTarget();
3532935058
35059 assert(sema.ownerUnit().unwrap().decl == union_type.decl);
35060
35330 assert(!union_type.haveLayout(ip));35061 assert(!union_type.haveLayout(ip));
3533135062
35332 if (union_type.flagsPtr(ip).status == .field_types_wip) {35063 if (union_type.flagsPtr(ip).status == .field_types_wip) {
...@@ -35336,7 +35067,7 @@ pub fn resolveUnionAlignment(...@@ -35336,7 +35067,7 @@ pub fn resolveUnionAlignment(
35336 union_type.flagsPtr(ip).assumed_pointer_aligned = true;35067 union_type.flagsPtr(ip).assumed_pointer_aligned = true;
35337 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));35068 const result = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8));
35338 union_type.flagsPtr(ip).alignment = result;35069 union_type.flagsPtr(ip).alignment = result;
35339 return result;35070 return;
35340 }35071 }
3534135072
35342 try sema.resolveTypeFieldsUnion(ty, union_type);35073 try sema.resolveTypeFieldsUnion(ty, union_type);
...@@ -35356,11 +35087,10 @@ pub fn resolveUnionAlignment(...@@ -35356,11 +35087,10 @@ pub fn resolveUnionAlignment(
35356 }35087 }
3535735088
35358 union_type.flagsPtr(ip).alignment = max_align;35089 union_type.flagsPtr(ip).alignment = max_align;
35359 return max_align;
35360}35090}
3536135091
35362/// This logic must be kept in sync with `Module.getUnionLayout`.35092/// This logic must be kept in sync with `Module.getUnionLayout`.
35363fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {35093pub fn resolveUnionLayout(sema: *Sema, ty: Type) SemaError!void {
35364 const zcu = sema.mod;35094 const zcu = sema.mod;
35365 const ip = &zcu.intern_pool;35095 const ip = &zcu.intern_pool;
3536635096
...@@ -35369,6 +35099,8 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35369,6 +35099,8 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
35369 // Load again, since the tag type might have changed due to resolution.35099 // Load again, since the tag type might have changed due to resolution.
35370 const union_type = ip.loadUnionType(ty.ip_index);35100 const union_type = ip.loadUnionType(ty.ip_index);
3537135101
35102 assert(sema.ownerUnit().unwrap().decl == union_type.decl);
35103
35372 switch (union_type.flagsPtr(ip).status) {35104 switch (union_type.flagsPtr(ip).status) {
35373 .none, .have_field_types => {},35105 .none, .have_field_types => {},
35374 .field_types_wip, .layout_wip => {35106 .field_types_wip, .layout_wip => {
...@@ -35477,53 +35209,15 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {...@@ -35477,53 +35209,15 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3547735209
35478/// Returns `error.AnalysisFail` if any of the types (recursively) failed to35210/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
35479/// be resolved.35211/// be resolved.
35480pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {35212pub fn resolveStructFully(sema: *Sema, ty: Type) SemaError!void {
35481 const mod = sema.mod;
35482 const ip = &mod.intern_pool;
35483 switch (ty.zigTypeTag(mod)) {
35484 .Pointer => {
35485 return sema.resolveTypeFully(ty.childType(mod));
35486 },
35487 .Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
35488 .struct_type => try sema.resolveStructFully(ty),
35489 .anon_struct_type => |tuple| {
35490 for (tuple.types.get(ip)) |field_ty| {
35491 try sema.resolveTypeFully(Type.fromInterned(field_ty));
35492 }
35493 },
35494 .simple_type => |simple_type| try sema.resolveSimpleType(simple_type),
35495 else => {},
35496 },
35497 .Union => return sema.resolveUnionFully(ty),
35498 .Array => return sema.resolveTypeFully(ty.childType(mod)),
35499 .Optional => {
35500 return sema.resolveTypeFully(ty.optionalChild(mod));
35501 },
35502 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload(mod)),
35503 .Fn => {
35504 const info = mod.typeToFunc(ty).?;
35505 if (info.is_generic) {
35506 // Resolving of generic function types is deferred to when
35507 // the function is instantiated.
35508 return;
35509 }
35510 for (0..info.param_types.len) |i| {
35511 const param_ty = info.param_types.get(ip)[i];
35512 try sema.resolveTypeFully(Type.fromInterned(param_ty));
35513 }
35514 try sema.resolveTypeFully(Type.fromInterned(info.return_type));
35515 },
35516 else => {},
35517 }
35518}
35519
35520fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
35521 try sema.resolveStructLayout(ty);35213 try sema.resolveStructLayout(ty);
3552235214
35523 const mod = sema.mod;35215 const mod = sema.mod;
35524 const ip = &mod.intern_pool;35216 const ip = &mod.intern_pool;
35525 const struct_type = mod.typeToStruct(ty).?;35217 const struct_type = mod.typeToStruct(ty).?;
3552635218
35219 assert(sema.ownerUnit().unwrap().decl == struct_type.decl.unwrap().?);
35220
35527 if (struct_type.setFullyResolved(ip)) return;35221 if (struct_type.setFullyResolved(ip)) return;
35528 errdefer struct_type.clearFullyResolved(ip);35222 errdefer struct_type.clearFullyResolved(ip);
3552935223
...@@ -35533,16 +35227,19 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {...@@ -35533,16 +35227,19 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
3553335227
35534 for (0..struct_type.field_types.len) |i| {35228 for (0..struct_type.field_types.len) |i| {
35535 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);35229 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
35536 try sema.resolveTypeFully(field_ty);35230 try field_ty.resolveFully(mod);
35537 }35231 }
35538}35232}
3553935233
35540fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {35234pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void {
35541 try sema.resolveUnionLayout(ty);35235 try sema.resolveUnionLayout(ty);
3554235236
35543 const mod = sema.mod;35237 const mod = sema.mod;
35544 const ip = &mod.intern_pool;35238 const ip = &mod.intern_pool;
35545 const union_obj = mod.typeToUnion(ty).?;35239 const union_obj = mod.typeToUnion(ty).?;
35240
35241 assert(sema.ownerUnit().unwrap().decl == union_obj.decl);
35242
35546 switch (union_obj.flagsPtr(ip).status) {35243 switch (union_obj.flagsPtr(ip).status) {
35547 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},35244 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
35548 .fully_resolved_wip, .fully_resolved => return,35245 .fully_resolved_wip, .fully_resolved => return,
...@@ -35558,7 +35255,7 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {...@@ -35558,7 +35255,7 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
35558 union_obj.flagsPtr(ip).status = .fully_resolved_wip;35255 union_obj.flagsPtr(ip).status = .fully_resolved_wip;
35559 for (0..union_obj.field_types.len) |field_index| {35256 for (0..union_obj.field_types.len) |field_index| {
35560 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);35257 const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
35561 try sema.resolveTypeFully(field_ty);35258 try field_ty.resolveFully(mod);
35562 }35259 }
35563 union_obj.flagsPtr(ip).status = .fully_resolved;35260 union_obj.flagsPtr(ip).status = .fully_resolved;
35564 }35261 }
...@@ -35567,135 +35264,18 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {...@@ -35567,135 +35264,18 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
35567 _ = try sema.typeRequiresComptime(ty);35264 _ = try sema.typeRequiresComptime(ty);
35568}35265}
3556935266
35570pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!void {
35571 const mod = sema.mod;
35572 const ip = &mod.intern_pool;
35573 const ty_ip = ty.toIntern();
35574
35575 switch (ty_ip) {
35576 .none => unreachable,
35577
35578 .u0_type,
35579 .i0_type,
35580 .u1_type,
35581 .u8_type,
35582 .i8_type,
35583 .u16_type,
35584 .i16_type,
35585 .u29_type,
35586 .u32_type,
35587 .i32_type,
35588 .u64_type,
35589 .i64_type,
35590 .u80_type,
35591 .u128_type,
35592 .i128_type,
35593 .usize_type,
35594 .isize_type,
35595 .c_char_type,
35596 .c_short_type,
35597 .c_ushort_type,
35598 .c_int_type,
35599 .c_uint_type,
35600 .c_long_type,
35601 .c_ulong_type,
35602 .c_longlong_type,
35603 .c_ulonglong_type,
35604 .c_longdouble_type,
35605 .f16_type,
35606 .f32_type,
35607 .f64_type,
35608 .f80_type,
35609 .f128_type,
35610 .anyopaque_type,
35611 .bool_type,
35612 .void_type,
35613 .type_type,
35614 .anyerror_type,
35615 .adhoc_inferred_error_set_type,
35616 .comptime_int_type,
35617 .comptime_float_type,
35618 .noreturn_type,
35619 .anyframe_type,
35620 .null_type,
35621 .undefined_type,
35622 .enum_literal_type,
35623 .manyptr_u8_type,
35624 .manyptr_const_u8_type,
35625 .manyptr_const_u8_sentinel_0_type,
35626 .single_const_pointer_to_comptime_int_type,
35627 .slice_const_u8_type,
35628 .slice_const_u8_sentinel_0_type,
35629 .optional_noreturn_type,
35630 .anyerror_void_error_union_type,
35631 .generic_poison_type,
35632 .empty_struct_type,
35633 => {},
35634
35635 .undef => unreachable,
35636 .zero => unreachable,
35637 .zero_usize => unreachable,
35638 .zero_u8 => unreachable,
35639 .one => unreachable,
35640 .one_usize => unreachable,
35641 .one_u8 => unreachable,
35642 .four_u8 => unreachable,
35643 .negative_one => unreachable,
35644 .calling_convention_c => unreachable,
35645 .calling_convention_inline => unreachable,
35646 .void_value => unreachable,
35647 .unreachable_value => unreachable,
35648 .null_value => unreachable,
35649 .bool_true => unreachable,
35650 .bool_false => unreachable,
35651 .empty_struct => unreachable,
35652 .generic_poison => unreachable,
35653
35654 else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {
35655 .type_struct,
35656 .type_struct_packed,
35657 .type_struct_packed_inits,
35658 => try sema.resolveTypeFieldsStruct(ty_ip, ip.loadStructType(ty_ip)),
35659
35660 .type_union => try sema.resolveTypeFieldsUnion(Type.fromInterned(ty_ip), ip.loadUnionType(ty_ip)),
35661 .simple_type => try sema.resolveSimpleType(ip.indexToKey(ty_ip).simple_type),
35662 else => {},
35663 },
35664 }
35665}
35666
35667/// Fully resolves a simple type. This is usually a nop, but for builtin types with
35668/// special InternPool indices (such as std.builtin.Type) it will analyze and fully
35669/// resolve the container type.
35670fn resolveSimpleType(sema: *Sema, simple_type: InternPool.SimpleType) CompileError!void {
35671 const builtin_type_name: []const u8 = switch (simple_type) {
35672 .atomic_order => "AtomicOrder",
35673 .atomic_rmw_op => "AtomicRmwOp",
35674 .calling_convention => "CallingConvention",
35675 .address_space => "AddressSpace",
35676 .float_mode => "FloatMode",
35677 .reduce_op => "ReduceOp",
35678 .call_modifier => "CallModifer",
35679 .prefetch_options => "PrefetchOptions",
35680 .export_options => "ExportOptions",
35681 .extern_options => "ExternOptions",
35682 .type_info => "Type",
35683 else => return,
35684 };
35685 // This will fully resolve the type.
35686 _ = try sema.getBuiltinType(builtin_type_name);
35687}
35688
35689pub fn resolveTypeFieldsStruct(35267pub fn resolveTypeFieldsStruct(
35690 sema: *Sema,35268 sema: *Sema,
35691 ty: InternPool.Index,35269 ty: InternPool.Index,
35692 struct_type: InternPool.LoadedStructType,35270 struct_type: InternPool.LoadedStructType,
35693) CompileError!void {35271) SemaError!void {
35694 const zcu = sema.mod;35272 const zcu = sema.mod;
35695 const ip = &zcu.intern_pool;35273 const ip = &zcu.intern_pool;
35696 // If there is no owner decl it means the struct has no fields.35274 // If there is no owner decl it means the struct has no fields.
35697 const owner_decl = struct_type.decl.unwrap() orelse return;35275 const owner_decl = struct_type.decl.unwrap() orelse return;
3569835276
35277 assert(sema.ownerUnit().unwrap().decl == owner_decl);
35278
35699 switch (zcu.declPtr(owner_decl).analysis) {35279 switch (zcu.declPtr(owner_decl).analysis) {
35700 .file_failure,35280 .file_failure,
35701 .dependency_failure,35281 .dependency_failure,
...@@ -35726,16 +35306,19 @@ pub fn resolveTypeFieldsStruct(...@@ -35726,16 +35306,19 @@ pub fn resolveTypeFieldsStruct(
35726 }35306 }
35727 return error.AnalysisFail;35307 return error.AnalysisFail;
35728 },35308 },
35729 else => |e| return e,35309 error.OutOfMemory => return error.OutOfMemory,
35310 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35730 };35311 };
35731}35312}
3573235313
35733pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {35314pub fn resolveStructFieldInits(sema: *Sema, ty: Type) SemaError!void {
35734 const zcu = sema.mod;35315 const zcu = sema.mod;
35735 const ip = &zcu.intern_pool;35316 const ip = &zcu.intern_pool;
35736 const struct_type = zcu.typeToStruct(ty) orelse return;35317 const struct_type = zcu.typeToStruct(ty) orelse return;
35737 const owner_decl = struct_type.decl.unwrap() orelse return;35318 const owner_decl = struct_type.decl.unwrap() orelse return;
3573835319
35320 assert(sema.ownerUnit().unwrap().decl == owner_decl);
35321
35739 // Inits can start as resolved35322 // Inits can start as resolved
35740 if (struct_type.haveFieldInits(ip)) return;35323 if (struct_type.haveFieldInits(ip)) return;
3574135324
...@@ -35758,15 +35341,19 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {...@@ -35758,15 +35341,19 @@ pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void {
35758 }35341 }
35759 return error.AnalysisFail;35342 return error.AnalysisFail;
35760 },35343 },
35761 else => |e| return e,35344 error.OutOfMemory => return error.OutOfMemory,
35345 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35762 };35346 };
35763 struct_type.setHaveFieldInits(ip);35347 struct_type.setHaveFieldInits(ip);
35764}35348}
3576535349
35766pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) CompileError!void {35350pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) SemaError!void {
35767 const zcu = sema.mod;35351 const zcu = sema.mod;
35768 const ip = &zcu.intern_pool;35352 const ip = &zcu.intern_pool;
35769 const owner_decl = zcu.declPtr(union_type.decl);35353 const owner_decl = zcu.declPtr(union_type.decl);
35354
35355 assert(sema.ownerUnit().unwrap().decl == union_type.decl);
35356
35770 switch (owner_decl.analysis) {35357 switch (owner_decl.analysis) {
35771 .file_failure,35358 .file_failure,
35772 .dependency_failure,35359 .dependency_failure,
...@@ -35804,7 +35391,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load...@@ -35804,7 +35391,8 @@ pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.Load
35804 }35391 }
35805 return error.AnalysisFail;35392 return error.AnalysisFail;
35806 },35393 },
35807 else => |e| return e,35394 error.OutOfMemory => return error.OutOfMemory,
35395 error.ComptimeBreak, error.ComptimeReturn, error.GenericPoison => unreachable,
35808 };35396 };
35809 union_type.flagsPtr(ip).status = .have_field_types;35397 union_type.flagsPtr(ip).status = .have_field_types;
35810}35398}
...@@ -35860,6 +35448,7 @@ fn resolveInferredErrorSet(...@@ -35860,6 +35448,7 @@ fn resolveInferredErrorSet(
35860 }35448 }
35861 // In this case we are dealing with the actual InferredErrorSet object that35449 // In this case we are dealing with the actual InferredErrorSet object that
35862 // corresponds to the function, not one created to track an inline/comptime call.35450 // corresponds to the function, not one created to track an inline/comptime call.
35451 try sema.addReferenceEntry(src, AnalUnit.wrap(.{ .func = func_index }));
35863 try sema.ensureFuncBodyAnalyzed(func_index);35452 try sema.ensureFuncBodyAnalyzed(func_index);
35864 }35453 }
3586535454
...@@ -36225,6 +35814,8 @@ fn semaStructFields(...@@ -36225,6 +35814,8 @@ fn semaStructFields(
3622535814
36226 struct_type.clearTypesWip(ip);35815 struct_type.clearTypesWip(ip);
36227 if (!any_inits) struct_type.setHaveFieldInits(ip);35816 if (!any_inits) struct_type.setHaveFieldInits(ip);
35817
35818 try sema.flushExports();
36228}35819}
3622935820
36230// This logic must be kept in sync with `semaStructFields`35821// This logic must be kept in sync with `semaStructFields`
...@@ -36365,6 +35956,8 @@ fn semaStructFieldInits(...@@ -36365,6 +35956,8 @@ fn semaStructFieldInits(
36365 struct_type.field_inits.get(ip)[field_i] = default_val.toIntern();35956 struct_type.field_inits.get(ip)[field_i] = default_val.toIntern();
36366 }35957 }
36367 }35958 }
35959
35960 try sema.flushExports();
36368}35961}
3636935962
36370fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void {35963fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void {
...@@ -36738,6 +36331,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded...@@ -36738,6 +36331,8 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded
36738 const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl));36331 const enum_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, mod.declPtr(union_type.decl));
36739 union_type.tagTypePtr(ip).* = enum_ty;36332 union_type.tagTypePtr(ip).* = enum_ty;
36740 }36333 }
36334
36335 try sema.flushExports();
36741}36336}
3674236337
36743fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value {36338fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value {
...@@ -36846,106 +36441,6 @@ fn generateUnionTagTypeSimple(...@@ -36846,106 +36441,6 @@ fn generateUnionTagTypeSimple(
36846 return enum_ty;36441 return enum_ty;
36847}36442}
3684836443
36849fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
36850 const zcu = sema.mod;
36851
36852 var block: Block = .{
36853 .parent = null,
36854 .sema = sema,
36855 .namespace = sema.owner_decl.src_namespace,
36856 .instructions = .{},
36857 .inlining = null,
36858 .is_comptime = true,
36859 .src_base_inst = sema.owner_decl.zir_decl_index.unwrap() orelse owner: {
36860 assert(sema.owner_decl.has_tv);
36861 assert(sema.owner_decl.owns_tv);
36862 switch (sema.owner_decl.typeOf(zcu).zigTypeTag(zcu)) {
36863 .Type => break :owner sema.owner_decl.val.toType().typeDeclInst(zcu).?,
36864 .Fn => {
36865 const owner = zcu.funcInfo(sema.owner_decl.val.toIntern()).generic_owner;
36866 const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl);
36867 break :owner generic_owner_decl.zir_decl_index.unwrap().?;
36868 },
36869 else => unreachable,
36870 }
36871 },
36872 .type_name_ctx = sema.owner_decl.name,
36873 };
36874 defer block.instructions.deinit(sema.gpa);
36875
36876 const src = block.nodeOffset(0);
36877
36878 const decl_index = try getBuiltinDecl(sema, &block, name);
36879 return sema.analyzeDeclVal(&block, src, decl_index);
36880}
36881
36882fn getBuiltinDecl(sema: *Sema, block: *Block, name: []const u8) CompileError!InternPool.DeclIndex {
36883 const gpa = sema.gpa;
36884
36885 const src = block.nodeOffset(0);
36886
36887 const mod = sema.mod;
36888 const ip = &mod.intern_pool;
36889 const std_mod = mod.std_mod;
36890 const std_file = (mod.importPkg(std_mod) catch unreachable).file;
36891 const opt_builtin_inst = (try sema.namespaceLookupRef(
36892 block,
36893 src,
36894 mod.declPtr(std_file.root_decl.unwrap().?).src_namespace.toOptional(),
36895 try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls),
36896 )) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");
36897 const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst, src);
36898 const builtin_ty = sema.analyzeAsType(block, src, builtin_inst) catch |err| switch (err) {
36899 error.AnalysisFail => std.debug.panic("std.builtin is corrupt", .{}),
36900 else => |e| return e,
36901 };
36902 const decl_index = (try sema.namespaceLookup(
36903 block,
36904 src,
36905 builtin_ty.getNamespaceIndex(mod),
36906 try ip.getOrPutString(gpa, name, .no_embedded_nulls),
36907 )) orelse std.debug.panic("lib/std/builtin.zig is corrupt and missing '{s}'", .{name});
36908 return decl_index;
36909}
36910
36911fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
36912 const zcu = sema.mod;
36913 const ty_inst = try sema.getBuiltin(name);
36914
36915 var block: Block = .{
36916 .parent = null,
36917 .sema = sema,
36918 .namespace = sema.owner_decl.src_namespace,
36919 .instructions = .{},
36920 .inlining = null,
36921 .is_comptime = true,
36922 .src_base_inst = sema.owner_decl.zir_decl_index.unwrap() orelse owner: {
36923 assert(sema.owner_decl.has_tv);
36924 assert(sema.owner_decl.owns_tv);
36925 switch (sema.owner_decl.typeOf(zcu).zigTypeTag(zcu)) {
36926 .Type => break :owner sema.owner_decl.val.toType().typeDeclInst(zcu).?,
36927 .Fn => {
36928 const owner = zcu.funcInfo(sema.owner_decl.val.toIntern()).generic_owner;
36929 const generic_owner_decl = zcu.declPtr(zcu.funcInfo(owner).owner_decl);
36930 break :owner generic_owner_decl.zir_decl_index.unwrap().?;
36931 },
36932 else => unreachable,
36933 }
36934 },
36935 .type_name_ctx = sema.owner_decl.name,
36936 };
36937 defer block.instructions.deinit(sema.gpa);
36938
36939 const src = block.nodeOffset(0);
36940
36941 const result_ty = sema.analyzeAsType(&block, src, ty_inst) catch |err| switch (err) {
36942 error.AnalysisFail => std.debug.panic("std.builtin.{s} is corrupt", .{name}),
36943 else => |e| return e,
36944 };
36945 try sema.resolveTypeFully(result_ty); // Should not fail
36946 return result_ty;
36947}
36948
36949/// There is another implementation of this in `Type.onePossibleValue`. This one36444/// There is another implementation of this in `Type.onePossibleValue`. This one
36950/// in `Sema` is for calling during semantic analysis, and performs field resolution36445/// in `Sema` is for calling during semantic analysis, and performs field resolution
36951/// to get the answer. The one in `Type` is for calling during codegen and asserts36446/// to get the answer. The one in `Type` is for calling during codegen and asserts
...@@ -37149,8 +36644,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37149,8 +36644,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37149 },36644 },
3715036645
37151 .struct_type => {36646 .struct_type => {
36647 // Resolving the layout first helps to avoid loops.
36648 // If the type has a coherent layout, we can recurse through fields safely.
36649 try ty.resolveLayout(zcu);
36650
37152 const struct_type = ip.loadStructType(ty.toIntern());36651 const struct_type = ip.loadStructType(ty.toIntern());
37153 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
3715436652
37155 if (struct_type.field_types.len == 0) {36653 if (struct_type.field_types.len == 0) {
37156 // In this case the struct has no fields at all and36654 // In this case the struct has no fields at all and
...@@ -37167,20 +36665,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37167,20 +36665,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37167 );36665 );
37168 for (field_vals, 0..) |*field_val, i| {36666 for (field_vals, 0..) |*field_val, i| {
37169 if (struct_type.fieldIsComptime(ip, i)) {36667 if (struct_type.fieldIsComptime(ip, i)) {
37170 try sema.resolveStructFieldInits(ty);36668 try ty.resolveStructFieldInits(zcu);
37171 field_val.* = struct_type.field_inits.get(ip)[i];36669 field_val.* = struct_type.field_inits.get(ip)[i];
37172 continue;36670 continue;
37173 }36671 }
37174 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);36672 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
37175 if (field_ty.eql(ty, zcu)) {
37176 const msg = try sema.errMsg(
37177 ty.srcLoc(zcu),
37178 "struct '{}' depends on itself",
37179 .{ty.fmt(zcu)},
37180 );
37181 try sema.addFieldErrNote(ty, i, msg, "while checking this field", .{});
37182 return sema.failWithOwnedErrorMsg(null, msg);
37183 }
37184 if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| {36673 if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| {
37185 field_val.* = field_opv.toIntern();36674 field_val.* = field_opv.toIntern();
37186 } else return null;36675 } else return null;
...@@ -37208,8 +36697,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37208,8 +36697,11 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37208 },36697 },
3720936698
37210 .union_type => {36699 .union_type => {
36700 // Resolving the layout first helps to avoid loops.
36701 // If the type has a coherent layout, we can recurse through fields safely.
36702 try ty.resolveLayout(zcu);
36703
37211 const union_obj = ip.loadUnionType(ty.toIntern());36704 const union_obj = ip.loadUnionType(ty.toIntern());
37212 try sema.resolveTypeFieldsUnion(ty, union_obj);
37213 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse36705 const tag_val = (try sema.typeHasOnePossibleValue(Type.fromInterned(union_obj.tagTypePtr(ip).*))) orelse
37214 return null;36706 return null;
37215 if (union_obj.field_types.len == 0) {36707 if (union_obj.field_types.len == 0) {
...@@ -37217,15 +36709,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -37217,15 +36709,6 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
37217 return Value.fromInterned(only);36709 return Value.fromInterned(only);
37218 }36710 }
37219 const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);36711 const only_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]);
37220 if (only_field_ty.eql(ty, zcu)) {
37221 const msg = try sema.errMsg(
37222 ty.srcLoc(zcu),
37223 "union '{}' depends on itself",
37224 .{ty.fmt(zcu)},
37225 );
37226 try sema.addFieldErrNote(ty, 0, msg, "while checking this field", .{});
37227 return sema.failWithOwnedErrorMsg(null, msg);
37228 }
37229 const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse36712 const val_val = (try sema.typeHasOnePossibleValue(only_field_ty)) orelse
37230 return null;36713 return null;
37231 const only = try zcu.intern(.{ .un = .{36714 const only = try zcu.intern(.{ .un = .{
...@@ -37343,7 +36826,7 @@ fn analyzeComptimeAlloc(...@@ -37343,7 +36826,7 @@ fn analyzeComptimeAlloc(
37343 // Needed to make an anon decl with type `var_type` (the `finish()` call below).36826 // Needed to make an anon decl with type `var_type` (the `finish()` call below).
37344 _ = try sema.typeHasOnePossibleValue(var_type);36827 _ = try sema.typeHasOnePossibleValue(var_type);
3734536828
37346 const ptr_type = try sema.ptrType(.{36829 const ptr_type = try mod.ptrTypeSema(.{
37347 .child = var_type.toIntern(),36830 .child = var_type.toIntern(),
37348 .flags = .{36831 .flags = .{
37349 .alignment = alignment,36832 .alignment = alignment,
...@@ -37530,64 +37013,28 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {...@@ -37530,64 +37013,28 @@ fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
3753037013
37531/// `generic_poison` will return false.37014/// `generic_poison` will return false.
37532/// May return false negatives when structs and unions are having their field types resolved.37015/// May return false negatives when structs and unions are having their field types resolved.
37533pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {37016pub fn typeRequiresComptime(sema: *Sema, ty: Type) SemaError!bool {
37534 return ty.comptimeOnlyAdvanced(sema.mod, sema);37017 return ty.comptimeOnlyAdvanced(sema.mod, .sema);
37535}37018}
3753637019
37537pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {37020pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) SemaError!bool {
37538 const mod = sema.mod;37021 return ty.hasRuntimeBitsAdvanced(sema.mod, false, .sema) catch |err| switch (err) {
37539 return ty.hasRuntimeBitsAdvanced(mod, false, .{ .sema = sema }) catch |err| switch (err) {
37540 error.NeedLazy => unreachable,37022 error.NeedLazy => unreachable,
37541 else => |e| return e,37023 else => |e| return e,
37542 };37024 };
37543}37025}
3754437026
37545pub fn typeAbiSize(sema: *Sema, ty: Type) !u64 {37027pub fn typeAbiSize(sema: *Sema, ty: Type) SemaError!u64 {
37546 try sema.resolveTypeLayout(ty);37028 try ty.resolveLayout(sema.mod);
37547 return ty.abiSize(sema.mod);37029 return ty.abiSize(sema.mod);
37548}37030}
3754937031
37550pub fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment {37032pub fn typeAbiAlignment(sema: *Sema, ty: Type) SemaError!Alignment {
37551 return (try ty.abiAlignmentAdvanced(sema.mod, .{ .sema = sema })).scalar;37033 return (try ty.abiAlignmentAdvanced(sema.mod, .sema)).scalar;
37552}
37553
37554/// Not valid to call for packed unions.
37555/// Keep implementation in sync with `Module.unionFieldNormalAlignment`.
37556pub fn unionFieldAlignment(sema: *Sema, u: InternPool.LoadedUnionType, field_index: u32) !Alignment {
37557 const mod = sema.mod;
37558 const ip = &mod.intern_pool;
37559 const field_align = u.fieldAlign(ip, field_index);
37560 if (field_align != .none) return field_align;
37561 const field_ty = Type.fromInterned(u.field_types.get(ip)[field_index]);
37562 if (field_ty.isNoReturn(sema.mod)) return .none;
37563 return sema.typeAbiAlignment(field_ty);
37564}
37565
37566/// Keep implementation in sync with `Module.structFieldAlignment`.
37567pub fn structFieldAlignment(
37568 sema: *Sema,
37569 explicit_alignment: InternPool.Alignment,
37570 field_ty: Type,
37571 layout: std.builtin.Type.ContainerLayout,
37572) !Alignment {
37573 if (explicit_alignment != .none)
37574 return explicit_alignment;
37575 const mod = sema.mod;
37576 switch (layout) {
37577 .@"packed" => return .none,
37578 .auto => if (mod.getTarget().ofmt != .c) return sema.typeAbiAlignment(field_ty),
37579 .@"extern" => {},
37580 }
37581 // extern
37582 const ty_abi_align = try sema.typeAbiAlignment(field_ty);
37583 if (field_ty.isAbiInt(mod) and field_ty.intInfo(mod).bits >= 128) {
37584 return ty_abi_align.maxStrict(.@"16");
37585 }
37586 return ty_abi_align;
37587}37034}
3758837035
37589pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {37036pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
37590 return ty.fnHasRuntimeBitsAdvanced(sema.mod, sema);37037 return ty.fnHasRuntimeBitsAdvanced(sema.mod, .sema);
37591}37038}
3759237039
37593fn unionFieldIndex(37040fn unionFieldIndex(
...@@ -37599,7 +37046,7 @@ fn unionFieldIndex(...@@ -37599,7 +37046,7 @@ fn unionFieldIndex(
37599) !u32 {37046) !u32 {
37600 const mod = sema.mod;37047 const mod = sema.mod;
37601 const ip = &mod.intern_pool;37048 const ip = &mod.intern_pool;
37602 try sema.resolveTypeFields(union_ty);37049 try union_ty.resolveFields(mod);
37603 const union_obj = mod.typeToUnion(union_ty).?;37050 const union_obj = mod.typeToUnion(union_ty).?;
37604 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse37051 const field_index = union_obj.loadTagType(ip).nameIndex(ip, field_name) orelse
37605 return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name);37052 return sema.failWithBadUnionFieldAccess(block, union_ty, union_obj, field_src, field_name);
...@@ -37615,7 +37062,7 @@ fn structFieldIndex(...@@ -37615,7 +37062,7 @@ fn structFieldIndex(
37615) !u32 {37062) !u32 {
37616 const mod = sema.mod;37063 const mod = sema.mod;
37617 const ip = &mod.intern_pool;37064 const ip = &mod.intern_pool;
37618 try sema.resolveTypeFields(struct_ty);37065 try struct_ty.resolveFields(mod);
37619 if (struct_ty.isAnonStruct(mod)) {37066 if (struct_ty.isAnonStruct(mod)) {
37620 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);37067 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
37621 } else {37068 } else {
...@@ -37646,10 +37093,6 @@ fn anonStructFieldIndex(...@@ -37646,10 +37093,6 @@ fn anonStructFieldIndex(
37646 });37093 });
37647}37094}
3764837095
37649fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {
37650 try sema.types_to_resolve.put(sema.gpa, ty.toIntern(), {});
37651}
37652
37653/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting37096/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
37654/// overflow_idx to the vector index the overflow was at (or 0 for a scalar).37097/// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
37655fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value {37098fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value {
...@@ -37707,8 +37150,8 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {...@@ -37707,8 +37150,8 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
37707 // resorting to BigInt first.37150 // resorting to BigInt first.
37708 var lhs_space: Value.BigIntSpace = undefined;37151 var lhs_space: Value.BigIntSpace = undefined;
37709 var rhs_space: Value.BigIntSpace = undefined;37152 var rhs_space: Value.BigIntSpace = undefined;
37710 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);37153 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, .sema);
37711 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);37154 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, .sema);
37712 const limbs = try sema.arena.alloc(37155 const limbs = try sema.arena.alloc(
37713 std.math.big.Limb,37156 std.math.big.Limb,
37714 @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,37157 @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
...@@ -37797,8 +37240,8 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {...@@ -37797,8 +37240,8 @@ fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
37797 // resorting to BigInt first.37240 // resorting to BigInt first.
37798 var lhs_space: Value.BigIntSpace = undefined;37241 var lhs_space: Value.BigIntSpace = undefined;
37799 var rhs_space: Value.BigIntSpace = undefined;37242 var rhs_space: Value.BigIntSpace = undefined;
37800 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);37243 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, .sema);
37801 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);37244 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, .sema);
37802 const limbs = try sema.arena.alloc(37245 const limbs = try sema.arena.alloc(
37803 std.math.big.Limb,37246 std.math.big.Limb,
37804 @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,37247 @max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
...@@ -37881,8 +37324,8 @@ fn intSubWithOverflowScalar(...@@ -37881,8 +37324,8 @@ fn intSubWithOverflowScalar(
3788137324
37882 var lhs_space: Value.BigIntSpace = undefined;37325 var lhs_space: Value.BigIntSpace = undefined;
37883 var rhs_space: Value.BigIntSpace = undefined;37326 var rhs_space: Value.BigIntSpace = undefined;
37884 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);37327 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, .sema);
37885 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);37328 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, .sema);
37886 const limbs = try sema.arena.alloc(37329 const limbs = try sema.arena.alloc(
37887 std.math.big.Limb,37330 std.math.big.Limb,
37888 std.math.big.int.calcTwosCompLimbCount(info.bits),37331 std.math.big.int.calcTwosCompLimbCount(info.bits),
...@@ -38069,7 +37512,7 @@ fn intFitsInType(...@@ -38069,7 +37512,7 @@ fn intFitsInType(
3806937512
38070fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {37513fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
38071 const mod = sema.mod;37514 const mod = sema.mod;
38072 if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema))) return false;37515 if (!(try int_val.compareAllWithZeroSema(.gte, mod))) return false;
38073 const end_val = try mod.intValue(tag_ty, end);37516 const end_val = try mod.intValue(tag_ty, end);
38074 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;37517 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;
38075 return true;37518 return true;
...@@ -38139,8 +37582,8 @@ fn intAddWithOverflowScalar(...@@ -38139,8 +37582,8 @@ fn intAddWithOverflowScalar(
3813937582
38140 var lhs_space: Value.BigIntSpace = undefined;37583 var lhs_space: Value.BigIntSpace = undefined;
38141 var rhs_space: Value.BigIntSpace = undefined;37584 var rhs_space: Value.BigIntSpace = undefined;
38142 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);37585 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, .sema);
38143 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);37586 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, .sema);
38144 const limbs = try sema.arena.alloc(37587 const limbs = try sema.arena.alloc(
38145 std.math.big.Limb,37588 std.math.big.Limb,
38146 std.math.big.int.calcTwosCompLimbCount(info.bits),37589 std.math.big.int.calcTwosCompLimbCount(info.bits),
...@@ -38194,7 +37637,7 @@ fn compareScalar(...@@ -38194,7 +37637,7 @@ fn compareScalar(
38194 switch (op) {37637 switch (op) {
38195 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),37638 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
38196 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),37639 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
38197 else => return Value.compareHeteroAdvanced(coerced_lhs, op, coerced_rhs, mod, sema),37640 else => return Value.compareHeteroAdvanced(coerced_lhs, op, coerced_rhs, mod, .sema),
38198 }37641 }
38199}37642}
3820037643
...@@ -38230,80 +37673,6 @@ fn compareVector(...@@ -38230,80 +37673,6 @@ fn compareVector(
38230 } })));37673 } })));
38231}37674}
3823237675
38233/// Returns the type of a pointer to an element.
38234/// Asserts that the type is a pointer, and that the element type is indexable.
38235/// If the element index is comptime-known, it must be passed in `offset`.
38236/// For *@Vector(n, T), return *align(a:b:h:v) T
38237/// For *[N]T, return *T
38238/// For [*]T, returns *T
38239/// For []T, returns *T
38240/// Handles const-ness and address spaces in particular.
38241/// This code is duplicated in `analyzePtrArithmetic`.
38242pub fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
38243 const mod = sema.mod;
38244 const ptr_info = ptr_ty.ptrInfo(mod);
38245 const elem_ty = ptr_ty.elemType2(mod);
38246 const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0;
38247 const parent_ty = ptr_ty.childType(mod);
38248
38249 const VI = InternPool.Key.PtrType.VectorIndex;
38250
38251 const vector_info: struct {
38252 host_size: u16 = 0,
38253 alignment: Alignment = .none,
38254 vector_index: VI = .none,
38255 } = if (parent_ty.isVector(mod) and ptr_info.flags.size == .One) blk: {
38256 const elem_bits = elem_ty.bitSize(mod);
38257 if (elem_bits == 0) break :blk .{};
38258 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
38259 if (!is_packed) break :blk .{};
38260
38261 break :blk .{
38262 .host_size = @intCast(parent_ty.arrayLen(mod)),
38263 .alignment = parent_ty.abiAlignment(mod),
38264 .vector_index = if (offset) |some| @enumFromInt(some) else .runtime,
38265 };
38266 } else .{};
38267
38268 const alignment: Alignment = a: {
38269 // Calculate the new pointer alignment.
38270 if (ptr_info.flags.alignment == .none) {
38271 // In case of an ABI-aligned pointer, any pointer arithmetic
38272 // maintains the same ABI-alignedness.
38273 break :a vector_info.alignment;
38274 }
38275 // If the addend is not a comptime-known value we can still count on
38276 // it being a multiple of the type size.
38277 const elem_size = try sema.typeAbiSize(elem_ty);
38278 const addend = if (offset) |off| elem_size * off else elem_size;
38279
38280 // The resulting pointer is aligned to the lcd between the offset (an
38281 // arbitrary number) and the alignment factor (always a power of two,
38282 // non zero).
38283 const new_align: Alignment = @enumFromInt(@min(
38284 @ctz(addend),
38285 ptr_info.flags.alignment.toLog2Units(),
38286 ));
38287 assert(new_align != .none);
38288 break :a new_align;
38289 };
38290 return sema.ptrType(.{
38291 .child = elem_ty.toIntern(),
38292 .flags = .{
38293 .alignment = alignment,
38294 .is_const = ptr_info.flags.is_const,
38295 .is_volatile = ptr_info.flags.is_volatile,
38296 .is_allowzero = is_allowzero,
38297 .address_space = ptr_info.flags.address_space,
38298 .vector_index = vector_info.vector_index,
38299 },
38300 .packed_offset = .{
38301 .host_size = vector_info.host_size,
38302 .bit_offset = 0,
38303 },
38304 });
38305}
38306
38307/// Merge lhs with rhs.37676/// Merge lhs with rhs.
38308/// Asserts that lhs and rhs are both error sets and are resolved.37677/// Asserts that lhs and rhs are both error sets and are resolved.
38309fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {37678fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
...@@ -38344,13 +37713,6 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool...@@ -38344,13 +37713,6 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool
38344 return sema.typeOf(ref).zigTypeTag(sema.mod) == tag;37713 return sema.typeOf(ref).zigTypeTag(sema.mod) == tag;
38345}37714}
3834637715
38347pub fn ptrType(sema: *Sema, info: InternPool.Key.PtrType) CompileError!Type {
38348 if (info.flags.alignment != .none) {
38349 _ = try sema.typeAbiAlignment(Type.fromInterned(info.child));
38350 }
38351 return sema.mod.ptrType(info);
38352}
38353
38354pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {37716pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38355 if (!sema.mod.comp.debug_incremental) return;37717 if (!sema.mod.comp.debug_incremental) return;
3835637718
...@@ -38362,7 +37724,7 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {...@@ -38362,7 +37724,7 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38362 return;37724 return;
38363 }37725 }
3836437726
38365 const depender = InternPool.AnalSubject.wrap(37727 const depender = AnalUnit.wrap(
38366 if (sema.owner_func_index != .none)37728 if (sema.owner_func_index != .none)
38367 .{ .func = sema.owner_func_index }37729 .{ .func = sema.owner_func_index }
38368 else37730 else
...@@ -38470,12 +37832,12 @@ fn maybeDerefSliceAsArray(...@@ -38470,12 +37832,12 @@ fn maybeDerefSliceAsArray(
38470 else => unreachable,37832 else => unreachable,
38471 };37833 };
38472 const elem_ty = Type.fromInterned(slice.ty).childType(zcu);37834 const elem_ty = Type.fromInterned(slice.ty).childType(zcu);
38473 const len = try Value.fromInterned(slice.len).toUnsignedIntAdvanced(sema);37835 const len = try Value.fromInterned(slice.len).toUnsignedIntSema(zcu);
38474 const array_ty = try zcu.arrayType(.{37836 const array_ty = try zcu.arrayType(.{
38475 .child = elem_ty.toIntern(),37837 .child = elem_ty.toIntern(),
38476 .len = len,37838 .len = len,
38477 });37839 });
38478 const ptr_ty = try sema.ptrType(p: {37840 const ptr_ty = try zcu.ptrTypeSema(p: {
38479 var p = Type.fromInterned(slice.ty).ptrInfo(zcu);37841 var p = Type.fromInterned(slice.ty).ptrInfo(zcu);
38480 p.flags.size = .One;37842 p.flags.size = .One;
38481 p.child = array_ty.toIntern();37843 p.child = array_ty.toIntern();
...@@ -38494,6 +37856,57 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check:...@@ -38494,6 +37856,57 @@ fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check:
38494 }37856 }
38495}37857}
3849637858
37859/// This should be called exactly once, at the end of a `Sema`'s lifetime.
37860/// It takes the exports stored in `sema.export` and flushes them to the `Zcu`
37861/// to be processed by the linker after the update.
37862pub fn flushExports(sema: *Sema) !void {
37863 if (sema.exports.items.len == 0) return;
37864
37865 const zcu = sema.mod;
37866 const gpa = zcu.gpa;
37867
37868 const unit = sema.ownerUnit();
37869
37870 // There may be existing exports. For instance, a struct may export
37871 // things during both field type resolution and field default resolution.
37872 //
37873 // So, pick up and delete any existing exports. This strategy performs
37874 // redundant work, but that's okay, because this case is exceedingly rare.
37875 if (zcu.single_exports.get(unit)) |export_idx| {
37876 try sema.exports.append(gpa, zcu.all_exports.items[export_idx]);
37877 } else if (zcu.multi_exports.get(unit)) |info| {
37878 try sema.exports.appendSlice(gpa, zcu.all_exports.items[info.index..][0..info.len]);
37879 }
37880 zcu.deleteUnitExports(unit);
37881
37882 // `sema.exports` is completed; store the data into the `Zcu`.
37883 if (sema.exports.items.len == 1) {
37884 try zcu.single_exports.ensureUnusedCapacity(gpa, 1);
37885 const export_idx = zcu.free_exports.popOrNull() orelse idx: {
37886 _ = try zcu.all_exports.addOne(gpa);
37887 break :idx zcu.all_exports.items.len - 1;
37888 };
37889 zcu.all_exports.items[export_idx] = sema.exports.items[0];
37890 zcu.single_exports.putAssumeCapacityNoClobber(unit, @intCast(export_idx));
37891 } else {
37892 try zcu.multi_exports.ensureUnusedCapacity(gpa, 1);
37893 const exports_base = zcu.all_exports.items.len;
37894 try zcu.all_exports.appendSlice(gpa, sema.exports.items);
37895 zcu.multi_exports.putAssumeCapacityNoClobber(unit, .{
37896 .index = @intCast(exports_base),
37897 .len = @intCast(sema.exports.items.len),
37898 });
37899 }
37900}
37901
37902pub fn ownerUnit(sema: Sema) AnalUnit {
37903 if (sema.owner_func_index != .none) {
37904 return AnalUnit.wrap(.{ .func = sema.owner_func_index });
37905 } else {
37906 return AnalUnit.wrap(.{ .decl = sema.owner_decl_index });
37907 }
37908}
37909
38497pub const bitCastVal = @import("Sema/bitcast.zig").bitCast;37910pub const bitCastVal = @import("Sema/bitcast.zig").bitCast;
38498pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice;37911pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice;
3849937912
src/Sema/bitcast.zig+5-5
...@@ -78,8 +78,8 @@ fn bitCastInner(...@@ -78,8 +78,8 @@ fn bitCastInner(
7878
79 const val_ty = val.typeOf(zcu);79 const val_ty = val.typeOf(zcu);
8080
81 try sema.resolveTypeLayout(val_ty);81 try val_ty.resolveLayout(zcu);
82 try sema.resolveTypeLayout(dest_ty);82 try dest_ty.resolveLayout(zcu);
8383
84 assert(val_ty.hasWellDefinedLayout(zcu));84 assert(val_ty.hasWellDefinedLayout(zcu));
8585
...@@ -136,8 +136,8 @@ fn bitCastSpliceInner(...@@ -136,8 +136,8 @@ fn bitCastSpliceInner(
136 const val_ty = val.typeOf(zcu);136 const val_ty = val.typeOf(zcu);
137 const splice_val_ty = splice_val.typeOf(zcu);137 const splice_val_ty = splice_val.typeOf(zcu);
138138
139 try sema.resolveTypeLayout(val_ty);139 try val_ty.resolveLayout(zcu);
140 try sema.resolveTypeLayout(splice_val_ty);140 try splice_val_ty.resolveLayout(zcu);
141141
142 const splice_bits = splice_val_ty.bitSize(zcu);142 const splice_bits = splice_val_ty.bitSize(zcu);
143143
...@@ -767,6 +767,6 @@ const assert = std.debug.assert;...@@ -767,6 +767,6 @@ const assert = std.debug.assert;
767const Sema = @import("../Sema.zig");767const Sema = @import("../Sema.zig");
768const Zcu = @import("../Zcu.zig");768const Zcu = @import("../Zcu.zig");
769const InternPool = @import("../InternPool.zig");769const InternPool = @import("../InternPool.zig");
770const Type = @import("../type.zig").Type;770const Type = @import("../Type.zig");
771const Value = @import("../Value.zig");771const Value = @import("../Value.zig");
772const CompileError = Zcu.CompileError;772const CompileError = Zcu.CompileError;
src/Sema/comptime_ptr_access.zig+1-1
...@@ -1054,7 +1054,7 @@ const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;...@@ -1054,7 +1054,7 @@ const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;
1054const Sema = @import("../Sema.zig");1054const Sema = @import("../Sema.zig");
1055const Block = Sema.Block;1055const Block = Sema.Block;
1056const MutableValue = @import("../mutable_value.zig").MutableValue;1056const MutableValue = @import("../mutable_value.zig").MutableValue;
1057const Type = @import("../type.zig").Type;1057const Type = @import("../Type.zig");
1058const Value = @import("../Value.zig");1058const Value = @import("../Value.zig");
1059const Zcu = @import("../Zcu.zig");1059const Zcu = @import("../Zcu.zig");
1060const LazySrcLoc = Zcu.LazySrcLoc;1060const LazySrcLoc = Zcu.LazySrcLoc;
src/Type.zig created+4009
...@@ -0,0 +1,4009 @@
1//! Both types and values are canonically represented by a single 32-bit integer
2//! which is an index into an `InternPool` data structure.
3//! This struct abstracts around this storage by providing methods only
4//! applicable to types rather than values in general.
5
6const std = @import("std");
7const builtin = @import("builtin");
8const Allocator = std.mem.Allocator;
9const Value = @import("Value.zig");
10const assert = std.debug.assert;
11const Target = std.Target;
12const Zcu = @import("Zcu.zig");
13/// Deprecated.
14const Module = Zcu;
15const log = std.log.scoped(.Type);
16const target_util = @import("target.zig");
17const Sema = @import("Sema.zig");
18const InternPool = @import("InternPool.zig");
19const Alignment = InternPool.Alignment;
20const Zir = std.zig.Zir;
21const Type = @This();
22const SemaError = Zcu.SemaError;
23
24ip_index: InternPool.Index,
25
26pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {
27 return ty.zigTypeTagOrPoison(mod) catch unreachable;
28}
29
30pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
31 return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern());
32}
33
34pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {
35 return switch (self.zigTypeTag(mod)) {
36 .ErrorUnion => self.errorUnionPayload(mod).baseZigTypeTag(mod),
37 .Optional => {
38 return self.optionalChild(mod).baseZigTypeTag(mod);
39 },
40 else => |t| t,
41 };
42}
43
44pub fn isSelfComparable(ty: Type, mod: *const Module, is_equality_cmp: bool) bool {
45 return switch (ty.zigTypeTag(mod)) {
46 .Int,
47 .Float,
48 .ComptimeFloat,
49 .ComptimeInt,
50 => true,
51
52 .Vector => ty.elemType2(mod).isSelfComparable(mod, is_equality_cmp),
53
54 .Bool,
55 .Type,
56 .Void,
57 .ErrorSet,
58 .Fn,
59 .Opaque,
60 .AnyFrame,
61 .Enum,
62 .EnumLiteral,
63 => is_equality_cmp,
64
65 .NoReturn,
66 .Array,
67 .Struct,
68 .Undefined,
69 .Null,
70 .ErrorUnion,
71 .Union,
72 .Frame,
73 => false,
74
75 .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr(mod)),
76 .Optional => {
77 if (!is_equality_cmp) return false;
78 return ty.optionalChild(mod).isSelfComparable(mod, is_equality_cmp);
79 },
80 };
81}
82
83/// If it is a function pointer, returns the function type. Otherwise returns null.
84pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {
85 if (ty.zigTypeTag(mod) != .Pointer) return null;
86 const elem_ty = ty.childType(mod);
87 if (elem_ty.zigTypeTag(mod) != .Fn) return null;
88 return elem_ty;
89}
90
91/// Asserts the type is a pointer.
92pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {
93 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const;
94}
95
96pub const ArrayInfo = struct {
97 elem_type: Type,
98 sentinel: ?Value = null,
99 len: u64,
100};
101
102pub fn arrayInfo(self: Type, mod: *const Module) ArrayInfo {
103 return .{
104 .len = self.arrayLen(mod),
105 .sentinel = self.sentinel(mod),
106 .elem_type = self.childType(mod),
107 };
108}
109
110pub fn ptrInfo(ty: Type, mod: *const Module) InternPool.Key.PtrType {
111 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
112 .ptr_type => |p| p,
113 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
114 .ptr_type => |p| p,
115 else => unreachable,
116 },
117 else => unreachable,
118 };
119}
120
121pub fn eql(a: Type, b: Type, mod: *const Module) bool {
122 _ = mod; // TODO: remove this parameter
123 // The InternPool data structure hashes based on Key to make interned objects
124 // unique. An Index can be treated simply as u32 value for the
125 // purpose of Type/Value hashing and equality.
126 return a.toIntern() == b.toIntern();
127}
128
129pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
130 _ = ty;
131 _ = unused_fmt_string;
132 _ = options;
133 _ = writer;
134 @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
135}
136
137pub const Formatter = std.fmt.Formatter(format2);
138
139pub fn fmt(ty: Type, module: *Module) Formatter {
140 return .{ .data = .{
141 .ty = ty,
142 .module = module,
143 } };
144}
145
146const FormatContext = struct {
147 ty: Type,
148 module: *Module,
149};
150
151fn format2(
152 ctx: FormatContext,
153 comptime unused_format_string: []const u8,
154 options: std.fmt.FormatOptions,
155 writer: anytype,
156) !void {
157 comptime assert(unused_format_string.len == 0);
158 _ = options;
159 return print(ctx.ty, writer, ctx.module);
160}
161
162pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {
163 return .{ .data = ty };
164}
165
166/// This is a debug function. In order to print types in a meaningful way
167/// we also need access to the module.
168pub fn dump(
169 start_type: Type,
170 comptime unused_format_string: []const u8,
171 options: std.fmt.FormatOptions,
172 writer: anytype,
173) @TypeOf(writer).Error!void {
174 _ = options;
175 comptime assert(unused_format_string.len == 0);
176 return writer.print("{any}", .{start_type.ip_index});
177}
178
179/// Prints a name suitable for `@typeName`.
180/// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
181pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
182 const ip = &mod.intern_pool;
183 switch (ip.indexToKey(ty.toIntern())) {
184 .int_type => |int_type| {
185 const sign_char: u8 = switch (int_type.signedness) {
186 .signed => 'i',
187 .unsigned => 'u',
188 };
189 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
190 },
191 .ptr_type => {
192 const info = ty.ptrInfo(mod);
193
194 if (info.sentinel != .none) switch (info.flags.size) {
195 .One, .C => unreachable,
196 .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod, null)}),
197 .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod, null)}),
198 } else switch (info.flags.size) {
199 .One => try writer.writeAll("*"),
200 .Many => try writer.writeAll("[*]"),
201 .C => try writer.writeAll("[*c]"),
202 .Slice => try writer.writeAll("[]"),
203 }
204 if (info.flags.alignment != .none or
205 info.packed_offset.host_size != 0 or
206 info.flags.vector_index != .none)
207 {
208 const alignment = if (info.flags.alignment != .none)
209 info.flags.alignment
210 else
211 Type.fromInterned(info.child).abiAlignment(mod);
212 try writer.print("align({d}", .{alignment.toByteUnits() orelse 0});
213
214 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
215 try writer.print(":{d}:{d}", .{
216 info.packed_offset.bit_offset, info.packed_offset.host_size,
217 });
218 }
219 if (info.flags.vector_index == .runtime) {
220 try writer.writeAll(":?");
221 } else if (info.flags.vector_index != .none) {
222 try writer.print(":{d}", .{@intFromEnum(info.flags.vector_index)});
223 }
224 try writer.writeAll(") ");
225 }
226 if (info.flags.address_space != .generic) {
227 try writer.print("addrspace(.{s}) ", .{@tagName(info.flags.address_space)});
228 }
229 if (info.flags.is_const) try writer.writeAll("const ");
230 if (info.flags.is_volatile) try writer.writeAll("volatile ");
231 if (info.flags.is_allowzero and info.flags.size != .C) try writer.writeAll("allowzero ");
232
233 try print(Type.fromInterned(info.child), writer, mod);
234 return;
235 },
236 .array_type => |array_type| {
237 if (array_type.sentinel == .none) {
238 try writer.print("[{d}]", .{array_type.len});
239 try print(Type.fromInterned(array_type.child), writer, mod);
240 } else {
241 try writer.print("[{d}:{}]", .{
242 array_type.len,
243 Value.fromInterned(array_type.sentinel).fmtValue(mod, null),
244 });
245 try print(Type.fromInterned(array_type.child), writer, mod);
246 }
247 return;
248 },
249 .vector_type => |vector_type| {
250 try writer.print("@Vector({d}, ", .{vector_type.len});
251 try print(Type.fromInterned(vector_type.child), writer, mod);
252 try writer.writeAll(")");
253 return;
254 },
255 .opt_type => |child| {
256 try writer.writeByte('?');
257 return print(Type.fromInterned(child), writer, mod);
258 },
259 .error_union_type => |error_union_type| {
260 try print(Type.fromInterned(error_union_type.error_set_type), writer, mod);
261 try writer.writeByte('!');
262 if (error_union_type.payload_type == .generic_poison_type) {
263 try writer.writeAll("anytype");
264 } else {
265 try print(Type.fromInterned(error_union_type.payload_type), writer, mod);
266 }
267 return;
268 },
269 .inferred_error_set_type => |func_index| {
270 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
271 const owner_decl = mod.funcOwnerDeclPtr(func_index);
272 try owner_decl.renderFullyQualifiedName(mod, writer);
273 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
274 },
275 .error_set_type => |error_set_type| {
276 const names = error_set_type.names;
277 try writer.writeAll("error{");
278 for (names.get(ip), 0..) |name, i| {
279 if (i != 0) try writer.writeByte(',');
280 try writer.print("{}", .{name.fmt(ip)});
281 }
282 try writer.writeAll("}");
283 },
284 .simple_type => |s| switch (s) {
285 .f16,
286 .f32,
287 .f64,
288 .f80,
289 .f128,
290 .usize,
291 .isize,
292 .c_char,
293 .c_short,
294 .c_ushort,
295 .c_int,
296 .c_uint,
297 .c_long,
298 .c_ulong,
299 .c_longlong,
300 .c_ulonglong,
301 .c_longdouble,
302 .anyopaque,
303 .bool,
304 .void,
305 .type,
306 .anyerror,
307 .comptime_int,
308 .comptime_float,
309 .noreturn,
310 .adhoc_inferred_error_set,
311 => return writer.writeAll(@tagName(s)),
312
313 .null,
314 .undefined,
315 => try writer.print("@TypeOf({s})", .{@tagName(s)}),
316
317 .enum_literal => try writer.print("@TypeOf(.{s})", .{@tagName(s)}),
318 .atomic_order => try writer.writeAll("std.builtin.AtomicOrder"),
319 .atomic_rmw_op => try writer.writeAll("std.builtin.AtomicRmwOp"),
320 .calling_convention => try writer.writeAll("std.builtin.CallingConvention"),
321 .address_space => try writer.writeAll("std.builtin.AddressSpace"),
322 .float_mode => try writer.writeAll("std.builtin.FloatMode"),
323 .reduce_op => try writer.writeAll("std.builtin.ReduceOp"),
324 .call_modifier => try writer.writeAll("std.builtin.CallModifier"),
325 .prefetch_options => try writer.writeAll("std.builtin.PrefetchOptions"),
326 .export_options => try writer.writeAll("std.builtin.ExportOptions"),
327 .extern_options => try writer.writeAll("std.builtin.ExternOptions"),
328 .type_info => try writer.writeAll("std.builtin.Type"),
329
330 .generic_poison => unreachable,
331 },
332 .struct_type => {
333 const struct_type = ip.loadStructType(ty.toIntern());
334 if (struct_type.decl.unwrap()) |decl_index| {
335 const decl = mod.declPtr(decl_index);
336 try decl.renderFullyQualifiedName(mod, writer);
337 } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| {
338 const namespace = mod.namespacePtr(namespace_index);
339 try namespace.renderFullyQualifiedName(mod, .empty, writer);
340 } else {
341 try writer.writeAll("@TypeOf(.{})");
342 }
343 },
344 .anon_struct_type => |anon_struct| {
345 if (anon_struct.types.len == 0) {
346 return writer.writeAll("@TypeOf(.{})");
347 }
348 try writer.writeAll("struct{");
349 for (anon_struct.types.get(ip), anon_struct.values.get(ip), 0..) |field_ty, val, i| {
350 if (i != 0) try writer.writeAll(", ");
351 if (val != .none) {
352 try writer.writeAll("comptime ");
353 }
354 if (anon_struct.names.len != 0) {
355 try writer.print("{}: ", .{anon_struct.names.get(ip)[i].fmt(&mod.intern_pool)});
356 }
357
358 try print(Type.fromInterned(field_ty), writer, mod);
359
360 if (val != .none) {
361 try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(mod, null)});
362 }
363 }
364 try writer.writeAll("}");
365 },
366
367 .union_type => {
368 const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl);
369 try decl.renderFullyQualifiedName(mod, writer);
370 },
371 .opaque_type => {
372 const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl);
373 try decl.renderFullyQualifiedName(mod, writer);
374 },
375 .enum_type => {
376 const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl);
377 try decl.renderFullyQualifiedName(mod, writer);
378 },
379 .func_type => |fn_info| {
380 if (fn_info.is_noinline) {
381 try writer.writeAll("noinline ");
382 }
383 try writer.writeAll("fn (");
384 const param_types = fn_info.param_types.get(&mod.intern_pool);
385 for (param_types, 0..) |param_ty, i| {
386 if (i != 0) try writer.writeAll(", ");
387 if (std.math.cast(u5, i)) |index| {
388 if (fn_info.paramIsComptime(index)) {
389 try writer.writeAll("comptime ");
390 }
391 if (fn_info.paramIsNoalias(index)) {
392 try writer.writeAll("noalias ");
393 }
394 }
395 if (param_ty == .generic_poison_type) {
396 try writer.writeAll("anytype");
397 } else {
398 try print(Type.fromInterned(param_ty), writer, mod);
399 }
400 }
401 if (fn_info.is_var_args) {
402 if (param_types.len != 0) {
403 try writer.writeAll(", ");
404 }
405 try writer.writeAll("...");
406 }
407 try writer.writeAll(") ");
408 if (fn_info.cc != .Unspecified) {
409 try writer.writeAll("callconv(.");
410 try writer.writeAll(@tagName(fn_info.cc));
411 try writer.writeAll(") ");
412 }
413 if (fn_info.return_type == .generic_poison_type) {
414 try writer.writeAll("anytype");
415 } else {
416 try print(Type.fromInterned(fn_info.return_type), writer, mod);
417 }
418 },
419 .anyframe_type => |child| {
420 if (child == .none) return writer.writeAll("anyframe");
421 try writer.writeAll("anyframe->");
422 return print(Type.fromInterned(child), writer, mod);
423 },
424
425 // values, not types
426 .undef,
427 .simple_value,
428 .variable,
429 .extern_func,
430 .func,
431 .int,
432 .err,
433 .error_union,
434 .enum_literal,
435 .enum_tag,
436 .empty_enum_value,
437 .float,
438 .ptr,
439 .slice,
440 .opt,
441 .aggregate,
442 .un,
443 // memoization, not types
444 .memoized_call,
445 => unreachable,
446 }
447}
448
449pub fn fromInterned(i: InternPool.Index) Type {
450 assert(i != .none);
451 return .{ .ip_index = i };
452}
453
454pub fn toIntern(ty: Type) InternPool.Index {
455 assert(ty.ip_index != .none);
456 return ty.ip_index;
457}
458
459pub fn toValue(self: Type) Value {
460 return Value.fromInterned(self.toIntern());
461}
462
463const RuntimeBitsError = SemaError || error{NeedLazy};
464
465/// true if and only if the type takes up space in memory at runtime.
466/// There are two reasons a type will return false:
467/// * the type is a comptime-only type. For example, the type `type` itself.
468/// - note, however, that a struct can have mixed fields and only the non-comptime-only
469/// fields will count towards the ABI size. For example, `struct {T: type, x: i32}`
470/// hasRuntimeBits()=true and abiSize()=4
471/// * the type has only one possible value, making its ABI size 0.
472/// - an enum with an explicit tag type has the ABI size of the integer tag type,
473/// making it one-possible-value only if the integer tag type has 0 bits.
474/// When `ignore_comptime_only` is true, then types that are comptime-only
475/// may return false positives.
476pub fn hasRuntimeBitsAdvanced(
477 ty: Type,
478 mod: *Module,
479 ignore_comptime_only: bool,
480 strat: ResolveStratLazy,
481) RuntimeBitsError!bool {
482 const ip = &mod.intern_pool;
483 return switch (ty.toIntern()) {
484 // False because it is a comptime-only type.
485 .empty_struct_type => false,
486 else => switch (ip.indexToKey(ty.toIntern())) {
487 .int_type => |int_type| int_type.bits != 0,
488 .ptr_type => {
489 // Pointers to zero-bit types still have a runtime address; however, pointers
490 // to comptime-only types do not, with the exception of function pointers.
491 if (ignore_comptime_only) return true;
492 return switch (strat) {
493 .sema => !try ty.comptimeOnlyAdvanced(mod, .sema),
494 .eager => !ty.comptimeOnly(mod),
495 .lazy => error.NeedLazy,
496 };
497 },
498 .anyframe_type => true,
499 .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and
500 try Type.fromInterned(array_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
501 .vector_type => |vector_type| return vector_type.len > 0 and
502 try Type.fromInterned(vector_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
503 .opt_type => |child| {
504 const child_ty = Type.fromInterned(child);
505 if (child_ty.isNoReturn(mod)) {
506 // Then the optional is comptime-known to be null.
507 return false;
508 }
509 if (ignore_comptime_only) return true;
510 return switch (strat) {
511 .sema => !try child_ty.comptimeOnlyAdvanced(mod, .sema),
512 .eager => !child_ty.comptimeOnly(mod),
513 .lazy => error.NeedLazy,
514 };
515 },
516 .error_union_type,
517 .error_set_type,
518 .inferred_error_set_type,
519 => true,
520
521 // These are function *bodies*, not pointers.
522 // They return false here because they are comptime-only types.
523 // Special exceptions have to be made when emitting functions due to
524 // this returning false.
525 .func_type => false,
526
527 .simple_type => |t| switch (t) {
528 .f16,
529 .f32,
530 .f64,
531 .f80,
532 .f128,
533 .usize,
534 .isize,
535 .c_char,
536 .c_short,
537 .c_ushort,
538 .c_int,
539 .c_uint,
540 .c_long,
541 .c_ulong,
542 .c_longlong,
543 .c_ulonglong,
544 .c_longdouble,
545 .bool,
546 .anyerror,
547 .adhoc_inferred_error_set,
548 .anyopaque,
549 .atomic_order,
550 .atomic_rmw_op,
551 .calling_convention,
552 .address_space,
553 .float_mode,
554 .reduce_op,
555 .call_modifier,
556 .prefetch_options,
557 .export_options,
558 .extern_options,
559 => true,
560
561 // These are false because they are comptime-only types.
562 .void,
563 .type,
564 .comptime_int,
565 .comptime_float,
566 .noreturn,
567 .null,
568 .undefined,
569 .enum_literal,
570 .type_info,
571 => false,
572
573 .generic_poison => unreachable,
574 },
575 .struct_type => {
576 const struct_type = ip.loadStructType(ty.toIntern());
577 if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {
578 // In this case, we guess that hasRuntimeBits() for this type is true,
579 // and then later if our guess was incorrect, we emit a compile error.
580 return true;
581 }
582 switch (strat) {
583 .sema => try ty.resolveFields(mod),
584 .eager => assert(struct_type.haveFieldTypes(ip)),
585 .lazy => if (!struct_type.haveFieldTypes(ip)) return error.NeedLazy,
586 }
587 for (0..struct_type.field_types.len) |i| {
588 if (struct_type.comptime_bits.getBit(ip, i)) continue;
589 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
590 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
591 return true;
592 } else {
593 return false;
594 }
595 },
596 .anon_struct_type => |tuple| {
597 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
598 if (val != .none) continue; // comptime field
599 if (try Type.fromInterned(field_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
600 }
601 return false;
602 },
603
604 .union_type => {
605 const union_type = ip.loadUnionType(ty.toIntern());
606 switch (union_type.flagsPtr(ip).runtime_tag) {
607 .none => {
608 if (union_type.flagsPtr(ip).status == .field_types_wip) {
609 // In this case, we guess that hasRuntimeBits() for this type is true,
610 // and then later if our guess was incorrect, we emit a compile error.
611 union_type.flagsPtr(ip).assumed_runtime_bits = true;
612 return true;
613 }
614 },
615 .safety, .tagged => {
616 const tag_ty = union_type.tagTypePtr(ip).*;
617 // tag_ty will be `none` if this union's tag type is not resolved yet,
618 // in which case we want control flow to continue down below.
619 if (tag_ty != .none and
620 try Type.fromInterned(tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
621 {
622 return true;
623 }
624 },
625 }
626 switch (strat) {
627 .sema => try ty.resolveFields(mod),
628 .eager => assert(union_type.flagsPtr(ip).status.haveFieldTypes()),
629 .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())
630 return error.NeedLazy,
631 }
632 for (0..union_type.field_types.len) |field_index| {
633 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
634 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
635 return true;
636 } else {
637 return false;
638 }
639 },
640
641 .opaque_type => true,
642 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
643
644 // values, not types
645 .undef,
646 .simple_value,
647 .variable,
648 .extern_func,
649 .func,
650 .int,
651 .err,
652 .error_union,
653 .enum_literal,
654 .enum_tag,
655 .empty_enum_value,
656 .float,
657 .ptr,
658 .slice,
659 .opt,
660 .aggregate,
661 .un,
662 // memoization, not types
663 .memoized_call,
664 => unreachable,
665 },
666 };
667}
668
669/// true if and only if the type has a well-defined memory layout
670/// readFrom/writeToMemory are supported only for types with a well-
671/// defined memory layout
672pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
673 const ip = &mod.intern_pool;
674 return switch (ip.indexToKey(ty.toIntern())) {
675 .int_type,
676 .vector_type,
677 => true,
678
679 .error_union_type,
680 .error_set_type,
681 .inferred_error_set_type,
682 .anon_struct_type,
683 .opaque_type,
684 .anyframe_type,
685 // These are function bodies, not function pointers.
686 .func_type,
687 => false,
688
689 .array_type => |array_type| Type.fromInterned(array_type.child).hasWellDefinedLayout(mod),
690 .opt_type => ty.isPtrLikeOptional(mod),
691 .ptr_type => |ptr_type| ptr_type.flags.size != .Slice,
692
693 .simple_type => |t| switch (t) {
694 .f16,
695 .f32,
696 .f64,
697 .f80,
698 .f128,
699 .usize,
700 .isize,
701 .c_char,
702 .c_short,
703 .c_ushort,
704 .c_int,
705 .c_uint,
706 .c_long,
707 .c_ulong,
708 .c_longlong,
709 .c_ulonglong,
710 .c_longdouble,
711 .bool,
712 .void,
713 => true,
714
715 .anyerror,
716 .adhoc_inferred_error_set,
717 .anyopaque,
718 .atomic_order,
719 .atomic_rmw_op,
720 .calling_convention,
721 .address_space,
722 .float_mode,
723 .reduce_op,
724 .call_modifier,
725 .prefetch_options,
726 .export_options,
727 .extern_options,
728 .type,
729 .comptime_int,
730 .comptime_float,
731 .noreturn,
732 .null,
733 .undefined,
734 .enum_literal,
735 .type_info,
736 .generic_poison,
737 => false,
738 },
739 .struct_type => {
740 const struct_type = ip.loadStructType(ty.toIntern());
741 // Struct with no fields have a well-defined layout of no bits.
742 return struct_type.layout != .auto or struct_type.field_types.len == 0;
743 },
744 .union_type => {
745 const union_type = ip.loadUnionType(ty.toIntern());
746 return switch (union_type.flagsPtr(ip).runtime_tag) {
747 .none, .safety => union_type.flagsPtr(ip).layout != .auto,
748 .tagged => false,
749 };
750 },
751 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
752 .auto => false,
753 .explicit, .nonexhaustive => true,
754 },
755
756 // values, not types
757 .undef,
758 .simple_value,
759 .variable,
760 .extern_func,
761 .func,
762 .int,
763 .err,
764 .error_union,
765 .enum_literal,
766 .enum_tag,
767 .empty_enum_value,
768 .float,
769 .ptr,
770 .slice,
771 .opt,
772 .aggregate,
773 .un,
774 // memoization, not types
775 .memoized_call,
776 => unreachable,
777 };
778}
779
780pub fn hasRuntimeBits(ty: Type, mod: *Module) bool {
781 return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable;
782}
783
784pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
785 return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable;
786}
787
788pub fn fnHasRuntimeBits(ty: Type, mod: *Module) bool {
789 return ty.fnHasRuntimeBitsAdvanced(mod, .normal) catch unreachable;
790}
791
792/// Determines whether a function type has runtime bits, i.e. whether a
793/// function with this type can exist at runtime.
794/// Asserts that `ty` is a function type.
795pub fn fnHasRuntimeBitsAdvanced(ty: Type, mod: *Module, strat: ResolveStrat) SemaError!bool {
796 const fn_info = mod.typeToFunc(ty).?;
797 if (fn_info.is_generic) return false;
798 if (fn_info.is_var_args) return true;
799 if (fn_info.cc == .Inline) return false;
800 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyAdvanced(mod, strat);
801}
802
803pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
804 switch (ty.zigTypeTag(mod)) {
805 .Fn => return ty.fnHasRuntimeBits(mod),
806 else => return ty.hasRuntimeBits(mod),
807 }
808}
809
810/// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.
811pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
812 return switch (ty.zigTypeTag(mod)) {
813 .Fn => true,
814 else => return ty.hasRuntimeBitsIgnoreComptime(mod),
815 };
816}
817
818pub fn isNoReturn(ty: Type, mod: *Module) bool {
819 return mod.intern_pool.isNoReturn(ty.toIntern());
820}
821
822/// Returns `none` if the pointer is naturally aligned and the element type is 0-bit.
823pub fn ptrAlignment(ty: Type, mod: *Module) Alignment {
824 return ptrAlignmentAdvanced(ty, mod, .normal) catch unreachable;
825}
826
827pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, strat: ResolveStrat) !Alignment {
828 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
829 .ptr_type => |ptr_type| {
830 if (ptr_type.flags.alignment != .none)
831 return ptr_type.flags.alignment;
832
833 if (strat == .sema) {
834 const res = try Type.fromInterned(ptr_type.child).abiAlignmentAdvanced(mod, .sema);
835 return res.scalar;
836 }
837
838 return (Type.fromInterned(ptr_type.child).abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
839 },
840 .opt_type => |child| Type.fromInterned(child).ptrAlignmentAdvanced(mod, strat),
841 else => unreachable,
842 };
843}
844
845pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
846 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
847 .ptr_type => |ptr_type| ptr_type.flags.address_space,
848 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
849 else => unreachable,
850 };
851}
852
853/// Never returns `none`. Asserts that all necessary type resolution is already done.
854pub fn abiAlignment(ty: Type, mod: *Module) Alignment {
855 return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
856}
857
858/// May capture a reference to `ty`.
859/// Returned value has type `comptime_int`.
860pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
861 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
862 .val => |val| return val,
863 .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits() orelse 0),
864 }
865}
866
867pub const AbiAlignmentAdvanced = union(enum) {
868 scalar: Alignment,
869 val: Value,
870};
871
872pub const ResolveStratLazy = enum {
873 /// Return a `lazy_size` or `lazy_align` value if necessary.
874 /// This value can be resolved later using `Value.resolveLazy`.
875 lazy,
876 /// Return a scalar result, expecting all necessary type resolution to be completed.
877 /// Backends should typically use this, since they must not perform type resolution.
878 eager,
879 /// Return a scalar result, performing type resolution as necessary.
880 /// This should typically be used from semantic analysis.
881 sema,
882};
883
884/// The chosen strategy can be easily optimized away in release builds.
885/// However, in debug builds, it helps to avoid acceidentally resolving types in backends.
886pub const ResolveStrat = enum {
887 /// Assert that all necessary resolution is completed.
888 /// Backends should typically use this, since they must not perform type resolution.
889 normal,
890 /// Perform type resolution as necessary using `Zcu`.
891 /// This should typically be used from semantic analysis.
892 sema,
893
894 pub fn toLazy(strat: ResolveStrat) ResolveStratLazy {
895 return switch (strat) {
896 .normal => .eager,
897 .sema => .sema,
898 };
899 }
900};
901
902/// If you pass `eager` you will get back `scalar` and assert the type is resolved.
903/// In this case there will be no error, guaranteed.
904/// If you pass `lazy` you may get back `scalar` or `val`.
905/// If `val` is returned, a reference to `ty` has been captured.
906/// If you pass `sema` you will get back `scalar` and resolve the type if
907/// necessary, possibly returning a CompileError.
908pub fn abiAlignmentAdvanced(
909 ty: Type,
910 mod: *Module,
911 strat: ResolveStratLazy,
912) SemaError!AbiAlignmentAdvanced {
913 const target = mod.getTarget();
914 const use_llvm = mod.comp.config.use_llvm;
915 const ip = &mod.intern_pool;
916
917 switch (ty.toIntern()) {
918 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = .@"1" },
919 else => switch (ip.indexToKey(ty.toIntern())) {
920 .int_type => |int_type| {
921 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
922 return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) };
923 },
924 .ptr_type, .anyframe_type => {
925 return .{ .scalar = ptrAbiAlignment(target) };
926 },
927 .array_type => |array_type| {
928 return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat);
929 },
930 .vector_type => |vector_type| {
931 if (vector_type.len == 0) return .{ .scalar = .@"1" };
932 switch (mod.comp.getZigBackend()) {
933 else => {
934 const elem_bits: u32 = @intCast(try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, .sema));
935 if (elem_bits == 0) return .{ .scalar = .@"1" };
936 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
937 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
938 return .{ .scalar = Alignment.fromByteUnits(alignment) };
939 },
940 .stage2_c => {
941 return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat);
942 },
943 .stage2_x86_64 => {
944 if (vector_type.child == .bool_type) {
945 if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" };
946 if (vector_type.len > 128 and std.Target.x86.featureSetHas(target.cpu.features, .avx2)) return .{ .scalar = .@"32" };
947 if (vector_type.len > 64) return .{ .scalar = .@"16" };
948 const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
949 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
950 return .{ .scalar = Alignment.fromByteUnits(alignment) };
951 }
952 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
953 if (elem_bytes == 0) return .{ .scalar = .@"1" };
954 const bytes = elem_bytes * vector_type.len;
955 if (bytes > 32 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" };
956 if (bytes > 16 and std.Target.x86.featureSetHas(target.cpu.features, .avx)) return .{ .scalar = .@"32" };
957 return .{ .scalar = .@"16" };
958 },
959 }
960 },
961
962 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
963 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, Type.fromInterned(info.payload_type)),
964
965 .error_set_type, .inferred_error_set_type => {
966 const bits = mod.errorSetBits();
967 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
968 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
969 },
970
971 // represents machine code; not a pointer
972 .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },
973
974 .simple_type => |t| switch (t) {
975 .bool,
976 .atomic_order,
977 .atomic_rmw_op,
978 .calling_convention,
979 .address_space,
980 .float_mode,
981 .reduce_op,
982 .call_modifier,
983 .prefetch_options,
984 .anyopaque,
985 => return .{ .scalar = .@"1" },
986
987 .usize,
988 .isize,
989 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
990
991 .export_options,
992 .extern_options,
993 .type_info,
994 => return .{ .scalar = ptrAbiAlignment(target) },
995
996 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
997 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
998 .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) },
999 .c_int => return .{ .scalar = cTypeAlign(target, .int) },
1000 .c_uint => return .{ .scalar = cTypeAlign(target, .uint) },
1001 .c_long => return .{ .scalar = cTypeAlign(target, .long) },
1002 .c_ulong => return .{ .scalar = cTypeAlign(target, .ulong) },
1003 .c_longlong => return .{ .scalar = cTypeAlign(target, .longlong) },
1004 .c_ulonglong => return .{ .scalar = cTypeAlign(target, .ulonglong) },
1005 .c_longdouble => return .{ .scalar = cTypeAlign(target, .longdouble) },
1006
1007 .f16 => return .{ .scalar = .@"2" },
1008 .f32 => return .{ .scalar = cTypeAlign(target, .float) },
1009 .f64 => switch (target.c_type_bit_size(.double)) {
1010 64 => return .{ .scalar = cTypeAlign(target, .double) },
1011 else => return .{ .scalar = .@"8" },
1012 },
1013 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1014 80 => return .{ .scalar = cTypeAlign(target, .longdouble) },
1015 else => {
1016 const u80_ty: Type = .{ .ip_index = .u80_type };
1017 return .{ .scalar = abiAlignment(u80_ty, mod) };
1018 },
1019 },
1020 .f128 => switch (target.c_type_bit_size(.longdouble)) {
1021 128 => return .{ .scalar = cTypeAlign(target, .longdouble) },
1022 else => return .{ .scalar = .@"16" },
1023 },
1024
1025 .anyerror, .adhoc_inferred_error_set => {
1026 const bits = mod.errorSetBits();
1027 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
1028 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
1029 },
1030
1031 .void,
1032 .type,
1033 .comptime_int,
1034 .comptime_float,
1035 .null,
1036 .undefined,
1037 .enum_literal,
1038 => return .{ .scalar = .@"1" },
1039
1040 .noreturn => unreachable,
1041 .generic_poison => unreachable,
1042 },
1043 .struct_type => {
1044 const struct_type = ip.loadStructType(ty.toIntern());
1045 if (struct_type.layout == .@"packed") {
1046 switch (strat) {
1047 .sema => try ty.resolveLayout(mod),
1048 .lazy => if (struct_type.backingIntType(ip).* == .none) return .{
1049 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1050 .ty = .comptime_int_type,
1051 .storage = .{ .lazy_align = ty.toIntern() },
1052 } }))),
1053 },
1054 .eager => {},
1055 }
1056 return .{ .scalar = Type.fromInterned(struct_type.backingIntType(ip).*).abiAlignment(mod) };
1057 }
1058
1059 if (struct_type.flagsPtr(ip).alignment == .none) switch (strat) {
1060 .eager => unreachable, // struct alignment not resolved
1061 .sema => try ty.resolveStructAlignment(mod),
1062 .lazy => return .{ .val = Value.fromInterned(try mod.intern(.{ .int = .{
1063 .ty = .comptime_int_type,
1064 .storage = .{ .lazy_align = ty.toIntern() },
1065 } })) },
1066 };
1067
1068 return .{ .scalar = struct_type.flagsPtr(ip).alignment };
1069 },
1070 .anon_struct_type => |tuple| {
1071 var big_align: Alignment = .@"1";
1072 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
1073 if (val != .none) continue; // comptime field
1074 switch (try Type.fromInterned(field_ty).abiAlignmentAdvanced(mod, strat)) {
1075 .scalar => |field_align| big_align = big_align.max(field_align),
1076 .val => switch (strat) {
1077 .eager => unreachable, // field type alignment not resolved
1078 .sema => unreachable, // passed to abiAlignmentAdvanced above
1079 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1080 .ty = .comptime_int_type,
1081 .storage = .{ .lazy_align = ty.toIntern() },
1082 } }))) },
1083 },
1084 }
1085 }
1086 return .{ .scalar = big_align };
1087 },
1088 .union_type => {
1089 const union_type = ip.loadUnionType(ty.toIntern());
1090
1091 if (union_type.flagsPtr(ip).alignment == .none) switch (strat) {
1092 .eager => unreachable, // union layout not resolved
1093 .sema => try ty.resolveUnionAlignment(mod),
1094 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1095 .ty = .comptime_int_type,
1096 .storage = .{ .lazy_align = ty.toIntern() },
1097 } }))) },
1098 };
1099
1100 return .{ .scalar = union_type.flagsPtr(ip).alignment };
1101 },
1102 .opaque_type => return .{ .scalar = .@"1" },
1103 .enum_type => return .{
1104 .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod),
1105 },
1106
1107 // values, not types
1108 .undef,
1109 .simple_value,
1110 .variable,
1111 .extern_func,
1112 .func,
1113 .int,
1114 .err,
1115 .error_union,
1116 .enum_literal,
1117 .enum_tag,
1118 .empty_enum_value,
1119 .float,
1120 .ptr,
1121 .slice,
1122 .opt,
1123 .aggregate,
1124 .un,
1125 // memoization, not types
1126 .memoized_call,
1127 => unreachable,
1128 },
1129 }
1130}
1131
1132fn abiAlignmentAdvancedErrorUnion(
1133 ty: Type,
1134 mod: *Module,
1135 strat: ResolveStratLazy,
1136 payload_ty: Type,
1137) SemaError!AbiAlignmentAdvanced {
1138 // This code needs to be kept in sync with the equivalent switch prong
1139 // in abiSizeAdvanced.
1140 const code_align = abiAlignment(Type.anyerror, mod);
1141 switch (strat) {
1142 .eager, .sema => {
1143 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1144 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1145 .ty = .comptime_int_type,
1146 .storage = .{ .lazy_align = ty.toIntern() },
1147 } }))) },
1148 else => |e| return e,
1149 })) {
1150 return .{ .scalar = code_align };
1151 }
1152 return .{ .scalar = code_align.max(
1153 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,
1154 ) };
1155 },
1156 .lazy => {
1157 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {
1158 .scalar => |payload_align| return .{ .scalar = code_align.max(payload_align) },
1159 .val => {},
1160 }
1161 return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1162 .ty = .comptime_int_type,
1163 .storage = .{ .lazy_align = ty.toIntern() },
1164 } }))) };
1165 },
1166 }
1167}
1168
1169fn abiAlignmentAdvancedOptional(
1170 ty: Type,
1171 mod: *Module,
1172 strat: ResolveStratLazy,
1173) SemaError!AbiAlignmentAdvanced {
1174 const target = mod.getTarget();
1175 const child_type = ty.optionalChild(mod);
1176
1177 switch (child_type.zigTypeTag(mod)) {
1178 .Pointer => return .{ .scalar = ptrAbiAlignment(target) },
1179 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
1180 .NoReturn => return .{ .scalar = .@"1" },
1181 else => {},
1182 }
1183
1184 switch (strat) {
1185 .eager, .sema => {
1186 if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1187 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1188 .ty = .comptime_int_type,
1189 .storage = .{ .lazy_align = ty.toIntern() },
1190 } }))) },
1191 else => |e| return e,
1192 })) {
1193 return .{ .scalar = .@"1" };
1194 }
1195 return child_type.abiAlignmentAdvanced(mod, strat);
1196 },
1197 .lazy => switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
1198 .scalar => |x| return .{ .scalar = x.max(.@"1") },
1199 .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1200 .ty = .comptime_int_type,
1201 .storage = .{ .lazy_align = ty.toIntern() },
1202 } }))) },
1203 },
1204 }
1205}
1206
1207/// May capture a reference to `ty`.
1208pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
1209 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
1210 .val => |val| return val,
1211 .scalar => |x| return mod.intValue(Type.comptime_int, x),
1212 }
1213}
1214
1215/// Asserts the type has the ABI size already resolved.
1216/// Types that return false for hasRuntimeBits() return 0.
1217pub fn abiSize(ty: Type, mod: *Module) u64 {
1218 return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar;
1219}
1220
1221const AbiSizeAdvanced = union(enum) {
1222 scalar: u64,
1223 val: Value,
1224};
1225
1226/// If you pass `eager` you will get back `scalar` and assert the type is resolved.
1227/// In this case there will be no error, guaranteed.
1228/// If you pass `lazy` you may get back `scalar` or `val`.
1229/// If `val` is returned, a reference to `ty` has been captured.
1230/// If you pass `sema` you will get back `scalar` and resolve the type if
1231/// necessary, possibly returning a CompileError.
1232pub fn abiSizeAdvanced(
1233 ty: Type,
1234 mod: *Module,
1235 strat: ResolveStratLazy,
1236) SemaError!AbiSizeAdvanced {
1237 const target = mod.getTarget();
1238 const use_llvm = mod.comp.config.use_llvm;
1239 const ip = &mod.intern_pool;
1240
1241 switch (ty.toIntern()) {
1242 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
1243
1244 else => switch (ip.indexToKey(ty.toIntern())) {
1245 .int_type => |int_type| {
1246 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1247 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target, use_llvm) };
1248 },
1249 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1250 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
1251 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1252 },
1253 .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1254
1255 .array_type => |array_type| {
1256 const len = array_type.lenIncludingSentinel();
1257 if (len == 0) return .{ .scalar = 0 };
1258 switch (try Type.fromInterned(array_type.child).abiSizeAdvanced(mod, strat)) {
1259 .scalar => |elem_size| return .{ .scalar = len * elem_size },
1260 .val => switch (strat) {
1261 .sema, .eager => unreachable,
1262 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1263 .ty = .comptime_int_type,
1264 .storage = .{ .lazy_size = ty.toIntern() },
1265 } }))) },
1266 },
1267 }
1268 },
1269 .vector_type => |vector_type| {
1270 const sub_strat: ResolveStrat = switch (strat) {
1271 .sema => .sema,
1272 .eager => .normal,
1273 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1274 .ty = .comptime_int_type,
1275 .storage = .{ .lazy_size = ty.toIntern() },
1276 } }))) },
1277 };
1278 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
1279 .scalar => |x| x,
1280 .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1281 .ty = .comptime_int_type,
1282 .storage = .{ .lazy_size = ty.toIntern() },
1283 } }))) },
1284 };
1285 const total_bytes = switch (mod.comp.getZigBackend()) {
1286 else => total_bytes: {
1287 const elem_bits = try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, sub_strat);
1288 const total_bits = elem_bits * vector_type.len;
1289 break :total_bytes (total_bits + 7) / 8;
1290 },
1291 .stage2_c => total_bytes: {
1292 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
1293 break :total_bytes elem_bytes * vector_type.len;
1294 },
1295 .stage2_x86_64 => total_bytes: {
1296 if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
1297 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
1298 break :total_bytes elem_bytes * vector_type.len;
1299 },
1300 };
1301 return AbiSizeAdvanced{ .scalar = alignment.forward(total_bytes) };
1302 },
1303
1304 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
1305
1306 .error_set_type, .inferred_error_set_type => {
1307 const bits = mod.errorSetBits();
1308 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1309 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1310 },
1311
1312 .error_union_type => |error_union_type| {
1313 const payload_ty = Type.fromInterned(error_union_type.payload_type);
1314 // This code needs to be kept in sync with the equivalent switch prong
1315 // in abiAlignmentAdvanced.
1316 const code_size = abiSize(Type.anyerror, mod);
1317 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1318 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1319 .ty = .comptime_int_type,
1320 .storage = .{ .lazy_size = ty.toIntern() },
1321 } }))) },
1322 else => |e| return e,
1323 })) {
1324 // Same as anyerror.
1325 return AbiSizeAdvanced{ .scalar = code_size };
1326 }
1327 const code_align = abiAlignment(Type.anyerror, mod);
1328 const payload_align = abiAlignment(payload_ty, mod);
1329 const payload_size = switch (try payload_ty.abiSizeAdvanced(mod, strat)) {
1330 .scalar => |elem_size| elem_size,
1331 .val => switch (strat) {
1332 .sema => unreachable,
1333 .eager => unreachable,
1334 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1335 .ty = .comptime_int_type,
1336 .storage = .{ .lazy_size = ty.toIntern() },
1337 } }))) },
1338 },
1339 };
1340
1341 var size: u64 = 0;
1342 if (code_align.compare(.gt, payload_align)) {
1343 size += code_size;
1344 size = payload_align.forward(size);
1345 size += payload_size;
1346 size = code_align.forward(size);
1347 } else {
1348 size += payload_size;
1349 size = code_align.forward(size);
1350 size += code_size;
1351 size = payload_align.forward(size);
1352 }
1353 return AbiSizeAdvanced{ .scalar = size };
1354 },
1355 .func_type => unreachable, // represents machine code; not a pointer
1356 .simple_type => |t| switch (t) {
1357 .bool,
1358 .atomic_order,
1359 .atomic_rmw_op,
1360 .calling_convention,
1361 .address_space,
1362 .float_mode,
1363 .reduce_op,
1364 .call_modifier,
1365 => return AbiSizeAdvanced{ .scalar = 1 },
1366
1367 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
1368 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
1369 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
1370 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
1371 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1372 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1373 else => {
1374 const u80_ty: Type = .{ .ip_index = .u80_type };
1375 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
1376 },
1377 },
1378
1379 .usize,
1380 .isize,
1381 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1382
1383 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
1384 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
1385 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
1386 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
1387 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
1388 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
1389 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
1390 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
1391 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
1392 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1393
1394 .anyopaque,
1395 .void,
1396 .type,
1397 .comptime_int,
1398 .comptime_float,
1399 .null,
1400 .undefined,
1401 .enum_literal,
1402 => return AbiSizeAdvanced{ .scalar = 0 },
1403
1404 .anyerror, .adhoc_inferred_error_set => {
1405 const bits = mod.errorSetBits();
1406 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1407 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1408 },
1409
1410 .prefetch_options => unreachable, // missing call to resolveTypeFields
1411 .export_options => unreachable, // missing call to resolveTypeFields
1412 .extern_options => unreachable, // missing call to resolveTypeFields
1413
1414 .type_info => unreachable,
1415 .noreturn => unreachable,
1416 .generic_poison => unreachable,
1417 },
1418 .struct_type => {
1419 const struct_type = ip.loadStructType(ty.toIntern());
1420 switch (strat) {
1421 .sema => try ty.resolveLayout(mod),
1422 .lazy => switch (struct_type.layout) {
1423 .@"packed" => {
1424 if (struct_type.backingIntType(ip).* == .none) return .{
1425 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1426 .ty = .comptime_int_type,
1427 .storage = .{ .lazy_size = ty.toIntern() },
1428 } }))),
1429 };
1430 },
1431 .auto, .@"extern" => {
1432 if (!struct_type.haveLayout(ip)) return .{
1433 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1434 .ty = .comptime_int_type,
1435 .storage = .{ .lazy_size = ty.toIntern() },
1436 } }))),
1437 };
1438 },
1439 },
1440 .eager => {},
1441 }
1442 switch (struct_type.layout) {
1443 .@"packed" => return .{
1444 .scalar = Type.fromInterned(struct_type.backingIntType(ip).*).abiSize(mod),
1445 },
1446 .auto, .@"extern" => {
1447 assert(struct_type.haveLayout(ip));
1448 return .{ .scalar = struct_type.size(ip).* };
1449 },
1450 }
1451 },
1452 .anon_struct_type => |tuple| {
1453 switch (strat) {
1454 .sema => try ty.resolveLayout(mod),
1455 .lazy, .eager => {},
1456 }
1457 const field_count = tuple.types.len;
1458 if (field_count == 0) {
1459 return AbiSizeAdvanced{ .scalar = 0 };
1460 }
1461 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
1462 },
1463
1464 .union_type => {
1465 const union_type = ip.loadUnionType(ty.toIntern());
1466 switch (strat) {
1467 .sema => try ty.resolveLayout(mod),
1468 .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{
1469 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1470 .ty = .comptime_int_type,
1471 .storage = .{ .lazy_size = ty.toIntern() },
1472 } }))),
1473 },
1474 .eager => {},
1475 }
1476
1477 assert(union_type.haveLayout(ip));
1478 return .{ .scalar = union_type.size(ip).* };
1479 },
1480 .opaque_type => unreachable, // no size available
1481 .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(mod) },
1482
1483 // values, not types
1484 .undef,
1485 .simple_value,
1486 .variable,
1487 .extern_func,
1488 .func,
1489 .int,
1490 .err,
1491 .error_union,
1492 .enum_literal,
1493 .enum_tag,
1494 .empty_enum_value,
1495 .float,
1496 .ptr,
1497 .slice,
1498 .opt,
1499 .aggregate,
1500 .un,
1501 // memoization, not types
1502 .memoized_call,
1503 => unreachable,
1504 },
1505 }
1506}
1507
1508fn abiSizeAdvancedOptional(
1509 ty: Type,
1510 mod: *Module,
1511 strat: ResolveStratLazy,
1512) SemaError!AbiSizeAdvanced {
1513 const child_ty = ty.optionalChild(mod);
1514
1515 if (child_ty.isNoReturn(mod)) {
1516 return AbiSizeAdvanced{ .scalar = 0 };
1517 }
1518
1519 if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1520 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1521 .ty = .comptime_int_type,
1522 .storage = .{ .lazy_size = ty.toIntern() },
1523 } }))) },
1524 else => |e| return e,
1525 })) return AbiSizeAdvanced{ .scalar = 1 };
1526
1527 if (ty.optionalReprIsPayload(mod)) {
1528 return abiSizeAdvanced(child_ty, mod, strat);
1529 }
1530
1531 const payload_size = switch (try child_ty.abiSizeAdvanced(mod, strat)) {
1532 .scalar => |elem_size| elem_size,
1533 .val => switch (strat) {
1534 .sema => unreachable,
1535 .eager => unreachable,
1536 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1537 .ty = .comptime_int_type,
1538 .storage = .{ .lazy_size = ty.toIntern() },
1539 } }))) },
1540 },
1541 };
1542
1543 // Optional types are represented as a struct with the child type as the first
1544 // field and a boolean as the second. Since the child type's abi alignment is
1545 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1546 // to the child type's ABI alignment.
1547 return AbiSizeAdvanced{
1548 .scalar = (child_ty.abiAlignment(mod).toByteUnits() orelse 0) + payload_size,
1549 };
1550}
1551
1552pub fn ptrAbiAlignment(target: Target) Alignment {
1553 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1554}
1555
1556pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {
1557 return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1558}
1559
1560pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
1561 return switch (target.cpu.arch) {
1562 .x86 => switch (bits) {
1563 0 => .none,
1564 1...8 => .@"1",
1565 9...16 => .@"2",
1566 17...64 => .@"4",
1567 else => .@"16",
1568 },
1569 .x86_64 => switch (bits) {
1570 0 => .none,
1571 1...8 => .@"1",
1572 9...16 => .@"2",
1573 17...32 => .@"4",
1574 33...64 => .@"8",
1575 else => switch (target_util.zigBackend(target, use_llvm)) {
1576 .stage2_x86_64 => .@"8",
1577 else => .@"16",
1578 },
1579 },
1580 else => return Alignment.fromByteUnits(@min(
1581 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1582 maxIntAlignment(target, use_llvm),
1583 )),
1584 };
1585}
1586
1587pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
1588 return switch (target.cpu.arch) {
1589 .avr => 1,
1590 .msp430 => 2,
1591 .xcore => 4,
1592
1593 .arm,
1594 .armeb,
1595 .thumb,
1596 .thumbeb,
1597 .hexagon,
1598 .mips,
1599 .mipsel,
1600 .powerpc,
1601 .powerpcle,
1602 .r600,
1603 .amdgcn,
1604 .riscv32,
1605 .sparc,
1606 .sparcel,
1607 .s390x,
1608 .lanai,
1609 .wasm32,
1610 .wasm64,
1611 => 8,
1612
1613 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1614 // is a relevant number in three cases:
1615 // 1. Different machine code instruction when loading into SIMD register.
1616 // 2. The C ABI wants 16 for extern structs.
1617 // 3. 16-byte cmpxchg needs 16-byte alignment.
1618 // Same logic for powerpc64, mips64, sparc64.
1619 .powerpc64,
1620 .powerpc64le,
1621 .mips64,
1622 .mips64el,
1623 .sparc64,
1624 => switch (target.ofmt) {
1625 .c => 16,
1626 else => 8,
1627 },
1628
1629 .x86_64 => switch (target_util.zigBackend(target, use_llvm)) {
1630 .stage2_x86_64 => 8,
1631 else => 16,
1632 },
1633
1634 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1635 .x86,
1636 .aarch64,
1637 .aarch64_be,
1638 .aarch64_32,
1639 .riscv64,
1640 .bpfel,
1641 .bpfeb,
1642 .nvptx,
1643 .nvptx64,
1644 => 16,
1645
1646 // Below this comment are unverified but based on the fact that C requires
1647 // int128_t to be 16 bytes aligned, it's a safe default.
1648 .spu_2,
1649 .csky,
1650 .arc,
1651 .m68k,
1652 .tce,
1653 .tcele,
1654 .le32,
1655 .amdil,
1656 .hsail,
1657 .spir,
1658 .kalimba,
1659 .renderscript32,
1660 .spirv,
1661 .spirv32,
1662 .shave,
1663 .le64,
1664 .amdil64,
1665 .hsail64,
1666 .spir64,
1667 .renderscript64,
1668 .ve,
1669 .spirv64,
1670 .dxil,
1671 .loongarch32,
1672 .loongarch64,
1673 .xtensa,
1674 => 16,
1675 };
1676}
1677
1678pub fn bitSize(ty: Type, mod: *Module) u64 {
1679 return bitSizeAdvanced(ty, mod, .normal) catch unreachable;
1680}
1681
1682pub fn bitSizeAdvanced(
1683 ty: Type,
1684 mod: *Module,
1685 strat: ResolveStrat,
1686) SemaError!u64 {
1687 const target = mod.getTarget();
1688 const ip = &mod.intern_pool;
1689
1690 const strat_lazy: ResolveStratLazy = strat.toLazy();
1691
1692 switch (ip.indexToKey(ty.toIntern())) {
1693 .int_type => |int_type| return int_type.bits,
1694 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1695 .Slice => return target.ptrBitWidth() * 2,
1696 else => return target.ptrBitWidth(),
1697 },
1698 .anyframe_type => return target.ptrBitWidth(),
1699
1700 .array_type => |array_type| {
1701 const len = array_type.lenIncludingSentinel();
1702 if (len == 0) return 0;
1703 const elem_ty = Type.fromInterned(array_type.child);
1704 const elem_size = @max(
1705 (try elem_ty.abiAlignmentAdvanced(mod, strat_lazy)).scalar.toByteUnits() orelse 0,
1706 (try elem_ty.abiSizeAdvanced(mod, strat_lazy)).scalar,
1707 );
1708 if (elem_size == 0) return 0;
1709 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, strat);
1710 return (len - 1) * 8 * elem_size + elem_bit_size;
1711 },
1712 .vector_type => |vector_type| {
1713 const child_ty = Type.fromInterned(vector_type.child);
1714 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, strat);
1715 return elem_bit_size * vector_type.len;
1716 },
1717 .opt_type => {
1718 // Optionals and error unions are not packed so their bitsize
1719 // includes padding bits.
1720 return (try abiSizeAdvanced(ty, mod, strat_lazy)).scalar * 8;
1721 },
1722
1723 .error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
1724
1725 .error_union_type => {
1726 // Optionals and error unions are not packed so their bitsize
1727 // includes padding bits.
1728 return (try abiSizeAdvanced(ty, mod, strat_lazy)).scalar * 8;
1729 },
1730 .func_type => unreachable, // represents machine code; not a pointer
1731 .simple_type => |t| switch (t) {
1732 .f16 => return 16,
1733 .f32 => return 32,
1734 .f64 => return 64,
1735 .f80 => return 80,
1736 .f128 => return 128,
1737
1738 .usize,
1739 .isize,
1740 => return target.ptrBitWidth(),
1741
1742 .c_char => return target.c_type_bit_size(.char),
1743 .c_short => return target.c_type_bit_size(.short),
1744 .c_ushort => return target.c_type_bit_size(.ushort),
1745 .c_int => return target.c_type_bit_size(.int),
1746 .c_uint => return target.c_type_bit_size(.uint),
1747 .c_long => return target.c_type_bit_size(.long),
1748 .c_ulong => return target.c_type_bit_size(.ulong),
1749 .c_longlong => return target.c_type_bit_size(.longlong),
1750 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
1751 .c_longdouble => return target.c_type_bit_size(.longdouble),
1752
1753 .bool => return 1,
1754 .void => return 0,
1755
1756 .anyerror,
1757 .adhoc_inferred_error_set,
1758 => return mod.errorSetBits(),
1759
1760 .anyopaque => unreachable,
1761 .type => unreachable,
1762 .comptime_int => unreachable,
1763 .comptime_float => unreachable,
1764 .noreturn => unreachable,
1765 .null => unreachable,
1766 .undefined => unreachable,
1767 .enum_literal => unreachable,
1768 .generic_poison => unreachable,
1769
1770 .atomic_order => unreachable,
1771 .atomic_rmw_op => unreachable,
1772 .calling_convention => unreachable,
1773 .address_space => unreachable,
1774 .float_mode => unreachable,
1775 .reduce_op => unreachable,
1776 .call_modifier => unreachable,
1777 .prefetch_options => unreachable,
1778 .export_options => unreachable,
1779 .extern_options => unreachable,
1780 .type_info => unreachable,
1781 },
1782 .struct_type => {
1783 const struct_type = ip.loadStructType(ty.toIntern());
1784 const is_packed = struct_type.layout == .@"packed";
1785 if (strat == .sema) {
1786 try ty.resolveFields(mod);
1787 if (is_packed) try ty.resolveLayout(mod);
1788 }
1789 if (is_packed) {
1790 return try Type.fromInterned(struct_type.backingIntType(ip).*).bitSizeAdvanced(mod, strat);
1791 }
1792 return (try ty.abiSizeAdvanced(mod, strat_lazy)).scalar * 8;
1793 },
1794
1795 .anon_struct_type => {
1796 if (strat == .sema) try ty.resolveFields(mod);
1797 return (try ty.abiSizeAdvanced(mod, strat_lazy)).scalar * 8;
1798 },
1799
1800 .union_type => {
1801 const union_type = ip.loadUnionType(ty.toIntern());
1802 const is_packed = ty.containerLayout(mod) == .@"packed";
1803 if (strat == .sema) {
1804 try ty.resolveFields(mod);
1805 if (is_packed) try ty.resolveLayout(mod);
1806 }
1807 if (!is_packed) {
1808 return (try ty.abiSizeAdvanced(mod, strat_lazy)).scalar * 8;
1809 }
1810 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1811
1812 var size: u64 = 0;
1813 for (0..union_type.field_types.len) |field_index| {
1814 const field_ty = union_type.field_types.get(ip)[field_index];
1815 size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, strat));
1816 }
1817
1818 return size;
1819 },
1820 .opaque_type => unreachable,
1821 .enum_type => return bitSizeAdvanced(Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), mod, strat),
1822
1823 // values, not types
1824 .undef,
1825 .simple_value,
1826 .variable,
1827 .extern_func,
1828 .func,
1829 .int,
1830 .err,
1831 .error_union,
1832 .enum_literal,
1833 .enum_tag,
1834 .empty_enum_value,
1835 .float,
1836 .ptr,
1837 .slice,
1838 .opt,
1839 .aggregate,
1840 .un,
1841 // memoization, not types
1842 .memoized_call,
1843 => unreachable,
1844 }
1845}
1846
1847/// Returns true if the type's layout is already resolved and it is safe
1848/// to use `abiSize`, `abiAlignment` and `bitSize` on it.
1849pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
1850 const ip = &mod.intern_pool;
1851 return switch (ip.indexToKey(ty.toIntern())) {
1852 .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
1853 .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
1854 .array_type => |array_type| {
1855 if (array_type.lenIncludingSentinel() == 0) return true;
1856 return Type.fromInterned(array_type.child).layoutIsResolved(mod);
1857 },
1858 .opt_type => |child| Type.fromInterned(child).layoutIsResolved(mod),
1859 .error_union_type => |k| Type.fromInterned(k.payload_type).layoutIsResolved(mod),
1860 else => true,
1861 };
1862}
1863
1864pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1865 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1866 .ptr_type => |ptr_info| ptr_info.flags.size == .One,
1867 else => false,
1868 };
1869}
1870
1871/// Asserts `ty` is a pointer.
1872pub fn ptrSize(ty: Type, mod: *const Module) std.builtin.Type.Pointer.Size {
1873 return ptrSizeOrNull(ty, mod).?;
1874}
1875
1876/// Returns `null` if `ty` is not a pointer.
1877pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1878 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1879 .ptr_type => |ptr_info| ptr_info.flags.size,
1880 else => null,
1881 };
1882}
1883
1884pub fn isSlice(ty: Type, mod: *const Module) bool {
1885 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1886 .ptr_type => |ptr_type| ptr_type.flags.size == .Slice,
1887 else => false,
1888 };
1889}
1890
1891pub fn slicePtrFieldType(ty: Type, mod: *const Module) Type {
1892 return Type.fromInterned(mod.intern_pool.slicePtrType(ty.toIntern()));
1893}
1894
1895pub fn isConstPtr(ty: Type, mod: *const Module) bool {
1896 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1897 .ptr_type => |ptr_type| ptr_type.flags.is_const,
1898 else => false,
1899 };
1900}
1901
1902pub fn isVolatilePtr(ty: Type, mod: *const Module) bool {
1903 return isVolatilePtrIp(ty, &mod.intern_pool);
1904}
1905
1906pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
1907 return switch (ip.indexToKey(ty.toIntern())) {
1908 .ptr_type => |ptr_type| ptr_type.flags.is_volatile,
1909 else => false,
1910 };
1911}
1912
1913pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
1914 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1915 .ptr_type => |ptr_type| ptr_type.flags.is_allowzero,
1916 .opt_type => true,
1917 else => false,
1918 };
1919}
1920
1921pub fn isCPtr(ty: Type, mod: *const Module) bool {
1922 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1923 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1924 else => false,
1925 };
1926}
1927
1928pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
1929 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1930 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1931 .Slice => false,
1932 .One, .Many, .C => true,
1933 },
1934 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1935 .ptr_type => |p| switch (p.flags.size) {
1936 .Slice, .C => false,
1937 .Many, .One => !p.flags.is_allowzero,
1938 },
1939 else => false,
1940 },
1941 else => false,
1942 };
1943}
1944
1945/// For pointer-like optionals, returns true, otherwise returns the allowzero property
1946/// of pointers.
1947pub fn ptrAllowsZero(ty: Type, mod: *const Module) bool {
1948 if (ty.isPtrLikeOptional(mod)) {
1949 return true;
1950 }
1951 return ty.ptrInfo(mod).flags.is_allowzero;
1952}
1953
1954/// See also `isPtrLikeOptional`.
1955pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
1956 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1957 .opt_type => |child_type| child_type == .anyerror_type or switch (mod.intern_pool.indexToKey(child_type)) {
1958 .ptr_type => |ptr_type| ptr_type.flags.size != .C and !ptr_type.flags.is_allowzero,
1959 .error_set_type, .inferred_error_set_type => true,
1960 else => false,
1961 },
1962 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1963 else => false,
1964 };
1965}
1966
1967/// Returns true if the type is optional and would be lowered to a single pointer
1968/// address value, using 0 for null. Note that this returns true for C pointers.
1969/// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
1970pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
1971 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1972 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1973 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1974 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1975 .Slice, .C => false,
1976 .Many, .One => !ptr_type.flags.is_allowzero,
1977 },
1978 else => false,
1979 },
1980 else => false,
1981 };
1982}
1983
1984/// For *[N]T, returns [N]T.
1985/// For *T, returns T.
1986/// For [*]T, returns T.
1987pub fn childType(ty: Type, mod: *const Module) Type {
1988 return childTypeIp(ty, &mod.intern_pool);
1989}
1990
1991pub fn childTypeIp(ty: Type, ip: *const InternPool) Type {
1992 return Type.fromInterned(ip.childType(ty.toIntern()));
1993}
1994
1995/// For *[N]T, returns T.
1996/// For ?*T, returns T.
1997/// For ?*[N]T, returns T.
1998/// For ?[*]T, returns T.
1999/// For *T, returns T.
2000/// For [*]T, returns T.
2001/// For [N]T, returns T.
2002/// For []T, returns T.
2003/// For anyframe->T, returns T.
2004pub fn elemType2(ty: Type, mod: *const Module) Type {
2005 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2006 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
2007 .One => Type.fromInterned(ptr_type.child).shallowElemType(mod),
2008 .Many, .C, .Slice => Type.fromInterned(ptr_type.child),
2009 },
2010 .anyframe_type => |child| {
2011 assert(child != .none);
2012 return Type.fromInterned(child);
2013 },
2014 .vector_type => |vector_type| Type.fromInterned(vector_type.child),
2015 .array_type => |array_type| Type.fromInterned(array_type.child),
2016 .opt_type => |child| Type.fromInterned(mod.intern_pool.childType(child)),
2017 else => unreachable,
2018 };
2019}
2020
2021fn shallowElemType(child_ty: Type, mod: *const Module) Type {
2022 return switch (child_ty.zigTypeTag(mod)) {
2023 .Array, .Vector => child_ty.childType(mod),
2024 else => child_ty,
2025 };
2026}
2027
2028/// For vectors, returns the element type. Otherwise returns self.
2029pub fn scalarType(ty: Type, mod: *Module) Type {
2030 return switch (ty.zigTypeTag(mod)) {
2031 .Vector => ty.childType(mod),
2032 else => ty,
2033 };
2034}
2035
2036/// Asserts that the type is an optional.
2037/// Note that for C pointers this returns the type unmodified.
2038pub fn optionalChild(ty: Type, mod: *const Module) Type {
2039 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2040 .opt_type => |child| Type.fromInterned(child),
2041 .ptr_type => |ptr_type| b: {
2042 assert(ptr_type.flags.size == .C);
2043 break :b ty;
2044 },
2045 else => unreachable,
2046 };
2047}
2048
2049/// Returns the tag type of a union, if the type is a union and it has a tag type.
2050/// Otherwise, returns `null`.
2051pub fn unionTagType(ty: Type, mod: *Module) ?Type {
2052 const ip = &mod.intern_pool;
2053 switch (ip.indexToKey(ty.toIntern())) {
2054 .union_type => {},
2055 else => return null,
2056 }
2057 const union_type = ip.loadUnionType(ty.toIntern());
2058 switch (union_type.flagsPtr(ip).runtime_tag) {
2059 .tagged => {
2060 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
2061 return Type.fromInterned(union_type.enum_tag_ty);
2062 },
2063 else => return null,
2064 }
2065}
2066
2067/// Same as `unionTagType` but includes safety tag.
2068/// Codegen should use this version.
2069pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
2070 const ip = &mod.intern_pool;
2071 return switch (ip.indexToKey(ty.toIntern())) {
2072 .union_type => {
2073 const union_type = ip.loadUnionType(ty.toIntern());
2074 if (!union_type.hasTag(ip)) return null;
2075 assert(union_type.haveFieldTypes(ip));
2076 return Type.fromInterned(union_type.enum_tag_ty);
2077 },
2078 else => null,
2079 };
2080}
2081
2082/// Asserts the type is a union; returns the tag type, even if the tag will
2083/// not be stored at runtime.
2084pub fn unionTagTypeHypothetical(ty: Type, mod: *Module) Type {
2085 const union_obj = mod.typeToUnion(ty).?;
2086 return Type.fromInterned(union_obj.enum_tag_ty);
2087}
2088
2089pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) ?Type {
2090 const ip = &mod.intern_pool;
2091 const union_obj = mod.typeToUnion(ty).?;
2092 const union_fields = union_obj.field_types.get(ip);
2093 const index = mod.unionTagFieldIndex(union_obj, enum_tag) orelse return null;
2094 return Type.fromInterned(union_fields[index]);
2095}
2096
2097pub fn unionFieldTypeByIndex(ty: Type, index: usize, mod: *Module) Type {
2098 const ip = &mod.intern_pool;
2099 const union_obj = mod.typeToUnion(ty).?;
2100 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
2101}
2102
2103pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
2104 const union_obj = mod.typeToUnion(ty).?;
2105 return mod.unionTagFieldIndex(union_obj, enum_tag);
2106}
2107
2108pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool {
2109 const ip = &mod.intern_pool;
2110 const union_obj = mod.typeToUnion(ty).?;
2111 for (union_obj.field_types.get(ip)) |field_ty| {
2112 if (Type.fromInterned(field_ty).hasRuntimeBits(mod)) return false;
2113 }
2114 return true;
2115}
2116
2117/// Returns the type used for backing storage of this union during comptime operations.
2118/// Asserts the type is either an extern or packed union.
2119pub fn unionBackingType(ty: Type, mod: *Module) !Type {
2120 return switch (ty.containerLayout(mod)) {
2121 .@"extern" => try mod.arrayType(.{ .len = ty.abiSize(mod), .child = .u8_type }),
2122 .@"packed" => try mod.intType(.unsigned, @intCast(ty.bitSize(mod))),
2123 .auto => unreachable,
2124 };
2125}
2126
2127pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {
2128 const ip = &mod.intern_pool;
2129 const union_obj = ip.loadUnionType(ty.toIntern());
2130 return mod.getUnionLayout(union_obj);
2131}
2132
2133pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
2134 const ip = &mod.intern_pool;
2135 return switch (ip.indexToKey(ty.toIntern())) {
2136 .struct_type => ip.loadStructType(ty.toIntern()).layout,
2137 .anon_struct_type => .auto,
2138 .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout,
2139 else => unreachable,
2140 };
2141}
2142
2143/// Asserts that the type is an error union.
2144pub fn errorUnionPayload(ty: Type, mod: *Module) Type {
2145 return Type.fromInterned(mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.payload_type);
2146}
2147
2148/// Asserts that the type is an error union.
2149pub fn errorUnionSet(ty: Type, mod: *Module) Type {
2150 return Type.fromInterned(mod.intern_pool.errorUnionSet(ty.toIntern()));
2151}
2152
2153/// Returns false for unresolved inferred error sets.
2154pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
2155 const ip = &mod.intern_pool;
2156 return switch (ty.toIntern()) {
2157 .anyerror_type, .adhoc_inferred_error_set_type => false,
2158 else => switch (ip.indexToKey(ty.toIntern())) {
2159 .error_set_type => |error_set_type| error_set_type.names.len == 0,
2160 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2161 .none, .anyerror_type => false,
2162 else => |t| ip.indexToKey(t).error_set_type.names.len == 0,
2163 },
2164 else => unreachable,
2165 },
2166 };
2167}
2168
2169/// Returns true if it is an error set that includes anyerror, false otherwise.
2170/// Note that the result may be a false negative if the type did not get error set
2171/// resolution prior to this call.
2172pub fn isAnyError(ty: Type, mod: *Module) bool {
2173 const ip = &mod.intern_pool;
2174 return switch (ty.toIntern()) {
2175 .anyerror_type => true,
2176 .adhoc_inferred_error_set_type => false,
2177 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2178 .inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type,
2179 else => false,
2180 },
2181 };
2182}
2183
2184pub fn isError(ty: Type, mod: *const Module) bool {
2185 return switch (ty.zigTypeTag(mod)) {
2186 .ErrorUnion, .ErrorSet => true,
2187 else => false,
2188 };
2189}
2190
2191/// Returns whether ty, which must be an error set, includes an error `name`.
2192/// Might return a false negative if `ty` is an inferred error set and not fully
2193/// resolved yet.
2194pub fn errorSetHasFieldIp(
2195 ip: *const InternPool,
2196 ty: InternPool.Index,
2197 name: InternPool.NullTerminatedString,
2198) bool {
2199 return switch (ty) {
2200 .anyerror_type => true,
2201 else => switch (ip.indexToKey(ty)) {
2202 .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null,
2203 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2204 .anyerror_type => true,
2205 .none => false,
2206 else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null,
2207 },
2208 else => unreachable,
2209 },
2210 };
2211}
2212
2213/// Returns whether ty, which must be an error set, includes an error `name`.
2214/// Might return a false negative if `ty` is an inferred error set and not fully
2215/// resolved yet.
2216pub fn errorSetHasField(ty: Type, name: []const u8, mod: *Module) bool {
2217 const ip = &mod.intern_pool;
2218 return switch (ty.toIntern()) {
2219 .anyerror_type => true,
2220 else => switch (ip.indexToKey(ty.toIntern())) {
2221 .error_set_type => |error_set_type| {
2222 // If the string is not interned, then the field certainly is not present.
2223 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2224 return error_set_type.nameIndex(ip, field_name_interned) != null;
2225 },
2226 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2227 .anyerror_type => true,
2228 .none => false,
2229 else => |t| {
2230 // If the string is not interned, then the field certainly is not present.
2231 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2232 return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null;
2233 },
2234 },
2235 else => unreachable,
2236 },
2237 };
2238}
2239
2240/// Asserts the type is an array or vector or struct.
2241pub fn arrayLen(ty: Type, mod: *const Module) u64 {
2242 return ty.arrayLenIp(&mod.intern_pool);
2243}
2244
2245pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
2246 return ip.aggregateTypeLen(ty.toIntern());
2247}
2248
2249pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
2250 return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern());
2251}
2252
2253pub fn vectorLen(ty: Type, mod: *const Module) u32 {
2254 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2255 .vector_type => |vector_type| vector_type.len,
2256 .anon_struct_type => |tuple| @intCast(tuple.types.len),
2257 else => unreachable,
2258 };
2259}
2260
2261/// Asserts the type is an array, pointer or vector.
2262pub fn sentinel(ty: Type, mod: *const Module) ?Value {
2263 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2264 .vector_type,
2265 .struct_type,
2266 .anon_struct_type,
2267 => null,
2268
2269 .array_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,
2270 .ptr_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,
2271
2272 else => unreachable,
2273 };
2274}
2275
2276/// Returns true if and only if the type is a fixed-width integer.
2277pub fn isInt(self: Type, mod: *const Module) bool {
2278 return self.toIntern() != .comptime_int_type and
2279 mod.intern_pool.isIntegerType(self.toIntern());
2280}
2281
2282/// Returns true if and only if the type is a fixed-width, signed integer.
2283pub fn isSignedInt(ty: Type, mod: *const Module) bool {
2284 return switch (ty.toIntern()) {
2285 .c_char_type => mod.getTarget().charSignedness() == .signed,
2286 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
2287 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2288 .int_type => |int_type| int_type.signedness == .signed,
2289 else => false,
2290 },
2291 };
2292}
2293
2294/// Returns true if and only if the type is a fixed-width, unsigned integer.
2295pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
2296 return switch (ty.toIntern()) {
2297 .c_char_type => mod.getTarget().charSignedness() == .unsigned,
2298 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
2299 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2300 .int_type => |int_type| int_type.signedness == .unsigned,
2301 else => false,
2302 },
2303 };
2304}
2305
2306/// Returns true for integers, enums, error sets, and packed structs.
2307/// If this function returns true, then intInfo() can be called on the type.
2308pub fn isAbiInt(ty: Type, mod: *Module) bool {
2309 return switch (ty.zigTypeTag(mod)) {
2310 .Int, .Enum, .ErrorSet => true,
2311 .Struct => ty.containerLayout(mod) == .@"packed",
2312 else => false,
2313 };
2314}
2315
2316/// Asserts the type is an integer, enum, error set, or vector of one of them.
2317pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType {
2318 const ip = &mod.intern_pool;
2319 const target = mod.getTarget();
2320 var ty = starting_ty;
2321
2322 while (true) switch (ty.toIntern()) {
2323 .anyerror_type, .adhoc_inferred_error_set_type => {
2324 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2325 },
2326 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
2327 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
2328 .c_char_type => return .{ .signedness = mod.getTarget().charSignedness(), .bits = target.c_type_bit_size(.char) },
2329 .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
2330 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
2331 .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
2332 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
2333 .c_long_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
2334 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
2335 .c_longlong_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
2336 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
2337 else => switch (ip.indexToKey(ty.toIntern())) {
2338 .int_type => |int_type| return int_type,
2339 .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*),
2340 .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
2341 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
2342
2343 .error_set_type, .inferred_error_set_type => {
2344 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2345 },
2346
2347 .anon_struct_type => unreachable,
2348
2349 .ptr_type => unreachable,
2350 .anyframe_type => unreachable,
2351 .array_type => unreachable,
2352
2353 .opt_type => unreachable,
2354 .error_union_type => unreachable,
2355 .func_type => unreachable,
2356 .simple_type => unreachable, // handled via Index enum tag above
2357
2358 .union_type => unreachable,
2359 .opaque_type => unreachable,
2360
2361 // values, not types
2362 .undef,
2363 .simple_value,
2364 .variable,
2365 .extern_func,
2366 .func,
2367 .int,
2368 .err,
2369 .error_union,
2370 .enum_literal,
2371 .enum_tag,
2372 .empty_enum_value,
2373 .float,
2374 .ptr,
2375 .slice,
2376 .opt,
2377 .aggregate,
2378 .un,
2379 // memoization, not types
2380 .memoized_call,
2381 => unreachable,
2382 },
2383 };
2384}
2385
2386pub fn isNamedInt(ty: Type) bool {
2387 return switch (ty.toIntern()) {
2388 .usize_type,
2389 .isize_type,
2390 .c_char_type,
2391 .c_short_type,
2392 .c_ushort_type,
2393 .c_int_type,
2394 .c_uint_type,
2395 .c_long_type,
2396 .c_ulong_type,
2397 .c_longlong_type,
2398 .c_ulonglong_type,
2399 => true,
2400
2401 else => false,
2402 };
2403}
2404
2405/// Returns `false` for `comptime_float`.
2406pub fn isRuntimeFloat(ty: Type) bool {
2407 return switch (ty.toIntern()) {
2408 .f16_type,
2409 .f32_type,
2410 .f64_type,
2411 .f80_type,
2412 .f128_type,
2413 .c_longdouble_type,
2414 => true,
2415
2416 else => false,
2417 };
2418}
2419
2420/// Returns `true` for `comptime_float`.
2421pub fn isAnyFloat(ty: Type) bool {
2422 return switch (ty.toIntern()) {
2423 .f16_type,
2424 .f32_type,
2425 .f64_type,
2426 .f80_type,
2427 .f128_type,
2428 .c_longdouble_type,
2429 .comptime_float_type,
2430 => true,
2431
2432 else => false,
2433 };
2434}
2435
2436/// Asserts the type is a fixed-size float or comptime_float.
2437/// Returns 128 for comptime_float types.
2438pub fn floatBits(ty: Type, target: Target) u16 {
2439 return switch (ty.toIntern()) {
2440 .f16_type => 16,
2441 .f32_type => 32,
2442 .f64_type => 64,
2443 .f80_type => 80,
2444 .f128_type, .comptime_float_type => 128,
2445 .c_longdouble_type => target.c_type_bit_size(.longdouble),
2446
2447 else => unreachable,
2448 };
2449}
2450
2451/// Asserts the type is a function or a function pointer.
2452pub fn fnReturnType(ty: Type, mod: *Module) Type {
2453 return Type.fromInterned(mod.intern_pool.funcTypeReturnType(ty.toIntern()));
2454}
2455
2456/// Asserts the type is a function.
2457pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
2458 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.cc;
2459}
2460
2461pub fn isValidParamType(self: Type, mod: *const Module) bool {
2462 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
2463 .Opaque, .NoReturn => false,
2464 else => true,
2465 };
2466}
2467
2468pub fn isValidReturnType(self: Type, mod: *const Module) bool {
2469 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
2470 .Opaque => false,
2471 else => true,
2472 };
2473}
2474
2475/// Asserts the type is a function.
2476pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
2477 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.is_var_args;
2478}
2479
2480pub fn isNumeric(ty: Type, mod: *const Module) bool {
2481 return switch (ty.toIntern()) {
2482 .f16_type,
2483 .f32_type,
2484 .f64_type,
2485 .f80_type,
2486 .f128_type,
2487 .c_longdouble_type,
2488 .comptime_int_type,
2489 .comptime_float_type,
2490 .usize_type,
2491 .isize_type,
2492 .c_char_type,
2493 .c_short_type,
2494 .c_ushort_type,
2495 .c_int_type,
2496 .c_uint_type,
2497 .c_long_type,
2498 .c_ulong_type,
2499 .c_longlong_type,
2500 .c_ulonglong_type,
2501 => true,
2502
2503 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2504 .int_type => true,
2505 else => false,
2506 },
2507 };
2508}
2509
2510/// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
2511/// resolves field types rather than asserting they are already resolved.
2512pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
2513 var ty = starting_type;
2514 const ip = &mod.intern_pool;
2515 while (true) switch (ty.toIntern()) {
2516 .empty_struct_type => return Value.empty_struct,
2517
2518 else => switch (ip.indexToKey(ty.toIntern())) {
2519 .int_type => |int_type| {
2520 if (int_type.bits == 0) {
2521 return try mod.intValue(ty, 0);
2522 } else {
2523 return null;
2524 }
2525 },
2526
2527 .ptr_type,
2528 .error_union_type,
2529 .func_type,
2530 .anyframe_type,
2531 .error_set_type,
2532 .inferred_error_set_type,
2533 => return null,
2534
2535 inline .array_type, .vector_type => |seq_type, seq_tag| {
2536 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
2537 if (seq_type.len + @intFromBool(has_sentinel) == 0) return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2538 .ty = ty.toIntern(),
2539 .storage = .{ .elems = &.{} },
2540 } })));
2541 if (try Type.fromInterned(seq_type.child).onePossibleValue(mod)) |opv| {
2542 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2543 .ty = ty.toIntern(),
2544 .storage = .{ .repeated_elem = opv.toIntern() },
2545 } })));
2546 }
2547 return null;
2548 },
2549 .opt_type => |child| {
2550 if (child == .noreturn_type) {
2551 return try mod.nullValue(ty);
2552 } else {
2553 return null;
2554 }
2555 },
2556
2557 .simple_type => |t| switch (t) {
2558 .f16,
2559 .f32,
2560 .f64,
2561 .f80,
2562 .f128,
2563 .usize,
2564 .isize,
2565 .c_char,
2566 .c_short,
2567 .c_ushort,
2568 .c_int,
2569 .c_uint,
2570 .c_long,
2571 .c_ulong,
2572 .c_longlong,
2573 .c_ulonglong,
2574 .c_longdouble,
2575 .anyopaque,
2576 .bool,
2577 .type,
2578 .anyerror,
2579 .comptime_int,
2580 .comptime_float,
2581 .enum_literal,
2582 .atomic_order,
2583 .atomic_rmw_op,
2584 .calling_convention,
2585 .address_space,
2586 .float_mode,
2587 .reduce_op,
2588 .call_modifier,
2589 .prefetch_options,
2590 .export_options,
2591 .extern_options,
2592 .type_info,
2593 .adhoc_inferred_error_set,
2594 => return null,
2595
2596 .void => return Value.void,
2597 .noreturn => return Value.@"unreachable",
2598 .null => return Value.null,
2599 .undefined => return Value.undef,
2600
2601 .generic_poison => unreachable,
2602 },
2603 .struct_type => {
2604 const struct_type = ip.loadStructType(ty.toIntern());
2605 assert(struct_type.haveFieldTypes(ip));
2606 if (struct_type.knownNonOpv(ip))
2607 return null;
2608 const field_vals = try mod.gpa.alloc(InternPool.Index, struct_type.field_types.len);
2609 defer mod.gpa.free(field_vals);
2610 for (field_vals, 0..) |*field_val, i_usize| {
2611 const i: u32 = @intCast(i_usize);
2612 if (struct_type.fieldIsComptime(ip, i)) {
2613 assert(struct_type.haveFieldInits(ip));
2614 field_val.* = struct_type.field_inits.get(ip)[i];
2615 continue;
2616 }
2617 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
2618 if (try field_ty.onePossibleValue(mod)) |field_opv| {
2619 field_val.* = field_opv.toIntern();
2620 } else return null;
2621 }
2622
2623 // In this case the struct has no runtime-known fields and
2624 // therefore has one possible value.
2625 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2626 .ty = ty.toIntern(),
2627 .storage = .{ .elems = field_vals },
2628 } })));
2629 },
2630
2631 .anon_struct_type => |tuple| {
2632 for (tuple.values.get(ip)) |val| {
2633 if (val == .none) return null;
2634 }
2635 // In this case the struct has all comptime-known fields and
2636 // therefore has one possible value.
2637 // TODO: write something like getCoercedInts to avoid needing to dupe
2638 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values.get(ip));
2639 defer mod.gpa.free(duped_values);
2640 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2641 .ty = ty.toIntern(),
2642 .storage = .{ .elems = duped_values },
2643 } })));
2644 },
2645
2646 .union_type => {
2647 const union_obj = ip.loadUnionType(ty.toIntern());
2648 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse
2649 return null;
2650 if (union_obj.field_types.len == 0) {
2651 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2652 return Value.fromInterned(only);
2653 }
2654 const only_field_ty = union_obj.field_types.get(ip)[0];
2655 const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(mod)) orelse
2656 return null;
2657 const only = try mod.intern(.{ .un = .{
2658 .ty = ty.toIntern(),
2659 .tag = tag_val.toIntern(),
2660 .val = val_val.toIntern(),
2661 } });
2662 return Value.fromInterned(only);
2663 },
2664 .opaque_type => return null,
2665 .enum_type => {
2666 const enum_type = ip.loadEnumType(ty.toIntern());
2667 switch (enum_type.tag_mode) {
2668 .nonexhaustive => {
2669 if (enum_type.tag_ty == .comptime_int_type) return null;
2670
2671 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
2672 const only = try mod.intern(.{ .enum_tag = .{
2673 .ty = ty.toIntern(),
2674 .int = int_opv.toIntern(),
2675 } });
2676 return Value.fromInterned(only);
2677 }
2678
2679 return null;
2680 },
2681 .auto, .explicit => {
2682 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
2683
2684 switch (enum_type.names.len) {
2685 0 => {
2686 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2687 return Value.fromInterned(only);
2688 },
2689 1 => {
2690 if (enum_type.values.len == 0) {
2691 const only = try mod.intern(.{ .enum_tag = .{
2692 .ty = ty.toIntern(),
2693 .int = try mod.intern(.{ .int = .{
2694 .ty = enum_type.tag_ty,
2695 .storage = .{ .u64 = 0 },
2696 } }),
2697 } });
2698 return Value.fromInterned(only);
2699 } else {
2700 return Value.fromInterned(enum_type.values.get(ip)[0]);
2701 }
2702 },
2703 else => return null,
2704 }
2705 },
2706 }
2707 },
2708
2709 // values, not types
2710 .undef,
2711 .simple_value,
2712 .variable,
2713 .extern_func,
2714 .func,
2715 .int,
2716 .err,
2717 .error_union,
2718 .enum_literal,
2719 .enum_tag,
2720 .empty_enum_value,
2721 .float,
2722 .ptr,
2723 .slice,
2724 .opt,
2725 .aggregate,
2726 .un,
2727 // memoization, not types
2728 .memoized_call,
2729 => unreachable,
2730 },
2731 };
2732}
2733
2734/// During semantic analysis, instead call `Sema.typeRequiresComptime` which
2735/// resolves field types rather than asserting they are already resolved.
2736pub fn comptimeOnly(ty: Type, mod: *Module) bool {
2737 return ty.comptimeOnlyAdvanced(mod, .normal) catch unreachable;
2738}
2739
2740/// `generic_poison` will return false.
2741/// May return false negatives when structs and unions are having their field types resolved.
2742pub fn comptimeOnlyAdvanced(ty: Type, mod: *Module, strat: ResolveStrat) SemaError!bool {
2743 const ip = &mod.intern_pool;
2744 return switch (ty.toIntern()) {
2745 .empty_struct_type => false,
2746
2747 else => switch (ip.indexToKey(ty.toIntern())) {
2748 .int_type => false,
2749 .ptr_type => |ptr_type| {
2750 const child_ty = Type.fromInterned(ptr_type.child);
2751 switch (child_ty.zigTypeTag(mod)) {
2752 .Fn => return !try child_ty.fnHasRuntimeBitsAdvanced(mod, strat),
2753 .Opaque => return false,
2754 else => return child_ty.comptimeOnlyAdvanced(mod, strat),
2755 }
2756 },
2757 .anyframe_type => |child| {
2758 if (child == .none) return false;
2759 return Type.fromInterned(child).comptimeOnlyAdvanced(mod, strat);
2760 },
2761 .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnlyAdvanced(mod, strat),
2762 .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnlyAdvanced(mod, strat),
2763 .opt_type => |child| return Type.fromInterned(child).comptimeOnlyAdvanced(mod, strat),
2764 .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnlyAdvanced(mod, strat),
2765
2766 .error_set_type,
2767 .inferred_error_set_type,
2768 => false,
2769
2770 // These are function bodies, not function pointers.
2771 .func_type => true,
2772
2773 .simple_type => |t| switch (t) {
2774 .f16,
2775 .f32,
2776 .f64,
2777 .f80,
2778 .f128,
2779 .usize,
2780 .isize,
2781 .c_char,
2782 .c_short,
2783 .c_ushort,
2784 .c_int,
2785 .c_uint,
2786 .c_long,
2787 .c_ulong,
2788 .c_longlong,
2789 .c_ulonglong,
2790 .c_longdouble,
2791 .anyopaque,
2792 .bool,
2793 .void,
2794 .anyerror,
2795 .adhoc_inferred_error_set,
2796 .noreturn,
2797 .generic_poison,
2798 .atomic_order,
2799 .atomic_rmw_op,
2800 .calling_convention,
2801 .address_space,
2802 .float_mode,
2803 .reduce_op,
2804 .call_modifier,
2805 .prefetch_options,
2806 .export_options,
2807 .extern_options,
2808 => false,
2809
2810 .type,
2811 .comptime_int,
2812 .comptime_float,
2813 .null,
2814 .undefined,
2815 .enum_literal,
2816 .type_info,
2817 => true,
2818 },
2819 .struct_type => {
2820 const struct_type = ip.loadStructType(ty.toIntern());
2821 // packed structs cannot be comptime-only because they have a well-defined
2822 // memory layout and every field has a well-defined bit pattern.
2823 if (struct_type.layout == .@"packed")
2824 return false;
2825
2826 // A struct with no fields is not comptime-only.
2827 return switch (struct_type.flagsPtr(ip).requires_comptime) {
2828 .no, .wip => false,
2829 .yes => true,
2830 .unknown => {
2831 assert(strat == .sema);
2832
2833 if (struct_type.flagsPtr(ip).field_types_wip)
2834 return false;
2835
2836 struct_type.flagsPtr(ip).requires_comptime = .wip;
2837 errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown;
2838
2839 try ty.resolveFields(mod);
2840
2841 for (0..struct_type.field_types.len) |i_usize| {
2842 const i: u32 = @intCast(i_usize);
2843 if (struct_type.fieldIsComptime(ip, i)) continue;
2844 const field_ty = struct_type.field_types.get(ip)[i];
2845 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, strat)) {
2846 // Note that this does not cause the layout to
2847 // be considered resolved. Comptime-only types
2848 // still maintain a layout of their
2849 // runtime-known fields.
2850 struct_type.flagsPtr(ip).requires_comptime = .yes;
2851 return true;
2852 }
2853 }
2854
2855 struct_type.flagsPtr(ip).requires_comptime = .no;
2856 return false;
2857 },
2858 };
2859 },
2860
2861 .anon_struct_type => |tuple| {
2862 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2863 const have_comptime_val = val != .none;
2864 if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, strat)) return true;
2865 }
2866 return false;
2867 },
2868
2869 .union_type => {
2870 const union_type = ip.loadUnionType(ty.toIntern());
2871 switch (union_type.flagsPtr(ip).requires_comptime) {
2872 .no, .wip => return false,
2873 .yes => return true,
2874 .unknown => {
2875 assert(strat == .sema);
2876
2877 if (union_type.flagsPtr(ip).status == .field_types_wip)
2878 return false;
2879
2880 union_type.flagsPtr(ip).requires_comptime = .wip;
2881 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
2882
2883 try ty.resolveFields(mod);
2884
2885 for (0..union_type.field_types.len) |field_idx| {
2886 const field_ty = union_type.field_types.get(ip)[field_idx];
2887 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, strat)) {
2888 union_type.flagsPtr(ip).requires_comptime = .yes;
2889 return true;
2890 }
2891 }
2892
2893 union_type.flagsPtr(ip).requires_comptime = .no;
2894 return false;
2895 },
2896 }
2897 },
2898
2899 .opaque_type => false,
2900
2901 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyAdvanced(mod, strat),
2902
2903 // values, not types
2904 .undef,
2905 .simple_value,
2906 .variable,
2907 .extern_func,
2908 .func,
2909 .int,
2910 .err,
2911 .error_union,
2912 .enum_literal,
2913 .enum_tag,
2914 .empty_enum_value,
2915 .float,
2916 .ptr,
2917 .slice,
2918 .opt,
2919 .aggregate,
2920 .un,
2921 // memoization, not types
2922 .memoized_call,
2923 => unreachable,
2924 },
2925 };
2926}
2927
2928pub fn isVector(ty: Type, mod: *const Module) bool {
2929 return ty.zigTypeTag(mod) == .Vector;
2930}
2931
2932/// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len.
2933pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 {
2934 if (!ty.isVector(zcu)) return 0;
2935 const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type;
2936 return v.len * Type.fromInterned(v.child).bitSize(zcu);
2937}
2938
2939pub fn isArrayOrVector(ty: Type, mod: *const Module) bool {
2940 return switch (ty.zigTypeTag(mod)) {
2941 .Array, .Vector => true,
2942 else => false,
2943 };
2944}
2945
2946pub fn isIndexable(ty: Type, mod: *Module) bool {
2947 return switch (ty.zigTypeTag(mod)) {
2948 .Array, .Vector => true,
2949 .Pointer => switch (ty.ptrSize(mod)) {
2950 .Slice, .Many, .C => true,
2951 .One => switch (ty.childType(mod).zigTypeTag(mod)) {
2952 .Array, .Vector => true,
2953 .Struct => ty.childType(mod).isTuple(mod),
2954 else => false,
2955 },
2956 },
2957 .Struct => ty.isTuple(mod),
2958 else => false,
2959 };
2960}
2961
2962pub fn indexableHasLen(ty: Type, mod: *Module) bool {
2963 return switch (ty.zigTypeTag(mod)) {
2964 .Array, .Vector => true,
2965 .Pointer => switch (ty.ptrSize(mod)) {
2966 .Many, .C => false,
2967 .Slice => true,
2968 .One => switch (ty.childType(mod).zigTypeTag(mod)) {
2969 .Array, .Vector => true,
2970 .Struct => ty.childType(mod).isTuple(mod),
2971 else => false,
2972 },
2973 },
2974 .Struct => ty.isTuple(mod),
2975 else => false,
2976 };
2977}
2978
2979/// Asserts that the type can have a namespace.
2980pub fn getNamespaceIndex(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex {
2981 return ty.getNamespace(zcu).?;
2982}
2983
2984/// Returns null if the type has no namespace.
2985pub fn getNamespace(ty: Type, zcu: *Zcu) ?InternPool.OptionalNamespaceIndex {
2986 const ip = &zcu.intern_pool;
2987 return switch (ip.indexToKey(ty.toIntern())) {
2988 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace,
2989 .struct_type => ip.loadStructType(ty.toIntern()).namespace,
2990 .union_type => ip.loadUnionType(ty.toIntern()).namespace,
2991 .enum_type => ip.loadEnumType(ty.toIntern()).namespace,
2992
2993 .anon_struct_type => .none,
2994 .simple_type => |s| switch (s) {
2995 .anyopaque,
2996 .atomic_order,
2997 .atomic_rmw_op,
2998 .calling_convention,
2999 .address_space,
3000 .float_mode,
3001 .reduce_op,
3002 .call_modifier,
3003 .prefetch_options,
3004 .export_options,
3005 .extern_options,
3006 .type_info,
3007 => .none,
3008 else => null,
3009 },
3010
3011 else => null,
3012 };
3013}
3014
3015// Works for vectors and vectors of integers.
3016pub fn minInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
3017 const scalar = try minIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
3018 return if (ty.zigTypeTag(mod) == .Vector) Value.fromInterned((try mod.intern(.{ .aggregate = .{
3019 .ty = dest_ty.toIntern(),
3020 .storage = .{ .repeated_elem = scalar.toIntern() },
3021 } }))) else scalar;
3022}
3023
3024/// Asserts that the type is an integer.
3025pub fn minIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
3026 const info = ty.intInfo(mod);
3027 if (info.signedness == .unsigned) return mod.intValue(dest_ty, 0);
3028 if (info.bits == 0) return mod.intValue(dest_ty, -1);
3029
3030 if (std.math.cast(u6, info.bits - 1)) |shift| {
3031 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
3032 return mod.intValue(dest_ty, n);
3033 }
3034
3035 var res = try std.math.big.int.Managed.init(mod.gpa);
3036 defer res.deinit();
3037
3038 try res.setTwosCompIntLimit(.min, info.signedness, info.bits);
3039
3040 return mod.intValue_big(dest_ty, res.toConst());
3041}
3042
3043// Works for vectors and vectors of integers.
3044/// The returned Value will have type dest_ty.
3045pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
3046 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
3047 return if (ty.zigTypeTag(mod) == .Vector) Value.fromInterned((try mod.intern(.{ .aggregate = .{
3048 .ty = dest_ty.toIntern(),
3049 .storage = .{ .repeated_elem = scalar.toIntern() },
3050 } }))) else scalar;
3051}
3052
3053/// The returned Value will have type dest_ty.
3054pub fn maxIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
3055 const info = ty.intInfo(mod);
3056
3057 switch (info.bits) {
3058 0 => return switch (info.signedness) {
3059 .signed => try mod.intValue(dest_ty, -1),
3060 .unsigned => try mod.intValue(dest_ty, 0),
3061 },
3062 1 => return switch (info.signedness) {
3063 .signed => try mod.intValue(dest_ty, 0),
3064 .unsigned => try mod.intValue(dest_ty, 1),
3065 },
3066 else => {},
3067 }
3068
3069 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
3070 .signed => {
3071 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);
3072 return mod.intValue(dest_ty, n);
3073 },
3074 .unsigned => {
3075 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);
3076 return mod.intValue(dest_ty, n);
3077 },
3078 };
3079
3080 var res = try std.math.big.int.Managed.init(mod.gpa);
3081 defer res.deinit();
3082
3083 try res.setTwosCompIntLimit(.max, info.signedness, info.bits);
3084
3085 return mod.intValue_big(dest_ty, res.toConst());
3086}
3087
3088/// Asserts the type is an enum or a union.
3089pub fn intTagType(ty: Type, mod: *Module) Type {
3090 const ip = &mod.intern_pool;
3091 return switch (ip.indexToKey(ty.toIntern())) {
3092 .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(mod),
3093 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
3094 else => unreachable,
3095 };
3096}
3097
3098pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
3099 const ip = &mod.intern_pool;
3100 return switch (ip.indexToKey(ty.toIntern())) {
3101 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
3102 .nonexhaustive => true,
3103 .auto, .explicit => false,
3104 },
3105 else => false,
3106 };
3107}
3108
3109// Asserts that `ty` is an error set and not `anyerror`.
3110// Asserts that `ty` is resolved if it is an inferred error set.
3111pub fn errorSetNames(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
3112 const ip = &mod.intern_pool;
3113 return switch (ip.indexToKey(ty.toIntern())) {
3114 .error_set_type => |x| x.names,
3115 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
3116 .none => unreachable, // unresolved inferred error set
3117 .anyerror_type => unreachable,
3118 else => |t| ip.indexToKey(t).error_set_type.names,
3119 },
3120 else => unreachable,
3121 };
3122}
3123
3124pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
3125 return mod.intern_pool.loadEnumType(ty.toIntern()).names;
3126}
3127
3128pub fn enumFieldCount(ty: Type, mod: *Module) usize {
3129 return mod.intern_pool.loadEnumType(ty.toIntern()).names.len;
3130}
3131
3132pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
3133 const ip = &mod.intern_pool;
3134 return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index];
3135}
3136
3137pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
3138 const ip = &mod.intern_pool;
3139 const enum_type = ip.loadEnumType(ty.toIntern());
3140 return enum_type.nameIndex(ip, field_name);
3141}
3142
3143/// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
3144/// an integer which represents the enum value. Returns the field index in
3145/// declaration order, or `null` if `enum_tag` does not match any field.
3146pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
3147 const ip = &mod.intern_pool;
3148 const enum_type = ip.loadEnumType(ty.toIntern());
3149 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
3150 .int => enum_tag.toIntern(),
3151 .enum_tag => |info| info.int,
3152 else => unreachable,
3153 };
3154 assert(ip.typeOf(int_tag) == enum_type.tag_ty);
3155 return enum_type.tagValueIndex(ip, int_tag);
3156}
3157
3158/// Returns none in the case of a tuple which uses the integer index as the field name.
3159pub fn structFieldName(ty: Type, index: usize, mod: *Module) InternPool.OptionalNullTerminatedString {
3160 const ip = &mod.intern_pool;
3161 return switch (ip.indexToKey(ty.toIntern())) {
3162 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index),
3163 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index),
3164 else => unreachable,
3165 };
3166}
3167
3168pub fn structFieldCount(ty: Type, mod: *Module) u32 {
3169 const ip = &mod.intern_pool;
3170 return switch (ip.indexToKey(ty.toIntern())) {
3171 .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,
3172 .anon_struct_type => |anon_struct| anon_struct.types.len,
3173 else => unreachable,
3174 };
3175}
3176
3177/// Supports structs and unions.
3178pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
3179 const ip = &mod.intern_pool;
3180 return switch (ip.indexToKey(ty.toIntern())) {
3181 .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
3182 .union_type => {
3183 const union_obj = ip.loadUnionType(ty.toIntern());
3184 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
3185 },
3186 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),
3187 else => unreachable,
3188 };
3189}
3190
3191pub fn structFieldAlign(ty: Type, index: usize, zcu: *Zcu) Alignment {
3192 return ty.structFieldAlignAdvanced(index, zcu, .normal) catch unreachable;
3193}
3194
3195pub fn structFieldAlignAdvanced(ty: Type, index: usize, zcu: *Zcu, strat: ResolveStrat) !Alignment {
3196 const ip = &zcu.intern_pool;
3197 switch (ip.indexToKey(ty.toIntern())) {
3198 .struct_type => {
3199 const struct_type = ip.loadStructType(ty.toIntern());
3200 assert(struct_type.layout != .@"packed");
3201 const explicit_align = struct_type.fieldAlign(ip, index);
3202 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
3203 return zcu.structFieldAlignmentAdvanced(explicit_align, field_ty, struct_type.layout, strat);
3204 },
3205 .anon_struct_type => |anon_struct| {
3206 return (try Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignmentAdvanced(zcu, strat.toLazy())).scalar;
3207 },
3208 .union_type => {
3209 const union_obj = ip.loadUnionType(ty.toIntern());
3210 return zcu.unionFieldNormalAlignmentAdvanced(union_obj, @intCast(index), strat);
3211 },
3212 else => unreachable,
3213 }
3214}
3215
3216pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
3217 const ip = &mod.intern_pool;
3218 switch (ip.indexToKey(ty.toIntern())) {
3219 .struct_type => {
3220 const struct_type = ip.loadStructType(ty.toIntern());
3221 const val = struct_type.fieldInit(ip, index);
3222 // TODO: avoid using `unreachable` to indicate this.
3223 if (val == .none) return Value.@"unreachable";
3224 return Value.fromInterned(val);
3225 },
3226 .anon_struct_type => |anon_struct| {
3227 const val = anon_struct.values.get(ip)[index];
3228 // TODO: avoid using `unreachable` to indicate this.
3229 if (val == .none) return Value.@"unreachable";
3230 return Value.fromInterned(val);
3231 },
3232 else => unreachable,
3233 }
3234}
3235
3236pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
3237 const ip = &mod.intern_pool;
3238 switch (ip.indexToKey(ty.toIntern())) {
3239 .struct_type => {
3240 const struct_type = ip.loadStructType(ty.toIntern());
3241 if (struct_type.fieldIsComptime(ip, index)) {
3242 assert(struct_type.haveFieldInits(ip));
3243 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
3244 } else {
3245 return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(mod);
3246 }
3247 },
3248 .anon_struct_type => |tuple| {
3249 const val = tuple.values.get(ip)[index];
3250 if (val == .none) {
3251 return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(mod);
3252 } else {
3253 return Value.fromInterned(val);
3254 }
3255 },
3256 else => unreachable,
3257 }
3258}
3259
3260pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
3261 const ip = &mod.intern_pool;
3262 return switch (ip.indexToKey(ty.toIntern())) {
3263 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
3264 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
3265 else => unreachable,
3266 };
3267}
3268
3269pub const FieldOffset = struct {
3270 field: usize,
3271 offset: u64,
3272};
3273
3274/// Supports structs and unions.
3275pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
3276 const ip = &mod.intern_pool;
3277 switch (ip.indexToKey(ty.toIntern())) {
3278 .struct_type => {
3279 const struct_type = ip.loadStructType(ty.toIntern());
3280 assert(struct_type.haveLayout(ip));
3281 assert(struct_type.layout != .@"packed");
3282 return struct_type.offsets.get(ip)[index];
3283 },
3284
3285 .anon_struct_type => |tuple| {
3286 var offset: u64 = 0;
3287 var big_align: Alignment = .none;
3288
3289 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
3290 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) {
3291 // comptime field
3292 if (i == index) return offset;
3293 continue;
3294 }
3295
3296 const field_align = Type.fromInterned(field_ty).abiAlignment(mod);
3297 big_align = big_align.max(field_align);
3298 offset = field_align.forward(offset);
3299 if (i == index) return offset;
3300 offset += Type.fromInterned(field_ty).abiSize(mod);
3301 }
3302 offset = big_align.max(.@"1").forward(offset);
3303 return offset;
3304 },
3305
3306 .union_type => {
3307 const union_type = ip.loadUnionType(ty.toIntern());
3308 if (!union_type.hasTag(ip))
3309 return 0;
3310 const layout = mod.getUnionLayout(union_type);
3311 if (layout.tag_align.compare(.gte, layout.payload_align)) {
3312 // {Tag, Payload}
3313 return layout.payload_align.forward(layout.tag_size);
3314 } else {
3315 // {Payload, Tag}
3316 return 0;
3317 }
3318 },
3319
3320 else => unreachable,
3321 }
3322}
3323
3324pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex {
3325 return ty.getOwnerDeclOrNull(mod) orelse unreachable;
3326}
3327
3328pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex {
3329 const ip = &mod.intern_pool;
3330 return switch (ip.indexToKey(ty.toIntern())) {
3331 .struct_type => ip.loadStructType(ty.toIntern()).decl.unwrap(),
3332 .union_type => ip.loadUnionType(ty.toIntern()).decl,
3333 .opaque_type => ip.loadOpaqueType(ty.toIntern()).decl,
3334 .enum_type => ip.loadEnumType(ty.toIntern()).decl,
3335 else => null,
3336 };
3337}
3338
3339pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Module.LazySrcLoc {
3340 const ip = &zcu.intern_pool;
3341 return .{
3342 .base_node_inst = switch (ip.indexToKey(ty.toIntern())) {
3343 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
3344 .declared => |d| d.zir_index,
3345 .reified => |r| r.zir_index,
3346 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3347 .empty_struct => return null,
3348 },
3349 else => return null,
3350 },
3351 .offset = Module.LazySrcLoc.Offset.nodeOffset(0),
3352 };
3353}
3354
3355pub fn srcLoc(ty: Type, zcu: *Zcu) Module.LazySrcLoc {
3356 return ty.srcLocOrNull(zcu).?;
3357}
3358
3359pub fn isGenericPoison(ty: Type) bool {
3360 return ty.toIntern() == .generic_poison_type;
3361}
3362
3363pub fn isTuple(ty: Type, mod: *Module) bool {
3364 const ip = &mod.intern_pool;
3365 return switch (ip.indexToKey(ty.toIntern())) {
3366 .struct_type => {
3367 const struct_type = ip.loadStructType(ty.toIntern());
3368 if (struct_type.layout == .@"packed") return false;
3369 if (struct_type.decl == .none) return false;
3370 return struct_type.flagsPtr(ip).is_tuple;
3371 },
3372 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
3373 else => false,
3374 };
3375}
3376
3377pub fn isAnonStruct(ty: Type, mod: *Module) bool {
3378 if (ty.toIntern() == .empty_struct_type) return true;
3379 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3380 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
3381 else => false,
3382 };
3383}
3384
3385pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3386 const ip = &mod.intern_pool;
3387 return switch (ip.indexToKey(ty.toIntern())) {
3388 .struct_type => {
3389 const struct_type = ip.loadStructType(ty.toIntern());
3390 if (struct_type.layout == .@"packed") return false;
3391 if (struct_type.decl == .none) return false;
3392 return struct_type.flagsPtr(ip).is_tuple;
3393 },
3394 .anon_struct_type => true,
3395 else => false,
3396 };
3397}
3398
3399pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
3400 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3401 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
3402 else => false,
3403 };
3404}
3405
3406pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3407 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3408 .anon_struct_type => true,
3409 else => false,
3410 };
3411}
3412
3413/// Traverses optional child types and error union payloads until the type
3414/// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
3415pub fn optEuBaseType(ty: Type, mod: *Module) Type {
3416 var cur = ty;
3417 while (true) switch (cur.zigTypeTag(mod)) {
3418 .Optional => cur = cur.optionalChild(mod),
3419 .ErrorUnion => cur = cur.errorUnionPayload(mod),
3420 else => return cur,
3421 };
3422}
3423
3424pub fn toUnsigned(ty: Type, mod: *Module) !Type {
3425 return switch (ty.zigTypeTag(mod)) {
3426 .Int => mod.intType(.unsigned, ty.intInfo(mod).bits),
3427 .Vector => try mod.vectorType(.{
3428 .len = ty.vectorLen(mod),
3429 .child = (try ty.childType(mod).toUnsigned(mod)).toIntern(),
3430 }),
3431 else => unreachable,
3432 };
3433}
3434
3435pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3436 const ip = &zcu.intern_pool;
3437 return switch (ip.indexToKey(ty.toIntern())) {
3438 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),
3439 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
3440 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
3441 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
3442 else => null,
3443 };
3444}
3445
3446pub fn typeDeclSrcLine(ty: Type, zcu: *const Zcu) ?u32 {
3447 const ip = &zcu.intern_pool;
3448 const tracked = switch (ip.indexToKey(ty.toIntern())) {
3449 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
3450 .declared => |d| d.zir_index,
3451 .reified => |r| r.zir_index,
3452 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3453 .empty_struct => return null,
3454 },
3455 else => return null,
3456 };
3457 const info = tracked.resolveFull(&zcu.intern_pool);
3458 const file = zcu.import_table.values()[zcu.path_digest_map.getIndex(info.path_digest).?];
3459 assert(file.zir_loaded);
3460 const zir = file.zir;
3461 const inst = zir.instructions.get(@intFromEnum(info.inst));
3462 assert(inst.tag == .extended);
3463 return switch (inst.data.extended.opcode) {
3464 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line,
3465 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3466 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3467 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
3468 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,
3469 else => unreachable,
3470 };
3471}
3472
3473/// Given a namespace type, returns its list of caotured values.
3474pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice {
3475 const ip = &zcu.intern_pool;
3476 return switch (ip.indexToKey(ty.toIntern())) {
3477 .struct_type => ip.loadStructType(ty.toIntern()).captures,
3478 .union_type => ip.loadUnionType(ty.toIntern()).captures,
3479 .enum_type => ip.loadEnumType(ty.toIntern()).captures,
3480 .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures,
3481 else => unreachable,
3482 };
3483}
3484
3485pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } {
3486 var cur_ty: Type = ty;
3487 var cur_len: u64 = 1;
3488 while (cur_ty.zigTypeTag(zcu) == .Array) {
3489 cur_len *= cur_ty.arrayLenIncludingSentinel(zcu);
3490 cur_ty = cur_ty.childType(zcu);
3491 }
3492 return .{ cur_ty, cur_len };
3493}
3494
3495pub fn packedStructFieldPtrInfo(struct_ty: Type, parent_ptr_ty: Type, field_idx: u32, zcu: *Zcu) union(enum) {
3496 /// The result is a bit-pointer with the same value and a new packed offset.
3497 bit_ptr: InternPool.Key.PtrType.PackedOffset,
3498 /// The result is a standard pointer.
3499 byte_ptr: struct {
3500 /// The byte offset of the field pointer from the parent pointer value.
3501 offset: u64,
3502 /// The alignment of the field pointer type.
3503 alignment: InternPool.Alignment,
3504 },
3505} {
3506 comptime assert(Type.packed_struct_layout_version == 2);
3507
3508 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
3509 const field_ty = struct_ty.structFieldType(field_idx, zcu);
3510
3511 var bit_offset: u16 = 0;
3512 var running_bits: u16 = 0;
3513 for (0..struct_ty.structFieldCount(zcu)) |i| {
3514 const f_ty = struct_ty.structFieldType(i, zcu);
3515 if (i == field_idx) {
3516 bit_offset = running_bits;
3517 }
3518 running_bits += @intCast(f_ty.bitSize(zcu));
3519 }
3520
3521 const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0)
3522 .{ parent_ptr_info.packed_offset.host_size, parent_ptr_info.packed_offset.bit_offset + bit_offset }
3523 else
3524 .{ (running_bits + 7) / 8, bit_offset };
3525
3526 // If the field happens to be byte-aligned, simplify the pointer type.
3527 // We can only do this if the pointee's bit size matches its ABI byte size,
3528 // so that loads and stores do not interfere with surrounding packed bits.
3529 //
3530 // TODO: we do not attempt this with big-endian targets yet because of nested
3531 // structs and floats. I need to double-check the desired behavior for big endian
3532 // targets before adding the necessary complications to this code. This will not
3533 // cause miscompilations; it only means the field pointer uses bit masking when it
3534 // might not be strictly necessary.
3535 if (res_bit_offset % 8 == 0 and field_ty.bitSize(zcu) == field_ty.abiSize(zcu) * 8 and zcu.getTarget().cpu.arch.endian() == .little) {
3536 const byte_offset = res_bit_offset / 8;
3537 const new_align = Alignment.fromLog2Units(@ctz(byte_offset | parent_ptr_ty.ptrAlignment(zcu).toByteUnits().?));
3538 return .{ .byte_ptr = .{
3539 .offset = byte_offset,
3540 .alignment = new_align,
3541 } };
3542 }
3543
3544 return .{ .bit_ptr = .{
3545 .host_size = res_host_size,
3546 .bit_offset = res_bit_offset,
3547 } };
3548}
3549
3550pub fn resolveLayout(ty: Type, zcu: *Zcu) SemaError!void {
3551 const ip = &zcu.intern_pool;
3552 switch (ip.indexToKey(ty.toIntern())) {
3553 .simple_type => |simple_type| return resolveSimpleType(simple_type, zcu),
3554 else => {},
3555 }
3556 switch (ty.zigTypeTag(zcu)) {
3557 .Struct => switch (ip.indexToKey(ty.toIntern())) {
3558 .anon_struct_type => |anon_struct_type| for (0..anon_struct_type.types.len) |i| {
3559 const field_ty = Type.fromInterned(anon_struct_type.types.get(ip)[i]);
3560 try field_ty.resolveLayout(zcu);
3561 },
3562 .struct_type => return ty.resolveStructInner(zcu, .layout),
3563 else => unreachable,
3564 },
3565 .Union => return ty.resolveUnionInner(zcu, .layout),
3566 .Array => {
3567 if (ty.arrayLenIncludingSentinel(zcu) == 0) return;
3568 const elem_ty = ty.childType(zcu);
3569 return elem_ty.resolveLayout(zcu);
3570 },
3571 .Optional => {
3572 const payload_ty = ty.optionalChild(zcu);
3573 return payload_ty.resolveLayout(zcu);
3574 },
3575 .ErrorUnion => {
3576 const payload_ty = ty.errorUnionPayload(zcu);
3577 return payload_ty.resolveLayout(zcu);
3578 },
3579 .Fn => {
3580 const info = zcu.typeToFunc(ty).?;
3581 if (info.is_generic) {
3582 // Resolving of generic function types is deferred to when
3583 // the function is instantiated.
3584 return;
3585 }
3586 for (0..info.param_types.len) |i| {
3587 const param_ty = info.param_types.get(ip)[i];
3588 try Type.fromInterned(param_ty).resolveLayout(zcu);
3589 }
3590 try Type.fromInterned(info.return_type).resolveLayout(zcu);
3591 },
3592 else => {},
3593 }
3594}
3595
3596pub fn resolveFields(ty: Type, zcu: *Zcu) SemaError!void {
3597 const ip = &zcu.intern_pool;
3598 const ty_ip = ty.toIntern();
3599
3600 switch (ty_ip) {
3601 .none => unreachable,
3602
3603 .u0_type,
3604 .i0_type,
3605 .u1_type,
3606 .u8_type,
3607 .i8_type,
3608 .u16_type,
3609 .i16_type,
3610 .u29_type,
3611 .u32_type,
3612 .i32_type,
3613 .u64_type,
3614 .i64_type,
3615 .u80_type,
3616 .u128_type,
3617 .i128_type,
3618 .usize_type,
3619 .isize_type,
3620 .c_char_type,
3621 .c_short_type,
3622 .c_ushort_type,
3623 .c_int_type,
3624 .c_uint_type,
3625 .c_long_type,
3626 .c_ulong_type,
3627 .c_longlong_type,
3628 .c_ulonglong_type,
3629 .c_longdouble_type,
3630 .f16_type,
3631 .f32_type,
3632 .f64_type,
3633 .f80_type,
3634 .f128_type,
3635 .anyopaque_type,
3636 .bool_type,
3637 .void_type,
3638 .type_type,
3639 .anyerror_type,
3640 .adhoc_inferred_error_set_type,
3641 .comptime_int_type,
3642 .comptime_float_type,
3643 .noreturn_type,
3644 .anyframe_type,
3645 .null_type,
3646 .undefined_type,
3647 .enum_literal_type,
3648 .manyptr_u8_type,
3649 .manyptr_const_u8_type,
3650 .manyptr_const_u8_sentinel_0_type,
3651 .single_const_pointer_to_comptime_int_type,
3652 .slice_const_u8_type,
3653 .slice_const_u8_sentinel_0_type,
3654 .optional_noreturn_type,
3655 .anyerror_void_error_union_type,
3656 .generic_poison_type,
3657 .empty_struct_type,
3658 => {},
3659
3660 .undef => unreachable,
3661 .zero => unreachable,
3662 .zero_usize => unreachable,
3663 .zero_u8 => unreachable,
3664 .one => unreachable,
3665 .one_usize => unreachable,
3666 .one_u8 => unreachable,
3667 .four_u8 => unreachable,
3668 .negative_one => unreachable,
3669 .calling_convention_c => unreachable,
3670 .calling_convention_inline => unreachable,
3671 .void_value => unreachable,
3672 .unreachable_value => unreachable,
3673 .null_value => unreachable,
3674 .bool_true => unreachable,
3675 .bool_false => unreachable,
3676 .empty_struct => unreachable,
3677 .generic_poison => unreachable,
3678
3679 else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {
3680 .type_struct,
3681 .type_struct_packed,
3682 .type_struct_packed_inits,
3683 => return ty.resolveStructInner(zcu, .fields),
3684
3685 .type_union => return ty.resolveUnionInner(zcu, .fields),
3686
3687 .simple_type => return resolveSimpleType(ip.indexToKey(ty_ip).simple_type, zcu),
3688
3689 else => {},
3690 },
3691 }
3692}
3693
3694pub fn resolveFully(ty: Type, zcu: *Zcu) SemaError!void {
3695 const ip = &zcu.intern_pool;
3696
3697 switch (ip.indexToKey(ty.toIntern())) {
3698 .simple_type => |simple_type| return resolveSimpleType(simple_type, zcu),
3699 else => {},
3700 }
3701
3702 switch (ty.zigTypeTag(zcu)) {
3703 .Type,
3704 .Void,
3705 .Bool,
3706 .NoReturn,
3707 .Int,
3708 .Float,
3709 .ComptimeFloat,
3710 .ComptimeInt,
3711 .Undefined,
3712 .Null,
3713 .ErrorSet,
3714 .Enum,
3715 .Opaque,
3716 .Frame,
3717 .AnyFrame,
3718 .Vector,
3719 .EnumLiteral,
3720 => {},
3721
3722 .Pointer => return ty.childType(zcu).resolveFully(zcu),
3723 .Array => return ty.childType(zcu).resolveFully(zcu),
3724 .Optional => return ty.optionalChild(zcu).resolveFully(zcu),
3725 .ErrorUnion => return ty.errorUnionPayload(zcu).resolveFully(zcu),
3726 .Fn => {
3727 const info = zcu.typeToFunc(ty).?;
3728 if (info.is_generic) return;
3729 for (0..info.param_types.len) |i| {
3730 const param_ty = info.param_types.get(ip)[i];
3731 try Type.fromInterned(param_ty).resolveFully(zcu);
3732 }
3733 try Type.fromInterned(info.return_type).resolveFully(zcu);
3734 },
3735
3736 .Struct => switch (ip.indexToKey(ty.toIntern())) {
3737 .anon_struct_type => |anon_struct_type| for (0..anon_struct_type.types.len) |i| {
3738 const field_ty = Type.fromInterned(anon_struct_type.types.get(ip)[i]);
3739 try field_ty.resolveFully(zcu);
3740 },
3741 .struct_type => return ty.resolveStructInner(zcu, .full),
3742 else => unreachable,
3743 },
3744 .Union => return ty.resolveUnionInner(zcu, .full),
3745 }
3746}
3747
3748pub fn resolveStructFieldInits(ty: Type, zcu: *Zcu) SemaError!void {
3749 // TODO: stop calling this for tuples!
3750 _ = zcu.typeToStruct(ty) orelse return;
3751 return ty.resolveStructInner(zcu, .inits);
3752}
3753
3754pub fn resolveStructAlignment(ty: Type, zcu: *Zcu) SemaError!void {
3755 return ty.resolveStructInner(zcu, .alignment);
3756}
3757
3758pub fn resolveUnionAlignment(ty: Type, zcu: *Zcu) SemaError!void {
3759 return ty.resolveUnionInner(zcu, .alignment);
3760}
3761
3762/// `ty` must be a struct.
3763fn resolveStructInner(
3764 ty: Type,
3765 zcu: *Zcu,
3766 resolution: enum { fields, inits, alignment, layout, full },
3767) SemaError!void {
3768 const gpa = zcu.gpa;
3769
3770 const struct_obj = zcu.typeToStruct(ty).?;
3771 const owner_decl_index = struct_obj.decl.unwrap() orelse return;
3772
3773 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3774 defer analysis_arena.deinit();
3775
3776 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);
3777 defer comptime_err_ret_trace.deinit();
3778
3779 var sema: Sema = .{
3780 .mod = zcu,
3781 .gpa = gpa,
3782 .arena = analysis_arena.allocator(),
3783 .code = undefined, // This ZIR will not be used.
3784 .owner_decl = zcu.declPtr(owner_decl_index),
3785 .owner_decl_index = owner_decl_index,
3786 .func_index = .none,
3787 .func_is_naked = false,
3788 .fn_ret_ty = Type.void,
3789 .fn_ret_ty_ies = null,
3790 .owner_func_index = .none,
3791 .comptime_err_ret_trace = &comptime_err_ret_trace,
3792 };
3793 defer sema.deinit();
3794
3795 switch (resolution) {
3796 .fields => return sema.resolveTypeFieldsStruct(ty.toIntern(), struct_obj),
3797 .inits => return sema.resolveStructFieldInits(ty),
3798 .alignment => return sema.resolveStructAlignment(ty.toIntern(), struct_obj),
3799 .layout => return sema.resolveStructLayout(ty),
3800 .full => return sema.resolveStructFully(ty),
3801 }
3802}
3803
3804/// `ty` must be a union.
3805fn resolveUnionInner(
3806 ty: Type,
3807 zcu: *Zcu,
3808 resolution: enum { fields, alignment, layout, full },
3809) SemaError!void {
3810 const gpa = zcu.gpa;
3811
3812 const union_obj = zcu.typeToUnion(ty).?;
3813 const owner_decl_index = union_obj.decl;
3814
3815 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3816 defer analysis_arena.deinit();
3817
3818 var comptime_err_ret_trace = std.ArrayList(Zcu.LazySrcLoc).init(gpa);
3819 defer comptime_err_ret_trace.deinit();
3820
3821 var sema: Sema = .{
3822 .mod = zcu,
3823 .gpa = gpa,
3824 .arena = analysis_arena.allocator(),
3825 .code = undefined, // This ZIR will not be used.
3826 .owner_decl = zcu.declPtr(owner_decl_index),
3827 .owner_decl_index = owner_decl_index,
3828 .func_index = .none,
3829 .func_is_naked = false,
3830 .fn_ret_ty = Type.void,
3831 .fn_ret_ty_ies = null,
3832 .owner_func_index = .none,
3833 .comptime_err_ret_trace = &comptime_err_ret_trace,
3834 };
3835 defer sema.deinit();
3836
3837 switch (resolution) {
3838 .fields => return sema.resolveTypeFieldsUnion(ty, union_obj),
3839 .alignment => return sema.resolveUnionAlignment(ty, union_obj),
3840 .layout => return sema.resolveUnionLayout(ty),
3841 .full => return sema.resolveUnionFully(ty),
3842 }
3843}
3844
3845/// Fully resolves a simple type. This is usually a nop, but for builtin types with
3846/// special InternPool indices (such as std.builtin.Type) it will analyze and fully
3847/// resolve the type.
3848fn resolveSimpleType(simple_type: InternPool.SimpleType, zcu: *Zcu) Allocator.Error!void {
3849 const builtin_type_name: []const u8 = switch (simple_type) {
3850 .atomic_order => "AtomicOrder",
3851 .atomic_rmw_op => "AtomicRmwOp",
3852 .calling_convention => "CallingConvention",
3853 .address_space => "AddressSpace",
3854 .float_mode => "FloatMode",
3855 .reduce_op => "ReduceOp",
3856 .call_modifier => "CallModifer",
3857 .prefetch_options => "PrefetchOptions",
3858 .export_options => "ExportOptions",
3859 .extern_options => "ExternOptions",
3860 .type_info => "Type",
3861 else => return,
3862 };
3863 // This will fully resolve the type.
3864 _ = try zcu.getBuiltinType(builtin_type_name);
3865}
3866
3867/// Returns the type of a pointer to an element.
3868/// Asserts that the type is a pointer, and that the element type is indexable.
3869/// If the element index is comptime-known, it must be passed in `offset`.
3870/// For *@Vector(n, T), return *align(a:b:h:v) T
3871/// For *[N]T, return *T
3872/// For [*]T, returns *T
3873/// For []T, returns *T
3874/// Handles const-ness and address spaces in particular.
3875/// This code is duplicated in `Sema.analyzePtrArithmetic`.
3876/// May perform type resolution and return a transitive `error.AnalysisFail`.
3877pub fn elemPtrType(ptr_ty: Type, offset: ?usize, zcu: *Zcu) !Type {
3878 const ptr_info = ptr_ty.ptrInfo(zcu);
3879 const elem_ty = ptr_ty.elemType2(zcu);
3880 const is_allowzero = ptr_info.flags.is_allowzero and (offset orelse 0) == 0;
3881 const parent_ty = ptr_ty.childType(zcu);
3882
3883 const VI = InternPool.Key.PtrType.VectorIndex;
3884
3885 const vector_info: struct {
3886 host_size: u16 = 0,
3887 alignment: Alignment = .none,
3888 vector_index: VI = .none,
3889 } = if (parent_ty.isVector(zcu) and ptr_info.flags.size == .One) blk: {
3890 const elem_bits = elem_ty.bitSize(zcu);
3891 if (elem_bits == 0) break :blk .{};
3892 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
3893 if (!is_packed) break :blk .{};
3894
3895 break :blk .{
3896 .host_size = @intCast(parent_ty.arrayLen(zcu)),
3897 .alignment = parent_ty.abiAlignment(zcu),
3898 .vector_index = if (offset) |some| @enumFromInt(some) else .runtime,
3899 };
3900 } else .{};
3901
3902 const alignment: Alignment = a: {
3903 // Calculate the new pointer alignment.
3904 if (ptr_info.flags.alignment == .none) {
3905 // In case of an ABI-aligned pointer, any pointer arithmetic
3906 // maintains the same ABI-alignedness.
3907 break :a vector_info.alignment;
3908 }
3909 // If the addend is not a comptime-known value we can still count on
3910 // it being a multiple of the type size.
3911 const elem_size = (try elem_ty.abiSizeAdvanced(zcu, .sema)).scalar;
3912 const addend = if (offset) |off| elem_size * off else elem_size;
3913
3914 // The resulting pointer is aligned to the lcd between the offset (an
3915 // arbitrary number) and the alignment factor (always a power of two,
3916 // non zero).
3917 const new_align: Alignment = @enumFromInt(@min(
3918 @ctz(addend),
3919 ptr_info.flags.alignment.toLog2Units(),
3920 ));
3921 assert(new_align != .none);
3922 break :a new_align;
3923 };
3924 return zcu.ptrTypeSema(.{
3925 .child = elem_ty.toIntern(),
3926 .flags = .{
3927 .alignment = alignment,
3928 .is_const = ptr_info.flags.is_const,
3929 .is_volatile = ptr_info.flags.is_volatile,
3930 .is_allowzero = is_allowzero,
3931 .address_space = ptr_info.flags.address_space,
3932 .vector_index = vector_info.vector_index,
3933 },
3934 .packed_offset = .{
3935 .host_size = vector_info.host_size,
3936 .bit_offset = 0,
3937 },
3938 });
3939}
3940
3941pub const @"u1": Type = .{ .ip_index = .u1_type };
3942pub const @"u8": Type = .{ .ip_index = .u8_type };
3943pub const @"u16": Type = .{ .ip_index = .u16_type };
3944pub const @"u29": Type = .{ .ip_index = .u29_type };
3945pub const @"u32": Type = .{ .ip_index = .u32_type };
3946pub const @"u64": Type = .{ .ip_index = .u64_type };
3947pub const @"u128": Type = .{ .ip_index = .u128_type };
3948
3949pub const @"i8": Type = .{ .ip_index = .i8_type };
3950pub const @"i16": Type = .{ .ip_index = .i16_type };
3951pub const @"i32": Type = .{ .ip_index = .i32_type };
3952pub const @"i64": Type = .{ .ip_index = .i64_type };
3953pub const @"i128": Type = .{ .ip_index = .i128_type };
3954
3955pub const @"f16": Type = .{ .ip_index = .f16_type };
3956pub const @"f32": Type = .{ .ip_index = .f32_type };
3957pub const @"f64": Type = .{ .ip_index = .f64_type };
3958pub const @"f80": Type = .{ .ip_index = .f80_type };
3959pub const @"f128": Type = .{ .ip_index = .f128_type };
3960
3961pub const @"bool": Type = .{ .ip_index = .bool_type };
3962pub const @"usize": Type = .{ .ip_index = .usize_type };
3963pub const @"isize": Type = .{ .ip_index = .isize_type };
3964pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type };
3965pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type };
3966pub const @"void": Type = .{ .ip_index = .void_type };
3967pub const @"type": Type = .{ .ip_index = .type_type };
3968pub const @"anyerror": Type = .{ .ip_index = .anyerror_type };
3969pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type };
3970pub const @"anyframe": Type = .{ .ip_index = .anyframe_type };
3971pub const @"null": Type = .{ .ip_index = .null_type };
3972pub const @"undefined": Type = .{ .ip_index = .undefined_type };
3973pub const @"noreturn": Type = .{ .ip_index = .noreturn_type };
3974
3975pub const @"c_char": Type = .{ .ip_index = .c_char_type };
3976pub const @"c_short": Type = .{ .ip_index = .c_short_type };
3977pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type };
3978pub const @"c_int": Type = .{ .ip_index = .c_int_type };
3979pub const @"c_uint": Type = .{ .ip_index = .c_uint_type };
3980pub const @"c_long": Type = .{ .ip_index = .c_long_type };
3981pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type };
3982pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
3983pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
3984pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
3985
3986pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
3987pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
3988pub const single_const_pointer_to_comptime_int: Type = .{
3989 .ip_index = .single_const_pointer_to_comptime_int_type,
3990};
3991pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
3992pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
3993
3994pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
3995
3996pub fn smallestUnsignedBits(max: u64) u16 {
3997 if (max == 0) return 0;
3998 const base = std.math.log2(max);
3999 const upper = (@as(u64, 1) << @as(u6, @intCast(base))) - 1;
4000 return @as(u16, @intCast(base + @intFromBool(upper < max)));
4001}
4002
4003/// This is only used for comptime asserts. Bump this number when you make a change
4004/// to packed struct layout to find out all the places in the codebase you need to edit!
4005pub const packed_struct_layout_version = 2;
4006
4007fn cTypeAlign(target: Target, c_type: Target.CType) Alignment {
4008 return Alignment.fromByteUnits(target.c_type_alignment(c_type));
4009}
src/Value.zig+199-109
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Type = @import("type.zig").Type;3const Type = @import("Type.zig");
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const BigIntConst = std.math.big.int.Const;5const BigIntConst = std.math.big.int.Const;
6const BigIntMutable = std.math.big.int.Mutable;6const BigIntMutable = std.math.big.int.Mutable;
...@@ -161,9 +161,11 @@ pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {...@@ -161,9 +161,11 @@ pub fn intFromEnum(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
161 };161 };
162}162}
163163
164pub const ResolveStrat = Type.ResolveStrat;
165
164/// Asserts the value is an integer.166/// Asserts the value is an integer.
165pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst {167pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst {
166 return val.toBigIntAdvanced(space, mod, null) catch unreachable;168 return val.toBigIntAdvanced(space, mod, .normal) catch unreachable;
167}169}
168170
169/// Asserts the value is an integer.171/// Asserts the value is an integer.
...@@ -171,7 +173,7 @@ pub fn toBigIntAdvanced(...@@ -171,7 +173,7 @@ pub fn toBigIntAdvanced(
171 val: Value,173 val: Value,
172 space: *BigIntSpace,174 space: *BigIntSpace,
173 mod: *Module,175 mod: *Module,
174 opt_sema: ?*Sema,176 strat: ResolveStrat,
175) Module.CompileError!BigIntConst {177) Module.CompileError!BigIntConst {
176 return switch (val.toIntern()) {178 return switch (val.toIntern()) {
177 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),179 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
...@@ -181,7 +183,7 @@ pub fn toBigIntAdvanced(...@@ -181,7 +183,7 @@ pub fn toBigIntAdvanced(
181 .int => |int| switch (int.storage) {183 .int => |int| switch (int.storage) {
182 .u64, .i64, .big_int => int.storage.toBigInt(space),184 .u64, .i64, .big_int => int.storage.toBigInt(space),
183 .lazy_align, .lazy_size => |ty| {185 .lazy_align, .lazy_size => |ty| {
184 if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty));186 if (strat == .sema) try Type.fromInterned(ty).resolveLayout(mod);
185 const x = switch (int.storage) {187 const x = switch (int.storage) {
186 else => unreachable,188 else => unreachable,
187 .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0,189 .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0,
...@@ -190,10 +192,10 @@ pub fn toBigIntAdvanced(...@@ -190,10 +192,10 @@ pub fn toBigIntAdvanced(
190 return BigIntMutable.init(&space.limbs, x).toConst();192 return BigIntMutable.init(&space.limbs, x).toConst();
191 },193 },
192 },194 },
193 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).toBigIntAdvanced(space, mod, opt_sema),195 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).toBigIntAdvanced(space, mod, strat),
194 .opt, .ptr => BigIntMutable.init(196 .opt, .ptr => BigIntMutable.init(
195 &space.limbs,197 &space.limbs,
196 (try val.getUnsignedIntAdvanced(mod, opt_sema)).?,198 (try val.getUnsignedIntAdvanced(mod, strat)).?,
197 ).toConst(),199 ).toConst(),
198 else => unreachable,200 else => unreachable,
199 },201 },
...@@ -228,12 +230,12 @@ pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {...@@ -228,12 +230,12 @@ pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {
228/// If the value fits in a u64, return it, otherwise null.230/// If the value fits in a u64, return it, otherwise null.
229/// Asserts not undefined.231/// Asserts not undefined.
230pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {232pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {
231 return getUnsignedIntAdvanced(val, mod, null) catch unreachable;233 return getUnsignedIntAdvanced(val, mod, .normal) catch unreachable;
232}234}
233235
234/// If the value fits in a u64, return it, otherwise null.236/// If the value fits in a u64, return it, otherwise null.
235/// Asserts not undefined.237/// Asserts not undefined.
236pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {238pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, strat: ResolveStrat) !?u64 {
237 return switch (val.toIntern()) {239 return switch (val.toIntern()) {
238 .undef => unreachable,240 .undef => unreachable,
239 .bool_false => 0,241 .bool_false => 0,
...@@ -244,28 +246,22 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64...@@ -244,28 +246,22 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64
244 .big_int => |big_int| big_int.to(u64) catch null,246 .big_int => |big_int| big_int.to(u64) catch null,
245 .u64 => |x| x,247 .u64 => |x| x,
246 .i64 => |x| std.math.cast(u64, x),248 .i64 => |x| std.math.cast(u64, x),
247 .lazy_align => |ty| if (opt_sema) |sema|249 .lazy_align => |ty| (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, strat.toLazy())).scalar.toByteUnits() orelse 0,
248 (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0250 .lazy_size => |ty| (try Type.fromInterned(ty).abiSizeAdvanced(mod, strat.toLazy())).scalar,
249 else
250 Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0,
251 .lazy_size => |ty| if (opt_sema) |sema|
252 (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar
253 else
254 Type.fromInterned(ty).abiSize(mod),
255 },251 },
256 .ptr => |ptr| switch (ptr.base_addr) {252 .ptr => |ptr| switch (ptr.base_addr) {
257 .int => ptr.byte_offset,253 .int => ptr.byte_offset,
258 .field => |field| {254 .field => |field| {
259 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;255 const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, strat)) orelse return null;
260 const struct_ty = Value.fromInterned(field.base).typeOf(mod).childType(mod);256 const struct_ty = Value.fromInterned(field.base).typeOf(mod).childType(mod);
261 if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);257 if (strat == .sema) try struct_ty.resolveLayout(mod);
262 return base_addr + struct_ty.structFieldOffset(@intCast(field.index), mod) + ptr.byte_offset;258 return base_addr + struct_ty.structFieldOffset(@intCast(field.index), mod) + ptr.byte_offset;
263 },259 },
264 else => null,260 else => null,
265 },261 },
266 .opt => |opt| switch (opt.val) {262 .opt => |opt| switch (opt.val) {
267 .none => 0,263 .none => 0,
268 else => |payload| Value.fromInterned(payload).getUnsignedIntAdvanced(mod, opt_sema),264 else => |payload| Value.fromInterned(payload).getUnsignedIntAdvanced(mod, strat),
269 },265 },
270 else => null,266 else => null,
271 },267 },
...@@ -273,13 +269,13 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64...@@ -273,13 +269,13 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64
273}269}
274270
275/// Asserts the value is an integer and it fits in a u64271/// Asserts the value is an integer and it fits in a u64
276pub fn toUnsignedInt(val: Value, mod: *Module) u64 {272pub fn toUnsignedInt(val: Value, zcu: *Zcu) u64 {
277 return getUnsignedInt(val, mod).?;273 return getUnsignedInt(val, zcu).?;
278}274}
279275
280/// Asserts the value is an integer and it fits in a u64276/// Asserts the value is an integer and it fits in a u64
281pub fn toUnsignedIntAdvanced(val: Value, sema: *Sema) !u64 {277pub fn toUnsignedIntSema(val: Value, zcu: *Zcu) !u64 {
282 return (try getUnsignedIntAdvanced(val, sema.mod, sema)).?;278 return (try getUnsignedIntAdvanced(val, zcu, .sema)).?;
283}279}
284280
285/// Asserts the value is an integer and it fits in a i64281/// Asserts the value is an integer and it fits in a i64
...@@ -1028,13 +1024,13 @@ pub fn floatHasFraction(self: Value, mod: *const Module) bool {...@@ -1028,13 +1024,13 @@ pub fn floatHasFraction(self: Value, mod: *const Module) bool {
1028}1024}
10291025
1030pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order {1026pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order {
1031 return orderAgainstZeroAdvanced(lhs, mod, null) catch unreachable;1027 return orderAgainstZeroAdvanced(lhs, mod, .normal) catch unreachable;
1032}1028}
10331029
1034pub fn orderAgainstZeroAdvanced(1030pub fn orderAgainstZeroAdvanced(
1035 lhs: Value,1031 lhs: Value,
1036 mod: *Module,1032 mod: *Module,
1037 opt_sema: ?*Sema,1033 strat: ResolveStrat,
1038) Module.CompileError!std.math.Order {1034) Module.CompileError!std.math.Order {
1039 return switch (lhs.toIntern()) {1035 return switch (lhs.toIntern()) {
1040 .bool_false => .eq,1036 .bool_false => .eq,
...@@ -1052,13 +1048,13 @@ pub fn orderAgainstZeroAdvanced(...@@ -1052,13 +1048,13 @@ pub fn orderAgainstZeroAdvanced(
1052 .lazy_size => |ty| return if (Type.fromInterned(ty).hasRuntimeBitsAdvanced(1048 .lazy_size => |ty| return if (Type.fromInterned(ty).hasRuntimeBitsAdvanced(
1053 mod,1049 mod,
1054 false,1050 false,
1055 if (opt_sema) |sema| .{ .sema = sema } else .eager,1051 strat.toLazy(),
1056 ) catch |err| switch (err) {1052 ) catch |err| switch (err) {
1057 error.NeedLazy => unreachable,1053 error.NeedLazy => unreachable,
1058 else => |e| return e,1054 else => |e| return e,
1059 }) .gt else .eq,1055 }) .gt else .eq,
1060 },1056 },
1061 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).orderAgainstZeroAdvanced(mod, opt_sema),1057 .enum_tag => |enum_tag| Value.fromInterned(enum_tag.int).orderAgainstZeroAdvanced(mod, strat),
1062 .float => |float| switch (float.storage) {1058 .float => |float| switch (float.storage) {
1063 inline else => |x| std.math.order(x, 0),1059 inline else => |x| std.math.order(x, 0),
1064 },1060 },
...@@ -1069,14 +1065,13 @@ pub fn orderAgainstZeroAdvanced(...@@ -1069,14 +1065,13 @@ pub fn orderAgainstZeroAdvanced(
10691065
1070/// Asserts the value is comparable.1066/// Asserts the value is comparable.
1071pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order {1067pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order {
1072 return orderAdvanced(lhs, rhs, mod, null) catch unreachable;1068 return orderAdvanced(lhs, rhs, mod, .normal) catch unreachable;
1073}1069}
10741070
1075/// Asserts the value is comparable.1071/// Asserts the value is comparable.
1076/// If opt_sema is null then this function asserts things are resolved and cannot fail.1072pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, strat: ResolveStrat) !std.math.Order {
1077pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !std.math.Order {1073 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, strat);
1078 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema);1074 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, strat);
1079 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema);
1080 switch (lhs_against_zero) {1075 switch (lhs_against_zero) {
1081 .lt => if (rhs_against_zero != .lt) return .lt,1076 .lt => if (rhs_against_zero != .lt) return .lt,
1082 .eq => return rhs_against_zero.invert(),1077 .eq => return rhs_against_zero.invert(),
...@@ -1096,15 +1091,15 @@ pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !st...@@ -1096,15 +1091,15 @@ pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !st
10961091
1097 var lhs_bigint_space: BigIntSpace = undefined;1092 var lhs_bigint_space: BigIntSpace = undefined;
1098 var rhs_bigint_space: BigIntSpace = undefined;1093 var rhs_bigint_space: BigIntSpace = undefined;
1099 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, mod, opt_sema);1094 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, mod, strat);
1100 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, mod, opt_sema);1095 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, mod, strat);
1101 return lhs_bigint.order(rhs_bigint);1096 return lhs_bigint.order(rhs_bigint);
1102}1097}
11031098
1104/// Asserts the value is comparable. Does not take a type parameter because it supports1099/// Asserts the value is comparable. Does not take a type parameter because it supports
1105/// comparisons between heterogeneous types.1100/// comparisons between heterogeneous types.
1106pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool {1101pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool {
1107 return compareHeteroAdvanced(lhs, op, rhs, mod, null) catch unreachable;1102 return compareHeteroAdvanced(lhs, op, rhs, mod, .normal) catch unreachable;
1108}1103}
11091104
1110pub fn compareHeteroAdvanced(1105pub fn compareHeteroAdvanced(
...@@ -1112,7 +1107,7 @@ pub fn compareHeteroAdvanced(...@@ -1112,7 +1107,7 @@ pub fn compareHeteroAdvanced(
1112 op: std.math.CompareOperator,1107 op: std.math.CompareOperator,
1113 rhs: Value,1108 rhs: Value,
1114 mod: *Module,1109 mod: *Module,
1115 opt_sema: ?*Sema,1110 strat: ResolveStrat,
1116) !bool {1111) !bool {
1117 if (lhs.pointerDecl(mod)) |lhs_decl| {1112 if (lhs.pointerDecl(mod)) |lhs_decl| {
1118 if (rhs.pointerDecl(mod)) |rhs_decl| {1113 if (rhs.pointerDecl(mod)) |rhs_decl| {
...@@ -1135,7 +1130,7 @@ pub fn compareHeteroAdvanced(...@@ -1135,7 +1130,7 @@ pub fn compareHeteroAdvanced(
1135 else => {},1130 else => {},
1136 }1131 }
1137 }1132 }
1138 return (try orderAdvanced(lhs, rhs, mod, opt_sema)).compare(op);1133 return (try orderAdvanced(lhs, rhs, mod, strat)).compare(op);
1139}1134}
11401135
1141/// Asserts the values are comparable. Both operands have type `ty`.1136/// Asserts the values are comparable. Both operands have type `ty`.
...@@ -1176,22 +1171,22 @@ pub fn compareScalar(...@@ -1176,22 +1171,22 @@ pub fn compareScalar(
1176///1171///
1177/// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`1172/// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
1178pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool {1173pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool {
1179 return compareAllWithZeroAdvancedExtra(lhs, op, mod, null) catch unreachable;1174 return compareAllWithZeroAdvancedExtra(lhs, op, mod, .normal) catch unreachable;
1180}1175}
11811176
1182pub fn compareAllWithZeroAdvanced(1177pub fn compareAllWithZeroSema(
1183 lhs: Value,1178 lhs: Value,
1184 op: std.math.CompareOperator,1179 op: std.math.CompareOperator,
1185 sema: *Sema,1180 zcu: *Zcu,
1186) Module.CompileError!bool {1181) Module.CompileError!bool {
1187 return compareAllWithZeroAdvancedExtra(lhs, op, sema.mod, sema);1182 return compareAllWithZeroAdvancedExtra(lhs, op, zcu, .sema);
1188}1183}
11891184
1190pub fn compareAllWithZeroAdvancedExtra(1185pub fn compareAllWithZeroAdvancedExtra(
1191 lhs: Value,1186 lhs: Value,
1192 op: std.math.CompareOperator,1187 op: std.math.CompareOperator,
1193 mod: *Module,1188 mod: *Module,
1194 opt_sema: ?*Sema,1189 strat: ResolveStrat,
1195) Module.CompileError!bool {1190) Module.CompileError!bool {
1196 if (lhs.isInf(mod)) {1191 if (lhs.isInf(mod)) {
1197 switch (op) {1192 switch (op) {
...@@ -1211,14 +1206,14 @@ pub fn compareAllWithZeroAdvancedExtra(...@@ -1211,14 +1206,14 @@ pub fn compareAllWithZeroAdvancedExtra(
1211 if (!std.math.order(byte, 0).compare(op)) break false;1206 if (!std.math.order(byte, 0).compare(op)) break false;
1212 } else true,1207 } else true,
1213 .elems => |elems| for (elems) |elem| {1208 .elems => |elems| for (elems) |elem| {
1214 if (!try Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, mod, opt_sema)) break false;1209 if (!try Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, mod, strat)) break false;
1215 } else true,1210 } else true,
1216 .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, mod, opt_sema),1211 .repeated_elem => |elem| Value.fromInterned(elem).compareAllWithZeroAdvancedExtra(op, mod, strat),
1217 },1212 },
1218 .undef => return false,1213 .undef => return false,
1219 else => {},1214 else => {},
1220 }1215 }
1221 return (try orderAgainstZeroAdvanced(lhs, mod, opt_sema)).compare(op);1216 return (try orderAgainstZeroAdvanced(lhs, mod, strat)).compare(op);
1222}1217}
12231218
1224pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {1219pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
...@@ -1279,9 +1274,9 @@ pub fn slicePtr(val: Value, mod: *Module) Value {...@@ -1279,9 +1274,9 @@ pub fn slicePtr(val: Value, mod: *Module) Value {
1279}1274}
12801275
1281/// Gets the `len` field of a slice value as a `u64`.1276/// Gets the `len` field of a slice value as a `u64`.
1282/// Resolves the length using the provided `Sema` if necessary.1277/// Resolves the length using `Sema` if necessary.
1283pub fn sliceLen(val: Value, sema: *Sema) !u64 {1278pub fn sliceLen(val: Value, zcu: *Zcu) !u64 {
1284 return Value.fromInterned(sema.mod.intern_pool.sliceLen(val.toIntern())).toUnsignedIntAdvanced(sema);1279 return Value.fromInterned(zcu.intern_pool.sliceLen(val.toIntern())).toUnsignedIntSema(zcu);
1285}1280}
12861281
1287/// Asserts the value is an aggregate, and returns the element value at the given index.1282/// Asserts the value is an aggregate, and returns the element value at the given index.
...@@ -1482,29 +1477,29 @@ pub fn isFloat(self: Value, mod: *const Module) bool {...@@ -1482,29 +1477,29 @@ pub fn isFloat(self: Value, mod: *const Module) bool {
1482}1477}
14831478
1484pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module) !Value {1479pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module) !Value {
1485 return floatFromIntAdvanced(val, arena, int_ty, float_ty, mod, null) catch |err| switch (err) {1480 return floatFromIntAdvanced(val, arena, int_ty, float_ty, mod, .normal) catch |err| switch (err) {
1486 error.OutOfMemory => return error.OutOfMemory,1481 error.OutOfMemory => return error.OutOfMemory,
1487 else => unreachable,1482 else => unreachable,
1488 };1483 };
1489}1484}
14901485
1491pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {1486pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, strat: ResolveStrat) !Value {
1492 if (int_ty.zigTypeTag(mod) == .Vector) {1487 if (int_ty.zigTypeTag(mod) == .Vector) {
1493 const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(mod));1488 const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(mod));
1494 const scalar_ty = float_ty.scalarType(mod);1489 const scalar_ty = float_ty.scalarType(mod);
1495 for (result_data, 0..) |*scalar, i| {1490 for (result_data, 0..) |*scalar, i| {
1496 const elem_val = try val.elemValue(mod, i);1491 const elem_val = try val.elemValue(mod, i);
1497 scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, mod, opt_sema)).toIntern();1492 scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, mod, strat)).toIntern();
1498 }1493 }
1499 return Value.fromInterned((try mod.intern(.{ .aggregate = .{1494 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
1500 .ty = float_ty.toIntern(),1495 .ty = float_ty.toIntern(),
1501 .storage = .{ .elems = result_data },1496 .storage = .{ .elems = result_data },
1502 } })));1497 } })));
1503 }1498 }
1504 return floatFromIntScalar(val, float_ty, mod, opt_sema);1499 return floatFromIntScalar(val, float_ty, mod, strat);
1505}1500}
15061501
1507pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {1502pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, strat: ResolveStrat) !Value {
1508 return switch (mod.intern_pool.indexToKey(val.toIntern())) {1503 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1509 .undef => try mod.undefValue(float_ty),1504 .undef => try mod.undefValue(float_ty),
1510 .int => |int| switch (int.storage) {1505 .int => |int| switch (int.storage) {
...@@ -1513,16 +1508,8 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*...@@ -1513,16 +1508,8 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*
1513 return mod.floatValue(float_ty, float);1508 return mod.floatValue(float_ty, float);
1514 },1509 },
1515 inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod),1510 inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod),
1516 .lazy_align => |ty| if (opt_sema) |sema| {1511 .lazy_align => |ty| return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, strat.toLazy())).scalar.toByteUnits() orelse 0, float_ty, mod),
1517 return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0, float_ty, mod);1512 .lazy_size => |ty| return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, strat.toLazy())).scalar, float_ty, mod),
1518 } else {
1519 return floatFromIntInner(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, float_ty, mod);
1520 },
1521 .lazy_size => |ty| if (opt_sema) |sema| {
1522 return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
1523 } else {
1524 return floatFromIntInner(Type.fromInterned(ty).abiSize(mod), float_ty, mod);
1525 },
1526 },1513 },
1527 else => unreachable,1514 else => unreachable,
1528 };1515 };
...@@ -3616,17 +3603,15 @@ pub const RuntimeIndex = InternPool.RuntimeIndex;...@@ -3616,17 +3603,15 @@ pub const RuntimeIndex = InternPool.RuntimeIndex;
36163603
3617/// `parent_ptr` must be a single-pointer to some optional.3604/// `parent_ptr` must be a single-pointer to some optional.
3618/// Returns a pointer to the payload of the optional.3605/// Returns a pointer to the payload of the optional.
3619/// This takes a `Sema` because it may need to perform type resolution.3606/// May perform type resolution.
3620pub fn ptrOptPayload(parent_ptr: Value, sema: *Sema) !Value {3607pub fn ptrOptPayload(parent_ptr: Value, zcu: *Zcu) !Value {
3621 const zcu = sema.mod;
3622
3623 const parent_ptr_ty = parent_ptr.typeOf(zcu);3608 const parent_ptr_ty = parent_ptr.typeOf(zcu);
3624 const opt_ty = parent_ptr_ty.childType(zcu);3609 const opt_ty = parent_ptr_ty.childType(zcu);
36253610
3626 assert(parent_ptr_ty.ptrSize(zcu) == .One);3611 assert(parent_ptr_ty.ptrSize(zcu) == .One);
3627 assert(opt_ty.zigTypeTag(zcu) == .Optional);3612 assert(opt_ty.zigTypeTag(zcu) == .Optional);
36283613
3629 const result_ty = try sema.ptrType(info: {3614 const result_ty = try zcu.ptrTypeSema(info: {
3630 var new = parent_ptr_ty.ptrInfo(zcu);3615 var new = parent_ptr_ty.ptrInfo(zcu);
3631 // We can correctly preserve alignment `.none`, since an optional has the same3616 // We can correctly preserve alignment `.none`, since an optional has the same
3632 // natural alignment as its child type.3617 // natural alignment as its child type.
...@@ -3651,17 +3636,15 @@ pub fn ptrOptPayload(parent_ptr: Value, sema: *Sema) !Value {...@@ -3651,17 +3636,15 @@ pub fn ptrOptPayload(parent_ptr: Value, sema: *Sema) !Value {
36513636
3652/// `parent_ptr` must be a single-pointer to some error union.3637/// `parent_ptr` must be a single-pointer to some error union.
3653/// Returns a pointer to the payload of the error union.3638/// Returns a pointer to the payload of the error union.
3654/// This takes a `Sema` because it may need to perform type resolution.3639/// May perform type resolution.
3655pub fn ptrEuPayload(parent_ptr: Value, sema: *Sema) !Value {3640pub fn ptrEuPayload(parent_ptr: Value, zcu: *Zcu) !Value {
3656 const zcu = sema.mod;
3657
3658 const parent_ptr_ty = parent_ptr.typeOf(zcu);3641 const parent_ptr_ty = parent_ptr.typeOf(zcu);
3659 const eu_ty = parent_ptr_ty.childType(zcu);3642 const eu_ty = parent_ptr_ty.childType(zcu);
36603643
3661 assert(parent_ptr_ty.ptrSize(zcu) == .One);3644 assert(parent_ptr_ty.ptrSize(zcu) == .One);
3662 assert(eu_ty.zigTypeTag(zcu) == .ErrorUnion);3645 assert(eu_ty.zigTypeTag(zcu) == .ErrorUnion);
36633646
3664 const result_ty = try sema.ptrType(info: {3647 const result_ty = try zcu.ptrTypeSema(info: {
3665 var new = parent_ptr_ty.ptrInfo(zcu);3648 var new = parent_ptr_ty.ptrInfo(zcu);
3666 // We can correctly preserve alignment `.none`, since an error union has a3649 // We can correctly preserve alignment `.none`, since an error union has a
3667 // natural alignment greater than or equal to that of its payload type.3650 // natural alignment greater than or equal to that of its payload type.
...@@ -3682,10 +3665,8 @@ pub fn ptrEuPayload(parent_ptr: Value, sema: *Sema) !Value {...@@ -3682,10 +3665,8 @@ pub fn ptrEuPayload(parent_ptr: Value, sema: *Sema) !Value {
3682/// `parent_ptr` must be a single-pointer to a struct, union, or slice.3665/// `parent_ptr` must be a single-pointer to a struct, union, or slice.
3683/// Returns a pointer to the aggregate field at the specified index.3666/// Returns a pointer to the aggregate field at the specified index.
3684/// For slices, uses `slice_ptr_index` and `slice_len_index`.3667/// For slices, uses `slice_ptr_index` and `slice_len_index`.
3685/// This takes a `Sema` because it may need to perform type resolution.3668/// May perform type resolution.
3686pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {3669pub fn ptrField(parent_ptr: Value, field_idx: u32, zcu: *Zcu) !Value {
3687 const zcu = sema.mod;
3688
3689 const parent_ptr_ty = parent_ptr.typeOf(zcu);3670 const parent_ptr_ty = parent_ptr.typeOf(zcu);
3690 const aggregate_ty = parent_ptr_ty.childType(zcu);3671 const aggregate_ty = parent_ptr_ty.childType(zcu);
36913672
...@@ -3698,17 +3679,17 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3698,17 +3679,17 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
3698 .Struct => field: {3679 .Struct => field: {
3699 const field_ty = aggregate_ty.structFieldType(field_idx, zcu);3680 const field_ty = aggregate_ty.structFieldType(field_idx, zcu);
3700 switch (aggregate_ty.containerLayout(zcu)) {3681 switch (aggregate_ty.containerLayout(zcu)) {
3701 .auto => break :field .{ field_ty, try aggregate_ty.structFieldAlignAdvanced(@intCast(field_idx), zcu, sema) },3682 .auto => break :field .{ field_ty, try aggregate_ty.structFieldAlignAdvanced(@intCast(field_idx), zcu, .sema) },
3702 .@"extern" => {3683 .@"extern" => {
3703 // Well-defined layout, so just offset the pointer appropriately.3684 // Well-defined layout, so just offset the pointer appropriately.
3704 const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu);3685 const byte_off = aggregate_ty.structFieldOffset(field_idx, zcu);
3705 const field_align = a: {3686 const field_align = a: {
3706 const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: {3687 const parent_align = if (parent_ptr_info.flags.alignment == .none) pa: {
3707 break :pa try sema.typeAbiAlignment(aggregate_ty);3688 break :pa (try aggregate_ty.abiAlignmentAdvanced(zcu, .sema)).scalar;
3708 } else parent_ptr_info.flags.alignment;3689 } else parent_ptr_info.flags.alignment;
3709 break :a InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(byte_off)));3690 break :a InternPool.Alignment.fromLog2Units(@min(parent_align.toLog2Units(), @ctz(byte_off)));
3710 };3691 };
3711 const result_ty = try sema.ptrType(info: {3692 const result_ty = try zcu.ptrTypeSema(info: {
3712 var new = parent_ptr_info;3693 var new = parent_ptr_info;
3713 new.child = field_ty.toIntern();3694 new.child = field_ty.toIntern();
3714 new.flags.alignment = field_align;3695 new.flags.alignment = field_align;
...@@ -3723,14 +3704,14 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3723,14 +3704,14 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
3723 new.packed_offset = packed_offset;3704 new.packed_offset = packed_offset;
3724 new.child = field_ty.toIntern();3705 new.child = field_ty.toIntern();
3725 if (new.flags.alignment == .none) {3706 if (new.flags.alignment == .none) {
3726 new.flags.alignment = try sema.typeAbiAlignment(aggregate_ty);3707 new.flags.alignment = (try aggregate_ty.abiAlignmentAdvanced(zcu, .sema)).scalar;
3727 }3708 }
3728 break :info new;3709 break :info new;
3729 });3710 });
3730 return zcu.getCoerced(parent_ptr, result_ty);3711 return zcu.getCoerced(parent_ptr, result_ty);
3731 },3712 },
3732 .byte_ptr => |ptr_info| {3713 .byte_ptr => |ptr_info| {
3733 const result_ty = try sema.ptrType(info: {3714 const result_ty = try zcu.ptrTypeSema(info: {
3734 var new = parent_ptr_info;3715 var new = parent_ptr_info;
3735 new.child = field_ty.toIntern();3716 new.child = field_ty.toIntern();
3736 new.packed_offset = .{3717 new.packed_offset = .{
...@@ -3749,10 +3730,10 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3749,10 +3730,10 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
3749 const union_obj = zcu.typeToUnion(aggregate_ty).?;3730 const union_obj = zcu.typeToUnion(aggregate_ty).?;
3750 const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]);3731 const field_ty = Type.fromInterned(union_obj.field_types.get(&zcu.intern_pool)[field_idx]);
3751 switch (aggregate_ty.containerLayout(zcu)) {3732 switch (aggregate_ty.containerLayout(zcu)) {
3752 .auto => break :field .{ field_ty, try aggregate_ty.structFieldAlignAdvanced(@intCast(field_idx), zcu, sema) },3733 .auto => break :field .{ field_ty, try aggregate_ty.structFieldAlignAdvanced(@intCast(field_idx), zcu, .sema) },
3753 .@"extern" => {3734 .@"extern" => {
3754 // Point to the same address.3735 // Point to the same address.
3755 const result_ty = try sema.ptrType(info: {3736 const result_ty = try zcu.ptrTypeSema(info: {
3756 var new = parent_ptr_info;3737 var new = parent_ptr_info;
3757 new.child = field_ty.toIntern();3738 new.child = field_ty.toIntern();
3758 break :info new;3739 break :info new;
...@@ -3762,28 +3743,28 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3762,28 +3743,28 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
3762 .@"packed" => {3743 .@"packed" => {
3763 // If the field has an ABI size matching its bit size, then we can continue to use a3744 // If the field has an ABI size matching its bit size, then we can continue to use a
3764 // non-bit pointer if the parent pointer is also a non-bit pointer.3745 // non-bit pointer if the parent pointer is also a non-bit pointer.
3765 if (parent_ptr_info.packed_offset.host_size == 0 and try sema.typeAbiSize(field_ty) * 8 == try field_ty.bitSizeAdvanced(zcu, sema)) {3746 if (parent_ptr_info.packed_offset.host_size == 0 and (try field_ty.abiSizeAdvanced(zcu, .sema)).scalar * 8 == try field_ty.bitSizeAdvanced(zcu, .sema)) {
3766 // We must offset the pointer on big-endian targets, since the bits of packed memory don't align nicely.3747 // We must offset the pointer on big-endian targets, since the bits of packed memory don't align nicely.
3767 const byte_offset = switch (zcu.getTarget().cpu.arch.endian()) {3748 const byte_offset = switch (zcu.getTarget().cpu.arch.endian()) {
3768 .little => 0,3749 .little => 0,
3769 .big => try sema.typeAbiSize(aggregate_ty) - try sema.typeAbiSize(field_ty),3750 .big => (try aggregate_ty.abiSizeAdvanced(zcu, .sema)).scalar - (try field_ty.abiSizeAdvanced(zcu, .sema)).scalar,
3770 };3751 };
3771 const result_ty = try sema.ptrType(info: {3752 const result_ty = try zcu.ptrTypeSema(info: {
3772 var new = parent_ptr_info;3753 var new = parent_ptr_info;
3773 new.child = field_ty.toIntern();3754 new.child = field_ty.toIntern();
3774 new.flags.alignment = InternPool.Alignment.fromLog2Units(3755 new.flags.alignment = InternPool.Alignment.fromLog2Units(
3775 @ctz(byte_offset | (try parent_ptr_ty.ptrAlignmentAdvanced(zcu, sema)).toByteUnits().?),3756 @ctz(byte_offset | (try parent_ptr_ty.ptrAlignmentAdvanced(zcu, .sema)).toByteUnits().?),
3776 );3757 );
3777 break :info new;3758 break :info new;
3778 });3759 });
3779 return parent_ptr.getOffsetPtr(byte_offset, result_ty, zcu);3760 return parent_ptr.getOffsetPtr(byte_offset, result_ty, zcu);
3780 } else {3761 } else {
3781 // The result must be a bit-pointer if it is not already.3762 // The result must be a bit-pointer if it is not already.
3782 const result_ty = try sema.ptrType(info: {3763 const result_ty = try zcu.ptrTypeSema(info: {
3783 var new = parent_ptr_info;3764 var new = parent_ptr_info;
3784 new.child = field_ty.toIntern();3765 new.child = field_ty.toIntern();
3785 if (new.packed_offset.host_size == 0) {3766 if (new.packed_offset.host_size == 0) {
3786 new.packed_offset.host_size = @intCast(((try aggregate_ty.bitSizeAdvanced(zcu, sema)) + 7) / 8);3767 new.packed_offset.host_size = @intCast(((try aggregate_ty.bitSizeAdvanced(zcu, .sema)) + 7) / 8);
3787 assert(new.packed_offset.bit_offset == 0);3768 assert(new.packed_offset.bit_offset == 0);
3788 }3769 }
3789 break :info new;3770 break :info new;
...@@ -3805,14 +3786,14 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3805,14 +3786,14 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
3805 };3786 };
38063787
3807 const new_align: InternPool.Alignment = if (parent_ptr_info.flags.alignment != .none) a: {3788 const new_align: InternPool.Alignment = if (parent_ptr_info.flags.alignment != .none) a: {
3808 const ty_align = try sema.typeAbiAlignment(field_ty);3789 const ty_align = (try field_ty.abiAlignmentAdvanced(zcu, .sema)).scalar;
3809 const true_field_align = if (field_align == .none) ty_align else field_align;3790 const true_field_align = if (field_align == .none) ty_align else field_align;
3810 const new_align = true_field_align.min(parent_ptr_info.flags.alignment);3791 const new_align = true_field_align.min(parent_ptr_info.flags.alignment);
3811 if (new_align == ty_align) break :a .none;3792 if (new_align == ty_align) break :a .none;
3812 break :a new_align;3793 break :a new_align;
3813 } else field_align;3794 } else field_align;
38143795
3815 const result_ty = try sema.ptrType(info: {3796 const result_ty = try zcu.ptrTypeSema(info: {
3816 var new = parent_ptr_info;3797 var new = parent_ptr_info;
3817 new.child = field_ty.toIntern();3798 new.child = field_ty.toIntern();
3818 new.flags.alignment = new_align;3799 new.flags.alignment = new_align;
...@@ -3834,10 +3815,8 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {...@@ -3834,10 +3815,8 @@ pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value {
38343815
3835/// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice.3816/// `orig_parent_ptr` must be either a single-pointer to an array or vector, or a many-pointer or C-pointer or slice.
3836/// Returns a pointer to the element at the specified index.3817/// Returns a pointer to the element at the specified index.
3837/// This takes a `Sema` because it may need to perform type resolution.3818/// May perform type resolution.
3838pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value {3819pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, zcu: *Zcu) !Value {
3839 const zcu = sema.mod;
3840
3841 const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) {3820 const parent_ptr = switch (orig_parent_ptr.typeOf(zcu).ptrSize(zcu)) {
3842 .One, .Many, .C => orig_parent_ptr,3821 .One, .Many, .C => orig_parent_ptr,
3843 .Slice => orig_parent_ptr.slicePtr(zcu),3822 .Slice => orig_parent_ptr.slicePtr(zcu),
...@@ -3845,7 +3824,7 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value {...@@ -3845,7 +3824,7 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value {
38453824
3846 const parent_ptr_ty = parent_ptr.typeOf(zcu);3825 const parent_ptr_ty = parent_ptr.typeOf(zcu);
3847 const elem_ty = parent_ptr_ty.childType(zcu);3826 const elem_ty = parent_ptr_ty.childType(zcu);
3848 const result_ty = try sema.elemPtrType(parent_ptr_ty, @intCast(field_idx));3827 const result_ty = try parent_ptr_ty.elemPtrType(@intCast(field_idx), zcu);
38493828
3850 if (parent_ptr.isUndef(zcu)) return zcu.undefValue(result_ty);3829 if (parent_ptr.isUndef(zcu)) return zcu.undefValue(result_ty);
38513830
...@@ -3862,21 +3841,21 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value {...@@ -3862,21 +3841,21 @@ pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value {
38623841
3863 const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) {3842 const strat: PtrStrat = switch (parent_ptr_ty.ptrSize(zcu)) {
3864 .One => switch (elem_ty.zigTypeTag(zcu)) {3843 .One => switch (elem_ty.zigTypeTag(zcu)) {
3865 .Vector => .{ .offset = field_idx * @divExact(try elem_ty.childType(zcu).bitSizeAdvanced(zcu, sema), 8) },3844 .Vector => .{ .offset = field_idx * @divExact(try elem_ty.childType(zcu).bitSizeAdvanced(zcu, .sema), 8) },
3866 .Array => strat: {3845 .Array => strat: {
3867 const arr_elem_ty = elem_ty.childType(zcu);3846 const arr_elem_ty = elem_ty.childType(zcu);
3868 if (try sema.typeRequiresComptime(arr_elem_ty)) {3847 if (try arr_elem_ty.comptimeOnlyAdvanced(zcu, .sema)) {
3869 break :strat .{ .elem_ptr = arr_elem_ty };3848 break :strat .{ .elem_ptr = arr_elem_ty };
3870 }3849 }
3871 break :strat .{ .offset = field_idx * try sema.typeAbiSize(arr_elem_ty) };3850 break :strat .{ .offset = field_idx * (try arr_elem_ty.abiSizeAdvanced(zcu, .sema)).scalar };
3872 },3851 },
3873 else => unreachable,3852 else => unreachable,
3874 },3853 },
38753854
3876 .Many, .C => if (try sema.typeRequiresComptime(elem_ty))3855 .Many, .C => if (try elem_ty.comptimeOnlyAdvanced(zcu, .sema))
3877 .{ .elem_ptr = elem_ty }3856 .{ .elem_ptr = elem_ty }
3878 else3857 else
3879 .{ .offset = field_idx * try sema.typeAbiSize(elem_ty) },3858 .{ .offset = field_idx * (try elem_ty.abiSizeAdvanced(zcu, .sema)).scalar },
38803859
3881 .Slice => unreachable,3860 .Slice => unreachable,
3882 };3861 };
...@@ -4014,11 +3993,7 @@ pub const PointerDeriveStep = union(enum) {...@@ -4014,11 +3993,7 @@ pub const PointerDeriveStep = union(enum) {
4014pub fn pointerDerivation(ptr_val: Value, arena: Allocator, zcu: *Zcu) Allocator.Error!PointerDeriveStep {3993pub fn pointerDerivation(ptr_val: Value, arena: Allocator, zcu: *Zcu) Allocator.Error!PointerDeriveStep {
4015 return ptr_val.pointerDerivationAdvanced(arena, zcu, null) catch |err| switch (err) {3994 return ptr_val.pointerDerivationAdvanced(arena, zcu, null) catch |err| switch (err) {
4016 error.OutOfMemory => |e| return e,3995 error.OutOfMemory => |e| return e,
4017 error.AnalysisFail,3996 error.AnalysisFail => unreachable,
4018 error.GenericPoison,
4019 error.ComptimeReturn,
4020 error.ComptimeBreak,
4021 => unreachable,
4022 };3997 };
4023}3998}
40243999
...@@ -4087,8 +4062,8 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, zcu: *Zcu, op...@@ -4087,8 +4062,8 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, zcu: *Zcu, op
4087 const base_ptr_ty = base_ptr.typeOf(zcu);4062 const base_ptr_ty = base_ptr.typeOf(zcu);
4088 const agg_ty = base_ptr_ty.childType(zcu);4063 const agg_ty = base_ptr_ty.childType(zcu);
4089 const field_ty, const field_align = switch (agg_ty.zigTypeTag(zcu)) {4064 const field_ty, const field_align = switch (agg_ty.zigTypeTag(zcu)) {
4090 .Struct => .{ agg_ty.structFieldType(@intCast(field.index), zcu), try agg_ty.structFieldAlignAdvanced(@intCast(field.index), zcu, opt_sema) },4065 .Struct => .{ agg_ty.structFieldType(@intCast(field.index), zcu), try agg_ty.structFieldAlignAdvanced(@intCast(field.index), zcu, .sema) },
4091 .Union => .{ agg_ty.unionFieldTypeByIndex(@intCast(field.index), zcu), try agg_ty.structFieldAlignAdvanced(@intCast(field.index), zcu, opt_sema) },4066 .Union => .{ agg_ty.unionFieldTypeByIndex(@intCast(field.index), zcu), try agg_ty.structFieldAlignAdvanced(@intCast(field.index), zcu, .sema) },
4092 .Pointer => .{ switch (field.index) {4067 .Pointer => .{ switch (field.index) {
4093 Value.slice_ptr_index => agg_ty.slicePtrFieldType(zcu),4068 Value.slice_ptr_index => agg_ty.slicePtrFieldType(zcu),
4094 Value.slice_len_index => Type.usize,4069 Value.slice_len_index => Type.usize,
...@@ -4269,3 +4244,118 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, zcu: *Zcu, op...@@ -4269,3 +4244,118 @@ pub fn pointerDerivationAdvanced(ptr_val: Value, arena: Allocator, zcu: *Zcu, op
4269 .new_ptr_ty = Type.fromInterned(ptr.ty),4244 .new_ptr_ty = Type.fromInterned(ptr.ty),
4270 } };4245 } };
4271}4246}
4247
4248pub fn resolveLazy(val: Value, arena: Allocator, zcu: *Zcu) Zcu.SemaError!Value {
4249 switch (zcu.intern_pool.indexToKey(val.toIntern())) {
4250 .int => |int| switch (int.storage) {
4251 .u64, .i64, .big_int => return val,
4252 .lazy_align, .lazy_size => return zcu.intValue(
4253 Type.fromInterned(int.ty),
4254 (try val.getUnsignedIntAdvanced(zcu, .sema)).?,
4255 ),
4256 },
4257 .slice => |slice| {
4258 const ptr = try Value.fromInterned(slice.ptr).resolveLazy(arena, zcu);
4259 const len = try Value.fromInterned(slice.len).resolveLazy(arena, zcu);
4260 if (ptr.toIntern() == slice.ptr and len.toIntern() == slice.len) return val;
4261 return Value.fromInterned(try zcu.intern(.{ .slice = .{
4262 .ty = slice.ty,
4263 .ptr = ptr.toIntern(),
4264 .len = len.toIntern(),
4265 } }));
4266 },
4267 .ptr => |ptr| {
4268 switch (ptr.base_addr) {
4269 .decl, .comptime_alloc, .anon_decl, .int => return val,
4270 .comptime_field => |field_val| {
4271 const resolved_field_val = (try Value.fromInterned(field_val).resolveLazy(arena, zcu)).toIntern();
4272 return if (resolved_field_val == field_val)
4273 val
4274 else
4275 Value.fromInterned((try zcu.intern(.{ .ptr = .{
4276 .ty = ptr.ty,
4277 .base_addr = .{ .comptime_field = resolved_field_val },
4278 .byte_offset = ptr.byte_offset,
4279 } })));
4280 },
4281 .eu_payload, .opt_payload => |base| {
4282 const resolved_base = (try Value.fromInterned(base).resolveLazy(arena, zcu)).toIntern();
4283 return if (resolved_base == base)
4284 val
4285 else
4286 Value.fromInterned((try zcu.intern(.{ .ptr = .{
4287 .ty = ptr.ty,
4288 .base_addr = switch (ptr.base_addr) {
4289 .eu_payload => .{ .eu_payload = resolved_base },
4290 .opt_payload => .{ .opt_payload = resolved_base },
4291 else => unreachable,
4292 },
4293 .byte_offset = ptr.byte_offset,
4294 } })));
4295 },
4296 .arr_elem, .field => |base_index| {
4297 const resolved_base = (try Value.fromInterned(base_index.base).resolveLazy(arena, zcu)).toIntern();
4298 return if (resolved_base == base_index.base)
4299 val
4300 else
4301 Value.fromInterned((try zcu.intern(.{ .ptr = .{
4302 .ty = ptr.ty,
4303 .base_addr = switch (ptr.base_addr) {
4304 .arr_elem => .{ .arr_elem = .{
4305 .base = resolved_base,
4306 .index = base_index.index,
4307 } },
4308 .field => .{ .field = .{
4309 .base = resolved_base,
4310 .index = base_index.index,
4311 } },
4312 else => unreachable,
4313 },
4314 .byte_offset = ptr.byte_offset,
4315 } })));
4316 },
4317 }
4318 },
4319 .aggregate => |aggregate| switch (aggregate.storage) {
4320 .bytes => return val,
4321 .elems => |elems| {
4322 var resolved_elems: []InternPool.Index = &.{};
4323 for (elems, 0..) |elem, i| {
4324 const resolved_elem = (try Value.fromInterned(elem).resolveLazy(arena, zcu)).toIntern();
4325 if (resolved_elems.len == 0 and resolved_elem != elem) {
4326 resolved_elems = try arena.alloc(InternPool.Index, elems.len);
4327 @memcpy(resolved_elems[0..i], elems[0..i]);
4328 }
4329 if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem;
4330 }
4331 return if (resolved_elems.len == 0) val else Value.fromInterned((try zcu.intern(.{ .aggregate = .{
4332 .ty = aggregate.ty,
4333 .storage = .{ .elems = resolved_elems },
4334 } })));
4335 },
4336 .repeated_elem => |elem| {
4337 const resolved_elem = (try Value.fromInterned(elem).resolveLazy(arena, zcu)).toIntern();
4338 return if (resolved_elem == elem) val else Value.fromInterned((try zcu.intern(.{ .aggregate = .{
4339 .ty = aggregate.ty,
4340 .storage = .{ .repeated_elem = resolved_elem },
4341 } })));
4342 },
4343 },
4344 .un => |un| {
4345 const resolved_tag = if (un.tag == .none)
4346 .none
4347 else
4348 (try Value.fromInterned(un.tag).resolveLazy(arena, zcu)).toIntern();
4349 const resolved_val = (try Value.fromInterned(un.val).resolveLazy(arena, zcu)).toIntern();
4350 return if (resolved_tag == un.tag and resolved_val == un.val)
4351 val
4352 else
4353 Value.fromInterned((try zcu.intern(.{ .un = .{
4354 .ty = un.ty,
4355 .tag = resolved_tag,
4356 .val = resolved_val,
4357 } })));
4358 },
4359 else => return val,
4360 }
4361}
src/Zcu.zig+442-338
...@@ -20,7 +20,7 @@ const Zcu = @This();...@@ -20,7 +20,7 @@ const Zcu = @This();
20const Compilation = @import("Compilation.zig");20const Compilation = @import("Compilation.zig");
21const Cache = std.Build.Cache;21const Cache = std.Build.Cache;
22const Value = @import("Value.zig");22const Value = @import("Value.zig");
23const Type = @import("type.zig").Type;23const Type = @import("Type.zig");
24const Package = @import("Package.zig");24const Package = @import("Package.zig");
25const link = @import("link.zig");25const link = @import("link.zig");
26const Air = @import("Air.zig");26const Air = @import("Air.zig");
...@@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir;...@@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir;
35const clang = @import("clang.zig");35const clang = @import("clang.zig");
36const InternPool = @import("InternPool.zig");36const InternPool = @import("InternPool.zig");
37const Alignment = InternPool.Alignment;37const Alignment = InternPool.Alignment;
38const AnalUnit = InternPool.AnalUnit;
38const BuiltinFn = std.zig.BuiltinFn;39const BuiltinFn = std.zig.BuiltinFn;
39const LlvmObject = @import("codegen/llvm.zig").Object;40const LlvmObject = @import("codegen/llvm.zig").Object;
4041
...@@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined,...@@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined,
71global_zir_cache: Compilation.Directory,72global_zir_cache: Compilation.Directory,
72/// Used by AstGen worker to load and store ZIR cache.73/// Used by AstGen worker to load and store ZIR cache.
73local_zir_cache: Compilation.Directory,74local_zir_cache: Compilation.Directory,
74/// It's rare for a decl to be exported, so we save memory by having a sparse75/// This is where all `Export` values are stored. Not all values here are necessarily valid exports;
75/// map of Decl indexes to details about them being exported.76/// to enumerate all exports, `single_exports` and `multi_exports` must be consulted.
76/// The Export memory is owned by the `export_owners` table; the slice itself77all_exports: ArrayListUnmanaged(Export) = .{},
77/// is owned by this table. The slice is guaranteed to not be empty.78/// This is a list of free indices in `all_exports`. These indices may be reused by exports from
78decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{},79/// future semantic analysis.
79/// Same as `decl_exports` but for exported constant values.80free_exports: ArrayListUnmanaged(u32) = .{},
80value_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, ArrayListUnmanaged(*Export)) = .{},81/// Maps from an `AnalUnit` which performs a single export, to the index into `all_exports` of
81/// This models the Decls that perform exports, so that `decl_exports` can be updated when a Decl82/// the export it performs. Note that the key is not the `Decl` being exported, but the `AnalUnit`
82/// is modified. Note that the key of this table is not the Decl being exported, but the Decl that83/// whose analysis triggered the export.
83/// is performing the export of another Decl.84single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{},
84/// This table owns the Export memory.85/// Like `single_exports`, but for `AnalUnit`s which perform multiple exports.
85export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{},86/// The exports are `all_exports.items[index..][0..len]`.
87multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
88 index: u32,
89 len: u32,
90}) = .{},
86/// The set of all the Zig source files in the Module. We keep track of this in order91/// The set of all the Zig source files in the Module. We keep track of this in order
87/// to iterate over it and check which source files have been modified on the file system when92/// to iterate over it and check which source files have been modified on the file system when
88/// an update is requested, as well as to cache `@import` results.93/// an update is requested, as well as to cache `@import` results.
...@@ -103,15 +108,11 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{},...@@ -103,15 +108,11 @@ embed_table: std.StringArrayHashMapUnmanaged(*EmbedFile) = .{},
103/// is not yet implemented.108/// is not yet implemented.
104intern_pool: InternPool = .{},109intern_pool: InternPool = .{},
105110
106/// We optimize memory usage for a compilation with no compile errors by storing the111/// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator.
107/// error messages and mapping outside of `Decl`.112failed_analysis: std.AutoArrayHashMapUnmanaged(AnalUnit, *ErrorMsg) = .{},
108/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.113/// Keep track of one `@compileLog` callsite per `AnalUnit`.
109/// Note that a Decl can succeed but the Fn it represents can fail. In this case,
110/// a Decl can have a failed_decls entry but have analysis status of success.
111failed_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, *ErrorMsg) = .{},
112/// Keep track of one `@compileLog` callsite per owner Decl.
113/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.114/// The value is the source location of the `@compileLog` call, convertible to a `LazySrcLoc`.
114compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct {115compile_log_sources: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
115 base_node_inst: InternPool.TrackedInst.Index,116 base_node_inst: InternPool.TrackedInst.Index,
116 node_offset: i32,117 node_offset: i32,
117 pub fn src(self: @This()) LazySrcLoc {118 pub fn src(self: @This()) LazySrcLoc {
...@@ -126,12 +127,11 @@ compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct {...@@ -126,12 +127,11 @@ compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct {
126failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{},127failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{},
127/// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator.128/// The ErrorMsg memory is owned by the `EmbedFile`, using Module's general purpose allocator.
128failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},129failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},
129/// Using a map here for consistency with the other fields here.130/// Key is index into `all_exports`.
130/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.131failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{},
131failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},132/// If analysis failed due to a cimport error, the corresponding Clang errors
132/// If a decl failed due to a cimport error, the corresponding Clang errors
133/// are stored here.133/// are stored here.
134cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{},134cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .{},
135135
136/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.136/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
137global_error_set: GlobalErrorSet = .{},137global_error_set: GlobalErrorSet = .{},
...@@ -139,26 +139,26 @@ global_error_set: GlobalErrorSet = .{},...@@ -139,26 +139,26 @@ global_error_set: GlobalErrorSet = .{},
139/// Maximum amount of distinct error values, set by --error-limit139/// Maximum amount of distinct error values, set by --error-limit
140error_limit: ErrorInt,140error_limit: ErrorInt,
141141
142/// Value is the number of PO or outdated Decls which this AnalSubject depends on.142/// Value is the number of PO or outdated Decls which this AnalUnit depends on.
143potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, u32) = .{},143potentially_outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{},
144/// Value is the number of PO or outdated Decls which this AnalSubject depends on.144/// Value is the number of PO or outdated Decls which this AnalUnit depends on.
145/// Once this value drops to 0, the AnalSubject is a candidate for re-analysis.145/// Once this value drops to 0, the AnalUnit is a candidate for re-analysis.
146outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, u32) = .{},146outdated: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{},
147/// This contains all `AnalSubject`s in `outdated` whose PO dependency count is 0.147/// This contains all `AnalUnit`s in `outdated` whose PO dependency count is 0.
148/// Such `AnalSubject`s are ready for immediate re-analysis.148/// Such `AnalUnit`s are ready for immediate re-analysis.
149/// See `findOutdatedToAnalyze` for details.149/// See `findOutdatedToAnalyze` for details.
150outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, void) = .{},150outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{},
151/// This contains a set of Decls which may not be in `outdated`, but are the151/// This contains a set of Decls which may not be in `outdated`, but are the
152/// root Decls of files which have updated source and thus must be re-analyzed.152/// root Decls of files which have updated source and thus must be re-analyzed.
153/// If such a Decl is only in this set, the struct type index may be preserved153/// If such a Decl is only in this set, the struct type index may be preserved
154/// (only the namespace might change). If such a Decl is also `outdated`, the154/// (only the namespace might change). If such a Decl is also `outdated`, the
155/// struct type index must be recreated.155/// struct type index must be recreated.
156outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},156outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
157/// This contains a list of AnalSubject whose analysis or codegen failed, but the157/// This contains a list of AnalUnit whose analysis or codegen failed, but the
158/// failure was something like running out of disk space, and trying again may158/// failure was something like running out of disk space, and trying again may
159/// succeed. On the next update, we will flush this list, marking all members of159/// succeed. On the next update, we will flush this list, marking all members of
160/// it as outdated.160/// it as outdated.
161retryable_failures: std.ArrayListUnmanaged(InternPool.AnalSubject) = .{},161retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .{},
162162
163stage1_flags: packed struct {163stage1_flags: packed struct {
164 have_winmain: bool = false,164 have_winmain: bool = false,
...@@ -176,12 +176,18 @@ emit_h: ?*GlobalEmitH,...@@ -176,12 +176,18 @@ emit_h: ?*GlobalEmitH,
176176
177test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},177test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
178178
179/// TODO: the key here will be a `Cau.Index`.
179global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{},180global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{},
180181
181reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {182/// Key is the `AnalUnit` *performing* the reference. This representation allows
182 referencer: Decl.Index,183/// incremental updates to quickly delete references caused by a specific `AnalUnit`.
183 src: LazySrcLoc,184/// Value is index into `all_reference` of the first reference triggered by the unit.
184}) = .{},185/// The `next` field on the `Reference` forms a linked list of all references
186/// triggered by the key `AnalUnit`.
187reference_table: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{},
188all_references: std.ArrayListUnmanaged(Reference) = .{},
189/// Freelist of indices in `all_references`.
190free_references: std.ArrayListUnmanaged(u32) = .{},
185191
186panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,192panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len,
187/// The panic function body.193/// The panic function body.
...@@ -262,13 +268,25 @@ pub const Exported = union(enum) {...@@ -262,13 +268,25 @@ pub const Exported = union(enum) {
262 decl_index: Decl.Index,268 decl_index: Decl.Index,
263 /// Constant value being exported.269 /// Constant value being exported.
264 value: InternPool.Index,270 value: InternPool.Index,
271
272 pub fn getValue(exported: Exported, zcu: *Zcu) Value {
273 return switch (exported) {
274 .decl_index => |decl_index| zcu.declPtr(decl_index).val,
275 .value => |value| Value.fromInterned(value),
276 };
277 }
278
279 pub fn getAlign(exported: Exported, zcu: *Zcu) Alignment {
280 return switch (exported) {
281 .decl_index => |decl_index| zcu.declPtr(decl_index).alignment,
282 .value => .none,
283 };
284 }
265};285};
266286
267pub const Export = struct {287pub const Export = struct {
268 opts: Options,288 opts: Options,
269 src: LazySrcLoc,289 src: LazySrcLoc,
270 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
271 owner_decl: Decl.Index,
272 exported: Exported,290 exported: Exported,
273 status: enum {291 status: enum {
274 in_progress,292 in_progress,
...@@ -285,50 +303,16 @@ pub const Export = struct {...@@ -285,50 +303,16 @@ pub const Export = struct {
285 section: InternPool.OptionalNullTerminatedString = .none,303 section: InternPool.OptionalNullTerminatedString = .none,
286 visibility: std.builtin.SymbolVisibility = .default,304 visibility: std.builtin.SymbolVisibility = .default,
287 };305 };
288
289 pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {
290 return exp.src.upgrade(mod);
291 }
292};306};
293307
294const ValueArena = struct {308pub const Reference = struct {
295 state: std.heap.ArenaAllocator.State,309 /// The `AnalUnit` whose semantic analysis was triggered by this reference.
296 state_acquired: ?*std.heap.ArenaAllocator.State = null,310 referenced: AnalUnit,
297311 /// Index into `all_references` of the next `Reference` triggered by the same `AnalUnit`.
298 /// If this ValueArena replaced an existing one during re-analysis, this is the previous instance312 /// `std.math.maxInt(u32)` is the sentinel.
299 prev: ?*ValueArena = null,313 next: u32,
300314 /// The source location of the reference.
301 /// Returns an allocator backed by either promoting `state`, or by the existing ArenaAllocator315 src: LazySrcLoc,
302 /// that has already promoted `state`. `out_arena_allocator` provides storage for the initial promotion,
303 /// and must live until the matching call to release().
304 pub fn acquire(self: *ValueArena, child_allocator: Allocator, out_arena_allocator: *std.heap.ArenaAllocator) Allocator {
305 if (self.state_acquired) |state_acquired| {
306 return @as(*std.heap.ArenaAllocator, @fieldParentPtr("state", state_acquired)).allocator();
307 }
308
309 out_arena_allocator.* = self.state.promote(child_allocator);
310 self.state_acquired = &out_arena_allocator.state;
311 return out_arena_allocator.allocator();
312 }
313
314 /// Releases the allocator acquired by `acquire. `arena_allocator` must match the one passed to `acquire`.
315 pub fn release(self: *ValueArena, arena_allocator: *std.heap.ArenaAllocator) void {
316 if (@as(*std.heap.ArenaAllocator, @fieldParentPtr("state", self.state_acquired.?)) == arena_allocator) {
317 self.state = self.state_acquired.?.*;
318 self.state_acquired = null;
319 }
320 }
321
322 pub fn deinit(self: ValueArena, child_allocator: Allocator) void {
323 assert(self.state_acquired == null);
324
325 const prev = self.prev;
326 self.state.promote(child_allocator).deinit();
327
328 if (prev) |p| {
329 p.deinit(child_allocator);
330 }
331 }
332};316};
333317
334pub const Decl = struct {318pub const Decl = struct {
...@@ -369,9 +353,9 @@ pub const Decl = struct {...@@ -369,9 +353,9 @@ pub const Decl = struct {
369 /// successfully complete semantic analysis.353 /// successfully complete semantic analysis.
370 dependency_failure,354 dependency_failure,
371 /// Semantic analysis failure.355 /// Semantic analysis failure.
372 /// There will be a corresponding ErrorMsg in Zcu.failed_decls.356 /// There will be a corresponding ErrorMsg in Zcu.failed_analysis.
373 sema_failure,357 sema_failure,
374 /// There will be a corresponding ErrorMsg in Zcu.failed_decls.358 /// There will be a corresponding ErrorMsg in Zcu.failed_analysis.
375 codegen_failure,359 codegen_failure,
376 /// Sematic analysis and constant value codegen of this Decl has360 /// Sematic analysis and constant value codegen of this Decl has
377 /// succeeded. However, the Decl may be outdated due to an in-progress361 /// succeeded. However, the Decl may be outdated due to an in-progress
...@@ -759,7 +743,7 @@ pub const File = struct {...@@ -759,7 +743,7 @@ pub const File = struct {
759 /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.743 /// Whether this file is a part of multiple packages. This is an error condition which will be reported after AstGen.
760 multi_pkg: bool = false,744 multi_pkg: bool = false,
761 /// List of references to this file, used for multi-package errors.745 /// List of references to this file, used for multi-package errors.
762 references: std.ArrayListUnmanaged(Reference) = .{},746 references: std.ArrayListUnmanaged(File.Reference) = .{},
763 /// The hash of the path to this file, used to store `InternPool.TrackedInst`.747 /// The hash of the path to this file, used to store `InternPool.TrackedInst`.
764 path_digest: Cache.BinDigest,748 path_digest: Cache.BinDigest,
765749
...@@ -772,7 +756,10 @@ pub const File = struct {...@@ -772,7 +756,10 @@ pub const File = struct {
772 /// A single reference to a file.756 /// A single reference to a file.
773 pub const Reference = union(enum) {757 pub const Reference = union(enum) {
774 /// The file is imported directly (i.e. not as a package) with @import.758 /// The file is imported directly (i.e. not as a package) with @import.
775 import: SrcLoc,759 import: struct {
760 file: *File,
761 token: Ast.TokenIndex,
762 },
776 /// The file is the root of a module.763 /// The file is the root of a module.
777 root: *Package.Module,764 root: *Package.Module,
778 };765 };
...@@ -926,7 +913,7 @@ pub const File = struct {...@@ -926,7 +913,7 @@ pub const File = struct {
926 }913 }
927914
928 /// Add a reference to this file during AstGen.915 /// Add a reference to this file during AstGen.
929 pub fn addReference(file: *File, mod: Module, ref: Reference) !void {916 pub fn addReference(file: *File, zcu: Zcu, ref: File.Reference) !void {
930 // Don't add the same module root twice. Note that since we always add module roots at the917 // Don't add the same module root twice. Note that since we always add module roots at the
931 // front of the references array (see below), this loop is actually O(1) on valid code.918 // front of the references array (see below), this loop is actually O(1) on valid code.
932 if (ref == .root) {919 if (ref == .root) {
...@@ -943,17 +930,17 @@ pub const File = struct {...@@ -943,17 +930,17 @@ pub const File = struct {
943 // to make multi-module errors more helpful (since "root-of" notes are generally more930 // to make multi-module errors more helpful (since "root-of" notes are generally more
944 // informative than "imported-from" notes). This path is hit very rarely, so the speed931 // informative than "imported-from" notes). This path is hit very rarely, so the speed
945 // of the insert operation doesn't matter too much.932 // of the insert operation doesn't matter too much.
946 .root => try file.references.insert(mod.gpa, 0, ref),933 .root => try file.references.insert(zcu.gpa, 0, ref),
947934
948 // Other references we'll just put at the end.935 // Other references we'll just put at the end.
949 else => try file.references.append(mod.gpa, ref),936 else => try file.references.append(zcu.gpa, ref),
950 }937 }
951938
952 const pkg = switch (ref) {939 const mod = switch (ref) {
953 .import => |loc| loc.file_scope.mod,940 .import => |import| import.file.mod,
954 .root => |pkg| pkg,941 .root => |mod| mod,
955 };942 };
956 if (pkg != file.mod) file.multi_pkg = true;943 if (mod != file.mod) file.multi_pkg = true;
957 }944 }
958945
959 /// Mark this file and every file referenced by it as multi_pkg and report an946 /// Mark this file and every file referenced by it as multi_pkg and report an
...@@ -993,36 +980,25 @@ pub const EmbedFile = struct {...@@ -993,36 +980,25 @@ pub const EmbedFile = struct {
993 owner: *Package.Module,980 owner: *Package.Module,
994 stat: Cache.File.Stat,981 stat: Cache.File.Stat,
995 val: InternPool.Index,982 val: InternPool.Index,
996 src_loc: SrcLoc,983 src_loc: LazySrcLoc,
997};984};
998985
999/// This struct holds data necessary to construct API-facing `AllErrors.Message`.986/// This struct holds data necessary to construct API-facing `AllErrors.Message`.
1000/// Its memory is managed with the general purpose allocator so that they987/// Its memory is managed with the general purpose allocator so that they
1001/// can be created and destroyed in response to incremental updates.988/// can be created and destroyed in response to incremental updates.
1002/// In some cases, the File could have been inferred from where the ErrorMsg
1003/// is stored. For example, if it is stored in Module.failed_decls, then the File
1004/// would be determined by the Decl Scope. However, the data structure contains the field
1005/// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different
1006/// file than the parent error message. It also simplifies processing of error messages.
1007pub const ErrorMsg = struct {989pub const ErrorMsg = struct {
1008 src_loc: SrcLoc,990 src_loc: LazySrcLoc,
1009 msg: []const u8,991 msg: []const u8,
1010 notes: []ErrorMsg = &.{},992 notes: []ErrorMsg = &.{},
1011 reference_trace: []Trace = &.{},993 reference_trace_root: AnalUnit.Optional = .none,
1012 hidden_references: u32 = 0,
1013
1014 pub const Trace = struct {
1015 decl: InternPool.NullTerminatedString,
1016 src_loc: SrcLoc,
1017 };
1018994
1019 pub fn create(995 pub fn create(
1020 gpa: Allocator,996 gpa: Allocator,
1021 src_loc: SrcLoc,997 src_loc: LazySrcLoc,
1022 comptime format: []const u8,998 comptime format: []const u8,
1023 args: anytype,999 args: anytype,
1024 ) !*ErrorMsg {1000 ) !*ErrorMsg {
1025 assert(src_loc.lazy != .unneeded);1001 assert(src_loc.offset != .unneeded);
1026 const err_msg = try gpa.create(ErrorMsg);1002 const err_msg = try gpa.create(ErrorMsg);
1027 errdefer gpa.destroy(err_msg);1003 errdefer gpa.destroy(err_msg);
1028 err_msg.* = try ErrorMsg.init(gpa, src_loc, format, args);1004 err_msg.* = try ErrorMsg.init(gpa, src_loc, format, args);
...@@ -1038,7 +1014,7 @@ pub const ErrorMsg = struct {...@@ -1038,7 +1014,7 @@ pub const ErrorMsg = struct {
10381014
1039 pub fn init(1015 pub fn init(
1040 gpa: Allocator,1016 gpa: Allocator,
1041 src_loc: SrcLoc,1017 src_loc: LazySrcLoc,
1042 comptime format: []const u8,1018 comptime format: []const u8,
1043 args: anytype,1019 args: anytype,
1044 ) !ErrorMsg {1020 ) !ErrorMsg {
...@@ -1054,7 +1030,6 @@ pub const ErrorMsg = struct {...@@ -1054,7 +1030,6 @@ pub const ErrorMsg = struct {
1054 }1030 }
1055 gpa.free(err_msg.notes);1031 gpa.free(err_msg.notes);
1056 gpa.free(err_msg.msg);1032 gpa.free(err_msg.msg);
1057 gpa.free(err_msg.reference_trace);
1058 err_msg.* = undefined;1033 err_msg.* = undefined;
1059 }1034 }
1060};1035};
...@@ -2027,15 +2002,12 @@ pub const LazySrcLoc = struct {...@@ -2027,15 +2002,12 @@ pub const LazySrcLoc = struct {
2027 entire_file,2002 entire_file,
2028 /// The source location points to a byte offset within a source file,2003 /// The source location points to a byte offset within a source file,
2029 /// offset from 0. The source file is determined contextually.2004 /// offset from 0. The source file is determined contextually.
2030 /// Inside a `SrcLoc`, the `file_scope` union field will be active.
2031 byte_abs: u32,2005 byte_abs: u32,
2032 /// The source location points to a token within a source file,2006 /// The source location points to a token within a source file,
2033 /// offset from 0. The source file is determined contextually.2007 /// offset from 0. The source file is determined contextually.
2034 /// Inside a `SrcLoc`, the `file_scope` union field will be active.
2035 token_abs: u32,2008 token_abs: u32,
2036 /// The source location points to an AST node within a source file,2009 /// The source location points to an AST node within a source file,
2037 /// offset from 0. The source file is determined contextually.2010 /// offset from 0. The source file is determined contextually.
2038 /// Inside a `SrcLoc`, the `file_scope` union field will be active.
2039 node_abs: u32,2011 node_abs: u32,
2040 /// The source location points to a byte offset within a source file,2012 /// The source location points to a byte offset within a source file,
2041 /// offset from the byte offset of the base node within the file.2013 /// offset from the byte offset of the base node within the file.
...@@ -2406,8 +2378,7 @@ pub const LazySrcLoc = struct {...@@ -2406,8 +2378,7 @@ pub const LazySrcLoc = struct {
2406 }2378 }
24072379
2408 /// Resolve the file and AST node of `base_node_inst` to get a resolved `SrcLoc`.2380 /// Resolve the file and AST node of `base_node_inst` to get a resolved `SrcLoc`.
2409 /// TODO: it is incorrect to store a `SrcLoc` anywhere due to incremental compilation.2381 /// The resulting `SrcLoc` should only be used ephemerally, as it is not correct across incremental updates.
2410 /// Probably the type should be removed entirely and this resolution performed on-the-fly when needed.
2411 pub fn upgrade(lazy: LazySrcLoc, zcu: *Zcu) SrcLoc {2382 pub fn upgrade(lazy: LazySrcLoc, zcu: *Zcu) SrcLoc {
2412 const file, const base_node = resolveBaseNode(lazy.base_node_inst, zcu);2383 const file, const base_node = resolveBaseNode(lazy.base_node_inst, zcu);
2413 return .{2384 return .{
...@@ -2452,8 +2423,6 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2452,8 +2423,6 @@ pub fn deinit(zcu: *Zcu) void {
2452 for (zcu.import_table.keys()) |key| {2423 for (zcu.import_table.keys()) |key| {
2453 gpa.free(key);2424 gpa.free(key);
2454 }2425 }
2455 var failed_decls = zcu.failed_decls;
2456 zcu.failed_decls = .{};
2457 for (zcu.import_table.values()) |value| {2426 for (zcu.import_table.values()) |value| {
2458 value.destroy(zcu);2427 value.destroy(zcu);
2459 }2428 }
...@@ -2471,10 +2440,10 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2471,10 +2440,10 @@ pub fn deinit(zcu: *Zcu) void {
2471 zcu.local_zir_cache.handle.close();2440 zcu.local_zir_cache.handle.close();
2472 zcu.global_zir_cache.handle.close();2441 zcu.global_zir_cache.handle.close();
24732442
2474 for (failed_decls.values()) |value| {2443 for (zcu.failed_analysis.values()) |value| {
2475 value.destroy(gpa);2444 value.destroy(gpa);
2476 }2445 }
2477 failed_decls.deinit(gpa);2446 zcu.failed_analysis.deinit(gpa);
24782447
2479 if (zcu.emit_h) |emit_h| {2448 if (zcu.emit_h) |emit_h| {
2480 for (emit_h.failed_decls.values()) |value| {2449 for (emit_h.failed_decls.values()) |value| {
...@@ -2505,22 +2474,12 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2505,22 +2474,12 @@ pub fn deinit(zcu: *Zcu) void {
2505 }2474 }
2506 zcu.cimport_errors.deinit(gpa);2475 zcu.cimport_errors.deinit(gpa);
25072476
2508 zcu.compile_log_decls.deinit(gpa);2477 zcu.compile_log_sources.deinit(gpa);
25092478
2510 for (zcu.decl_exports.values()) |*export_list| {2479 zcu.all_exports.deinit(gpa);
2511 export_list.deinit(gpa);2480 zcu.free_exports.deinit(gpa);
2512 }2481 zcu.single_exports.deinit(gpa);
2513 zcu.decl_exports.deinit(gpa);2482 zcu.multi_exports.deinit(gpa);
2514
2515 for (zcu.value_exports.values()) |*export_list| {
2516 export_list.deinit(gpa);
2517 }
2518 zcu.value_exports.deinit(gpa);
2519
2520 for (zcu.export_owners.values()) |*value| {
2521 freeExportList(gpa, value);
2522 }
2523 zcu.export_owners.deinit(gpa);
25242483
2525 zcu.global_error_set.deinit(gpa);2484 zcu.global_error_set.deinit(gpa);
25262485
...@@ -2538,6 +2497,8 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2538,6 +2497,8 @@ pub fn deinit(zcu: *Zcu) void {
2538 zcu.global_assembly.deinit(gpa);2497 zcu.global_assembly.deinit(gpa);
25392498
2540 zcu.reference_table.deinit(gpa);2499 zcu.reference_table.deinit(gpa);
2500 zcu.all_references.deinit(gpa);
2501 zcu.free_references.deinit(gpa);
25412502
2542 {2503 {
2543 var it = zcu.intern_pool.allocated_namespaces.iterator(0);2504 var it = zcu.intern_pool.allocated_namespaces.iterator(0);
...@@ -2590,11 +2551,6 @@ pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {...@@ -2590,11 +2551,6 @@ pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
2590 return decl_index == namespace.decl_index;2551 return decl_index == namespace.decl_index;
2591}2552}
25922553
2593fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {
2594 for (export_list.items) |exp| gpa.destroy(exp);
2595 export_list.deinit(gpa);
2596}
2597
2598// TODO https://github.com/ziglang/zig/issues/86432554// TODO https://github.com/ziglang/zig/issues/8643
2599const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;2555const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
2600const HackDataLayout = extern struct {2556const HackDataLayout = extern struct {
...@@ -3137,9 +3093,9 @@ fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {...@@ -3137,9 +3093,9 @@ fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void {
3137 }3093 }
3138}3094}
31393095
3140/// Given a AnalSubject which is newly outdated or PO, mark all AnalSubjects which may3096/// Given a AnalUnit which is newly outdated or PO, mark all AnalUnits which may
3141/// in turn be PO, due to a dependency on the original AnalSubject's tyval or IES.3097/// in turn be PO, due to a dependency on the original AnalUnit's tyval or IES.
3142fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternPool.AnalSubject) !void {3098fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUnit) !void {
3143 var it = zcu.intern_pool.dependencyIterator(switch (maybe_outdated.unwrap()) {3099 var it = zcu.intern_pool.dependencyIterator(switch (maybe_outdated.unwrap()) {
3144 .decl => |decl_index| .{ .decl_val = decl_index }, // TODO: also `decl_ref` deps when introduced3100 .decl => |decl_index| .{ .decl_val = decl_index }, // TODO: also `decl_ref` deps when introduced
3145 .func => |func_index| .{ .func_ies = func_index },3101 .func => |func_index| .{ .func_ies = func_index },
...@@ -3161,12 +3117,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternP...@@ -3161,12 +3117,12 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternP
3161 continue;3117 continue;
3162 }3118 }
3163 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);3119 try zcu.potentially_outdated.putNoClobber(zcu.gpa, po, 1);
3164 // This AnalSubject was not already PO, so we must recursively mark its dependers as also PO.3120 // This AnalUnit was not already PO, so we must recursively mark its dependers as also PO.
3165 try zcu.markTransitiveDependersPotentiallyOutdated(po);3121 try zcu.markTransitiveDependersPotentiallyOutdated(po);
3166 }3122 }
3167}3123}
31683124
3169pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject {3125pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
3170 if (!zcu.comp.debug_incremental) return null;3126 if (!zcu.comp.debug_incremental) return null;
31713127
3172 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {3128 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {
...@@ -3174,8 +3130,8 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject...@@ -3174,8 +3130,8 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject
3174 return null;3130 return null;
3175 }3131 }
31763132
3177 // Our goal is to find an outdated AnalSubject which itself has no outdated or3133 // Our goal is to find an outdated AnalUnit which itself has no outdated or
3178 // PO dependencies. Most of the time, such an AnalSubject will exist - we track3134 // PO dependencies. Most of the time, such an AnalUnit will exist - we track
3179 // them in the `outdated_ready` set for efficiency. However, this is not3135 // them in the `outdated_ready` set for efficiency. However, this is not
3180 // necessarily the case, since the Decl dependency graph may contain loops3136 // necessarily the case, since the Decl dependency graph may contain loops
3181 // via mutually recursive definitions:3137 // via mutually recursive definitions:
...@@ -3197,7 +3153,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject...@@ -3197,7 +3153,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject
3197 // `outdated`. This set will be small (number of files changed in this3153 // `outdated`. This set will be small (number of files changed in this
3198 // update), so it's alright for us to just iterate here.3154 // update), so it's alright for us to just iterate here.
3199 for (zcu.outdated_file_root.keys()) |file_decl| {3155 for (zcu.outdated_file_root.keys()) |file_decl| {
3200 const decl_depender = InternPool.AnalSubject.wrap(.{ .decl = file_decl });3156 const decl_depender = AnalUnit.wrap(.{ .decl = file_decl });
3201 if (zcu.outdated.contains(decl_depender)) {3157 if (zcu.outdated.contains(decl_depender)) {
3202 // Since we didn't hit this in the first loop, this Decl must have3158 // Since we didn't hit this in the first loop, this Decl must have
3203 // pending dependencies, so is ineligible.3159 // pending dependencies, so is ineligible.
...@@ -3213,7 +3169,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject...@@ -3213,7 +3169,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject
3213 return decl_depender;3169 return decl_depender;
3214 }3170 }
32153171
3216 // There is no single AnalSubject which is ready for re-analysis. Instead, we3172 // There is no single AnalUnit which is ready for re-analysis. Instead, we
3217 // must assume that some Decl with PO dependencies is outdated - e.g. in the3173 // must assume that some Decl with PO dependencies is outdated - e.g. in the
3218 // above example we arbitrarily pick one of A or B. We should select a Decl,3174 // above example we arbitrarily pick one of A or B. We should select a Decl,
3219 // since a Decl is definitely responsible for the loop in the dependency3175 // since a Decl is definitely responsible for the loop in the dependency
...@@ -3221,7 +3177,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject...@@ -3221,7 +3177,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject
32213177
3222 // The choice of this Decl could have a big impact on how much total3178 // The choice of this Decl could have a big impact on how much total
3223 // analysis we perform, since if analysis concludes its tyval is unchanged,3179 // analysis we perform, since if analysis concludes its tyval is unchanged,
3224 // then other PO AnalSubject may be resolved as up-to-date. To hopefully avoid3180 // then other PO AnalUnit may be resolved as up-to-date. To hopefully avoid
3225 // doing too much work, let's find a Decl which the most things depend on -3181 // doing too much work, let's find a Decl which the most things depend on -
3226 // the idea is that this will resolve a lot of loops (but this is only a3182 // the idea is that this will resolve a lot of loops (but this is only a
3227 // heuristic).3183 // heuristic).
...@@ -3271,7 +3227,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject...@@ -3271,7 +3227,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject
3271 chosen_decl_dependers,3227 chosen_decl_dependers,
3272 });3228 });
32733229
3274 return InternPool.AnalSubject.wrap(.{ .decl = chosen_decl_idx.? });3230 return AnalUnit.wrap(.{ .decl = chosen_decl_idx.? });
3275}3231}
32763232
3277/// During an incremental update, before semantic analysis, call this to flush all values from3233/// During an incremental update, before semantic analysis, call this to flush all values from
...@@ -3281,12 +3237,12 @@ pub fn flushRetryableFailures(zcu: *Zcu) !void {...@@ -3281,12 +3237,12 @@ pub fn flushRetryableFailures(zcu: *Zcu) !void {
3281 for (zcu.retryable_failures.items) |depender| {3237 for (zcu.retryable_failures.items) |depender| {
3282 if (zcu.outdated.contains(depender)) continue;3238 if (zcu.outdated.contains(depender)) continue;
3283 if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| {3239 if (zcu.potentially_outdated.fetchSwapRemove(depender)) |kv| {
3284 // This AnalSubject was already PO, but we now consider it outdated.3240 // This AnalUnit was already PO, but we now consider it outdated.
3285 // Any transitive dependencies are already marked PO.3241 // Any transitive dependencies are already marked PO.
3286 try zcu.outdated.put(gpa, depender, kv.value);3242 try zcu.outdated.put(gpa, depender, kv.value);
3287 continue;3243 continue;
3288 }3244 }
3289 // This AnalSubject was not marked PO, but is now outdated. Mark it as3245 // This AnalUnit was not marked PO, but is now outdated. Mark it as
3290 // such, then recursively mark transitive dependencies as PO.3246 // such, then recursively mark transitive dependencies as PO.
3291 try zcu.outdated.put(gpa, depender, 0);3247 try zcu.outdated.put(gpa, depender, 0);
3292 try zcu.markTransitiveDependersPotentiallyOutdated(depender);3248 try zcu.markTransitiveDependersPotentiallyOutdated(depender);
...@@ -3456,7 +3412,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3456,7 +3412,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3456 // which tries to limit re-analysis to Decls whose previously listed3412 // which tries to limit re-analysis to Decls whose previously listed
3457 // dependencies are all up-to-date.3413 // dependencies are all up-to-date.
34583414
3459 const decl_as_depender = InternPool.AnalSubject.wrap(.{ .decl = decl_index });3415 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });
3460 const decl_was_outdated = mod.outdated.swapRemove(decl_as_depender) or3416 const decl_was_outdated = mod.outdated.swapRemove(decl_as_depender) or
3461 mod.potentially_outdated.swapRemove(decl_as_depender);3417 mod.potentially_outdated.swapRemove(decl_as_depender);
34623418
...@@ -3485,7 +3441,8 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3485,7 +3441,8 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3485 // The exports this Decl performs will be re-discovered, so we remove them here3441 // The exports this Decl performs will be re-discovered, so we remove them here
3486 // prior to re-analysis.3442 // prior to re-analysis.
3487 if (build_options.only_c) unreachable;3443 if (build_options.only_c) unreachable;
3488 try mod.deleteDeclExports(decl_index);3444 mod.deleteUnitExports(decl_as_depender);
3445 mod.deleteUnitReferences(decl_as_depender);
3489 }3446 }
34903447
3491 const sema_result: SemaDeclResult = blk: {3448 const sema_result: SemaDeclResult = blk: {
...@@ -3521,11 +3478,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -3521,11 +3478,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
3521 error.GenericPoison => unreachable,3478 error.GenericPoison => unreachable,
3522 else => |e| {3479 else => |e| {
3523 decl.analysis = .sema_failure;3480 decl.analysis = .sema_failure;
3524 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);3481 try mod.failed_analysis.ensureUnusedCapacity(mod.gpa, 1);
3525 try mod.retryable_failures.append(mod.gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));3482 try mod.retryable_failures.append(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
3526 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(3483 mod.failed_analysis.putAssumeCapacityNoClobber(AnalUnit.wrap(.{ .decl = decl_index }), try ErrorMsg.create(
3527 mod.gpa,3484 mod.gpa,
3528 decl.navSrcLoc(mod).upgrade(mod),3485 decl.navSrcLoc(mod),
3529 "unable to analyze: {s}",3486 "unable to analyze: {s}",
3530 .{@errorName(e)},3487 .{@errorName(e)},
3531 ));3488 ));
...@@ -3581,7 +3538,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3581,7 +3538,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3581 // that's the case, we should remove this function from the binary.3538 // that's the case, we should remove this function from the binary.
3582 if (decl.val.ip_index != func_index) {3539 if (decl.val.ip_index != func_index) {
3583 try zcu.markDependeeOutdated(.{ .func_ies = func_index });3540 try zcu.markDependeeOutdated(.{ .func_ies = func_index });
3584 ip.removeDependenciesForDepender(gpa, InternPool.AnalSubject.wrap(.{ .func = func_index }));3541 ip.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index }));
3585 ip.remove(func_index);3542 ip.remove(func_index);
3586 @panic("TODO: remove orphaned function from binary");3543 @panic("TODO: remove orphaned function from binary");
3587 }3544 }
...@@ -3607,12 +3564,15 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3607,12 +3564,15 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3607 .complete => {},3564 .complete => {},
3608 }3565 }
36093566
3610 const func_as_depender = InternPool.AnalSubject.wrap(.{ .func = func_index });3567 const func_as_depender = AnalUnit.wrap(.{ .func = func_index });
3611 const was_outdated = zcu.outdated.swapRemove(func_as_depender) or3568 const was_outdated = zcu.outdated.swapRemove(func_as_depender) or
3612 zcu.potentially_outdated.swapRemove(func_as_depender);3569 zcu.potentially_outdated.swapRemove(func_as_depender);
36133570
3614 if (was_outdated) {3571 if (was_outdated) {
3572 if (build_options.only_c) unreachable;
3615 _ = zcu.outdated_ready.swapRemove(func_as_depender);3573 _ = zcu.outdated_ready.swapRemove(func_as_depender);
3574 zcu.deleteUnitExports(func_as_depender);
3575 zcu.deleteUnitReferences(func_as_depender);
3616 }3576 }
36173577
3618 switch (func.analysis(ip).state) {3578 switch (func.analysis(ip).state) {
...@@ -3647,7 +3607,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3647,7 +3607,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3647 },3607 },
3648 error.OutOfMemory => return error.OutOfMemory,3608 error.OutOfMemory => return error.OutOfMemory,
3649 };3609 };
3650 defer air.deinit(gpa);3610 errdefer air.deinit(gpa);
36513611
3652 const invalidate_ies_deps = i: {3612 const invalidate_ies_deps = i: {
3653 if (!was_outdated) break :i false;3613 if (!was_outdated) break :i false;
...@@ -3669,13 +3629,36 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3669,13 +3629,36 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3669 const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);3629 const dump_llvm_ir = build_options.enable_debug_extensions and (comp.verbose_llvm_ir != null or comp.verbose_llvm_bc != null);
36703630
3671 if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {3631 if (comp.bin_file == null and zcu.llvm_object == null and !dump_air and !dump_llvm_ir) {
3632 air.deinit(gpa);
3672 return;3633 return;
3673 }3634 }
36743635
3636 try comp.work_queue.writeItem(.{ .codegen_func = .{
3637 .func = func_index,
3638 .air = air,
3639 } });
3640}
3641
3642/// Takes ownership of `air`, even on error.
3643/// If any types referenced by `air` are unresolved, marks the codegen as failed.
3644pub fn linkerUpdateFunc(zcu: *Zcu, func_index: InternPool.Index, air: Air) Allocator.Error!void {
3645 const gpa = zcu.gpa;
3646 const ip = &zcu.intern_pool;
3647 const comp = zcu.comp;
3648
3649 defer {
3650 var air_mut = air;
3651 air_mut.deinit(gpa);
3652 }
3653
3654 const func = zcu.funcInfo(func_index);
3655 const decl_index = func.owner_decl;
3656 const decl = zcu.declPtr(decl_index);
3657
3675 var liveness = try Liveness.analyze(gpa, air, ip);3658 var liveness = try Liveness.analyze(gpa, air, ip);
3676 defer liveness.deinit(gpa);3659 defer liveness.deinit(gpa);
36773660
3678 if (dump_air) {3661 if (build_options.enable_debug_extensions and comp.verbose_air) {
3679 const fqn = try decl.fullyQualifiedName(zcu);3662 const fqn = try decl.fullyQualifiedName(zcu);
3680 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});3663 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
3681 @import("print_air.zig").dump(zcu, air, liveness);3664 @import("print_air.zig").dump(zcu, air, liveness);
...@@ -3683,7 +3666,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3683,7 +3666,7 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3683 }3666 }
36843667
3685 if (std.debug.runtime_safety) {3668 if (std.debug.runtime_safety) {
3686 var verify = Liveness.Verify{3669 var verify: Liveness.Verify = .{
3687 .gpa = gpa,3670 .gpa = gpa,
3688 .air = air,3671 .air = air,
3689 .liveness = liveness,3672 .liveness = liveness,
...@@ -3694,12 +3677,12 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3694,12 +3677,12 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3694 verify.verify() catch |err| switch (err) {3677 verify.verify() catch |err| switch (err) {
3695 error.OutOfMemory => return error.OutOfMemory,3678 error.OutOfMemory => return error.OutOfMemory,
3696 else => {3679 else => {
3697 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);3680 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
3698 zcu.failed_decls.putAssumeCapacityNoClobber(3681 zcu.failed_analysis.putAssumeCapacityNoClobber(
3699 decl_index,3682 AnalUnit.wrap(.{ .func = func_index }),
3700 try Module.ErrorMsg.create(3683 try Module.ErrorMsg.create(
3701 gpa,3684 gpa,
3702 decl.navSrcLoc(zcu).upgrade(zcu),3685 decl.navSrcLoc(zcu),
3703 "invalid liveness: {s}",3686 "invalid liveness: {s}",
3704 .{@errorName(err)},3687 .{@errorName(err)},
3705 ),3688 ),
...@@ -3713,31 +3696,34 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In...@@ -3713,31 +3696,34 @@ pub fn ensureFuncBodyAnalyzed(zcu: *Zcu, maybe_coerced_func_index: InternPool.In
3713 const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(zcu)).toSlice(ip), 0);3696 const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(zcu)).toSlice(ip), 0);
3714 defer codegen_prog_node.end();3697 defer codegen_prog_node.end();
37153698
3716 if (comp.bin_file) |lf| {3699 if (!air.typesFullyResolved(zcu)) {
3700 // A type we depend on failed to resolve. This is a transitive failure.
3701 // Correcting this failure will involve changing a type this function
3702 // depends on, hence triggering re-analysis of this function, so this
3703 // interacts correctly with incremental compilation.
3704 func.analysis(ip).state = .codegen_failure;
3705 } else if (comp.bin_file) |lf| {
3717 lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {3706 lf.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3718 error.OutOfMemory => return error.OutOfMemory,3707 error.OutOfMemory => return error.OutOfMemory,
3719 error.AnalysisFail => {3708 error.AnalysisFail => {
3720 func.analysis(ip).state = .codegen_failure;3709 func.analysis(ip).state = .codegen_failure;
3721 },3710 },
3722 else => {3711 else => {
3723 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);3712 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
3724 zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(3713 zcu.failed_analysis.putAssumeCapacityNoClobber(AnalUnit.wrap(.{ .func = func_index }), try Module.ErrorMsg.create(
3725 gpa,3714 gpa,
3726 decl.navSrcLoc(zcu).upgrade(zcu),3715 decl.navSrcLoc(zcu),
3727 "unable to codegen: {s}",3716 "unable to codegen: {s}",
3728 .{@errorName(err)},3717 .{@errorName(err)},
3729 ));3718 ));
3730 func.analysis(ip).state = .codegen_failure;3719 func.analysis(ip).state = .codegen_failure;
3731 try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalSubject.wrap(.{ .func = func_index }));3720 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .func = func_index }));
3732 },3721 },
3733 };3722 };
3734 } else if (zcu.llvm_object) |llvm_object| {3723 } else if (zcu.llvm_object) |llvm_object| {
3735 if (build_options.only_c) unreachable;3724 if (build_options.only_c) unreachable;
3736 llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {3725 llvm_object.updateFunc(zcu, func_index, air, liveness) catch |err| switch (err) {
3737 error.OutOfMemory => return error.OutOfMemory,3726 error.OutOfMemory => return error.OutOfMemory,
3738 error.AnalysisFail => {
3739 func.analysis(ip).state = .codegen_failure;
3740 },
3741 };3727 };
3742 }3728 }
3743}3729}
...@@ -3773,7 +3759,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)...@@ -3773,7 +3759,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)
37733759
3774 assert(decl.has_tv);3760 assert(decl.has_tv);
37753761
3776 const func_as_depender = InternPool.AnalSubject.wrap(.{ .func = func_index });3762 const func_as_depender = AnalUnit.wrap(.{ .func = func_index });
3777 const is_outdated = mod.outdated.contains(func_as_depender) or3763 const is_outdated = mod.outdated.contains(func_as_depender) or
3778 mod.potentially_outdated.contains(func_as_depender);3764 mod.potentially_outdated.contains(func_as_depender);
37793765
...@@ -3792,7 +3778,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)...@@ -3792,7 +3778,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: InternPool.Index)
37923778
3793 // Decl itself is safely analyzed, and body analysis is not yet queued3779 // Decl itself is safely analyzed, and body analysis is not yet queued
37943780
3795 try mod.comp.work_queue.writeItem(.{ .codegen_func = func_index });3781 try mod.comp.work_queue.writeItem(.{ .analyze_func = func_index });
3796 if (mod.emit_h != null) {3782 if (mod.emit_h != null) {
3797 // TODO: we ideally only want to do this if the function's type changed3783 // TODO: we ideally only want to do this if the function's type changed
3798 // since the last update3784 // since the last update
...@@ -3857,7 +3843,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa...@@ -3857,7 +3843,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa
3857 if (zcu.comp.debug_incremental) {3843 if (zcu.comp.debug_incremental) {
3858 try ip.addDependency(3844 try ip.addDependency(
3859 gpa,3845 gpa,
3860 InternPool.AnalSubject.wrap(.{ .decl = decl_index }),3846 AnalUnit.wrap(.{ .decl = decl_index }),
3861 .{ .src_hash = tracked_inst },3847 .{ .src_hash = tracked_inst },
3862 );3848 );
3863 }3849 }
...@@ -3869,7 +3855,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa...@@ -3869,7 +3855,7 @@ fn getFileRootStruct(zcu: *Zcu, decl_index: Decl.Index, namespace_index: Namespa
3869 decl.analysis = .complete;3855 decl.analysis = .complete;
38703856
3871 try zcu.scanNamespace(namespace_index, decls, decl);3857 try zcu.scanNamespace(namespace_index, decls, decl);
38723858 try zcu.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
3873 return wip_ty.finish(ip, decl_index, namespace_index.toOptional());3859 return wip_ty.finish(ip, decl_index, namespace_index.toOptional());
3874}3860}
38753861
...@@ -3906,7 +3892,7 @@ fn semaFileUpdate(zcu: *Zcu, file: *File, type_outdated: bool) SemaError!bool {...@@ -3906,7 +3892,7 @@ fn semaFileUpdate(zcu: *Zcu, file: *File, type_outdated: bool) SemaError!bool {
39063892
3907 if (type_outdated) {3893 if (type_outdated) {
3908 // Invalidate the existing type, reusing the decl and namespace.3894 // Invalidate the existing type, reusing the decl and namespace.
3909 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalSubject.wrap(.{ .decl = file.root_decl.unwrap().? }));3895 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = file.root_decl.unwrap().? }));
3910 zcu.intern_pool.remove(decl.val.toIntern());3896 zcu.intern_pool.remove(decl.val.toIntern());
3911 decl.val = undefined;3897 decl.val = undefined;
3912 _ = try zcu.getFileRootStruct(file.root_decl.unwrap().?, decl.src_namespace, file);3898 _ = try zcu.getFileRootStruct(file.root_decl.unwrap().?, decl.src_namespace, file);
...@@ -4097,7 +4083,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -4097,7 +4083,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
4097 break :ip_index .none;4083 break :ip_index .none;
4098 };4084 };
40994085
4100 mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));4086 mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .decl = decl_index }));
41014087
4102 decl.analysis = .in_progress;4088 decl.analysis = .in_progress;
41034089
...@@ -4160,7 +4146,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -4160,7 +4146,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
4160 // Note this resolves the type of the Decl, not the value; if this Decl4146 // Note this resolves the type of the Decl, not the value; if this Decl
4161 // is a struct, for example, this resolves `type` (which needs no resolution),4147 // is a struct, for example, this resolves `type` (which needs no resolution),
4162 // not the struct itself.4148 // not the struct itself.
4163 try sema.resolveTypeLayout(decl_ty);4149 try decl_ty.resolveLayout(mod);
41644150
4165 if (decl.kind == .@"usingnamespace") {4151 if (decl.kind == .@"usingnamespace") {
4166 if (!decl_ty.eql(Type.type, mod)) {4152 if (!decl_ty.eql(Type.type, mod)) {
...@@ -4277,7 +4263,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -4277,7 +4263,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
4277 if (has_runtime_bits) {4263 if (has_runtime_bits) {
4278 // Needed for codegen_decl which will call updateDecl and then the4264 // Needed for codegen_decl which will call updateDecl and then the
4279 // codegen backend wants full access to the Decl Type.4265 // codegen backend wants full access to the Decl Type.
4280 try sema.resolveTypeFully(decl_ty);4266 try decl_ty.resolveFully(mod);
42814267
4282 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });4268 try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
42834269
...@@ -4293,6 +4279,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {...@@ -4293,6 +4279,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult {
4293 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);4279 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
4294 }4280 }
42954281
4282 try sema.flushExports();
4283
4296 return result;4284 return result;
4297}4285}
42984286
...@@ -4323,7 +4311,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult {...@@ -4323,7 +4311,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult {
4323 // with a new Decl.4311 // with a new Decl.
4324 //4312 //
4325 // Yes, this does mean that any type owner Decl has a constant value for its entire lifetime.4313 // Yes, this does mean that any type owner Decl has a constant value for its entire lifetime.
4326 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));4314 zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
4327 zcu.intern_pool.remove(decl.val.toIntern());4315 zcu.intern_pool.remove(decl.val.toIntern());
4328 decl.analysis = .dependency_failure;4316 decl.analysis = .dependency_failure;
4329 return .{4317 return .{
...@@ -4525,7 +4513,7 @@ pub fn embedFile(...@@ -4525,7 +4513,7 @@ pub fn embedFile(
4525 mod: *Module,4513 mod: *Module,
4526 cur_file: *File,4514 cur_file: *File,
4527 import_string: []const u8,4515 import_string: []const u8,
4528 src_loc: SrcLoc,4516 src_loc: LazySrcLoc,
4529) !InternPool.Index {4517) !InternPool.Index {
4530 const gpa = mod.gpa;4518 const gpa = mod.gpa;
45314519
...@@ -4600,7 +4588,7 @@ fn newEmbedFile(...@@ -4600,7 +4588,7 @@ fn newEmbedFile(
4600 sub_file_path: []const u8,4588 sub_file_path: []const u8,
4601 resolved_path: []const u8,4589 resolved_path: []const u8,
4602 result: **EmbedFile,4590 result: **EmbedFile,
4603 src_loc: SrcLoc,4591 src_loc: LazySrcLoc,
4604) !InternPool.Index {4592) !InternPool.Index {
4605 const gpa = mod.gpa;4593 const gpa = mod.gpa;
4606 const ip = &mod.intern_pool;4594 const ip = &mod.intern_pool;
...@@ -4949,63 +4937,85 @@ pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!vo...@@ -4949,63 +4937,85 @@ pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!vo
4949 }4937 }
4950}4938}
49514939
4952/// Delete all the Export objects that are caused by this Decl. Re-analysis of4940/// Delete all the Export objects that are caused by this `AnalUnit`. Re-analysis of
4953/// this Decl will cause them to be re-created (or not).4941/// this `AnalUnit` will cause them to be re-created (or not).
4954fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {4942pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
4955 var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;4943 const gpa = zcu.gpa;
49564944
4957 for (export_owners.items) |exp| {4945 const exports_base, const exports_len = if (zcu.single_exports.fetchSwapRemove(anal_unit)) |kv|
4958 switch (exp.exported) {4946 .{ kv.value, 1 }
4959 .decl_index => |exported_decl_index| {4947 else if (zcu.multi_exports.fetchSwapRemove(anal_unit)) |info|
4960 if (mod.decl_exports.getPtr(exported_decl_index)) |export_list| {4948 .{ info.value.index, info.value.len }
4961 // Remove exports with owner_decl matching the regenerating decl.4949 else
4962 const list = export_list.items;4950 return;
4963 var i: usize = 0;4951
4964 var new_len = list.len;4952 const exports = zcu.all_exports.items[exports_base..][0..exports_len];
4965 while (i < new_len) {4953
4966 if (list[i].owner_decl == decl_index) {4954 // In an only-c build, we're guaranteed to never use incremental compilation, so there are
4967 mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]);4955 // guaranteed not to be any exports in the output file that need deleting (since we only call
4968 new_len -= 1;4956 // `updateExports` on flush).
4969 } else {4957 // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports
4970 i += 1;4958 // within a single update.
4971 }4959 if (!build_options.only_c) {
4972 }4960 for (exports, exports_base..) |exp, export_idx| {
4973 export_list.shrinkAndFree(mod.gpa, new_len);4961 if (zcu.comp.bin_file) |lf| {
4974 if (new_len == 0) {4962 lf.deleteExport(exp.exported, exp.opts.name);
4975 assert(mod.decl_exports.swapRemove(exported_decl_index));4963 }
4976 }4964 if (zcu.failed_exports.fetchSwapRemove(@intCast(export_idx))) |failed_kv| {
4977 }4965 failed_kv.value.destroy(gpa);
4978 },4966 }
4979 .value => |value| {
4980 if (mod.value_exports.getPtr(value)) |export_list| {
4981 // Remove exports with owner_decl matching the regenerating decl.
4982 const list = export_list.items;
4983 var i: usize = 0;
4984 var new_len = list.len;
4985 while (i < new_len) {
4986 if (list[i].owner_decl == decl_index) {
4987 mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]);
4988 new_len -= 1;
4989 } else {
4990 i += 1;
4991 }
4992 }
4993 export_list.shrinkAndFree(mod.gpa, new_len);
4994 if (new_len == 0) {
4995 assert(mod.value_exports.swapRemove(value));
4996 }
4997 }
4998 },
4999 }
5000 if (mod.comp.bin_file) |lf| {
5001 try lf.deleteDeclExport(decl_index, exp.opts.name);
5002 }
5003 if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| {
5004 failed_kv.value.destroy(mod.gpa);
5005 }4967 }
5006 mod.gpa.destroy(exp);
5007 }4968 }
5008 export_owners.deinit(mod.gpa);4969
4970 zcu.free_exports.ensureUnusedCapacity(gpa, exports_len) catch {
4971 // This space will be reused eventually, so we need not propagate this error.
4972 // Just leak it for now, and let GC reclaim it later on.
4973 return;
4974 };
4975 for (exports_base..exports_base + exports_len) |export_idx| {
4976 zcu.free_exports.appendAssumeCapacity(@intCast(export_idx));
4977 }
4978}
4979
4980/// Delete all references in `reference_table` which are caused by this `AnalUnit`.
4981/// Re-analysis of the `AnalUnit` will cause appropriate references to be recreated.
4982fn deleteUnitReferences(zcu: *Zcu, anal_unit: AnalUnit) void {
4983 const gpa = zcu.gpa;
4984
4985 const kv = zcu.reference_table.fetchSwapRemove(anal_unit) orelse return;
4986 var idx = kv.value;
4987
4988 while (idx != std.math.maxInt(u32)) {
4989 zcu.free_references.append(gpa, idx) catch {
4990 // This space will be reused eventually, so we need not propagate this error.
4991 // Just leak it for now, and let GC reclaim it later on.
4992 return;
4993 };
4994 idx = zcu.all_references.items[idx].next;
4995 }
4996}
4997
4998pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit, ref_src: LazySrcLoc) Allocator.Error!void {
4999 const gpa = zcu.gpa;
5000
5001 try zcu.reference_table.ensureUnusedCapacity(gpa, 1);
5002
5003 const ref_idx = zcu.free_references.popOrNull() orelse idx: {
5004 _ = try zcu.all_references.addOne(gpa);
5005 break :idx zcu.all_references.items.len - 1;
5006 };
5007
5008 errdefer comptime unreachable;
5009
5010 const gop = zcu.reference_table.getOrPutAssumeCapacity(src_unit);
5011
5012 zcu.all_references.items[ref_idx] = .{
5013 .referenced = referenced_unit,
5014 .next = if (gop.found_existing) gop.value_ptr.* else std.math.maxInt(u32),
5015 .src = ref_src,
5016 };
5017
5018 gop.value_ptr.* = @intCast(ref_idx);
5009}5019}
50105020
5011pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air {5021pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air {
...@@ -5026,7 +5036,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -5026,7 +5036,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
5026 const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0);5036 const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0);
5027 defer decl_prog_node.end();5037 defer decl_prog_node.end();
50285038
5029 mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalSubject.wrap(.{ .func = func_index }));5039 mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index }));
50305040
5031 var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa);5041 var comptime_err_ret_trace = std.ArrayList(LazySrcLoc).init(gpa);
5032 defer comptime_err_ret_trace.deinit();5042 defer comptime_err_ret_trace.deinit();
...@@ -5245,22 +5255,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -5245,22 +5255,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
5245 else => |e| return e,5255 else => |e| return e,
5246 };5256 };
52475257
5248 // Similarly, resolve any queued up types that were requested to be resolved for5258 try sema.flushExports();
5249 // the backends.
5250 for (sema.types_to_resolve.keys()) |ty| {
5251 sema.resolveTypeFully(Type.fromInterned(ty)) catch |err| switch (err) {
5252 error.GenericPoison => unreachable,
5253 error.ComptimeReturn => unreachable,
5254 error.ComptimeBreak => unreachable,
5255 error.AnalysisFail => {
5256 // In this case our function depends on a type that had a compile error.
5257 // We should not try to lower this function.
5258 decl.analysis = .dependency_failure;
5259 return error.AnalysisFail;
5260 },
5261 else => |e| return e,
5262 };
5263 }
52645259
5265 return .{5260 return .{
5266 .instructions = sema.air_instructions.toOwnedSlice(),5261 .instructions = sema.air_instructions.toOwnedSlice(),
...@@ -5341,17 +5336,13 @@ pub fn initNewAnonDecl(...@@ -5341,17 +5336,13 @@ pub fn initNewAnonDecl(
5341 new_decl.analysis = .complete;5336 new_decl.analysis = .complete;
5342}5337}
53435338
5344pub fn errNoteNonLazy(5339pub fn errNote(
5345 mod: *Module,5340 mod: *Module,
5346 src_loc: SrcLoc,5341 src_loc: LazySrcLoc,
5347 parent: *ErrorMsg,5342 parent: *ErrorMsg,
5348 comptime format: []const u8,5343 comptime format: []const u8,
5349 args: anytype,5344 args: anytype,
5350) error{OutOfMemory}!void {5345) error{OutOfMemory}!void {
5351 if (src_loc.lazy == .unneeded) {
5352 assert(parent.src_loc.lazy == .unneeded);
5353 return;
5354 }
5355 const msg = try std.fmt.allocPrint(mod.gpa, format, args);5346 const msg = try std.fmt.allocPrint(mod.gpa, format, args);
5356 errdefer mod.gpa.free(msg);5347 errdefer mod.gpa.free(msg);
53575348
...@@ -5392,76 +5383,130 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void {...@@ -5392,76 +5383,130 @@ fn lockAndClearFileCompileError(mod: *Module, file: *File) void {
5392/// Called from `Compilation.update`, after everything is done, just before5383/// Called from `Compilation.update`, after everything is done, just before
5393/// reporting compile errors. In this function we emit exported symbol collision5384/// reporting compile errors. In this function we emit exported symbol collision
5394/// errors and communicate exported symbols to the linker backend.5385/// errors and communicate exported symbols to the linker backend.
5395pub fn processExports(mod: *Module) !void {5386pub fn processExports(zcu: *Zcu) !void {
5387 const gpa = zcu.gpa;
5388
5389 // First, construct a mapping of every exported value and Decl to the indices of all its different exports.
5390 var decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(u32)) = .{};
5391 var value_exports: std.AutoArrayHashMapUnmanaged(InternPool.Index, ArrayListUnmanaged(u32)) = .{};
5392 defer {
5393 for (decl_exports.values()) |*exports| {
5394 exports.deinit(gpa);
5395 }
5396 decl_exports.deinit(gpa);
5397 for (value_exports.values()) |*exports| {
5398 exports.deinit(gpa);
5399 }
5400 value_exports.deinit(gpa);
5401 }
5402
5403 // We note as a heuristic:
5404 // * It is rare to export a value.
5405 // * It is rare for one Decl to be exported multiple times.
5406 // So, this ensureTotalCapacity serves as a reasonable (albeit very approximate) optimization.
5407 try decl_exports.ensureTotalCapacity(gpa, zcu.single_exports.count() + zcu.multi_exports.count());
5408
5409 for (zcu.single_exports.values()) |export_idx| {
5410 const exp = zcu.all_exports.items[export_idx];
5411 const value_ptr, const found_existing = switch (exp.exported) {
5412 .decl_index => |i| gop: {
5413 const gop = try decl_exports.getOrPut(gpa, i);
5414 break :gop .{ gop.value_ptr, gop.found_existing };
5415 },
5416 .value => |i| gop: {
5417 const gop = try value_exports.getOrPut(gpa, i);
5418 break :gop .{ gop.value_ptr, gop.found_existing };
5419 },
5420 };
5421 if (!found_existing) value_ptr.* = .{};
5422 try value_ptr.append(gpa, export_idx);
5423 }
5424
5425 for (zcu.multi_exports.values()) |info| {
5426 for (zcu.all_exports.items[info.index..][0..info.len], info.index..) |exp, export_idx| {
5427 const value_ptr, const found_existing = switch (exp.exported) {
5428 .decl_index => |i| gop: {
5429 const gop = try decl_exports.getOrPut(gpa, i);
5430 break :gop .{ gop.value_ptr, gop.found_existing };
5431 },
5432 .value => |i| gop: {
5433 const gop = try value_exports.getOrPut(gpa, i);
5434 break :gop .{ gop.value_ptr, gop.found_existing };
5435 },
5436 };
5437 if (!found_existing) value_ptr.* = .{};
5438 try value_ptr.append(gpa, @intCast(export_idx));
5439 }
5440 }
5441
5396 // Map symbol names to `Export` for name collision detection.5442 // Map symbol names to `Export` for name collision detection.
5397 var symbol_exports: SymbolExports = .{};5443 var symbol_exports: SymbolExports = .{};
5398 defer symbol_exports.deinit(mod.gpa);5444 defer symbol_exports.deinit(gpa);
53995445
5400 for (mod.decl_exports.keys(), mod.decl_exports.values()) |exported_decl, exports_list| {5446 for (decl_exports.keys(), decl_exports.values()) |exported_decl, exports_list| {
5401 const exported: Exported = .{ .decl_index = exported_decl };5447 const exported: Exported = .{ .decl_index = exported_decl };
5402 try processExportsInner(mod, &symbol_exports, exported, exports_list.items);5448 try processExportsInner(zcu, &symbol_exports, exported, exports_list.items);
5403 }5449 }
54045450
5405 for (mod.value_exports.keys(), mod.value_exports.values()) |exported_value, exports_list| {5451 for (value_exports.keys(), value_exports.values()) |exported_value, exports_list| {
5406 const exported: Exported = .{ .value = exported_value };5452 const exported: Exported = .{ .value = exported_value };
5407 try processExportsInner(mod, &symbol_exports, exported, exports_list.items);5453 try processExportsInner(zcu, &symbol_exports, exported, exports_list.items);
5408 }5454 }
5409}5455}
54105456
5411const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export);5457const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, u32);
54125458
5413fn processExportsInner(5459fn processExportsInner(
5414 zcu: *Zcu,5460 zcu: *Zcu,
5415 symbol_exports: *SymbolExports,5461 symbol_exports: *SymbolExports,
5416 exported: Exported,5462 exported: Exported,
5417 exports: []const *Export,5463 export_indices: []const u32,
5418) error{OutOfMemory}!void {5464) error{OutOfMemory}!void {
5419 const gpa = zcu.gpa;5465 const gpa = zcu.gpa;
54205466
5421 for (exports) |new_export| {5467 for (export_indices) |export_idx| {
5468 const new_export = &zcu.all_exports.items[export_idx];
5422 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);5469 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);
5423 if (gop.found_existing) {5470 if (gop.found_existing) {
5424 new_export.status = .failed_retryable;5471 new_export.status = .failed_retryable;
5425 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);5472 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
5426 const src_loc = new_export.getSrcLoc(zcu);5473 const msg = try ErrorMsg.create(gpa, new_export.src, "exported symbol collision: {}", .{
5427 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{
5428 new_export.opts.name.fmt(&zcu.intern_pool),5474 new_export.opts.name.fmt(&zcu.intern_pool),
5429 });5475 });
5430 errdefer msg.destroy(gpa);5476 errdefer msg.destroy(gpa);
5431 const other_export = gop.value_ptr.*;5477 const other_export = zcu.all_exports.items[gop.value_ptr.*];
5432 const other_src_loc = other_export.getSrcLoc(zcu);5478 try zcu.errNote(other_export.src, msg, "other symbol here", .{});
5433 try zcu.errNoteNonLazy(other_src_loc, msg, "other symbol here", .{});5479 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);
5434 zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);
5435 new_export.status = .failed;5480 new_export.status = .failed;
5436 } else {5481 } else {
5437 gop.value_ptr.* = new_export;5482 gop.value_ptr.* = export_idx;
5438 }5483 }
5439 }5484 }
5440 if (zcu.comp.bin_file) |lf| {5485 if (zcu.comp.bin_file) |lf| {
5441 try handleUpdateExports(zcu, exports, lf.updateExports(zcu, exported, exports));5486 try handleUpdateExports(zcu, export_indices, lf.updateExports(zcu, exported, export_indices));
5442 } else if (zcu.llvm_object) |llvm_object| {5487 } else if (zcu.llvm_object) |llvm_object| {
5443 if (build_options.only_c) unreachable;5488 if (build_options.only_c) unreachable;
5444 try handleUpdateExports(zcu, exports, llvm_object.updateExports(zcu, exported, exports));5489 try handleUpdateExports(zcu, export_indices, llvm_object.updateExports(zcu, exported, export_indices));
5445 }5490 }
5446}5491}
54475492
5448fn handleUpdateExports(5493fn handleUpdateExports(
5449 zcu: *Zcu,5494 zcu: *Zcu,
5450 exports: []const *Export,5495 export_indices: []const u32,
5451 result: link.File.UpdateExportsError!void,5496 result: link.File.UpdateExportsError!void,
5452) Allocator.Error!void {5497) Allocator.Error!void {
5453 const gpa = zcu.gpa;5498 const gpa = zcu.gpa;
5454 result catch |err| switch (err) {5499 result catch |err| switch (err) {
5455 error.OutOfMemory => return error.OutOfMemory,5500 error.OutOfMemory => return error.OutOfMemory,
5456 error.AnalysisFail => {5501 error.AnalysisFail => {
5457 const new_export = exports[0];5502 const export_idx = export_indices[0];
5503 const new_export = &zcu.all_exports.items[export_idx];
5458 new_export.status = .failed_retryable;5504 new_export.status = .failed_retryable;
5459 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);5505 try zcu.failed_exports.ensureUnusedCapacity(gpa, 1);
5460 const src_loc = new_export.getSrcLoc(zcu);5506 const msg = try ErrorMsg.create(gpa, new_export.src, "unable to export: {s}", .{
5461 const msg = try ErrorMsg.create(gpa, src_loc, "unable to export: {s}", .{
5462 @errorName(err),5507 @errorName(err),
5463 });5508 });
5464 zcu.failed_exports.putAssumeCapacityNoClobber(new_export, msg);5509 zcu.failed_exports.putAssumeCapacityNoClobber(export_idx, msg);
5465 },5510 },
5466 };5511 };
5467}5512}
...@@ -5619,24 +5664,21 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {...@@ -5619,24 +5664,21 @@ pub fn linkerUpdateDecl(zcu: *Zcu, decl_index: Decl.Index) !void {
5619 },5664 },
5620 else => {5665 else => {
5621 const gpa = zcu.gpa;5666 const gpa = zcu.gpa;
5622 try zcu.failed_decls.ensureUnusedCapacity(gpa, 1);5667 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
5623 zcu.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(5668 zcu.failed_analysis.putAssumeCapacityNoClobber(AnalUnit.wrap(.{ .decl = decl_index }), try ErrorMsg.create(
5624 gpa,5669 gpa,
5625 decl.navSrcLoc(zcu).upgrade(zcu),5670 decl.navSrcLoc(zcu),
5626 "unable to codegen: {s}",5671 "unable to codegen: {s}",
5627 .{@errorName(err)},5672 .{@errorName(err)},
5628 ));5673 ));
5629 decl.analysis = .codegen_failure;5674 decl.analysis = .codegen_failure;
5630 try zcu.retryable_failures.append(zcu.gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index }));5675 try zcu.retryable_failures.append(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
5631 },5676 },
5632 };5677 };
5633 } else if (zcu.llvm_object) |llvm_object| {5678 } else if (zcu.llvm_object) |llvm_object| {
5634 if (build_options.only_c) unreachable;5679 if (build_options.only_c) unreachable;
5635 llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) {5680 llvm_object.updateDecl(zcu, decl_index) catch |err| switch (err) {
5636 error.OutOfMemory => return error.OutOfMemory,5681 error.OutOfMemory => return error.OutOfMemory,
5637 error.AnalysisFail => {
5638 decl.analysis = .codegen_failure;
5639 },
5640 };5682 };
5641 }5683 }
5642}5684}
...@@ -5652,9 +5694,8 @@ fn reportRetryableFileError(...@@ -5652,9 +5694,8 @@ fn reportRetryableFileError(
5652 const err_msg = try ErrorMsg.create(5694 const err_msg = try ErrorMsg.create(
5653 mod.gpa,5695 mod.gpa,
5654 .{5696 .{
5655 .file_scope = file,5697 .base_node_inst = try mod.intern_pool.trackZir(mod.gpa, file, .main_struct_inst),
5656 .base_node = 0,5698 .offset = .entire_file,
5657 .lazy = .entire_file,
5658 },5699 },
5659 format,5700 format,
5660 args,5701 args,
...@@ -5684,14 +5725,6 @@ pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u...@@ -5684,14 +5725,6 @@ pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u
5684 }5725 }
5685}5726}
56865727
5687pub fn getDeclExports(mod: Module, decl_index: Decl.Index) []const *Export {
5688 if (mod.decl_exports.get(decl_index)) |l| {
5689 return l.items;
5690 } else {
5691 return &[0]*Export{};
5692 }
5693}
5694
5695pub const Feature = enum {5728pub const Feature = enum {
5696 panic_fn,5729 panic_fn,
5697 panic_unwrap_error,5730 panic_unwrap_error,
...@@ -5786,6 +5819,16 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type...@@ -5786,6 +5819,16 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type
5786 return Type.fromInterned((try intern(mod, .{ .ptr_type = canon_info })));5819 return Type.fromInterned((try intern(mod, .{ .ptr_type = canon_info })));
5787}5820}
57885821
5822/// Like `ptrType`, but if `info` specifies an `alignment`, first ensures the pointer
5823/// child type's alignment is resolved so that an invalid alignment is not used.
5824/// In general, prefer this function during semantic analysis.
5825pub fn ptrTypeSema(zcu: *Zcu, info: InternPool.Key.PtrType) SemaError!Type {
5826 if (info.flags.alignment != .none) {
5827 _ = try Type.fromInterned(info.child).abiAlignmentAdvanced(zcu, .sema);
5828 }
5829 return zcu.ptrType(info);
5830}
5831
5789pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {5832pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
5790 return ptrType(mod, .{ .child = child_type.toIntern() });5833 return ptrType(mod, .{ .child = child_type.toIntern() });
5791}5834}
...@@ -6361,15 +6404,21 @@ pub fn unionAbiAlignment(mod: *Module, loaded_union: InternPool.LoadedUnionType)...@@ -6361,15 +6404,21 @@ pub fn unionAbiAlignment(mod: *Module, loaded_union: InternPool.LoadedUnionType)
6361 return max_align;6404 return max_align;
6362}6405}
63636406
6364/// Returns the field alignment, assuming the union is not packed.6407/// Returns the field alignment of a non-packed union. Asserts the layout is not packed.
6365/// Keep implementation in sync with `Sema.unionFieldAlignment`.6408pub fn unionFieldNormalAlignment(zcu: *Zcu, loaded_union: InternPool.LoadedUnionType, field_index: u32) Alignment {
6366/// Prefer to call that function instead of this one during Sema.6409 return zcu.unionFieldNormalAlignmentAdvanced(loaded_union, field_index, .normal) catch unreachable;
6367pub fn unionFieldNormalAlignment(mod: *Module, loaded_union: InternPool.LoadedUnionType, field_index: u32) Alignment {6410}
6368 const ip = &mod.intern_pool;6411
6412/// Returns the field alignment of a non-packed union. Asserts the layout is not packed.
6413/// If `strat` is `.sema`, may perform type resolution.
6414pub fn unionFieldNormalAlignmentAdvanced(zcu: *Zcu, loaded_union: InternPool.LoadedUnionType, field_index: u32, strat: Type.ResolveStrat) SemaError!Alignment {
6415 const ip = &zcu.intern_pool;
6416 assert(loaded_union.flagsPtr(ip).layout != .@"packed");
6369 const field_align = loaded_union.fieldAlign(ip, field_index);6417 const field_align = loaded_union.fieldAlign(ip, field_index);
6370 if (field_align != .none) return field_align;6418 if (field_align != .none) return field_align;
6371 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);6419 const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]);
6372 return field_ty.abiAlignment(mod);6420 if (field_ty.isNoReturn(zcu)) return .none;
6421 return (try field_ty.abiAlignmentAdvanced(zcu, strat.toLazy())).scalar;
6373}6422}
63746423
6375/// Returns the index of the active field, given the current tag value6424/// Returns the index of the active field, given the current tag value
...@@ -6380,41 +6429,37 @@ pub fn unionTagFieldIndex(mod: *Module, loaded_union: InternPool.LoadedUnionType...@@ -6380,41 +6429,37 @@ pub fn unionTagFieldIndex(mod: *Module, loaded_union: InternPool.LoadedUnionType
6380 return loaded_union.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());6429 return loaded_union.loadTagType(ip).tagValueIndex(ip, enum_tag.toIntern());
6381}6430}
63826431
6383/// Returns the field alignment of a non-packed struct in byte units.6432/// Returns the field alignment of a non-packed struct. Asserts the layout is not packed.
6384/// Keep implementation in sync with `Sema.structFieldAlignment`.
6385/// asserts the layout is not packed.
6386pub fn structFieldAlignment(6433pub fn structFieldAlignment(
6387 mod: *Module,6434 zcu: *Zcu,
6388 explicit_alignment: InternPool.Alignment,6435 explicit_alignment: InternPool.Alignment,
6389 field_ty: Type,6436 field_ty: Type,
6390 layout: std.builtin.Type.ContainerLayout,6437 layout: std.builtin.Type.ContainerLayout,
6391) Alignment {6438) Alignment {
6439 return zcu.structFieldAlignmentAdvanced(explicit_alignment, field_ty, layout, .normal) catch unreachable;
6440}
6441
6442/// Returns the field alignment of a non-packed struct. Asserts the layout is not packed.
6443/// If `strat` is `.sema`, may perform type resolution.
6444pub fn structFieldAlignmentAdvanced(
6445 zcu: *Zcu,
6446 explicit_alignment: InternPool.Alignment,
6447 field_ty: Type,
6448 layout: std.builtin.Type.ContainerLayout,
6449 strat: Type.ResolveStrat,
6450) SemaError!Alignment {
6392 assert(layout != .@"packed");6451 assert(layout != .@"packed");
6393 if (explicit_alignment != .none) return explicit_alignment;6452 if (explicit_alignment != .none) return explicit_alignment;
6453 const ty_abi_align = (try field_ty.abiAlignmentAdvanced(zcu, strat.toLazy())).scalar;
6394 switch (layout) {6454 switch (layout) {
6395 .@"packed" => unreachable,6455 .@"packed" => unreachable,
6396 .auto => {6456 .auto => if (zcu.getTarget().ofmt != .c) return ty_abi_align,
6397 if (mod.getTarget().ofmt == .c) {6457 .@"extern" => {},
6398 return structFieldAlignmentExtern(mod, field_ty);
6399 } else {
6400 return field_ty.abiAlignment(mod);
6401 }
6402 },
6403 .@"extern" => return structFieldAlignmentExtern(mod, field_ty),
6404 }6458 }
6405}6459 // extern
64066460 if (field_ty.isAbiInt(zcu) and field_ty.intInfo(zcu).bits >= 128) {
6407/// Returns the field alignment of an extern struct in byte units.6461 return ty_abi_align.maxStrict(.@"16");
6408/// This logic is duplicated in Type.abiAlignmentAdvanced.
6409pub fn structFieldAlignmentExtern(mod: *Module, field_ty: Type) Alignment {
6410 const ty_abi_align = field_ty.abiAlignment(mod);
6411
6412 if (field_ty.isAbiInt(mod) and field_ty.intInfo(mod).bits >= 128) {
6413 // The C ABI requires 128 bit integer fields of structs
6414 // to be 16-bytes aligned.
6415 return ty_abi_align.max(.@"16");
6416 }6462 }
6417
6418 return ty_abi_align;6463 return ty_abi_align;
6419}6464}
64206465
...@@ -6440,3 +6485,62 @@ pub fn structPackedFieldBitOffset(...@@ -6440,3 +6485,62 @@ pub fn structPackedFieldBitOffset(
6440 }6485 }
6441 unreachable; // index out of bounds6486 unreachable; // index out of bounds
6442}6487}
6488
6489pub const ResolvedReference = struct {
6490 referencer: AnalUnit,
6491 src: LazySrcLoc,
6492};
6493
6494/// Returns a mapping from an `AnalUnit` to where it is referenced.
6495/// TODO: in future, this must be adapted to traverse from roots of analysis. That way, we can
6496/// use the returned map to determine which units have become unreferenced in an incremental update.
6497pub fn resolveReferences(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, ResolvedReference) {
6498 const gpa = zcu.gpa;
6499
6500 var result: std.AutoHashMapUnmanaged(AnalUnit, ResolvedReference) = .{};
6501 errdefer result.deinit(gpa);
6502
6503 // This is not a sufficient size, but a lower bound.
6504 try result.ensureTotalCapacity(gpa, @intCast(zcu.reference_table.count()));
6505
6506 for (zcu.reference_table.keys(), zcu.reference_table.values()) |referencer, first_ref_idx| {
6507 assert(first_ref_idx != std.math.maxInt(u32));
6508 var ref_idx = first_ref_idx;
6509 while (ref_idx != std.math.maxInt(u32)) {
6510 const ref = zcu.all_references.items[ref_idx];
6511 const gop = try result.getOrPut(gpa, ref.referenced);
6512 if (!gop.found_existing) {
6513 gop.value_ptr.* = .{ .referencer = referencer, .src = ref.src };
6514 }
6515 ref_idx = ref.next;
6516 }
6517 }
6518
6519 return result;
6520}
6521
6522pub fn getBuiltin(zcu: *Zcu, name: []const u8) Allocator.Error!Air.Inst.Ref {
6523 const decl_index = try zcu.getBuiltinDecl(name);
6524 zcu.ensureDeclAnalyzed(decl_index) catch @panic("std.builtin is corrupt");
6525 return Air.internedToRef(zcu.declPtr(decl_index).val.toIntern());
6526}
6527
6528pub fn getBuiltinDecl(zcu: *Zcu, name: []const u8) Allocator.Error!InternPool.DeclIndex {
6529 const gpa = zcu.gpa;
6530 const ip = &zcu.intern_pool;
6531 const std_file = (zcu.importPkg(zcu.std_mod) catch @panic("failed to import lib/std.zig")).file;
6532 const std_namespace = zcu.declPtr(std_file.root_decl.unwrap().?).getOwnedInnerNamespace(zcu).?;
6533 const builtin_str = try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls);
6534 const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");
6535 zcu.ensureDeclAnalyzed(builtin_decl) catch @panic("std.builtin is corrupt");
6536 const builtin_namespace = zcu.declPtr(builtin_decl).getInnerNamespace(zcu) orelse @panic("std.builtin is corrupt");
6537 const name_str = try ip.getOrPutString(gpa, name, .no_embedded_nulls);
6538 return builtin_namespace.decls.getKeyAdapted(name_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");
6539}
6540
6541pub fn getBuiltinType(zcu: *Zcu, name: []const u8) Allocator.Error!Type {
6542 const ty_inst = try zcu.getBuiltin(name);
6543 const ty = Type.fromInterned(ty_inst.toInterned() orelse @panic("std.builtin is corrupt"));
6544 ty.resolveFully(zcu) catch @panic("std.builtin is corrupt");
6545 return ty;
6546}
src/arch/aarch64/CodeGen.zig+3-3
...@@ -8,7 +8,7 @@ const Air = @import("../../Air.zig");...@@ -8,7 +8,7 @@ const Air = @import("../../Air.zig");
8const Mir = @import("Mir.zig");8const Mir = @import("Mir.zig");
9const Emit = @import("Emit.zig");9const Emit = @import("Emit.zig");
10const Liveness = @import("../../Liveness.zig");10const Liveness = @import("../../Liveness.zig");
11const Type = @import("../../type.zig").Type;11const Type = @import("../../Type.zig");
12const Value = @import("../../Value.zig");12const Value = @import("../../Value.zig");
13const link = @import("../../link.zig");13const link = @import("../../link.zig");
14const Zcu = @import("../../Zcu.zig");14const Zcu = @import("../../Zcu.zig");
...@@ -59,7 +59,7 @@ args: []MCValue,...@@ -59,7 +59,7 @@ args: []MCValue,
59ret_mcv: MCValue,59ret_mcv: MCValue,
60fn_type: Type,60fn_type: Type,
61arg_index: u32,61arg_index: u32,
62src_loc: Module.SrcLoc,62src_loc: Module.LazySrcLoc,
63stack_align: u32,63stack_align: u32,
6464
65/// MIR Instructions65/// MIR Instructions
...@@ -331,7 +331,7 @@ const Self = @This();...@@ -331,7 +331,7 @@ const Self = @This();
331331
332pub fn generate(332pub fn generate(
333 lf: *link.File,333 lf: *link.File,
334 src_loc: Module.SrcLoc,334 src_loc: Module.LazySrcLoc,
335 func_index: InternPool.Index,335 func_index: InternPool.Index,
336 air: Air,336 air: Air,
337 liveness: Liveness,337 liveness: Liveness,
src/arch/aarch64/Emit.zig+1-1
...@@ -22,7 +22,7 @@ bin_file: *link.File,...@@ -22,7 +22,7 @@ bin_file: *link.File,
22debug_output: DebugInfoOutput,22debug_output: DebugInfoOutput,
23target: *const std.Target,23target: *const std.Target,
24err_msg: ?*ErrorMsg = null,24err_msg: ?*ErrorMsg = null,
25src_loc: Module.SrcLoc,25src_loc: Module.LazySrcLoc,
26code: *std.ArrayList(u8),26code: *std.ArrayList(u8),
2727
28prev_di_line: u32,28prev_di_line: u32,
src/arch/aarch64/abi.zig+1-1
...@@ -3,7 +3,7 @@ const builtin = @import("builtin");...@@ -3,7 +3,7 @@ const builtin = @import("builtin");
3const bits = @import("bits.zig");3const bits = @import("bits.zig");
4const Register = bits.Register;4const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;6const Type = @import("../../Type.zig");
7const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
8/// Deprecated.8/// Deprecated.
9const Module = Zcu;9const Module = Zcu;
src/arch/arm/CodeGen.zig+3-3
...@@ -8,7 +8,7 @@ const Air = @import("../../Air.zig");...@@ -8,7 +8,7 @@ const Air = @import("../../Air.zig");
8const Mir = @import("Mir.zig");8const Mir = @import("Mir.zig");
9const Emit = @import("Emit.zig");9const Emit = @import("Emit.zig");
10const Liveness = @import("../../Liveness.zig");10const Liveness = @import("../../Liveness.zig");
11const Type = @import("../../type.zig").Type;11const Type = @import("../../Type.zig");
12const Value = @import("../../Value.zig");12const Value = @import("../../Value.zig");
13const link = @import("../../link.zig");13const link = @import("../../link.zig");
14const Zcu = @import("../../Zcu.zig");14const Zcu = @import("../../Zcu.zig");
...@@ -59,7 +59,7 @@ args: []MCValue,...@@ -59,7 +59,7 @@ args: []MCValue,
59ret_mcv: MCValue,59ret_mcv: MCValue,
60fn_type: Type,60fn_type: Type,
61arg_index: u32,61arg_index: u32,
62src_loc: Module.SrcLoc,62src_loc: Module.LazySrcLoc,
63stack_align: u32,63stack_align: u32,
6464
65/// MIR Instructions65/// MIR Instructions
...@@ -338,7 +338,7 @@ const Self = @This();...@@ -338,7 +338,7 @@ const Self = @This();
338338
339pub fn generate(339pub fn generate(
340 lf: *link.File,340 lf: *link.File,
341 src_loc: Module.SrcLoc,341 src_loc: Module.LazySrcLoc,
342 func_index: InternPool.Index,342 func_index: InternPool.Index,
343 air: Air,343 air: Air,
344 liveness: Liveness,344 liveness: Liveness,
src/arch/arm/Emit.zig+2-2
...@@ -11,7 +11,7 @@ const link = @import("../../link.zig");...@@ -11,7 +11,7 @@ const link = @import("../../link.zig");
11const Zcu = @import("../../Zcu.zig");11const Zcu = @import("../../Zcu.zig");
12/// Deprecated.12/// Deprecated.
13const Module = Zcu;13const Module = Zcu;
14const Type = @import("../../type.zig").Type;14const Type = @import("../../Type.zig");
15const ErrorMsg = Module.ErrorMsg;15const ErrorMsg = Module.ErrorMsg;
16const Target = std.Target;16const Target = std.Target;
17const assert = std.debug.assert;17const assert = std.debug.assert;
...@@ -26,7 +26,7 @@ bin_file: *link.File,...@@ -26,7 +26,7 @@ bin_file: *link.File,
26debug_output: DebugInfoOutput,26debug_output: DebugInfoOutput,
27target: *const std.Target,27target: *const std.Target,
28err_msg: ?*ErrorMsg = null,28err_msg: ?*ErrorMsg = null,
29src_loc: Module.SrcLoc,29src_loc: Module.LazySrcLoc,
30code: *std.ArrayList(u8),30code: *std.ArrayList(u8),
3131
32prev_di_line: u32,32prev_di_line: u32,
src/arch/arm/abi.zig+1-1
...@@ -3,7 +3,7 @@ const assert = std.debug.assert;...@@ -3,7 +3,7 @@ const assert = std.debug.assert;
3const bits = @import("bits.zig");3const bits = @import("bits.zig");
4const Register = bits.Register;4const Register = bits.Register;
5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;5const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
6const Type = @import("../../type.zig").Type;6const Type = @import("../../Type.zig");
7const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
8/// Deprecated.8/// Deprecated.
9const Module = Zcu;9const Module = Zcu;
src/arch/riscv64/CodeGen.zig+3-3
...@@ -7,7 +7,7 @@ const Air = @import("../../Air.zig");...@@ -7,7 +7,7 @@ const Air = @import("../../Air.zig");
7const Mir = @import("Mir.zig");7const Mir = @import("Mir.zig");
8const Emit = @import("Emit.zig");8const Emit = @import("Emit.zig");
9const Liveness = @import("../../Liveness.zig");9const Liveness = @import("../../Liveness.zig");
10const Type = @import("../../type.zig").Type;10const Type = @import("../../Type.zig");
11const Value = @import("../../Value.zig");11const Value = @import("../../Value.zig");
12const link = @import("../../link.zig");12const link = @import("../../link.zig");
13const Zcu = @import("../../Zcu.zig");13const Zcu = @import("../../Zcu.zig");
...@@ -59,7 +59,7 @@ args: []MCValue,...@@ -59,7 +59,7 @@ args: []MCValue,
59ret_mcv: InstTracking,59ret_mcv: InstTracking,
60fn_type: Type,60fn_type: Type,
61arg_index: usize,61arg_index: usize,
62src_loc: Zcu.SrcLoc,62src_loc: Zcu.LazySrcLoc,
6363
64/// MIR Instructions64/// MIR Instructions
65mir_instructions: std.MultiArrayList(Mir.Inst) = .{},65mir_instructions: std.MultiArrayList(Mir.Inst) = .{},
...@@ -696,7 +696,7 @@ const CallView = enum(u1) {...@@ -696,7 +696,7 @@ const CallView = enum(u1) {
696696
697pub fn generate(697pub fn generate(
698 bin_file: *link.File,698 bin_file: *link.File,
699 src_loc: Zcu.SrcLoc,699 src_loc: Zcu.LazySrcLoc,
700 func_index: InternPool.Index,700 func_index: InternPool.Index,
701 air: Air,701 air: Air,
702 liveness: Liveness,702 liveness: Liveness,
src/arch/riscv64/Lower.zig+1-1
...@@ -8,7 +8,7 @@ allocator: Allocator,...@@ -8,7 +8,7 @@ allocator: Allocator,
8mir: Mir,8mir: Mir,
9cc: std.builtin.CallingConvention,9cc: std.builtin.CallingConvention,
10err_msg: ?*ErrorMsg = null,10err_msg: ?*ErrorMsg = null,
11src_loc: Zcu.SrcLoc,11src_loc: Zcu.LazySrcLoc,
12result_insts_len: u8 = undefined,12result_insts_len: u8 = undefined,
13result_relocs_len: u8 = undefined,13result_relocs_len: u8 = undefined,
14result_insts: [14result_insts: [
src/arch/riscv64/Mir.zig+1-1
...@@ -431,7 +431,7 @@ pub const RegisterList = struct {...@@ -431,7 +431,7 @@ pub const RegisterList = struct {
431const Mir = @This();431const Mir = @This();
432const std = @import("std");432const std = @import("std");
433const builtin = @import("builtin");433const builtin = @import("builtin");
434const Type = @import("../../type.zig").Type;434const Type = @import("../../Type.zig");
435435
436const assert = std.debug.assert;436const assert = std.debug.assert;
437437
src/arch/riscv64/abi.zig+1-1
...@@ -2,7 +2,7 @@ const std = @import("std");...@@ -2,7 +2,7 @@ const std = @import("std");
2const bits = @import("bits.zig");2const bits = @import("bits.zig");
3const Register = bits.Register;3const Register = bits.Register;
4const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;4const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
5const Type = @import("../../type.zig").Type;5const Type = @import("../../Type.zig");
6const InternPool = @import("../../InternPool.zig");6const InternPool = @import("../../InternPool.zig");
7const Zcu = @import("../../Zcu.zig");7const Zcu = @import("../../Zcu.zig");
8const assert = std.debug.assert;8const assert = std.debug.assert;
src/arch/sparc64/CodeGen.zig+3-3
...@@ -21,7 +21,7 @@ const Air = @import("../../Air.zig");...@@ -21,7 +21,7 @@ const Air = @import("../../Air.zig");
21const Mir = @import("Mir.zig");21const Mir = @import("Mir.zig");
22const Emit = @import("Emit.zig");22const Emit = @import("Emit.zig");
23const Liveness = @import("../../Liveness.zig");23const Liveness = @import("../../Liveness.zig");
24const Type = @import("../../type.zig").Type;24const Type = @import("../../Type.zig");
25const CodeGenError = codegen.CodeGenError;25const CodeGenError = codegen.CodeGenError;
26const Result = @import("../../codegen.zig").Result;26const Result = @import("../../codegen.zig").Result;
27const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;27const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
...@@ -64,7 +64,7 @@ args: []MCValue,...@@ -64,7 +64,7 @@ args: []MCValue,
64ret_mcv: MCValue,64ret_mcv: MCValue,
65fn_type: Type,65fn_type: Type,
66arg_index: usize,66arg_index: usize,
67src_loc: Module.SrcLoc,67src_loc: Module.LazySrcLoc,
68stack_align: Alignment,68stack_align: Alignment,
6969
70/// MIR Instructions70/// MIR Instructions
...@@ -263,7 +263,7 @@ const BigTomb = struct {...@@ -263,7 +263,7 @@ const BigTomb = struct {
263263
264pub fn generate(264pub fn generate(
265 lf: *link.File,265 lf: *link.File,
266 src_loc: Module.SrcLoc,266 src_loc: Module.LazySrcLoc,
267 func_index: InternPool.Index,267 func_index: InternPool.Index,
268 air: Air,268 air: Air,
269 liveness: Liveness,269 liveness: Liveness,
src/arch/sparc64/Emit.zig+1-1
...@@ -24,7 +24,7 @@ bin_file: *link.File,...@@ -24,7 +24,7 @@ bin_file: *link.File,
24debug_output: DebugInfoOutput,24debug_output: DebugInfoOutput,
25target: *const std.Target,25target: *const std.Target,
26err_msg: ?*ErrorMsg = null,26err_msg: ?*ErrorMsg = null,
27src_loc: Module.SrcLoc,27src_loc: Module.LazySrcLoc,
28code: *std.ArrayList(u8),28code: *std.ArrayList(u8),
2929
30prev_di_line: u32,30prev_di_line: u32,
src/arch/wasm/CodeGen.zig+4-4
...@@ -13,7 +13,7 @@ const codegen = @import("../../codegen.zig");...@@ -13,7 +13,7 @@ const codegen = @import("../../codegen.zig");
13const Zcu = @import("../../Zcu.zig");13const Zcu = @import("../../Zcu.zig");
14const InternPool = @import("../../InternPool.zig");14const InternPool = @import("../../InternPool.zig");
15const Decl = Zcu.Decl;15const Decl = Zcu.Decl;
16const Type = @import("../../type.zig").Type;16const Type = @import("../../Type.zig");
17const Value = @import("../../Value.zig");17const Value = @import("../../Value.zig");
18const Compilation = @import("../../Compilation.zig");18const Compilation = @import("../../Compilation.zig");
19const link = @import("../../link.zig");19const link = @import("../../link.zig");
...@@ -765,7 +765,7 @@ pub fn deinit(func: *CodeGen) void {...@@ -765,7 +765,7 @@ pub fn deinit(func: *CodeGen) void {
765/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig765/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig
766fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {766fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {
767 const mod = func.bin_file.base.comp.module.?;767 const mod = func.bin_file.base.comp.module.?;
768 const src_loc = func.decl.navSrcLoc(mod).upgrade(mod);768 const src_loc = func.decl.navSrcLoc(mod);
769 func.err_msg = try Zcu.ErrorMsg.create(func.gpa, src_loc, fmt, args);769 func.err_msg = try Zcu.ErrorMsg.create(func.gpa, src_loc, fmt, args);
770 return error.CodegenFail;770 return error.CodegenFail;
771}771}
...@@ -1202,7 +1202,7 @@ fn genFunctype(...@@ -1202,7 +1202,7 @@ fn genFunctype(
12021202
1203pub fn generate(1203pub fn generate(
1204 bin_file: *link.File,1204 bin_file: *link.File,
1205 src_loc: Zcu.SrcLoc,1205 src_loc: Zcu.LazySrcLoc,
1206 func_index: InternPool.Index,1206 func_index: InternPool.Index,
1207 air: Air,1207 air: Air,
1208 liveness: Liveness,1208 liveness: Liveness,
...@@ -3162,7 +3162,7 @@ fn lowerAnonDeclRef(...@@ -3162,7 +3162,7 @@ fn lowerAnonDeclRef(
3162 }3162 }
31633163
3164 const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;3164 const decl_align = mod.intern_pool.indexToKey(anon_decl.orig_ty).ptr_type.flags.alignment;
3165 const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.navSrcLoc(mod).upgrade(mod));3165 const res = try func.bin_file.lowerAnonDecl(decl_val, decl_align, func.decl.navSrcLoc(mod));
3166 switch (res) {3166 switch (res) {
3167 .ok => {},3167 .ok => {},
3168 .fail => |em| {3168 .fail => |em| {
src/arch/wasm/Emit.zig+1-1
...@@ -257,7 +257,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {...@@ -257,7 +257,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
257 const comp = emit.bin_file.base.comp;257 const comp = emit.bin_file.base.comp;
258 const zcu = comp.module.?;258 const zcu = comp.module.?;
259 const gpa = comp.gpa;259 const gpa = comp.gpa;
260 emit.error_msg = try Zcu.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).navSrcLoc(zcu).upgrade(zcu), format, args);260 emit.error_msg = try Zcu.ErrorMsg.create(gpa, zcu.declPtr(emit.decl_index).navSrcLoc(zcu), format, args);
261 return error.EmitFail;261 return error.EmitFail;
262}262}
263263
src/arch/wasm/abi.zig+1-1
...@@ -8,7 +8,7 @@ const std = @import("std");...@@ -8,7 +8,7 @@ const std = @import("std");
8const Target = std.Target;8const Target = std.Target;
9const assert = std.debug.assert;9const assert = std.debug.assert;
1010
11const Type = @import("../../type.zig").Type;11const Type = @import("../../Type.zig");
12const Zcu = @import("../../Zcu.zig");12const Zcu = @import("../../Zcu.zig");
1313
14/// Defines how to pass a type as part of a function signature,14/// Defines how to pass a type as part of a function signature,
src/arch/x86_64/CodeGen.zig+4-4
...@@ -32,7 +32,7 @@ const Module = Zcu;...@@ -32,7 +32,7 @@ const Module = Zcu;
32const InternPool = @import("../../InternPool.zig");32const InternPool = @import("../../InternPool.zig");
33const Alignment = InternPool.Alignment;33const Alignment = InternPool.Alignment;
34const Target = std.Target;34const Target = std.Target;
35const Type = @import("../../type.zig").Type;35const Type = @import("../../Type.zig");
36const Value = @import("../../Value.zig");36const Value = @import("../../Value.zig");
37const Instruction = @import("encoder.zig").Instruction;37const Instruction = @import("encoder.zig").Instruction;
3838
...@@ -74,7 +74,7 @@ va_info: union {...@@ -74,7 +74,7 @@ va_info: union {
74ret_mcv: InstTracking,74ret_mcv: InstTracking,
75fn_type: Type,75fn_type: Type,
76arg_index: u32,76arg_index: u32,
77src_loc: Module.SrcLoc,77src_loc: Module.LazySrcLoc,
7878
79eflags_inst: ?Air.Inst.Index = null,79eflags_inst: ?Air.Inst.Index = null,
8080
...@@ -795,7 +795,7 @@ const Self = @This();...@@ -795,7 +795,7 @@ const Self = @This();
795795
796pub fn generate(796pub fn generate(
797 bin_file: *link.File,797 bin_file: *link.File,
798 src_loc: Module.SrcLoc,798 src_loc: Module.LazySrcLoc,
799 func_index: InternPool.Index,799 func_index: InternPool.Index,
800 air: Air,800 air: Air,
801 liveness: Liveness,801 liveness: Liveness,
...@@ -971,7 +971,7 @@ pub fn generate(...@@ -971,7 +971,7 @@ pub fn generate(
971971
972pub fn generateLazy(972pub fn generateLazy(
973 bin_file: *link.File,973 bin_file: *link.File,
974 src_loc: Module.SrcLoc,974 src_loc: Module.LazySrcLoc,
975 lazy_sym: link.File.LazySymbol,975 lazy_sym: link.File.LazySymbol,
976 code: *std.ArrayList(u8),976 code: *std.ArrayList(u8),
977 debug_output: DebugInfoOutput,977 debug_output: DebugInfoOutput,
src/arch/x86_64/Lower.zig+1-1
...@@ -8,7 +8,7 @@ allocator: Allocator,...@@ -8,7 +8,7 @@ allocator: Allocator,
8mir: Mir,8mir: Mir,
9cc: std.builtin.CallingConvention,9cc: std.builtin.CallingConvention,
10err_msg: ?*ErrorMsg = null,10err_msg: ?*ErrorMsg = null,
11src_loc: Module.SrcLoc,11src_loc: Module.LazySrcLoc,
12result_insts_len: u8 = undefined,12result_insts_len: u8 = undefined,
13result_relocs_len: u8 = undefined,13result_relocs_len: u8 = undefined,
14result_insts: [14result_insts: [
src/arch/x86_64/abi.zig+1-1
...@@ -537,6 +537,6 @@ const testing = std.testing;...@@ -537,6 +537,6 @@ const testing = std.testing;
537const InternPool = @import("../../InternPool.zig");537const InternPool = @import("../../InternPool.zig");
538const Register = @import("bits.zig").Register;538const Register = @import("bits.zig").Register;
539const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;539const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
540const Type = @import("../../type.zig").Type;540const Type = @import("../../Type.zig");
541const Value = @import("../../Value.zig");541const Value = @import("../../Value.zig");
542const Zcu = @import("../../Zcu.zig");542const Zcu = @import("../../Zcu.zig");
src/codegen.zig+12-12
...@@ -20,7 +20,7 @@ const Zcu = @import("Zcu.zig");...@@ -20,7 +20,7 @@ const Zcu = @import("Zcu.zig");
20/// Deprecated.20/// Deprecated.
21const Module = Zcu;21const Module = Zcu;
22const Target = std.Target;22const Target = std.Target;
23const Type = @import("type.zig").Type;23const Type = @import("Type.zig");
24const Value = @import("Value.zig");24const Value = @import("Value.zig");
25const Zir = std.zig.Zir;25const Zir = std.zig.Zir;
26const Alignment = InternPool.Alignment;26const Alignment = InternPool.Alignment;
...@@ -47,7 +47,7 @@ pub const DebugInfoOutput = union(enum) {...@@ -47,7 +47,7 @@ pub const DebugInfoOutput = union(enum) {
4747
48pub fn generateFunction(48pub fn generateFunction(
49 lf: *link.File,49 lf: *link.File,
50 src_loc: Module.SrcLoc,50 src_loc: Module.LazySrcLoc,
51 func_index: InternPool.Index,51 func_index: InternPool.Index,
52 air: Air,52 air: Air,
53 liveness: Liveness,53 liveness: Liveness,
...@@ -79,7 +79,7 @@ pub fn generateFunction(...@@ -79,7 +79,7 @@ pub fn generateFunction(
7979
80pub fn generateLazyFunction(80pub fn generateLazyFunction(
81 lf: *link.File,81 lf: *link.File,
82 src_loc: Module.SrcLoc,82 src_loc: Module.LazySrcLoc,
83 lazy_sym: link.File.LazySymbol,83 lazy_sym: link.File.LazySymbol,
84 code: *std.ArrayList(u8),84 code: *std.ArrayList(u8),
85 debug_output: DebugInfoOutput,85 debug_output: DebugInfoOutput,
...@@ -105,7 +105,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian...@@ -105,7 +105,7 @@ fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian
105105
106pub fn generateLazySymbol(106pub fn generateLazySymbol(
107 bin_file: *link.File,107 bin_file: *link.File,
108 src_loc: Module.SrcLoc,108 src_loc: Module.LazySrcLoc,
109 lazy_sym: link.File.LazySymbol,109 lazy_sym: link.File.LazySymbol,
110 // TODO don't use an "out" parameter like this; put it in the result instead110 // TODO don't use an "out" parameter like this; put it in the result instead
111 alignment: *Alignment,111 alignment: *Alignment,
...@@ -171,7 +171,7 @@ pub fn generateLazySymbol(...@@ -171,7 +171,7 @@ pub fn generateLazySymbol(
171171
172pub fn generateSymbol(172pub fn generateSymbol(
173 bin_file: *link.File,173 bin_file: *link.File,
174 src_loc: Module.SrcLoc,174 src_loc: Module.LazySrcLoc,
175 val: Value,175 val: Value,
176 code: *std.ArrayList(u8),176 code: *std.ArrayList(u8),
177 debug_output: DebugInfoOutput,177 debug_output: DebugInfoOutput,
...@@ -618,7 +618,7 @@ pub fn generateSymbol(...@@ -618,7 +618,7 @@ pub fn generateSymbol(
618618
619fn lowerPtr(619fn lowerPtr(
620 bin_file: *link.File,620 bin_file: *link.File,
621 src_loc: Module.SrcLoc,621 src_loc: Module.LazySrcLoc,
622 ptr_val: InternPool.Index,622 ptr_val: InternPool.Index,
623 code: *std.ArrayList(u8),623 code: *std.ArrayList(u8),
624 debug_output: DebugInfoOutput,624 debug_output: DebugInfoOutput,
...@@ -683,7 +683,7 @@ const RelocInfo = struct {...@@ -683,7 +683,7 @@ const RelocInfo = struct {
683683
684fn lowerAnonDeclRef(684fn lowerAnonDeclRef(
685 lf: *link.File,685 lf: *link.File,
686 src_loc: Module.SrcLoc,686 src_loc: Module.LazySrcLoc,
687 anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl,687 anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl,
688 code: *std.ArrayList(u8),688 code: *std.ArrayList(u8),
689 debug_output: DebugInfoOutput,689 debug_output: DebugInfoOutput,
...@@ -730,7 +730,7 @@ fn lowerAnonDeclRef(...@@ -730,7 +730,7 @@ fn lowerAnonDeclRef(
730730
731fn lowerDeclRef(731fn lowerDeclRef(
732 lf: *link.File,732 lf: *link.File,
733 src_loc: Module.SrcLoc,733 src_loc: Module.LazySrcLoc,
734 decl_index: InternPool.DeclIndex,734 decl_index: InternPool.DeclIndex,
735 code: *std.ArrayList(u8),735 code: *std.ArrayList(u8),
736 debug_output: DebugInfoOutput,736 debug_output: DebugInfoOutput,
...@@ -814,7 +814,7 @@ pub const GenResult = union(enum) {...@@ -814,7 +814,7 @@ pub const GenResult = union(enum) {
814814
815 fn fail(815 fn fail(
816 gpa: Allocator,816 gpa: Allocator,
817 src_loc: Module.SrcLoc,817 src_loc: Module.LazySrcLoc,
818 comptime format: []const u8,818 comptime format: []const u8,
819 args: anytype,819 args: anytype,
820 ) Allocator.Error!GenResult {820 ) Allocator.Error!GenResult {
...@@ -825,7 +825,7 @@ pub const GenResult = union(enum) {...@@ -825,7 +825,7 @@ pub const GenResult = union(enum) {
825825
826fn genDeclRef(826fn genDeclRef(
827 lf: *link.File,827 lf: *link.File,
828 src_loc: Module.SrcLoc,828 src_loc: Module.LazySrcLoc,
829 val: Value,829 val: Value,
830 ptr_decl_index: InternPool.DeclIndex,830 ptr_decl_index: InternPool.DeclIndex,
831) CodeGenError!GenResult {831) CodeGenError!GenResult {
...@@ -931,7 +931,7 @@ fn genDeclRef(...@@ -931,7 +931,7 @@ fn genDeclRef(
931931
932fn genUnnamedConst(932fn genUnnamedConst(
933 lf: *link.File,933 lf: *link.File,
934 src_loc: Module.SrcLoc,934 src_loc: Module.LazySrcLoc,
935 val: Value,935 val: Value,
936 owner_decl_index: InternPool.DeclIndex,936 owner_decl_index: InternPool.DeclIndex,
937) CodeGenError!GenResult {937) CodeGenError!GenResult {
...@@ -970,7 +970,7 @@ fn genUnnamedConst(...@@ -970,7 +970,7 @@ fn genUnnamedConst(
970970
971pub fn genTypedValue(971pub fn genTypedValue(
972 lf: *link.File,972 lf: *link.File,
973 src_loc: Module.SrcLoc,973 src_loc: Module.LazySrcLoc,
974 val: Value,974 val: Value,
975 owner_decl_index: InternPool.DeclIndex,975 owner_decl_index: InternPool.DeclIndex,
976) CodeGenError!GenResult {976) CodeGenError!GenResult {
src/codegen/c.zig+148-232
...@@ -9,7 +9,7 @@ const Zcu = @import("../Zcu.zig");...@@ -9,7 +9,7 @@ const Zcu = @import("../Zcu.zig");
9const Module = @import("../Package/Module.zig");9const Module = @import("../Package/Module.zig");
10const Compilation = @import("../Compilation.zig");10const Compilation = @import("../Compilation.zig");
11const Value = @import("../Value.zig");11const Value = @import("../Value.zig");
12const Type = @import("../type.zig").Type;12const Type = @import("../Type.zig");
13const C = link.File.C;13const C = link.File.C;
14const Decl = Zcu.Decl;14const Decl = Zcu.Decl;
15const trace = @import("../tracy.zig").trace;15const trace = @import("../tracy.zig").trace;
...@@ -637,7 +637,7 @@ pub const DeclGen = struct {...@@ -637,7 +637,7 @@ pub const DeclGen = struct {
637 const zcu = dg.zcu;637 const zcu = dg.zcu;
638 const decl_index = dg.pass.decl;638 const decl_index = dg.pass.decl;
639 const decl = zcu.declPtr(decl_index);639 const decl = zcu.declPtr(decl_index);
640 const src_loc = decl.navSrcLoc(zcu).upgrade(zcu);640 const src_loc = decl.navSrcLoc(zcu);
641 dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);641 dg.error_msg = try Zcu.ErrorMsg.create(dg.gpa, src_loc, format, args);
642 return error.AnalysisFail;642 return error.AnalysisFail;
643 }643 }
...@@ -731,8 +731,6 @@ pub const DeclGen = struct {...@@ -731,8 +731,6 @@ pub const DeclGen = struct {
731 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)731 if (decl.val.getExternFunc(zcu)) |extern_func| if (extern_func.decl != decl_index)
732 return dg.renderDeclValue(writer, extern_func.decl, location);732 return dg.renderDeclValue(writer, extern_func.decl, location);
733733
734 if (decl.val.getVariable(zcu)) |variable| try dg.renderFwdDecl(decl_index, variable, .tentative);
735
736 // We shouldn't cast C function pointers as this is UB (when you call734 // We shouldn't cast C function pointers as this is UB (when you call
737 // them). The analysis until now should ensure that the C function735 // them). The analysis until now should ensure that the C function
738 // pointers are compatible. If they are not, then there is a bug736 // pointers are compatible. If they are not, then there is a bug
...@@ -748,7 +746,7 @@ pub const DeclGen = struct {...@@ -748,7 +746,7 @@ pub const DeclGen = struct {
748 try writer.writeByte(')');746 try writer.writeByte(')');
749 }747 }
750 try writer.writeByte('&');748 try writer.writeByte('&');
751 try dg.renderDeclName(writer, decl_index, 0);749 try dg.renderDeclName(writer, decl_index);
752 if (need_cast) try writer.writeByte(')');750 if (need_cast) try writer.writeByte(')');
753 }751 }
754752
...@@ -1765,19 +1763,22 @@ pub const DeclGen = struct {...@@ -1765,19 +1763,22 @@ pub const DeclGen = struct {
1765 fn renderFunctionSignature(1763 fn renderFunctionSignature(
1766 dg: *DeclGen,1764 dg: *DeclGen,
1767 w: anytype,1765 w: anytype,
1768 fn_decl_index: InternPool.DeclIndex,1766 fn_val: Value,
1767 fn_align: InternPool.Alignment,
1769 kind: CType.Kind,1768 kind: CType.Kind,
1770 name: union(enum) {1769 name: union(enum) {
1771 export_index: u32,1770 decl: InternPool.DeclIndex,
1772 ident: []const u8,
1773 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),1771 fmt_ctype_pool_string: std.fmt.Formatter(formatCTypePoolString),
1772 @"export": struct {
1773 main_name: InternPool.NullTerminatedString,
1774 extern_name: InternPool.NullTerminatedString,
1775 },
1774 },1776 },
1775 ) !void {1777 ) !void {
1776 const zcu = dg.zcu;1778 const zcu = dg.zcu;
1777 const ip = &zcu.intern_pool;1779 const ip = &zcu.intern_pool;
17781780
1779 const fn_decl = zcu.declPtr(fn_decl_index);1781 const fn_ty = fn_val.typeOf(zcu);
1780 const fn_ty = fn_decl.typeOf(zcu);
1781 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);1782 const fn_ctype = try dg.ctypeFromType(fn_ty, kind);
17821783
1783 const fn_info = zcu.typeToFunc(fn_ty).?;1784 const fn_info = zcu.typeToFunc(fn_ty).?;
...@@ -1788,7 +1789,7 @@ pub const DeclGen = struct {...@@ -1788,7 +1789,7 @@ pub const DeclGen = struct {
1788 else => unreachable,1789 else => unreachable,
1789 }1790 }
1790 }1791 }
1791 if (fn_decl.val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold)1792 if (fn_val.getFunction(zcu)) |func| if (func.analysis(ip).is_cold)
1792 try w.writeAll("zig_cold ");1793 try w.writeAll("zig_cold ");
1793 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");1794 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
17941795
...@@ -1799,22 +1800,11 @@ pub const DeclGen = struct {...@@ -1799,22 +1800,11 @@ pub const DeclGen = struct {
1799 trailing = .maybe_space;1800 trailing = .maybe_space;
1800 }1801 }
18011802
1802 switch (kind) {1803 try w.print("{}", .{trailing});
1803 .forward => {},
1804 .complete => if (fn_decl.alignment.toByteUnits()) |a| {
1805 try w.print("{}zig_align_fn({})", .{ trailing, a });
1806 trailing = .maybe_space;
1807 },
1808 else => unreachable,
1809 }
1810
1811 switch (name) {1804 switch (name) {
1812 .export_index => |export_index| {1805 .decl => |decl_index| try dg.renderDeclName(w, decl_index),
1813 try w.print("{}", .{trailing});1806 .fmt_ctype_pool_string => |fmt| try w.print("{ }", .{fmt}),
1814 try dg.renderDeclName(w, fn_decl_index, export_index);1807 .@"export" => |@"export"| try w.print("{ }", .{fmtIdent(@"export".extern_name.toSlice(ip))}),
1815 },
1816 .ident => |ident| try w.print("{}{ }", .{ trailing, fmtIdent(ident) }),
1817 .fmt_ctype_pool_string => |fmt| try w.print("{}{ }", .{ trailing, fmt }),
1818 }1808 }
18191809
1820 try renderTypeSuffix(1810 try renderTypeSuffix(
...@@ -1833,44 +1823,30 @@ pub const DeclGen = struct {...@@ -1833,44 +1823,30 @@ pub const DeclGen = struct {
18331823
1834 switch (kind) {1824 switch (kind) {
1835 .forward => {1825 .forward => {
1836 if (fn_decl.alignment.toByteUnits()) |a| {1826 if (fn_align.toByteUnits()) |a| try w.print(" zig_align_fn({})", .{a});
1837 try w.print(" zig_align_fn({})", .{a});
1838 }
1839 switch (name) {1827 switch (name) {
1840 .export_index => |export_index| mangled: {1828 .decl, .fmt_ctype_pool_string => {},
1841 const maybe_exports = zcu.decl_exports.get(fn_decl_index);1829 .@"export" => |@"export"| {
1842 const external_name = (if (maybe_exports) |exports|1830 const extern_name = @"export".extern_name.toSlice(ip);
1843 exports.items[export_index].opts.name1831 const is_mangled = isMangledIdent(extern_name, true);
1844 else if (fn_decl.isExtern(zcu))1832 const is_export = @"export".extern_name != @"export".main_name;
1845 fn_decl.name
1846 else
1847 break :mangled).toSlice(ip);
1848 const is_mangled = isMangledIdent(external_name, true);
1849 const is_export = export_index > 0;
1850 if (is_mangled and is_export) {1833 if (is_mangled and is_export) {
1851 try w.print(" zig_mangled_export({ }, {s}, {s})", .{1834 try w.print(" zig_mangled_export({ }, {s}, {s})", .{
1852 fmtIdent(external_name),1835 fmtIdent(extern_name),
1853 fmtStringLiteral(external_name, null),1836 fmtStringLiteral(extern_name, null),
1854 fmtStringLiteral(1837 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1855 maybe_exports.?.items[0].opts.name.toSlice(ip),
1856 null,
1857 ),
1858 });1838 });
1859 } else if (is_mangled) {1839 } else if (is_mangled) {
1860 try w.print(" zig_mangled_final({ }, {s})", .{1840 try w.print(" zig_mangled({ }, {s})", .{
1861 fmtIdent(external_name), fmtStringLiteral(external_name, null),1841 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
1862 });1842 });
1863 } else if (is_export) {1843 } else if (is_export) {
1864 try w.print(" zig_export({s}, {s})", .{1844 try w.print(" zig_export({s}, {s})", .{
1865 fmtStringLiteral(1845 fmtStringLiteral(@"export".main_name.toSlice(ip), null),
1866 maybe_exports.?.items[0].opts.name.toSlice(ip),1846 fmtStringLiteral(extern_name, null),
1867 null,
1868 ),
1869 fmtStringLiteral(external_name, null),
1870 });1847 });
1871 }1848 }
1872 },1849 },
1873 .ident, .fmt_ctype_pool_string => {},
1874 }1850 }
1875 },1851 },
1876 .complete => {},1852 .complete => {},
...@@ -2085,21 +2061,11 @@ pub const DeclGen = struct {...@@ -2085,21 +2061,11 @@ pub const DeclGen = struct {
2085 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});2061 try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{});
2086 }2062 }
20872063
2088 fn declIsGlobal(dg: *DeclGen, val: Value) bool {
2089 const zcu = dg.zcu;
2090 return switch (zcu.intern_pool.indexToKey(val.toIntern())) {
2091 .variable => |variable| zcu.decl_exports.contains(variable.decl),
2092 .extern_func => true,
2093 .func => |func| zcu.decl_exports.contains(func.owner_decl),
2094 else => unreachable,
2095 };
2096 }
2097
2098 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {2064 fn writeName(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2099 switch (c_value) {2065 switch (c_value) {
2100 .new_local, .local => |i| try w.print("t{d}", .{i}),2066 .new_local, .local => |i| try w.print("t{d}", .{i}),
2101 .constant => |val| try renderAnonDeclName(w, val),2067 .constant => |val| try renderAnonDeclName(w, val),
2102 .decl => |decl| try dg.renderDeclName(w, decl, 0),2068 .decl => |decl| try dg.renderDeclName(w, decl),
2103 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2069 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
2104 else => unreachable,2070 else => unreachable,
2105 }2071 }
...@@ -2111,10 +2077,10 @@ pub const DeclGen = struct {...@@ -2111,10 +2077,10 @@ pub const DeclGen = struct {
2111 .constant => |val| try renderAnonDeclName(w, val),2077 .constant => |val| try renderAnonDeclName(w, val),
2112 .arg, .arg_array => unreachable,2078 .arg, .arg_array => unreachable,
2113 .field => |i| try w.print("f{d}", .{i}),2079 .field => |i| try w.print("f{d}", .{i}),
2114 .decl => |decl| try dg.renderDeclName(w, decl, 0),2080 .decl => |decl| try dg.renderDeclName(w, decl),
2115 .decl_ref => |decl| {2081 .decl_ref => |decl| {
2116 try w.writeByte('&');2082 try w.writeByte('&');
2117 try dg.renderDeclName(w, decl, 0);2083 try dg.renderDeclName(w, decl);
2118 },2084 },
2119 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),2085 .undef => |ty| try dg.renderUndefValue(w, ty, .Other),
2120 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),2086 .identifier => |ident| try w.print("{ }", .{fmtIdent(ident)}),
...@@ -2142,10 +2108,10 @@ pub const DeclGen = struct {...@@ -2142,10 +2108,10 @@ pub const DeclGen = struct {
2142 .field => |i| try w.print("f{d}", .{i}),2108 .field => |i| try w.print("f{d}", .{i}),
2143 .decl => |decl| {2109 .decl => |decl| {
2144 try w.writeAll("(*");2110 try w.writeAll("(*");
2145 try dg.renderDeclName(w, decl, 0);2111 try dg.renderDeclName(w, decl);
2146 try w.writeByte(')');2112 try w.writeByte(')');
2147 },2113 },
2148 .decl_ref => |decl| try dg.renderDeclName(w, decl, 0),2114 .decl_ref => |decl| try dg.renderDeclName(w, decl),
2149 .undef => unreachable,2115 .undef => unreachable,
2150 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),2116 .identifier => |ident| try w.print("(*{ })", .{fmtIdent(ident)}),
2151 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{2117 .payload_identifier => |ident| try w.print("(*{ }.{ })", .{
...@@ -2195,19 +2161,12 @@ pub const DeclGen = struct {...@@ -2195,19 +2161,12 @@ pub const DeclGen = struct {
2195 dg: *DeclGen,2161 dg: *DeclGen,
2196 decl_index: InternPool.DeclIndex,2162 decl_index: InternPool.DeclIndex,
2197 variable: InternPool.Key.Variable,2163 variable: InternPool.Key.Variable,
2198 fwd_kind: enum { tentative, final },
2199 ) !void {2164 ) !void {
2200 const zcu = dg.zcu;2165 const zcu = dg.zcu;
2201 const decl = zcu.declPtr(decl_index);2166 const decl = zcu.declPtr(decl_index);
2202 const fwd = dg.fwdDeclWriter();2167 const fwd = dg.fwdDeclWriter();
2203 const is_global = variable.is_extern or dg.declIsGlobal(decl.val);2168 try fwd.writeAll(if (variable.is_extern) "zig_extern " else "static ");
2204 try fwd.writeAll(if (is_global) "zig_extern " else "static ");2169 if (variable.is_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
2205 const maybe_exports = zcu.decl_exports.get(decl_index);
2206 const export_weak_linkage = if (maybe_exports) |exports|
2207 exports.items[0].opts.linkage == .weak
2208 else
2209 false;
2210 if (variable.is_weak_linkage or export_weak_linkage) try fwd.writeAll("zig_weak_linkage ");
2211 if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal ");2170 if (variable.is_threadlocal and !dg.mod.single_threaded) try fwd.writeAll("zig_threadlocal ");
2212 try dg.renderTypeAndName(2171 try dg.renderTypeAndName(
2213 fwd,2172 fwd,
...@@ -2217,38 +2176,17 @@ pub const DeclGen = struct {...@@ -2217,38 +2176,17 @@ pub const DeclGen = struct {
2217 decl.alignment,2176 decl.alignment,
2218 .complete,2177 .complete,
2219 );2178 );
2220 mangled: {
2221 const external_name = (if (maybe_exports) |exports|
2222 exports.items[0].opts.name
2223 else if (variable.is_extern)
2224 decl.name
2225 else
2226 break :mangled).toSlice(&zcu.intern_pool);
2227 if (isMangledIdent(external_name, true)) {
2228 try fwd.print(" zig_mangled_{s}({ }, {s})", .{
2229 @tagName(fwd_kind),
2230 fmtIdent(external_name),
2231 fmtStringLiteral(external_name, null),
2232 });
2233 }
2234 }
2235 try fwd.writeAll(";\n");2179 try fwd.writeAll(";\n");
2236 }2180 }
22372181
2238 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void {2182 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex) !void {
2239 const zcu = dg.zcu;2183 const zcu = dg.zcu;
2240 const ip = &zcu.intern_pool;2184 const ip = &zcu.intern_pool;
2241 const decl = zcu.declPtr(decl_index);2185 const decl = zcu.declPtr(decl_index);
22422186
2243 if (zcu.decl_exports.get(decl_index)) |exports| {2187 if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| try writer.print("{ }", .{
2244 try writer.print("{ }", .{2188 fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
2245 fmtIdent(exports.items[export_index].opts.name.toSlice(ip)),2189 }) else {
2246 });
2247 } else if (decl.getExternDecl(zcu).unwrap()) |extern_decl_index| {
2248 try writer.print("{ }", .{
2249 fmtIdent(zcu.declPtr(extern_decl_index).name.toSlice(ip)),
2250 });
2251 } else {
2252 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),2190 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
2253 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.2191 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
2254 var name: [100]u8 = undefined;2192 var name: [100]u8 = undefined;
...@@ -2761,69 +2699,6 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2761,69 +2699,6 @@ pub fn genErrDecls(o: *Object) !void {
2761 try writer.writeAll("};\n");2699 try writer.writeAll("};\n");
2762}2700}
27632701
2764fn genExports(o: *Object) !void {
2765 const tracy = trace(@src());
2766 defer tracy.end();
2767
2768 const zcu = o.dg.zcu;
2769 const ip = &zcu.intern_pool;
2770 const decl_index = switch (o.dg.pass) {
2771 .decl => |decl| decl,
2772 .anon, .flush => return,
2773 };
2774 const decl = zcu.declPtr(decl_index);
2775 const fwd = o.dg.fwdDeclWriter();
2776
2777 const exports = zcu.decl_exports.get(decl_index) orelse return;
2778 if (exports.items.len < 2) return;
2779
2780 const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) {
2781 .func => return for (exports.items[1..], 1..) |@"export", i| {
2782 try fwd.writeAll("zig_extern ");
2783 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
2784 try o.dg.renderFunctionSignature(
2785 fwd,
2786 decl_index,
2787 .forward,
2788 .{ .export_index = @intCast(i) },
2789 );
2790 try fwd.writeAll(";\n");
2791 },
2792 .extern_func => {
2793 // TODO: when sema allows re-exporting extern decls
2794 unreachable;
2795 },
2796 .variable => |variable| variable.is_const,
2797 else => true,
2798 };
2799 for (exports.items[1..]) |@"export"| {
2800 try fwd.writeAll("zig_extern ");
2801 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
2802 const export_name = @"export".opts.name.toSlice(ip);
2803 try o.dg.renderTypeAndName(
2804 fwd,
2805 decl.typeOf(zcu),
2806 .{ .identifier = export_name },
2807 CQualifiers.init(.{ .@"const" = is_variable_const }),
2808 decl.alignment,
2809 .complete,
2810 );
2811 if (isMangledIdent(export_name, true)) {
2812 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
2813 fmtIdent(export_name),
2814 fmtStringLiteral(export_name, null),
2815 fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
2816 });
2817 } else {
2818 try fwd.print(" zig_export({s}, {s})", .{
2819 fmtStringLiteral(exports.items[0].opts.name.toSlice(ip), null),
2820 fmtStringLiteral(export_name, null),
2821 });
2822 }
2823 try fwd.writeAll(";\n");
2824 }
2825}
2826
2827pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {2702pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void {
2828 const zcu = o.dg.zcu;2703 const zcu = o.dg.zcu;
2829 const ip = &zcu.intern_pool;2704 const ip = &zcu.intern_pool;
...@@ -2885,19 +2760,19 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn...@@ -2885,19 +2760,19 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn
2885 const fn_info = fn_ctype.info(ctype_pool).function;2760 const fn_info = fn_ctype.info(ctype_pool).function;
2886 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);2761 const fn_name = fmtCTypePoolString(val.fn_name, lazy_ctype_pool);
28872762
2888 const fwd_decl_writer = o.dg.fwdDeclWriter();2763 const fwd = o.dg.fwdDeclWriter();
2889 try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)});2764 try fwd.print("static zig_{s} ", .{@tagName(key)});
2890 try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{2765 try o.dg.renderFunctionSignature(fwd, fn_decl.val, fn_decl.alignment, .forward, .{
2891 .fmt_ctype_pool_string = fn_name,2766 .fmt_ctype_pool_string = fn_name,
2892 });2767 });
2893 try fwd_decl_writer.writeAll(";\n");2768 try fwd.writeAll(";\n");
28942769
2895 try w.print("static zig_{s} ", .{@tagName(key)});2770 try w.print("zig_{s} ", .{@tagName(key)});
2896 try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{2771 try o.dg.renderFunctionSignature(w, fn_decl.val, .none, .complete, .{
2897 .fmt_ctype_pool_string = fn_name,2772 .fmt_ctype_pool_string = fn_name,
2898 });2773 });
2899 try w.writeAll(" {\n return ");2774 try w.writeAll(" {\n return ");
2900 try o.dg.renderDeclName(w, fn_decl_index, 0);2775 try o.dg.renderDeclName(w, fn_decl_index);
2901 try w.writeByte('(');2776 try w.writeByte('(');
2902 for (0..fn_info.param_ctypes.len) |arg| {2777 for (0..fn_info.param_ctypes.len) |arg| {
2903 if (arg > 0) try w.writeAll(", ");2778 if (arg > 0) try w.writeAll(", ");
...@@ -2921,21 +2796,26 @@ pub fn genFunc(f: *Function) !void {...@@ -2921,21 +2796,26 @@ pub fn genFunc(f: *Function) !void {
2921 o.code_header = std.ArrayList(u8).init(gpa);2796 o.code_header = std.ArrayList(u8).init(gpa);
2922 defer o.code_header.deinit();2797 defer o.code_header.deinit();
29232798
2924 const is_global = o.dg.declIsGlobal(decl.val);2799 const fwd = o.dg.fwdDeclWriter();
2925 const fwd_decl_writer = o.dg.fwdDeclWriter();2800 try fwd.writeAll("static ");
2926 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2801 try o.dg.renderFunctionSignature(
29272802 fwd,
2928 if (zcu.decl_exports.get(decl_index)) |exports|2803 decl.val,
2929 if (exports.items[0].opts.linkage == .weak) try fwd_decl_writer.writeAll("zig_weak_linkage_fn ");2804 decl.alignment,
2930 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });2805 .forward,
2931 try fwd_decl_writer.writeAll(";\n");2806 .{ .decl = decl_index },
2932 try genExports(o);2807 );
2808 try fwd.writeAll(";\n");
29332809
2934 try o.indent_writer.insertNewline();
2935 if (!is_global) try o.writer().writeAll("static ");
2936 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|2810 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
2937 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});2811 try o.writer().print("zig_linksection_fn({s}) ", .{fmtStringLiteral(s, null)});
2938 try o.dg.renderFunctionSignature(o.writer(), decl_index, .complete, .{ .export_index = 0 });2812 try o.dg.renderFunctionSignature(
2813 o.writer(),
2814 decl.val,
2815 .none,
2816 .complete,
2817 .{ .decl = decl_index },
2818 );
2939 try o.writer().writeByte(' ');2819 try o.writer().writeByte(' ');
29402820
2941 // In case we need to use the header, populate it with a copy of the function2821 // In case we need to use the header, populate it with a copy of the function
...@@ -2949,7 +2829,6 @@ pub fn genFunc(f: *Function) !void {...@@ -2949,7 +2829,6 @@ pub fn genFunc(f: *Function) !void {
29492829
2950 const main_body = f.air.getMainBody();2830 const main_body = f.air.getMainBody();
2951 try genBodyResolveState(f, undefined, &.{}, main_body, false);2831 try genBodyResolveState(f, undefined, &.{}, main_body, false);
2952
2953 try o.indent_writer.insertNewline();2832 try o.indent_writer.insertNewline();
29542833
2955 // Take advantage of the free_locals map to bucket locals per type. All2834 // Take advantage of the free_locals map to bucket locals per type. All
...@@ -3007,20 +2886,25 @@ pub fn genDecl(o: *Object) !void {...@@ -3007,20 +2886,25 @@ pub fn genDecl(o: *Object) !void {
30072886
3008 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;2887 if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return;
3009 if (decl.val.getExternFunc(zcu)) |_| {2888 if (decl.val.getExternFunc(zcu)) |_| {
3010 const fwd_decl_writer = o.dg.fwdDeclWriter();2889 const fwd = o.dg.fwdDeclWriter();
3011 try fwd_decl_writer.writeAll("zig_extern ");2890 try fwd.writeAll("zig_extern ");
3012 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 });2891 try o.dg.renderFunctionSignature(
3013 try fwd_decl_writer.writeAll(";\n");2892 fwd,
3014 try genExports(o);2893 decl.val,
2894 decl.alignment,
2895 .forward,
2896 .{ .@"export" = .{
2897 .main_name = decl.name,
2898 .extern_name = decl.name,
2899 } },
2900 );
2901 try fwd.writeAll(";\n");
3015 } else if (decl.val.getVariable(zcu)) |variable| {2902 } else if (decl.val.getVariable(zcu)) |variable| {
3016 try o.dg.renderFwdDecl(decl_index, variable, .final);2903 try o.dg.renderFwdDecl(decl_index, variable);
3017 try genExports(o);
30182904
3019 if (variable.is_extern) return;2905 if (variable.is_extern) return;
30202906
3021 const is_global = variable.is_extern or o.dg.declIsGlobal(decl.val);
3022 const w = o.writer();2907 const w = o.writer();
3023 if (!is_global) try w.writeAll("static ");
3024 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");2908 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
3025 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");2909 if (variable.is_threadlocal and !o.dg.mod.single_threaded) try w.writeAll("zig_threadlocal ");
3026 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|2910 if (decl.@"linksection".toSlice(&zcu.intern_pool)) |s|
...@@ -3032,46 +2916,27 @@ pub fn genDecl(o: *Object) !void {...@@ -3032,46 +2916,27 @@ pub fn genDecl(o: *Object) !void {
3032 try w.writeByte(';');2916 try w.writeByte(';');
3033 try o.indent_writer.insertNewline();2917 try o.indent_writer.insertNewline();
3034 } else {2918 } else {
3035 const is_global = o.dg.zcu.decl_exports.contains(decl_index);
3036 const decl_c_value = .{ .decl = decl_index };2919 const decl_c_value = .{ .decl = decl_index };
3037 try genDeclValue(o, decl.val, is_global, decl_c_value, decl.alignment, decl.@"linksection");2920 try genDeclValue(o, decl.val, decl_c_value, decl.alignment, decl.@"linksection");
3038 }2921 }
3039}2922}
30402923
3041pub fn genDeclValue(2924pub fn genDeclValue(
3042 o: *Object,2925 o: *Object,
3043 val: Value,2926 val: Value,
3044 is_global: bool,
3045 decl_c_value: CValue,2927 decl_c_value: CValue,
3046 alignment: Alignment,2928 alignment: Alignment,
3047 @"linksection": InternPool.OptionalNullTerminatedString,2929 @"linksection": InternPool.OptionalNullTerminatedString,
3048) !void {2930) !void {
3049 const zcu = o.dg.zcu;2931 const zcu = o.dg.zcu;
3050 const fwd_decl_writer = o.dg.fwdDeclWriter();
3051
3052 const ty = val.typeOf(zcu);2932 const ty = val.typeOf(zcu);
30532933
3054 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2934 const fwd = o.dg.fwdDeclWriter();
3055 try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete);2935 try fwd.writeAll("static ");
3056 switch (o.dg.pass) {2936 try o.dg.renderTypeAndName(fwd, ty, decl_c_value, Const, alignment, .complete);
3057 .decl => |decl_index| {2937 try fwd.writeAll(";\n");
3058 if (zcu.decl_exports.get(decl_index)) |exports| {
3059 const export_name = exports.items[0].opts.name.toSlice(&zcu.intern_pool);
3060 if (isMangledIdent(export_name, true)) {
3061 try fwd_decl_writer.print(" zig_mangled_final({ }, {s})", .{
3062 fmtIdent(export_name), fmtStringLiteral(export_name, null),
3063 });
3064 }
3065 }
3066 },
3067 .anon => {},
3068 .flush => unreachable,
3069 }
3070 try fwd_decl_writer.writeAll(";\n");
3071 try genExports(o);
30722938
3073 const w = o.writer();2939 const w = o.writer();
3074 if (!is_global) try w.writeAll("static ");
3075 if (@"linksection".toSlice(&zcu.intern_pool)) |s|2940 if (@"linksection".toSlice(&zcu.intern_pool)) |s|
3076 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});2941 try w.print("zig_linksection({s}) ", .{fmtStringLiteral(s, null)});
3077 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);2942 try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete);
...@@ -3080,22 +2945,73 @@ pub fn genDeclValue(...@@ -3080,22 +2945,73 @@ pub fn genDeclValue(
3080 try w.writeAll(";\n");2945 try w.writeAll(";\n");
3081}2946}
30822947
3083pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {2948pub fn genExports(dg: *DeclGen, exported: Zcu.Exported, export_indices: []const u32) !void {
3084 const tracy = trace(@src());
3085 defer tracy.end();
3086
3087 const zcu = dg.zcu;2949 const zcu = dg.zcu;
3088 const decl_index = dg.pass.decl;2950 const ip = &zcu.intern_pool;
3089 const decl = zcu.declPtr(decl_index);2951 const fwd = dg.fwdDeclWriter();
3090 const writer = dg.fwdDeclWriter();
30912952
3092 switch (decl.typeOf(zcu).zigTypeTag(zcu)) {2953 const main_name = zcu.all_exports.items[export_indices[0]].opts.name;
3093 .Fn => if (dg.declIsGlobal(decl.val)) {2954 try fwd.writeAll("#define ");
3094 try writer.writeAll("zig_extern ");2955 switch (exported) {
3095 try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });2956 .decl_index => |decl_index| try dg.renderDeclName(fwd, decl_index),
3096 try dg.fwd_decl.appendSlice(";\n");2957 .value => |value| try DeclGen.renderAnonDeclName(fwd, Value.fromInterned(value)),
2958 }
2959 try fwd.writeByte(' ');
2960 try fwd.print("{ }", .{fmtIdent(main_name.toSlice(ip))});
2961 try fwd.writeByte('\n');
2962
2963 const is_const = switch (ip.indexToKey(exported.getValue(zcu).toIntern())) {
2964 .func, .extern_func => return for (export_indices) |export_index| {
2965 const @"export" = &zcu.all_exports.items[export_index];
2966 try fwd.writeAll("zig_extern ");
2967 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn ");
2968 try dg.renderFunctionSignature(
2969 fwd,
2970 exported.getValue(zcu),
2971 exported.getAlign(zcu),
2972 .forward,
2973 .{ .@"export" = .{
2974 .main_name = main_name,
2975 .extern_name = @"export".opts.name,
2976 } },
2977 );
2978 try fwd.writeAll(";\n");
3097 },2979 },
3098 else => {},2980 .variable => |variable| variable.is_const,
2981 else => true,
2982 };
2983 for (export_indices) |export_index| {
2984 const @"export" = &zcu.all_exports.items[export_index];
2985 try fwd.writeAll("zig_extern ");
2986 if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage ");
2987 const extern_name = @"export".opts.name.toSlice(ip);
2988 const is_mangled = isMangledIdent(extern_name, true);
2989 const is_export = @"export".opts.name != main_name;
2990 try dg.renderTypeAndName(
2991 fwd,
2992 exported.getValue(zcu).typeOf(zcu),
2993 .{ .identifier = extern_name },
2994 CQualifiers.init(.{ .@"const" = is_const }),
2995 exported.getAlign(zcu),
2996 .complete,
2997 );
2998 if (is_mangled and is_export) {
2999 try fwd.print(" zig_mangled_export({ }, {s}, {s})", .{
3000 fmtIdent(extern_name),
3001 fmtStringLiteral(extern_name, null),
3002 fmtStringLiteral(main_name.toSlice(ip), null),
3003 });
3004 } else if (is_mangled) {
3005 try fwd.print(" zig_mangled({ }, {s})", .{
3006 fmtIdent(extern_name), fmtStringLiteral(extern_name, null),
3007 });
3008 } else if (is_export) {
3009 try fwd.print(" zig_export({s}, {s})", .{
3010 fmtStringLiteral(main_name.toSlice(ip), null),
3011 fmtStringLiteral(extern_name, null),
3012 });
3013 }
3014 try fwd.writeAll(";\n");
3099 }3015 }
3100}3016}
31013017
...@@ -4552,7 +4468,7 @@ fn airCall(...@@ -4552,7 +4468,7 @@ fn airCall(
4552 };4468 };
4553 };4469 };
4554 switch (modifier) {4470 switch (modifier) {
4555 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0),4471 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl),
4556 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(4472 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(
4557 @unionInit(LazyFnKey, @tagName(m), fn_decl),4473 @unionInit(LazyFnKey, @tagName(m), fn_decl),
4558 @unionInit(LazyFnValue.Data, @tagName(m), {}),4474 @unionInit(LazyFnValue.Data, @tagName(m), {}),
src/codegen/c/Type.zig+1-1
...@@ -2583,6 +2583,6 @@ const assert = std.debug.assert;...@@ -2583,6 +2583,6 @@ const assert = std.debug.assert;
2583const CType = @This();2583const CType = @This();
2584const Module = @import("../../Package/Module.zig");2584const Module = @import("../../Package/Module.zig");
2585const std = @import("std");2585const std = @import("std");
2586const Type = @import("../../type.zig").Type;2586const Type = @import("../../Type.zig");
2587const Zcu = @import("../../Zcu.zig");2587const Zcu = @import("../../Zcu.zig");
2588const DeclIndex = @import("../../InternPool.zig").DeclIndex;2588const DeclIndex = @import("../../InternPool.zig").DeclIndex;
src/codegen/llvm.zig+117-159
...@@ -22,7 +22,7 @@ const Package = @import("../Package.zig");...@@ -22,7 +22,7 @@ const Package = @import("../Package.zig");
22const Air = @import("../Air.zig");22const Air = @import("../Air.zig");
23const Liveness = @import("../Liveness.zig");23const Liveness = @import("../Liveness.zig");
24const Value = @import("../Value.zig");24const Value = @import("../Value.zig");
25const Type = @import("../type.zig").Type;25const Type = @import("../Type.zig");
26const x86_64_abi = @import("../arch/x86_64/abi.zig");26const x86_64_abi = @import("../arch/x86_64/abi.zig");
27const wasm_c_abi = @import("../arch/wasm/abi.zig");27const wasm_c_abi = @import("../arch/wasm/abi.zig");
28const aarch64_c_abi = @import("../arch/aarch64/abi.zig");28const aarch64_c_abi = @import("../arch/aarch64/abi.zig");
...@@ -848,10 +848,6 @@ pub const Object = struct {...@@ -848,10 +848,6 @@ pub const Object = struct {
848 /// Note that the values are not added until `emit`, when all errors in848 /// Note that the values are not added until `emit`, when all errors in
849 /// the compilation are known.849 /// the compilation are known.
850 error_name_table: Builder.Variable.Index,850 error_name_table: Builder.Variable.Index,
851 /// This map is usually very close to empty. It tracks only the cases when a
852 /// second extern Decl could not be emitted with the correct name due to a
853 /// name collision.
854 extern_collisions: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, void),
855851
856 /// Memoizes a null `?usize` value.852 /// Memoizes a null `?usize` value.
857 null_opt_usize: Builder.Constant,853 null_opt_usize: Builder.Constant,
...@@ -1011,7 +1007,6 @@ pub const Object = struct {...@@ -1011,7 +1007,6 @@ pub const Object = struct {
1011 .named_enum_map = .{},1007 .named_enum_map = .{},
1012 .type_map = .{},1008 .type_map = .{},
1013 .error_name_table = .none,1009 .error_name_table = .none,
1014 .extern_collisions = .{},
1015 .null_opt_usize = .no_init,1010 .null_opt_usize = .no_init,
1016 .struct_field_map = .{},1011 .struct_field_map = .{},
1017 };1012 };
...@@ -1029,7 +1024,6 @@ pub const Object = struct {...@@ -1029,7 +1024,6 @@ pub const Object = struct {
1029 self.anon_decl_map.deinit(gpa);1024 self.anon_decl_map.deinit(gpa);
1030 self.named_enum_map.deinit(gpa);1025 self.named_enum_map.deinit(gpa);
1031 self.type_map.deinit(gpa);1026 self.type_map.deinit(gpa);
1032 self.extern_collisions.deinit(gpa);
1033 self.builder.deinit();1027 self.builder.deinit();
1034 self.struct_field_map.deinit(gpa);1028 self.struct_field_map.deinit(gpa);
1035 self.* = undefined;1029 self.* = undefined;
...@@ -1121,61 +1115,6 @@ pub const Object = struct {...@@ -1121,61 +1115,6 @@ pub const Object = struct {
1121 try object.builder.finishModuleAsm();1115 try object.builder.finishModuleAsm();
1122 }1116 }
11231117
1124 fn resolveExportExternCollisions(object: *Object) !void {
1125 const mod = object.module;
1126
1127 // This map has externs with incorrect symbol names.
1128 for (object.extern_collisions.keys()) |decl_index| {
1129 const global = object.decl_map.get(decl_index) orelse continue;
1130 // Same logic as below but for externs instead of exports.
1131 const decl_name = object.builder.strtabStringIfExists(mod.declPtr(decl_index).name.toSlice(&mod.intern_pool)) orelse continue;
1132 const other_global = object.builder.getGlobal(decl_name) orelse continue;
1133 if (other_global.toConst().getBase(&object.builder) ==
1134 global.toConst().getBase(&object.builder)) continue;
1135
1136 try global.replace(other_global, &object.builder);
1137 }
1138 object.extern_collisions.clearRetainingCapacity();
1139
1140 for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {
1141 const global = object.decl_map.get(decl_index) orelse continue;
1142 try resolveGlobalCollisions(object, global, export_list.items);
1143 }
1144
1145 for (mod.value_exports.keys(), mod.value_exports.values()) |val, export_list| {
1146 const global = object.anon_decl_map.get(val) orelse continue;
1147 try resolveGlobalCollisions(object, global, export_list.items);
1148 }
1149 }
1150
1151 fn resolveGlobalCollisions(
1152 object: *Object,
1153 global: Builder.Global.Index,
1154 export_list: []const *Module.Export,
1155 ) !void {
1156 const mod = object.module;
1157 const global_base = global.toConst().getBase(&object.builder);
1158 for (export_list) |exp| {
1159 // Detect if the LLVM global has already been created as an extern. In such
1160 // case, we need to replace all uses of it with this exported global.
1161 const exp_name = object.builder.strtabStringIfExists(exp.opts.name.toSlice(&mod.intern_pool)) orelse continue;
1162
1163 const other_global = object.builder.getGlobal(exp_name) orelse continue;
1164 if (other_global.toConst().getBase(&object.builder) == global_base) continue;
1165
1166 try global.takeName(other_global, &object.builder);
1167 try other_global.replace(global, &object.builder);
1168 // Problem: now we need to replace in the decl_map that
1169 // the extern decl index points to this new global. However we don't
1170 // know the decl index.
1171 // Even if we did, a future incremental update to the extern would then
1172 // treat the LLVM global as an extern rather than an export, so it would
1173 // need a way to check that.
1174 // This is a TODO that needs to be solved when making
1175 // the LLVM backend support incremental compilation.
1176 }
1177 }
1178
1179 pub const EmitOptions = struct {1118 pub const EmitOptions = struct {
1180 pre_ir_path: ?[]const u8,1119 pre_ir_path: ?[]const u8,
1181 pre_bc_path: ?[]const u8,1120 pre_bc_path: ?[]const u8,
...@@ -1193,7 +1132,6 @@ pub const Object = struct {...@@ -1193,7 +1132,6 @@ pub const Object = struct {
11931132
1194 pub fn emit(self: *Object, options: EmitOptions) !void {1133 pub fn emit(self: *Object, options: EmitOptions) !void {
1195 {1134 {
1196 try self.resolveExportExternCollisions();
1197 try self.genErrorNameTable();1135 try self.genErrorNameTable();
1198 try self.genCmpLtErrorsLenFunction();1136 try self.genCmpLtErrorsLenFunction();
1199 try self.genModuleLevelAssembly();1137 try self.genModuleLevelAssembly();
...@@ -1698,8 +1636,7 @@ pub const Object = struct {...@@ -1698,8 +1636,7 @@ pub const Object = struct {
1698 const file = try o.getDebugFile(namespace.file_scope);1636 const file = try o.getDebugFile(namespace.file_scope);
16991637
1700 const line_number = decl.navSrcLine(zcu) + 1;1638 const line_number = decl.navSrcLine(zcu) + 1;
1701 const is_internal_linkage = decl.val.getExternFunc(zcu) == null and1639 const is_internal_linkage = decl.val.getExternFunc(zcu) == null;
1702 !zcu.decl_exports.contains(decl_index);
1703 const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu));1640 const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu));
17041641
1705 const subprogram = try o.builder.debugSubprogram(1642 const subprogram = try o.builder.debugSubprogram(
...@@ -1752,7 +1689,7 @@ pub const Object = struct {...@@ -1752,7 +1689,7 @@ pub const Object = struct {
1752 fg.genBody(air.getMainBody()) catch |err| switch (err) {1689 fg.genBody(air.getMainBody()) catch |err| switch (err) {
1753 error.CodegenFail => {1690 error.CodegenFail => {
1754 decl.analysis = .codegen_failure;1691 decl.analysis = .codegen_failure;
1755 try zcu.failed_decls.put(zcu.gpa, decl_index, dg.err_msg.?);1692 try zcu.failed_analysis.put(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), dg.err_msg.?);
1756 dg.err_msg = null;1693 dg.err_msg = null;
1757 return;1694 return;
1758 },1695 },
...@@ -1760,8 +1697,6 @@ pub const Object = struct {...@@ -1760,8 +1697,6 @@ pub const Object = struct {
1760 };1697 };
17611698
1762 try fg.wip.finish();1699 try fg.wip.finish();
1763
1764 try o.updateExports(zcu, .{ .decl_index = decl_index }, zcu.getDeclExports(decl_index));
1765 }1700 }
17661701
1767 pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void {1702 pub fn updateDecl(self: *Object, module: *Module, decl_index: InternPool.DeclIndex) !void {
...@@ -1775,72 +1710,31 @@ pub const Object = struct {...@@ -1775,72 +1710,31 @@ pub const Object = struct {
1775 dg.genDecl() catch |err| switch (err) {1710 dg.genDecl() catch |err| switch (err) {
1776 error.CodegenFail => {1711 error.CodegenFail => {
1777 decl.analysis = .codegen_failure;1712 decl.analysis = .codegen_failure;
1778 try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?);1713 try module.failed_analysis.put(module.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), dg.err_msg.?);
1779 dg.err_msg = null;1714 dg.err_msg = null;
1780 return;1715 return;
1781 },1716 },
1782 else => |e| return e,1717 else => |e| return e,
1783 };1718 };
1784 try self.updateExports(module, .{ .decl_index = decl_index }, module.getDeclExports(decl_index));
1785 }1719 }
17861720
1787 pub fn updateExports(1721 pub fn updateExports(
1788 self: *Object,1722 self: *Object,
1789 mod: *Module,1723 mod: *Module,
1790 exported: Module.Exported,1724 exported: Module.Exported,
1791 exports: []const *Module.Export,1725 export_indices: []const u32,
1792 ) link.File.UpdateExportsError!void {1726 ) link.File.UpdateExportsError!void {
1793 const decl_index = switch (exported) {1727 const decl_index = switch (exported) {
1794 .decl_index => |i| i,1728 .decl_index => |i| i,
1795 .value => |val| return updateExportedValue(self, mod, val, exports),1729 .value => |val| return updateExportedValue(self, mod, val, export_indices),
1796 };1730 };
1797 const gpa = mod.gpa;
1798 const ip = &mod.intern_pool;1731 const ip = &mod.intern_pool;
1799 // If the module does not already have the function, we ignore this function call1732 const global_index = self.decl_map.get(decl_index).?;
1800 // because we call `updateExports` at the end of `updateFunc` and `updateDecl`.
1801 const global_index = self.decl_map.get(decl_index) orelse return;
1802 const decl = mod.declPtr(decl_index);1733 const decl = mod.declPtr(decl_index);
1803 const comp = mod.comp;1734 const comp = mod.comp;
1804 if (decl.isExtern(mod)) {
1805 const decl_name = decl_name: {
1806 if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) {
1807 if (decl.getOwnedExternFunc(mod).?.lib_name.toSlice(ip)) |lib_name| {
1808 if (!std.mem.eql(u8, lib_name, "c")) {
1809 break :decl_name try self.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name });
1810 }
1811 }
1812 }
1813 break :decl_name try self.builder.strtabString(decl.name.toSlice(ip));
1814 };
18151735
1816 if (self.builder.getGlobal(decl_name)) |other_global| {1736 if (export_indices.len != 0) {
1817 if (other_global != global_index) {1737 return updateExportedGlobal(self, mod, global_index, export_indices);
1818 try self.extern_collisions.put(gpa, decl_index, {});
1819 }
1820 }
1821
1822 try global_index.rename(decl_name, &self.builder);
1823 global_index.setLinkage(.external, &self.builder);
1824 global_index.setUnnamedAddr(.default, &self.builder);
1825 if (comp.config.dll_export_fns)
1826 global_index.setDllStorageClass(.default, &self.builder);
1827
1828 if (decl.val.getVariable(mod)) |decl_var| {
1829 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1830 if (decl_var.is_threadlocal) .generaldynamic else .default,
1831 &self.builder,
1832 );
1833 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
1834 }
1835 } else if (exports.len != 0) {
1836 const main_exp_name = try self.builder.strtabString(exports[0].opts.name.toSlice(ip));
1837 try global_index.rename(main_exp_name, &self.builder);
1838
1839 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
1840 global_index.ptrConst(&self.builder).kind
1841 .variable.setThreadLocal(.generaldynamic, &self.builder);
1842
1843 return updateExportedGlobal(self, mod, global_index, exports);
1844 } else {1738 } else {
1845 const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip));1739 const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(mod)).toSlice(ip));
1846 try global_index.rename(fqn, &self.builder);1740 try global_index.rename(fqn, &self.builder);
...@@ -1848,17 +1742,6 @@ pub const Object = struct {...@@ -1848,17 +1742,6 @@ pub const Object = struct {
1848 if (comp.config.dll_export_fns)1742 if (comp.config.dll_export_fns)
1849 global_index.setDllStorageClass(.default, &self.builder);1743 global_index.setDllStorageClass(.default, &self.builder);
1850 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);1744 global_index.setUnnamedAddr(.unnamed_addr, &self.builder);
1851 if (decl.val.getVariable(mod)) |decl_var| {
1852 const decl_namespace = mod.namespacePtr(decl.src_namespace);
1853 const single_threaded = decl_namespace.file_scope.mod.single_threaded;
1854 global_index.ptrConst(&self.builder).kind.variable.setThreadLocal(
1855 if (decl_var.is_threadlocal and !single_threaded)
1856 .generaldynamic
1857 else
1858 .default,
1859 &self.builder,
1860 );
1861 }
1862 }1745 }
1863 }1746 }
18641747
...@@ -1866,11 +1749,11 @@ pub const Object = struct {...@@ -1866,11 +1749,11 @@ pub const Object = struct {
1866 o: *Object,1749 o: *Object,
1867 mod: *Module,1750 mod: *Module,
1868 exported_value: InternPool.Index,1751 exported_value: InternPool.Index,
1869 exports: []const *Module.Export,1752 export_indices: []const u32,
1870 ) link.File.UpdateExportsError!void {1753 ) link.File.UpdateExportsError!void {
1871 const gpa = mod.gpa;1754 const gpa = mod.gpa;
1872 const ip = &mod.intern_pool;1755 const ip = &mod.intern_pool;
1873 const main_exp_name = try o.builder.strtabString(exports[0].opts.name.toSlice(ip));1756 const main_exp_name = try o.builder.strtabString(mod.all_exports.items[export_indices[0]].opts.name.toSlice(ip));
1874 const global_index = i: {1757 const global_index = i: {
1875 const gop = try o.anon_decl_map.getOrPut(gpa, exported_value);1758 const gop = try o.anon_decl_map.getOrPut(gpa, exported_value);
1876 if (gop.found_existing) {1759 if (gop.found_existing) {
...@@ -1894,32 +1777,57 @@ pub const Object = struct {...@@ -1894,32 +1777,57 @@ pub const Object = struct {
1894 try variable_index.setInitializer(init_val, &o.builder);1777 try variable_index.setInitializer(init_val, &o.builder);
1895 break :i global_index;1778 break :i global_index;
1896 };1779 };
1897 return updateExportedGlobal(o, mod, global_index, exports);1780 return updateExportedGlobal(o, mod, global_index, export_indices);
1898 }1781 }
18991782
1900 fn updateExportedGlobal(1783 fn updateExportedGlobal(
1901 o: *Object,1784 o: *Object,
1902 mod: *Module,1785 mod: *Module,
1903 global_index: Builder.Global.Index,1786 global_index: Builder.Global.Index,
1904 exports: []const *Module.Export,1787 export_indices: []const u32,
1905 ) link.File.UpdateExportsError!void {1788 ) link.File.UpdateExportsError!void {
1906 const comp = mod.comp;1789 const comp = mod.comp;
1907 const ip = &mod.intern_pool;1790 const ip = &mod.intern_pool;
1791 const first_export = mod.all_exports.items[export_indices[0]];
1792
1793 // We will rename this global to have a name matching `first_export`.
1794 // Successive exports become aliases.
1795 // If the first export name already exists, then there is a corresponding
1796 // extern global - we replace it with this global.
1797 const first_exp_name = try o.builder.strtabString(first_export.opts.name.toSlice(ip));
1798 if (o.builder.getGlobal(first_exp_name)) |other_global| replace: {
1799 if (other_global.toConst().getBase(&o.builder) == global_index.toConst().getBase(&o.builder)) {
1800 break :replace; // this global already has the name we want
1801 }
1802 try global_index.takeName(other_global, &o.builder);
1803 try other_global.replace(global_index, &o.builder);
1804 // Problem: now we need to replace in the decl_map that
1805 // the extern decl index points to this new global. However we don't
1806 // know the decl index.
1807 // Even if we did, a future incremental update to the extern would then
1808 // treat the LLVM global as an extern rather than an export, so it would
1809 // need a way to check that.
1810 // This is a TODO that needs to be solved when making
1811 // the LLVM backend support incremental compilation.
1812 } else {
1813 try global_index.rename(first_exp_name, &o.builder);
1814 }
1815
1908 global_index.setUnnamedAddr(.default, &o.builder);1816 global_index.setUnnamedAddr(.default, &o.builder);
1909 if (comp.config.dll_export_fns)1817 if (comp.config.dll_export_fns)
1910 global_index.setDllStorageClass(.dllexport, &o.builder);1818 global_index.setDllStorageClass(.dllexport, &o.builder);
1911 global_index.setLinkage(switch (exports[0].opts.linkage) {1819 global_index.setLinkage(switch (first_export.opts.linkage) {
1912 .internal => unreachable,1820 .internal => unreachable,
1913 .strong => .external,1821 .strong => .external,
1914 .weak => .weak_odr,1822 .weak => .weak_odr,
1915 .link_once => .linkonce_odr,1823 .link_once => .linkonce_odr,
1916 }, &o.builder);1824 }, &o.builder);
1917 global_index.setVisibility(switch (exports[0].opts.visibility) {1825 global_index.setVisibility(switch (first_export.opts.visibility) {
1918 .default => .default,1826 .default => .default,
1919 .hidden => .hidden,1827 .hidden => .hidden,
1920 .protected => .protected,1828 .protected => .protected,
1921 }, &o.builder);1829 }, &o.builder);
1922 if (exports[0].opts.section.toSlice(ip)) |section|1830 if (first_export.opts.section.toSlice(ip)) |section|
1923 switch (global_index.ptrConst(&o.builder).kind) {1831 switch (global_index.ptrConst(&o.builder).kind) {
1924 .variable => |impl_index| impl_index.setSection(1832 .variable => |impl_index| impl_index.setSection(
1925 try o.builder.string(section),1833 try o.builder.string(section),
...@@ -1936,7 +1844,8 @@ pub const Object = struct {...@@ -1936,7 +1844,8 @@ pub const Object = struct {
1936 // The planned solution to this is https://github.com/ziglang/zig/issues/132651844 // The planned solution to this is https://github.com/ziglang/zig/issues/13265
1937 // Until then we iterate over existing aliases and make them point1845 // Until then we iterate over existing aliases and make them point
1938 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.1846 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
1939 for (exports[1..]) |exp| {1847 for (export_indices[1..]) |export_idx| {
1848 const exp = mod.all_exports.items[export_idx];
1940 const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));1849 const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip));
1941 if (o.builder.getGlobal(exp_name)) |global| {1850 if (o.builder.getGlobal(exp_name)) |global| {
1942 switch (global.ptrConst(&o.builder).kind) {1851 switch (global.ptrConst(&o.builder).kind) {
...@@ -1944,7 +1853,13 @@ pub const Object = struct {...@@ -1944,7 +1853,13 @@ pub const Object = struct {
1944 alias.setAliasee(global_index.toConst(), &o.builder);1853 alias.setAliasee(global_index.toConst(), &o.builder);
1945 continue;1854 continue;
1946 },1855 },
1947 .variable, .function => {},1856 .variable, .function => {
1857 // This existing global is an `extern` corresponding to this export.
1858 // Replace it with the global being exported.
1859 // This existing global must be replaced with the alias.
1860 try global.rename(.empty, &o.builder);
1861 try global.replace(global_index, &o.builder);
1862 },
1948 .replaced => unreachable,1863 .replaced => unreachable,
1949 }1864 }
1950 }1865 }
...@@ -2688,7 +2603,10 @@ pub const Object = struct {...@@ -2688,7 +2603,10 @@ pub const Object = struct {
2688 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;2603 if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(mod)) continue;
26892604
2690 const field_size = Type.fromInterned(field_ty).abiSize(mod);2605 const field_size = Type.fromInterned(field_ty).abiSize(mod);
2691 const field_align = mod.unionFieldNormalAlignment(union_type, @intCast(field_index));2606 const field_align: InternPool.Alignment = switch (union_type.flagsPtr(ip).layout) {
2607 .@"packed" => .none,
2608 .auto, .@"extern" => mod.unionFieldNormalAlignment(union_type, @intCast(field_index)),
2609 };
26922610
2693 const field_name = tag_type.names.get(ip)[field_index];2611 const field_name = tag_type.names.get(ip)[field_index];
2694 fields.appendAssumeCapacity(try o.builder.debugMemberType(2612 fields.appendAssumeCapacity(try o.builder.debugMemberType(
...@@ -4729,7 +4647,7 @@ pub const DeclGen = struct {...@@ -4729,7 +4647,7 @@ pub const DeclGen = struct {
4729 const o = dg.object;4647 const o = dg.object;
4730 const gpa = o.gpa;4648 const gpa = o.gpa;
4731 const mod = o.module;4649 const mod = o.module;
4732 const src_loc = dg.decl.navSrcLoc(mod).upgrade(mod);4650 const src_loc = dg.decl.navSrcLoc(mod);
4733 dg.err_msg = try Module.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args);4651 dg.err_msg = try Module.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args);
4734 return error.CodegenFail;4652 return error.CodegenFail;
4735 }4653 }
...@@ -4762,36 +4680,77 @@ pub const DeclGen = struct {...@@ -4762,36 +4680,77 @@ pub const DeclGen = struct {
4762 else => try o.lowerValue(init_val),4680 else => try o.lowerValue(init_val),
4763 }, &o.builder);4681 }, &o.builder);
47644682
4683 if (decl.val.getVariable(zcu)) |decl_var| {
4684 const decl_namespace = zcu.namespacePtr(decl.src_namespace);
4685 const single_threaded = decl_namespace.file_scope.mod.single_threaded;
4686 variable_index.setThreadLocal(
4687 if (decl_var.is_threadlocal and !single_threaded) .generaldynamic else .default,
4688 &o.builder,
4689 );
4690 }
4691
4765 const line_number = decl.navSrcLine(zcu) + 1;4692 const line_number = decl.navSrcLine(zcu) + 1;
4766 const is_internal_linkage = !o.module.decl_exports.contains(decl_index);
47674693
4768 const namespace = zcu.namespacePtr(decl.src_namespace);4694 const namespace = zcu.namespacePtr(decl.src_namespace);
4769 const owner_mod = namespace.file_scope.mod;4695 const owner_mod = namespace.file_scope.mod;
47704696
4771 if (owner_mod.strip) return;4697 if (!owner_mod.strip) {
4698 const debug_file = try o.getDebugFile(namespace.file_scope);
4699
4700 const debug_global_var = try o.builder.debugGlobalVar(
4701 try o.builder.metadataString(decl.name.toSlice(ip)), // Name
4702 try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name
4703 debug_file, // File
4704 debug_file, // Scope
4705 line_number,
4706 try o.lowerDebugType(decl.typeOf(zcu)),
4707 variable_index,
4708 .{ .local = !decl.isExtern(zcu) },
4709 );
47724710
4773 const debug_file = try o.getDebugFile(namespace.file_scope);4711 const debug_expression = try o.builder.debugExpression(&.{});
47744712
4775 const debug_global_var = try o.builder.debugGlobalVar(4713 const debug_global_var_expression = try o.builder.debugGlobalVarExpression(
4776 try o.builder.metadataString(decl.name.toSlice(ip)), // Name4714 debug_global_var,
4777 try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name4715 debug_expression,
4778 debug_file, // File4716 );
4779 debug_file, // Scope
4780 line_number,
4781 try o.lowerDebugType(decl.typeOf(zcu)),
4782 variable_index,
4783 .{ .local = is_internal_linkage },
4784 );
47854717
4786 const debug_expression = try o.builder.debugExpression(&.{});4718 variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder);
4719 try o.debug_globals.append(o.gpa, debug_global_var_expression);
4720 }
4721 }
47874722
4788 const debug_global_var_expression = try o.builder.debugGlobalVarExpression(4723 if (decl.isExtern(zcu)) {
4789 debug_global_var,4724 const global_index = o.decl_map.get(decl_index).?;
4790 debug_expression,
4791 );
47924725
4793 variable_index.setGlobalVariableExpression(debug_global_var_expression, &o.builder);4726 const decl_name = decl_name: {
4794 try o.debug_globals.append(o.gpa, debug_global_var_expression);4727 if (zcu.getTarget().isWasm() and decl.typeOf(zcu).zigTypeTag(zcu) == .Fn) {
4728 if (decl.getOwnedExternFunc(zcu).?.lib_name.toSlice(ip)) |lib_name| {
4729 if (!std.mem.eql(u8, lib_name, "c")) {
4730 break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ decl.name.fmt(ip), lib_name });
4731 }
4732 }
4733 }
4734 break :decl_name try o.builder.strtabString(decl.name.toSlice(ip));
4735 };
4736
4737 if (o.builder.getGlobal(decl_name)) |other_global| {
4738 if (other_global != global_index) {
4739 // Another global already has this name; just use it in place of this global.
4740 try global_index.replace(other_global, &o.builder);
4741 return;
4742 }
4743 }
4744
4745 try global_index.rename(decl_name, &o.builder);
4746 global_index.setLinkage(.external, &o.builder);
4747 global_index.setUnnamedAddr(.default, &o.builder);
4748 if (zcu.comp.config.dll_export_fns)
4749 global_index.setDllStorageClass(.default, &o.builder);
4750
4751 if (decl.val.getVariable(zcu)) |decl_var| {
4752 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &o.builder);
4753 }
4795 }4754 }
4796 }4755 }
4797};4756};
...@@ -5193,7 +5152,6 @@ pub const FuncGen = struct {...@@ -5193,7 +5152,6 @@ pub const FuncGen = struct {
51935152
5194 const fqn = try decl.fullyQualifiedName(zcu);5153 const fqn = try decl.fullyQualifiedName(zcu);
51955154
5196 const is_internal_linkage = !zcu.decl_exports.contains(decl_index);
5197 const fn_ty = try zcu.funcType(.{5155 const fn_ty = try zcu.funcType(.{
5198 .param_types = &.{},5156 .param_types = &.{},
5199 .return_type = .void_type,5157 .return_type = .void_type,
...@@ -5211,7 +5169,7 @@ pub const FuncGen = struct {...@@ -5211,7 +5169,7 @@ pub const FuncGen = struct {
5211 .sp_flags = .{5169 .sp_flags = .{
5212 .Optimized = owner_mod.optimize_mode != .Debug,5170 .Optimized = owner_mod.optimize_mode != .Debug,
5213 .Definition = true,5171 .Definition = true,
5214 .LocalToUnit = is_internal_linkage,5172 .LocalToUnit = true, // TODO: we can't know this at this point, since the function could be exported later!
5215 },5173 },
5216 },5174 },
5217 o.debug_compile_unit,5175 o.debug_compile_unit,
src/codegen/spirv.zig+4-4
...@@ -9,7 +9,7 @@ const Zcu = @import("../Zcu.zig");...@@ -9,7 +9,7 @@ const Zcu = @import("../Zcu.zig");
9/// Deprecated.9/// Deprecated.
10const Module = Zcu;10const Module = Zcu;
11const Decl = Module.Decl;11const Decl = Module.Decl;
12const Type = @import("../type.zig").Type;12const Type = @import("../Type.zig");
13const Value = @import("../Value.zig");13const Value = @import("../Value.zig");
14const Air = @import("../Air.zig");14const Air = @import("../Air.zig");
15const Liveness = @import("../Liveness.zig");15const Liveness = @import("../Liveness.zig");
...@@ -218,7 +218,7 @@ pub const Object = struct {...@@ -218,7 +218,7 @@ pub const Object = struct {
218218
219 decl_gen.genDecl() catch |err| switch (err) {219 decl_gen.genDecl() catch |err| switch (err) {
220 error.CodegenFail => {220 error.CodegenFail => {
221 try mod.failed_decls.put(mod.gpa, decl_index, decl_gen.error_msg.?);221 try mod.failed_analysis.put(mod.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }), decl_gen.error_msg.?);
222 },222 },
223 else => |other| {223 else => |other| {
224 // There might be an error that happened *after* self.error_msg224 // There might be an error that happened *after* self.error_msg
...@@ -415,7 +415,7 @@ const DeclGen = struct {...@@ -415,7 +415,7 @@ const DeclGen = struct {
415 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {415 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
416 @setCold(true);416 @setCold(true);
417 const mod = self.module;417 const mod = self.module;
418 const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod).upgrade(mod);418 const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod);
419 assert(self.error_msg == null);419 assert(self.error_msg == null);
420 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);420 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
421 return error.CodegenFail;421 return error.CodegenFail;
...@@ -6439,7 +6439,7 @@ const DeclGen = struct {...@@ -6439,7 +6439,7 @@ const DeclGen = struct {
6439 // TODO: Translate proper error locations.6439 // TODO: Translate proper error locations.
6440 assert(as.errors.items.len != 0);6440 assert(as.errors.items.len != 0);
6441 assert(self.error_msg == null);6441 assert(self.error_msg == null);
6442 const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod).upgrade(mod);6442 const src_loc = self.module.declPtr(self.decl_index).navSrcLoc(mod);
6443 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});6443 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
6444 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);6444 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);
64456445
src/link.zig+8-9
...@@ -18,7 +18,7 @@ const Zcu = @import("Zcu.zig");...@@ -18,7 +18,7 @@ const Zcu = @import("Zcu.zig");
18/// Deprecated.18/// Deprecated.
19const Module = Zcu;19const Module = Zcu;
20const InternPool = @import("InternPool.zig");20const InternPool = @import("InternPool.zig");
21const Type = @import("type.zig").Type;21const Type = @import("Type.zig");
22const Value = @import("Value.zig");22const Value = @import("Value.zig");
23const LlvmObject = @import("codegen/llvm.zig").Object;23const LlvmObject = @import("codegen/llvm.zig").Object;
24const lldMain = @import("main.zig").lldMain;24const lldMain = @import("main.zig").lldMain;
...@@ -606,12 +606,12 @@ pub const File = struct {...@@ -606,12 +606,12 @@ pub const File = struct {
606 base: *File,606 base: *File,
607 module: *Module,607 module: *Module,
608 exported: Module.Exported,608 exported: Module.Exported,
609 exports: []const *Module.Export,609 export_indices: []const u32,
610 ) UpdateExportsError!void {610 ) UpdateExportsError!void {
611 switch (base.tag) {611 switch (base.tag) {
612 inline else => |tag| {612 inline else => |tag| {
613 if (tag != .c and build_options.only_c) unreachable;613 if (tag != .c and build_options.only_c) unreachable;
614 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, exports);614 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(module, exported, export_indices);
615 },615 },
616 }616 }
617 }617 }
...@@ -646,7 +646,7 @@ pub const File = struct {...@@ -646,7 +646,7 @@ pub const File = struct {
646 base: *File,646 base: *File,
647 decl_val: InternPool.Index,647 decl_val: InternPool.Index,
648 decl_align: InternPool.Alignment,648 decl_align: InternPool.Alignment,
649 src_loc: Module.SrcLoc,649 src_loc: Module.LazySrcLoc,
650 ) !LowerResult {650 ) !LowerResult {
651 if (build_options.only_c) @compileError("unreachable");651 if (build_options.only_c) @compileError("unreachable");
652 switch (base.tag) {652 switch (base.tag) {
...@@ -671,21 +671,20 @@ pub const File = struct {...@@ -671,21 +671,20 @@ pub const File = struct {
671 }671 }
672 }672 }
673673
674 pub fn deleteDeclExport(674 pub fn deleteExport(
675 base: *File,675 base: *File,
676 decl_index: InternPool.DeclIndex,676 exported: Zcu.Exported,
677 name: InternPool.NullTerminatedString,677 name: InternPool.NullTerminatedString,
678 ) !void {678 ) void {
679 if (build_options.only_c) @compileError("unreachable");679 if (build_options.only_c) @compileError("unreachable");
680 switch (base.tag) {680 switch (base.tag) {
681 .plan9,681 .plan9,
682 .c,
683 .spirv,682 .spirv,
684 .nvptx,683 .nvptx,
685 => {},684 => {},
686685
687 inline else => |tag| {686 inline else => |tag| {
688 return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteDeclExport(decl_index, name);687 return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteExport(exported, name);
689 },688 },
690 }689 }
691 }690 }
src/link/C.zig+141-31
...@@ -14,7 +14,7 @@ const Compilation = @import("../Compilation.zig");...@@ -14,7 +14,7 @@ const Compilation = @import("../Compilation.zig");
14const codegen = @import("../codegen/c.zig");14const codegen = @import("../codegen/c.zig");
15const link = @import("../link.zig");15const link = @import("../link.zig");
16const trace = @import("../tracy.zig").trace;16const trace = @import("../tracy.zig").trace;
17const Type = @import("../type.zig").Type;17const Type = @import("../Type.zig");
18const Value = @import("../Value.zig");18const Value = @import("../Value.zig");
19const Air = @import("../Air.zig");19const Air = @import("../Air.zig");
20const Liveness = @import("../Liveness.zig");20const Liveness = @import("../Liveness.zig");
...@@ -39,6 +39,9 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{},...@@ -39,6 +39,9 @@ anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, DeclBlock) = .{},
39/// the keys of `anon_decls`.39/// the keys of `anon_decls`.
40aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},40aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{},
4141
42exported_decls: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, ExportedBlock) = .{},
43exported_values: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{},
44
42/// Optimization, `updateDecl` reuses this buffer rather than creating a new45/// Optimization, `updateDecl` reuses this buffer rather than creating a new
43/// one with every call.46/// one with every call.
44fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},47fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{},
...@@ -80,6 +83,11 @@ pub const DeclBlock = struct {...@@ -80,6 +83,11 @@ pub const DeclBlock = struct {
80 }83 }
81};84};
8285
86/// Per-exported-symbol data.
87pub const ExportedBlock = struct {
88 fwd_decl: String = String.empty,
89};
90
83pub fn getString(this: C, s: String) []const u8 {91pub fn getString(this: C, s: String) []const u8 {
84 return this.string_bytes.items[s.start..][0..s.len];92 return this.string_bytes.items[s.start..][0..s.len];
85}93}
...@@ -238,9 +246,13 @@ pub fn updateFunc(...@@ -238,9 +246,13 @@ pub fn updateFunc(
238 function.deinit();246 function.deinit();
239 }247 }
240248
249 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
241 codegen.genFunc(&function) catch |err| switch (err) {250 codegen.genFunc(&function) catch |err| switch (err) {
242 error.AnalysisFail => {251 error.AnalysisFail => {
243 try zcu.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?);252 zcu.failed_analysis.putAssumeCapacityNoClobber(
253 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
254 function.object.dg.error_msg.?,
255 );
244 return;256 return;
245 },257 },
246 else => |e| return e,258 else => |e| return e,
...@@ -288,7 +300,7 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {...@@ -288,7 +300,7 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void {
288300
289 const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };301 const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) };
290 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;302 const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none;
291 codegen.genDeclValue(&object, c_value.constant, false, c_value, alignment, .none) catch |err| switch (err) {303 codegen.genDeclValue(&object, c_value.constant, c_value, alignment, .none) catch |err| switch (err) {
292 error.AnalysisFail => {304 error.AnalysisFail => {
293 @panic("TODO: C backend AnalysisFail on anonymous decl");305 @panic("TODO: C backend AnalysisFail on anonymous decl");
294 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);306 //try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
...@@ -351,9 +363,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {...@@ -351,9 +363,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
351 code.* = object.code.moveToUnmanaged();363 code.* = object.code.moveToUnmanaged();
352 }364 }
353365
366 try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
354 codegen.genDecl(&object) catch |err| switch (err) {367 codegen.genDecl(&object) catch |err| switch (err) {
355 error.AnalysisFail => {368 error.AnalysisFail => {
356 try zcu.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);369 zcu.failed_analysis.putAssumeCapacityNoClobber(
370 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
371 object.dg.error_msg.?,
372 );
357 return;373 return;
358 },374 },
359 else => |e| return e,375 else => |e| return e,
...@@ -451,20 +467,40 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo...@@ -451,20 +467,40 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
451 {467 {
452 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};468 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
453 defer export_names.deinit(gpa);469 defer export_names.deinit(gpa);
454 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.decl_exports.entries.len));470 try export_names.ensureTotalCapacity(gpa, @intCast(zcu.single_exports.count()));
455 for (zcu.decl_exports.values()) |exports| for (exports.items) |@"export"|471 for (zcu.single_exports.values()) |export_index| {
456 try export_names.put(gpa, @"export".opts.name, {});472 export_names.putAssumeCapacity(zcu.all_exports.items[export_index].opts.name, {});
457473 }
458 for (self.anon_decls.values()) |*decl_block| {474 for (zcu.multi_exports.values()) |info| {
459 try self.flushDeclBlock(zcu, zcu.root_mod, &f, decl_block, export_names, .none);475 try export_names.ensureUnusedCapacity(gpa, info.len);
476 for (zcu.all_exports.items[info.index..][0..info.len]) |@"export"| {
477 export_names.putAssumeCapacity(@"export".opts.name, {});
478 }
460 }479 }
461480
481 for (self.anon_decls.keys(), self.anon_decls.values()) |value, *decl_block| try self.flushDeclBlock(
482 zcu,
483 zcu.root_mod,
484 &f,
485 decl_block,
486 self.exported_values.getPtr(value),
487 export_names,
488 .none,
489 );
490
462 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {491 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, *decl_block| {
463 const decl = zcu.declPtr(decl_index);492 const decl = zcu.declPtr(decl_index);
464 assert(decl.has_tv);493 const extern_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
465 const extern_symbol_name = if (decl.isExtern(zcu)) decl.name.toOptional() else .none;
466 const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod;494 const mod = zcu.namespacePtr(decl.src_namespace).file_scope.mod;
467 try self.flushDeclBlock(zcu, mod, &f, decl_block, export_names, extern_symbol_name);495 try self.flushDeclBlock(
496 zcu,
497 mod,
498 &f,
499 decl_block,
500 self.exported_decls.getPtr(decl_index),
501 export_names,
502 extern_name,
503 );
468 }504 }
469 }505 }
470506
...@@ -497,12 +533,27 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo...@@ -497,12 +533,27 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: std.Progress.Node) !vo
497 f.file_size += lazy_fwd_decl_len;533 f.file_size += lazy_fwd_decl_len;
498534
499 // Now the code.535 // Now the code.
500 const anon_decl_values = self.anon_decls.values();536 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + (self.anon_decls.count() + self.decl_table.count()) * 2);
501 const decl_values = self.decl_table.values();
502 try f.all_buffers.ensureUnusedCapacity(gpa, 1 + anon_decl_values.len + decl_values.len);
503 f.appendBufAssumeCapacity(self.lazy_code_buf.items);537 f.appendBufAssumeCapacity(self.lazy_code_buf.items);
504 for (anon_decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code));538 for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| f.appendCodeAssumeCapacity(
505 for (decl_values) |db| f.appendBufAssumeCapacity(self.getString(db.code));539 if (self.exported_values.contains(anon_decl))
540 .default
541 else switch (zcu.intern_pool.indexToKey(anon_decl)) {
542 .extern_func => .zig_extern,
543 .variable => |variable| if (variable.is_extern) .zig_extern else .static,
544 else => .static,
545 },
546 self.getString(decl_block.code),
547 );
548 for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| f.appendCodeAssumeCapacity(
549 if (self.exported_decls.contains(decl_index))
550 .default
551 else if (zcu.declPtr(decl_index).isExtern(zcu))
552 .zig_extern
553 else
554 .static,
555 self.getString(decl_block.code),
556 );
506557
507 const file = self.base.file.?;558 const file = self.base.file.?;
508 try file.setEndPos(f.file_size);559 try file.setEndPos(f.file_size);
...@@ -532,6 +583,16 @@ const Flush = struct {...@@ -532,6 +583,16 @@ const Flush = struct {
532 f.file_size += buf.len;583 f.file_size += buf.len;
533 }584 }
534585
586 fn appendCodeAssumeCapacity(f: *Flush, storage: enum { default, zig_extern, static }, code: []const u8) void {
587 if (code.len == 0) return;
588 f.appendBufAssumeCapacity(switch (storage) {
589 .default => "\n",
590 .zig_extern => "\nzig_extern ",
591 .static => "\nstatic ",
592 });
593 f.appendBufAssumeCapacity(code);
594 }
595
535 fn deinit(f: *Flush, gpa: Allocator) void {596 fn deinit(f: *Flush, gpa: Allocator) void {
536 f.all_buffers.deinit(gpa);597 f.all_buffers.deinit(gpa);
537 f.asm_buf.deinit(gpa);598 f.asm_buf.deinit(gpa);
...@@ -719,19 +780,20 @@ fn flushDeclBlock(...@@ -719,19 +780,20 @@ fn flushDeclBlock(
719 zcu: *Zcu,780 zcu: *Zcu,
720 mod: *Module,781 mod: *Module,
721 f: *Flush,782 f: *Flush,
722 decl_block: *DeclBlock,783 decl_block: *const DeclBlock,
784 exported_block: ?*const ExportedBlock,
723 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),785 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
724 extern_symbol_name: InternPool.OptionalNullTerminatedString,786 extern_name: InternPool.OptionalNullTerminatedString,
725) FlushDeclError!void {787) FlushDeclError!void {
726 const gpa = self.base.comp.gpa;788 const gpa = self.base.comp.gpa;
727 try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns);789 try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns);
728 try f.all_buffers.ensureUnusedCapacity(gpa, 1);790 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
729 fwd_decl: {791 // avoid emitting extern decls that are already exported
730 if (extern_symbol_name.unwrap()) |name| {792 if (extern_name.unwrap()) |name| if (export_names.contains(name)) return;
731 if (export_names.contains(name)) break :fwd_decl;793 f.appendBufAssumeCapacity(self.getString(if (exported_block) |exported|
732 }794 exported.fwd_decl
733 f.appendBufAssumeCapacity(self.getString(decl_block.fwd_decl));795 else
734 }796 decl_block.fwd_decl));
735}797}
736798
737pub fn flushEmitH(zcu: *Zcu) !void {799pub fn flushEmitH(zcu: *Zcu) !void {
...@@ -781,10 +843,58 @@ pub fn updateExports(...@@ -781,10 +843,58 @@ pub fn updateExports(
781 self: *C,843 self: *C,
782 zcu: *Zcu,844 zcu: *Zcu,
783 exported: Zcu.Exported,845 exported: Zcu.Exported,
784 exports: []const *Zcu.Export,846 export_indices: []const u32,
785) !void {847) !void {
786 _ = exports;848 const gpa = self.base.comp.gpa;
787 _ = exported;849 const mod, const pass: codegen.DeclGen.Pass, const decl_block, const exported_block = switch (exported) {
788 _ = zcu;850 .decl_index => |decl_index| .{
789 _ = self;851 zcu.namespacePtr(zcu.declPtr(decl_index).src_namespace).file_scope.mod,
852 .{ .decl = decl_index },
853 self.decl_table.getPtr(decl_index).?,
854 (try self.exported_decls.getOrPut(gpa, decl_index)).value_ptr,
855 },
856 .value => |value| .{
857 zcu.root_mod,
858 .{ .anon = value },
859 self.anon_decls.getPtr(value).?,
860 (try self.exported_values.getOrPut(gpa, value)).value_ptr,
861 },
862 };
863 const ctype_pool = &decl_block.ctype_pool;
864 const fwd_decl = &self.fwd_decl_buf;
865 fwd_decl.clearRetainingCapacity();
866 var dg: codegen.DeclGen = .{
867 .gpa = gpa,
868 .zcu = zcu,
869 .mod = mod,
870 .error_msg = null,
871 .pass = pass,
872 .is_naked_fn = false,
873 .fwd_decl = fwd_decl.toManaged(gpa),
874 .ctype_pool = decl_block.ctype_pool,
875 .scratch = .{},
876 .anon_decl_deps = .{},
877 .aligned_anon_decls = .{},
878 };
879 defer {
880 assert(dg.anon_decl_deps.count() == 0);
881 assert(dg.aligned_anon_decls.count() == 0);
882 fwd_decl.* = dg.fwd_decl.moveToUnmanaged();
883 ctype_pool.* = dg.ctype_pool.move();
884 ctype_pool.freeUnusedCapacity(gpa);
885 dg.scratch.deinit(gpa);
886 }
887 try codegen.genExports(&dg, exported, export_indices);
888 exported_block.* = .{ .fwd_decl = try self.addString(dg.fwd_decl.items) };
889}
890
891pub fn deleteExport(
892 self: *C,
893 exported: Zcu.Exported,
894 _: InternPool.NullTerminatedString,
895) void {
896 switch (exported) {
897 .decl_index => |decl_index| _ = self.exported_decls.swapRemove(decl_index),
898 .value => |value| _ = self.exported_values.swapRemove(value),
899 }
790}900}
src/link/Coff.zig+32-37
...@@ -1144,7 +1144,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:...@@ -1144,7 +1144,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
11441144
1145 const res = try codegen.generateFunction(1145 const res = try codegen.generateFunction(
1146 &self.base,1146 &self.base,
1147 decl.navSrcLoc(mod).upgrade(mod),1147 decl.navSrcLoc(mod),
1148 func_index,1148 func_index,
1149 air,1149 air,
1150 liveness,1150 liveness,
...@@ -1155,16 +1155,14 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:...@@ -1155,16 +1155,14 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air:
1155 .ok => code_buffer.items,1155 .ok => code_buffer.items,
1156 .fail => |em| {1156 .fail => |em| {
1157 func.analysis(&mod.intern_pool).state = .codegen_failure;1157 func.analysis(&mod.intern_pool).state = .codegen_failure;
1158 try mod.failed_decls.put(mod.gpa, decl_index, em);1158 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1159 return;1159 return;
1160 },1160 },
1161 };1161 };
11621162
1163 try self.updateDeclCode(decl_index, code, .FUNCTION);1163 try self.updateDeclCode(decl_index, code, .FUNCTION);
11641164
1165 // Since we updated the vaddr and the size, each corresponding export1165 // Exports will be updated by `Zcu.processExports` after the update.
1166 // symbol also needs to be updated.
1167 return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1168}1166}
11691167
1170pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 {1168pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 {
...@@ -1181,11 +1179,11 @@ pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclInd...@@ -1181,11 +1179,11 @@ pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclInd
1181 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });1179 const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
1182 defer gpa.free(sym_name);1180 defer gpa.free(sym_name);
1183 const ty = val.typeOf(mod);1181 const ty = val.typeOf(mod);
1184 const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.navSrcLoc(mod).upgrade(mod))) {1182 const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.navSrcLoc(mod))) {
1185 .ok => |atom_index| atom_index,1183 .ok => |atom_index| atom_index,
1186 .fail => |em| {1184 .fail => |em| {
1187 decl.analysis = .codegen_failure;1185 decl.analysis = .codegen_failure;
1188 try mod.failed_decls.put(mod.gpa, decl_index, em);1186 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1189 log.err("{s}", .{em.msg});1187 log.err("{s}", .{em.msg});
1190 return error.CodegenFail;1188 return error.CodegenFail;
1191 },1189 },
...@@ -1199,7 +1197,7 @@ const LowerConstResult = union(enum) {...@@ -1199,7 +1197,7 @@ const LowerConstResult = union(enum) {
1199 fail: *Module.ErrorMsg,1197 fail: *Module.ErrorMsg,
1200};1198};
12011199
1202fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult {1200fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.LazySrcLoc) !LowerConstResult {
1203 const gpa = self.base.comp.gpa;1201 const gpa = self.base.comp.gpa;
12041202
1205 var code_buffer = std.ArrayList(u8).init(gpa);1203 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -1272,23 +1270,21 @@ pub fn updateDecl(...@@ -1272,23 +1270,21 @@ pub fn updateDecl(
1272 defer code_buffer.deinit();1270 defer code_buffer.deinit();
12731271
1274 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;1272 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
1275 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .none, .{1273 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod), decl_val, &code_buffer, .none, .{
1276 .parent_atom_index = atom.getSymbolIndex().?,1274 .parent_atom_index = atom.getSymbolIndex().?,
1277 });1275 });
1278 const code = switch (res) {1276 const code = switch (res) {
1279 .ok => code_buffer.items,1277 .ok => code_buffer.items,
1280 .fail => |em| {1278 .fail => |em| {
1281 decl.analysis = .codegen_failure;1279 decl.analysis = .codegen_failure;
1282 try mod.failed_decls.put(mod.gpa, decl_index, em);1280 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1283 return;1281 return;
1284 },1282 },
1285 };1283 };
12861284
1287 try self.updateDeclCode(decl_index, code, .NULL);1285 try self.updateDeclCode(decl_index, code, .NULL);
12881286
1289 // Since we updated the vaddr and the size, each corresponding export1287 // Exports will be updated by `Zcu.processExports` after the update.
1290 // symbol also needs to be updated.
1291 return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1292}1288}
12931289
1294fn updateLazySymbolAtom(1290fn updateLazySymbolAtom(
...@@ -1313,14 +1309,7 @@ fn updateLazySymbolAtom(...@@ -1313,14 +1309,7 @@ fn updateLazySymbolAtom(
1313 const atom = self.getAtomPtr(atom_index);1309 const atom = self.getAtomPtr(atom_index);
1314 const local_sym_index = atom.getSymbolIndex().?;1310 const local_sym_index = atom.getSymbolIndex().?;
13151311
1316 const src = if (sym.ty.srcLocOrNull(mod)) |src|1312 const src = sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded;
1317 src.upgrade(mod)
1318 else
1319 Module.SrcLoc{
1320 .file_scope = undefined,
1321 .base_node = undefined,
1322 .lazy = .unneeded,
1323 };
1324 const res = try codegen.generateLazySymbol(1313 const res = try codegen.generateLazySymbol(
1325 &self.base,1314 &self.base,
1326 src,1315 src,
...@@ -1509,7 +1498,7 @@ pub fn updateExports(...@@ -1509,7 +1498,7 @@ pub fn updateExports(
1509 self: *Coff,1498 self: *Coff,
1510 mod: *Module,1499 mod: *Module,
1511 exported: Module.Exported,1500 exported: Module.Exported,
1512 exports: []const *Module.Export,1501 export_indices: []const u32,
1513) link.File.UpdateExportsError!void {1502) link.File.UpdateExportsError!void {
1514 if (build_options.skip_non_native and builtin.object_format != .coff) {1503 if (build_options.skip_non_native and builtin.object_format != .coff) {
1515 @panic("Attempted to compile for object format that was disabled by build configuration");1504 @panic("Attempted to compile for object format that was disabled by build configuration");
...@@ -1522,7 +1511,8 @@ pub fn updateExports(...@@ -1522,7 +1511,8 @@ pub fn updateExports(
1522 if (comp.config.use_llvm) {1511 if (comp.config.use_llvm) {
1523 // Even in the case of LLVM, we need to notice certain exported symbols in order to1512 // Even in the case of LLVM, we need to notice certain exported symbols in order to
1524 // detect the default subsystem.1513 // detect the default subsystem.
1525 for (exports) |exp| {1514 for (export_indices) |export_idx| {
1515 const exp = mod.all_exports.items[export_idx];
1526 const exported_decl_index = switch (exp.exported) {1516 const exported_decl_index = switch (exp.exported) {
1527 .decl_index => |i| i,1517 .decl_index => |i| i,
1528 .value => continue,1518 .value => continue,
...@@ -1552,7 +1542,7 @@ pub fn updateExports(...@@ -1552,7 +1542,7 @@ pub fn updateExports(
1552 }1542 }
1553 }1543 }
15541544
1555 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);1545 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices);
15561546
1557 const gpa = comp.gpa;1547 const gpa = comp.gpa;
15581548
...@@ -1562,15 +1552,15 @@ pub fn updateExports(...@@ -1562,15 +1552,15 @@ pub fn updateExports(
1562 break :blk self.decls.getPtr(decl_index).?;1552 break :blk self.decls.getPtr(decl_index).?;
1563 },1553 },
1564 .value => |value| self.anon_decls.getPtr(value) orelse blk: {1554 .value => |value| self.anon_decls.getPtr(value) orelse blk: {
1565 const first_exp = exports[0];1555 const first_exp = mod.all_exports.items[export_indices[0]];
1566 const res = try self.lowerAnonDecl(value, .none, first_exp.getSrcLoc(mod));1556 const res = try self.lowerAnonDecl(value, .none, first_exp.src);
1567 switch (res) {1557 switch (res) {
1568 .ok => {},1558 .ok => {},
1569 .fail => |em| {1559 .fail => |em| {
1570 // TODO maybe it's enough to return an error here and let Module.processExportsInner1560 // TODO maybe it's enough to return an error here and let Module.processExportsInner
1571 // handle the error?1561 // handle the error?
1572 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1562 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1573 mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em);1563 mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
1574 return;1564 return;
1575 },1565 },
1576 }1566 }
...@@ -1580,14 +1570,15 @@ pub fn updateExports(...@@ -1580,14 +1570,15 @@ pub fn updateExports(
1580 const atom_index = metadata.atom;1570 const atom_index = metadata.atom;
1581 const atom = self.getAtom(atom_index);1571 const atom = self.getAtom(atom_index);
15821572
1583 for (exports) |exp| {1573 for (export_indices) |export_idx| {
1574 const exp = mod.all_exports.items[export_idx];
1584 log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)});1575 log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)});
15851576
1586 if (exp.opts.section.toSlice(&mod.intern_pool)) |section_name| {1577 if (exp.opts.section.toSlice(&mod.intern_pool)) |section_name| {
1587 if (!mem.eql(u8, section_name, ".text")) {1578 if (!mem.eql(u8, section_name, ".text")) {
1588 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(1579 try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create(
1589 gpa,1580 gpa,
1590 exp.getSrcLoc(mod),1581 exp.src,
1591 "Unimplemented: ExportOptions.section",1582 "Unimplemented: ExportOptions.section",
1592 .{},1583 .{},
1593 ));1584 ));
...@@ -1596,9 +1587,9 @@ pub fn updateExports(...@@ -1596,9 +1587,9 @@ pub fn updateExports(
1596 }1587 }
15971588
1598 if (exp.opts.linkage == .link_once) {1589 if (exp.opts.linkage == .link_once) {
1599 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(1590 try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create(
1600 gpa,1591 gpa,
1601 exp.getSrcLoc(mod),1592 exp.src,
1602 "Unimplemented: GlobalLinkage.link_once",1593 "Unimplemented: GlobalLinkage.link_once",
1603 .{},1594 .{},
1604 ));1595 ));
...@@ -1641,13 +1632,16 @@ pub fn updateExports(...@@ -1641,13 +1632,16 @@ pub fn updateExports(
1641 }1632 }
1642}1633}
16431634
1644pub fn deleteDeclExport(1635pub fn deleteExport(
1645 self: *Coff,1636 self: *Coff,
1646 decl_index: InternPool.DeclIndex,1637 exported: Zcu.Exported,
1647 name: InternPool.NullTerminatedString,1638 name: InternPool.NullTerminatedString,
1648) void {1639) void {
1649 if (self.llvm_object) |_| return;1640 if (self.llvm_object) |_| return;
1650 const metadata = self.decls.getPtr(decl_index) orelse return;1641 const metadata = switch (exported) {
1642 .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return,
1643 .value => |value| self.anon_decls.getPtr(value) orelse return,
1644 };
1651 const mod = self.base.comp.module.?;1645 const mod = self.base.comp.module.?;
1652 const name_slice = name.toSlice(&mod.intern_pool);1646 const name_slice = name.toSlice(&mod.intern_pool);
1653 const sym_index = metadata.getExportPtr(self, name_slice) orelse return;1647 const sym_index = metadata.getExportPtr(self, name_slice) orelse return;
...@@ -1866,7 +1860,7 @@ pub fn lowerAnonDecl(...@@ -1866,7 +1860,7 @@ pub fn lowerAnonDecl(
1866 self: *Coff,1860 self: *Coff,
1867 decl_val: InternPool.Index,1861 decl_val: InternPool.Index,
1868 explicit_alignment: InternPool.Alignment,1862 explicit_alignment: InternPool.Alignment,
1869 src_loc: Module.SrcLoc,1863 src_loc: Module.LazySrcLoc,
1870) !codegen.Result {1864) !codegen.Result {
1871 const gpa = self.base.comp.gpa;1865 const gpa = self.base.comp.gpa;
1872 const mod = self.base.comp.module.?;1866 const mod = self.base.comp.module.?;
...@@ -2748,8 +2742,9 @@ const Object = @import("Coff/Object.zig");...@@ -2748,8 +2742,9 @@ const Object = @import("Coff/Object.zig");
2748const Relocation = @import("Coff/Relocation.zig");2742const Relocation = @import("Coff/Relocation.zig");
2749const TableSection = @import("table_section.zig").TableSection;2743const TableSection = @import("table_section.zig").TableSection;
2750const StringTable = @import("StringTable.zig");2744const StringTable = @import("StringTable.zig");
2751const Type = @import("../type.zig").Type;2745const Type = @import("../Type.zig");
2752const Value = @import("../Value.zig");2746const Value = @import("../Value.zig");
2747const AnalUnit = InternPool.AnalUnit;
27532748
2754pub const base_tag: link.File.Tag = .coff;2749pub const base_tag: link.File.Tag = .coff;
27552750
src/link/Dwarf.zig+1-1
...@@ -2969,5 +2969,5 @@ const Zcu = @import("../Zcu.zig");...@@ -2969,5 +2969,5 @@ const Zcu = @import("../Zcu.zig");
2969const Module = Zcu;2969const Module = Zcu;
2970const InternPool = @import("../InternPool.zig");2970const InternPool = @import("../InternPool.zig");
2971const StringTable = @import("StringTable.zig");2971const StringTable = @import("StringTable.zig");
2972const Type = @import("../type.zig").Type;2972const Type = @import("../Type.zig");
2973const Value = @import("../Value.zig");2973const Value = @import("../Value.zig");
src/link/Elf.zig+7-7
...@@ -552,7 +552,7 @@ pub fn lowerAnonDecl(...@@ -552,7 +552,7 @@ pub fn lowerAnonDecl(
552 self: *Elf,552 self: *Elf,
553 decl_val: InternPool.Index,553 decl_val: InternPool.Index,
554 explicit_alignment: InternPool.Alignment,554 explicit_alignment: InternPool.Alignment,
555 src_loc: Module.SrcLoc,555 src_loc: Module.LazySrcLoc,
556) !codegen.Result {556) !codegen.Result {
557 return self.zigObjectPtr().?.lowerAnonDecl(self, decl_val, explicit_alignment, src_loc);557 return self.zigObjectPtr().?.lowerAnonDecl(self, decl_val, explicit_alignment, src_loc);
558}558}
...@@ -3011,13 +3011,13 @@ pub fn updateExports(...@@ -3011,13 +3011,13 @@ pub fn updateExports(
3011 self: *Elf,3011 self: *Elf,
3012 mod: *Module,3012 mod: *Module,
3013 exported: Module.Exported,3013 exported: Module.Exported,
3014 exports: []const *Module.Export,3014 export_indices: []const u32,
3015) link.File.UpdateExportsError!void {3015) link.File.UpdateExportsError!void {
3016 if (build_options.skip_non_native and builtin.object_format != .elf) {3016 if (build_options.skip_non_native and builtin.object_format != .elf) {
3017 @panic("Attempted to compile for object format that was disabled by build configuration");3017 @panic("Attempted to compile for object format that was disabled by build configuration");
3018 }3018 }
3019 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);3019 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices);
3020 return self.zigObjectPtr().?.updateExports(self, mod, exported, exports);3020 return self.zigObjectPtr().?.updateExports(self, mod, exported, export_indices);
3021}3021}
30223022
3023pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void {3023pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void {
...@@ -3025,13 +3025,13 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.Dec...@@ -3025,13 +3025,13 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.Dec
3025 return self.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index);3025 return self.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index);
3026}3026}
30273027
3028pub fn deleteDeclExport(3028pub fn deleteExport(
3029 self: *Elf,3029 self: *Elf,
3030 decl_index: InternPool.DeclIndex,3030 exported: Zcu.Exported,
3031 name: InternPool.NullTerminatedString,3031 name: InternPool.NullTerminatedString,
3032) void {3032) void {
3033 if (self.llvm_object) |_| return;3033 if (self.llvm_object) |_| return;
3034 return self.zigObjectPtr().?.deleteDeclExport(self, decl_index, name);3034 return self.zigObjectPtr().?.deleteExport(self, exported, name);
3035}3035}
30363036
3037fn addLinkerDefinedSymbols(self: *Elf) !void {3037fn addLinkerDefinedSymbols(self: *Elf) !void {
src/link/Elf/ZigObject.zig+31-37
...@@ -686,7 +686,7 @@ pub fn lowerAnonDecl(...@@ -686,7 +686,7 @@ pub fn lowerAnonDecl(
686 elf_file: *Elf,686 elf_file: *Elf,
687 decl_val: InternPool.Index,687 decl_val: InternPool.Index,
688 explicit_alignment: InternPool.Alignment,688 explicit_alignment: InternPool.Alignment,
689 src_loc: Module.SrcLoc,689 src_loc: Module.LazySrcLoc,
690) !codegen.Result {690) !codegen.Result {
691 const gpa = elf_file.base.comp.gpa;691 const gpa = elf_file.base.comp.gpa;
692 const mod = elf_file.base.comp.module.?;692 const mod = elf_file.base.comp.module.?;
...@@ -1074,7 +1074,7 @@ pub fn updateFunc(...@@ -1074,7 +1074,7 @@ pub fn updateFunc(
1074 const res = if (decl_state) |*ds|1074 const res = if (decl_state) |*ds|
1075 try codegen.generateFunction(1075 try codegen.generateFunction(
1076 &elf_file.base,1076 &elf_file.base,
1077 decl.navSrcLoc(mod).upgrade(mod),1077 decl.navSrcLoc(mod),
1078 func_index,1078 func_index,
1079 air,1079 air,
1080 liveness,1080 liveness,
...@@ -1084,7 +1084,7 @@ pub fn updateFunc(...@@ -1084,7 +1084,7 @@ pub fn updateFunc(
1084 else1084 else
1085 try codegen.generateFunction(1085 try codegen.generateFunction(
1086 &elf_file.base,1086 &elf_file.base,
1087 decl.navSrcLoc(mod).upgrade(mod),1087 decl.navSrcLoc(mod),
1088 func_index,1088 func_index,
1089 air,1089 air,
1090 liveness,1090 liveness,
...@@ -1096,7 +1096,7 @@ pub fn updateFunc(...@@ -1096,7 +1096,7 @@ pub fn updateFunc(
1096 .ok => code_buffer.items,1096 .ok => code_buffer.items,
1097 .fail => |em| {1097 .fail => |em| {
1098 func.analysis(&mod.intern_pool).state = .codegen_failure;1098 func.analysis(&mod.intern_pool).state = .codegen_failure;
1099 try mod.failed_decls.put(mod.gpa, decl_index, em);1099 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1100 return;1100 return;
1101 },1101 },
1102 };1102 };
...@@ -1115,9 +1115,7 @@ pub fn updateFunc(...@@ -1115,9 +1115,7 @@ pub fn updateFunc(
1115 );1115 );
1116 }1116 }
11171117
1118 // Since we updated the vaddr and the size, each corresponding export1118 // Exports will be updated by `Zcu.processExports` after the update.
1119 // symbol also needs to be updated.
1120 return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1121}1119}
11221120
1123pub fn updateDecl(1121pub fn updateDecl(
...@@ -1158,13 +1156,13 @@ pub fn updateDecl(...@@ -1158,13 +1156,13 @@ pub fn updateDecl(
1158 // TODO implement .debug_info for global variables1156 // TODO implement .debug_info for global variables
1159 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;1157 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
1160 const res = if (decl_state) |*ds|1158 const res = if (decl_state) |*ds|
1161 try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .{1159 try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod), decl_val, &code_buffer, .{
1162 .dwarf = ds,1160 .dwarf = ds,
1163 }, .{1161 }, .{
1164 .parent_atom_index = sym_index,1162 .parent_atom_index = sym_index,
1165 })1163 })
1166 else1164 else
1167 try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .none, .{1165 try codegen.generateSymbol(&elf_file.base, decl.navSrcLoc(mod), decl_val, &code_buffer, .none, .{
1168 .parent_atom_index = sym_index,1166 .parent_atom_index = sym_index,
1169 });1167 });
11701168
...@@ -1172,7 +1170,7 @@ pub fn updateDecl(...@@ -1172,7 +1170,7 @@ pub fn updateDecl(
1172 .ok => code_buffer.items,1170 .ok => code_buffer.items,
1173 .fail => |em| {1171 .fail => |em| {
1174 decl.analysis = .codegen_failure;1172 decl.analysis = .codegen_failure;
1175 try mod.failed_decls.put(mod.gpa, decl_index, em);1173 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1176 return;1174 return;
1177 },1175 },
1178 };1176 };
...@@ -1194,9 +1192,7 @@ pub fn updateDecl(...@@ -1194,9 +1192,7 @@ pub fn updateDecl(
1194 );1192 );
1195 }1193 }
11961194
1197 // Since we updated the vaddr and the size, each corresponding export1195 // Exports will be updated by `Zcu.processExports` after the update.
1198 // symbol also needs to be updated.
1199 return self.updateExports(elf_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
1200}1196}
12011197
1202fn updateLazySymbol(1198fn updateLazySymbol(
...@@ -1221,14 +1217,7 @@ fn updateLazySymbol(...@@ -1221,14 +1217,7 @@ fn updateLazySymbol(
1221 break :blk try self.strtab.insert(gpa, name);1217 break :blk try self.strtab.insert(gpa, name);
1222 };1218 };
12231219
1224 const src = if (sym.ty.srcLocOrNull(mod)) |src|1220 const src = sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded;
1225 src.upgrade(mod)
1226 else
1227 Module.SrcLoc{
1228 .file_scope = undefined,
1229 .base_node = undefined,
1230 .lazy = .unneeded,
1231 };
1232 const res = try codegen.generateLazySymbol(1221 const res = try codegen.generateLazySymbol(
1233 &elf_file.base,1222 &elf_file.base,
1234 src,1223 src,
...@@ -1306,12 +1295,12 @@ pub fn lowerUnnamedConst(...@@ -1306,12 +1295,12 @@ pub fn lowerUnnamedConst(
1306 val,1295 val,
1307 ty.abiAlignment(mod),1296 ty.abiAlignment(mod),
1308 elf_file.zig_data_rel_ro_section_index.?,1297 elf_file.zig_data_rel_ro_section_index.?,
1309 decl.navSrcLoc(mod).upgrade(mod),1298 decl.navSrcLoc(mod),
1310 )) {1299 )) {
1311 .ok => |sym_index| sym_index,1300 .ok => |sym_index| sym_index,
1312 .fail => |em| {1301 .fail => |em| {
1313 decl.analysis = .codegen_failure;1302 decl.analysis = .codegen_failure;
1314 try mod.failed_decls.put(mod.gpa, decl_index, em);1303 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1315 log.err("{s}", .{em.msg});1304 log.err("{s}", .{em.msg});
1316 return error.CodegenFail;1305 return error.CodegenFail;
1317 },1306 },
...@@ -1333,7 +1322,7 @@ fn lowerConst(...@@ -1333,7 +1322,7 @@ fn lowerConst(
1333 val: Value,1322 val: Value,
1334 required_alignment: InternPool.Alignment,1323 required_alignment: InternPool.Alignment,
1335 output_section_index: u32,1324 output_section_index: u32,
1336 src_loc: Module.SrcLoc,1325 src_loc: Module.LazySrcLoc,
1337) !LowerConstResult {1326) !LowerConstResult {
1338 const gpa = elf_file.base.comp.gpa;1327 const gpa = elf_file.base.comp.gpa;
13391328
...@@ -1386,7 +1375,7 @@ pub fn updateExports(...@@ -1386,7 +1375,7 @@ pub fn updateExports(
1386 elf_file: *Elf,1375 elf_file: *Elf,
1387 mod: *Module,1376 mod: *Module,
1388 exported: Module.Exported,1377 exported: Module.Exported,
1389 exports: []const *Module.Export,1378 export_indices: []const u32,
1390) link.File.UpdateExportsError!void {1379) link.File.UpdateExportsError!void {
1391 const tracy = trace(@src());1380 const tracy = trace(@src());
1392 defer tracy.end();1381 defer tracy.end();
...@@ -1398,15 +1387,15 @@ pub fn updateExports(...@@ -1398,15 +1387,15 @@ pub fn updateExports(
1398 break :blk self.decls.getPtr(decl_index).?;1387 break :blk self.decls.getPtr(decl_index).?;
1399 },1388 },
1400 .value => |value| self.anon_decls.getPtr(value) orelse blk: {1389 .value => |value| self.anon_decls.getPtr(value) orelse blk: {
1401 const first_exp = exports[0];1390 const first_exp = mod.all_exports.items[export_indices[0]];
1402 const res = try self.lowerAnonDecl(elf_file, value, .none, first_exp.getSrcLoc(mod));1391 const res = try self.lowerAnonDecl(elf_file, value, .none, first_exp.src);
1403 switch (res) {1392 switch (res) {
1404 .ok => {},1393 .ok => {},
1405 .fail => |em| {1394 .fail => |em| {
1406 // TODO maybe it's enough to return an error here and let Module.processExportsInner1395 // TODO maybe it's enough to return an error here and let Module.processExportsInner
1407 // handle the error?1396 // handle the error?
1408 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1397 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1409 mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em);1398 mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
1410 return;1399 return;
1411 },1400 },
1412 }1401 }
...@@ -1418,13 +1407,14 @@ pub fn updateExports(...@@ -1418,13 +1407,14 @@ pub fn updateExports(
1418 const esym = self.local_esyms.items(.elf_sym)[esym_index];1407 const esym = self.local_esyms.items(.elf_sym)[esym_index];
1419 const esym_shndx = self.local_esyms.items(.shndx)[esym_index];1408 const esym_shndx = self.local_esyms.items(.shndx)[esym_index];
14201409
1421 for (exports) |exp| {1410 for (export_indices) |export_idx| {
1411 const exp = mod.all_exports.items[export_idx];
1422 if (exp.opts.section.unwrap()) |section_name| {1412 if (exp.opts.section.unwrap()) |section_name| {
1423 if (!section_name.eqlSlice(".text", &mod.intern_pool)) {1413 if (!section_name.eqlSlice(".text", &mod.intern_pool)) {
1424 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1414 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1425 mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create(1415 mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create(
1426 gpa,1416 gpa,
1427 exp.getSrcLoc(mod),1417 exp.src,
1428 "Unimplemented: ExportOptions.section",1418 "Unimplemented: ExportOptions.section",
1429 .{},1419 .{},
1430 ));1420 ));
...@@ -1437,9 +1427,9 @@ pub fn updateExports(...@@ -1437,9 +1427,9 @@ pub fn updateExports(
1437 .weak => elf.STB_WEAK,1427 .weak => elf.STB_WEAK,
1438 .link_once => {1428 .link_once => {
1439 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1429 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1440 mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create(1430 mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create(
1441 gpa,1431 gpa,
1442 exp.getSrcLoc(mod),1432 exp.src,
1443 "Unimplemented: GlobalLinkage.LinkOnce",1433 "Unimplemented: GlobalLinkage.LinkOnce",
1444 .{},1434 .{},
1445 ));1435 ));
...@@ -1487,13 +1477,16 @@ pub fn updateDeclLineNumber(...@@ -1487,13 +1477,16 @@ pub fn updateDeclLineNumber(
1487 }1477 }
1488}1478}
14891479
1490pub fn deleteDeclExport(1480pub fn deleteExport(
1491 self: *ZigObject,1481 self: *ZigObject,
1492 elf_file: *Elf,1482 elf_file: *Elf,
1493 decl_index: InternPool.DeclIndex,1483 exported: Zcu.Exported,
1494 name: InternPool.NullTerminatedString,1484 name: InternPool.NullTerminatedString,
1495) void {1485) void {
1496 const metadata = self.decls.getPtr(decl_index) orelse return;1486 const metadata = switch (exported) {
1487 .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return,
1488 .value => |value| self.anon_decls.getPtr(value) orelse return,
1489 };
1497 const mod = elf_file.base.comp.module.?;1490 const mod = elf_file.base.comp.module.?;
1498 const exp_name = name.toSlice(&mod.intern_pool);1491 const exp_name = name.toSlice(&mod.intern_pool);
1499 const esym_index = metadata.@"export"(self, exp_name) orelse return;1492 const esym_index = metadata.@"export"(self, exp_name) orelse return;
...@@ -1654,6 +1647,7 @@ const Module = Zcu;...@@ -1654,6 +1647,7 @@ const Module = Zcu;
1654const Object = @import("Object.zig");1647const Object = @import("Object.zig");
1655const Symbol = @import("Symbol.zig");1648const Symbol = @import("Symbol.zig");
1656const StringTable = @import("../StringTable.zig");1649const StringTable = @import("../StringTable.zig");
1657const Type = @import("../../type.zig").Type;1650const Type = @import("../../Type.zig");
1658const Value = @import("../../Value.zig");1651const Value = @import("../../Value.zig");
1652const AnalUnit = InternPool.AnalUnit;
1659const ZigObject = @This();1653const ZigObject = @This();
src/link/MachO.zig+8-8
...@@ -3207,22 +3207,22 @@ pub fn updateExports(...@@ -3207,22 +3207,22 @@ pub fn updateExports(
3207 self: *MachO,3207 self: *MachO,
3208 mod: *Module,3208 mod: *Module,
3209 exported: Module.Exported,3209 exported: Module.Exported,
3210 exports: []const *Module.Export,3210 export_indices: []const u32,
3211) link.File.UpdateExportsError!void {3211) link.File.UpdateExportsError!void {
3212 if (build_options.skip_non_native and builtin.object_format != .macho) {3212 if (build_options.skip_non_native and builtin.object_format != .macho) {
3213 @panic("Attempted to compile for object format that was disabled by build configuration");3213 @panic("Attempted to compile for object format that was disabled by build configuration");
3214 }3214 }
3215 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);3215 if (self.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices);
3216 return self.getZigObject().?.updateExports(self, mod, exported, exports);3216 return self.getZigObject().?.updateExports(self, mod, exported, export_indices);
3217}3217}
32183218
3219pub fn deleteDeclExport(3219pub fn deleteExport(
3220 self: *MachO,3220 self: *MachO,
3221 decl_index: InternPool.DeclIndex,3221 exported: Zcu.Exported,
3222 name: InternPool.NullTerminatedString,3222 name: InternPool.NullTerminatedString,
3223) Allocator.Error!void {3223) void {
3224 if (self.llvm_object) |_| return;3224 if (self.llvm_object) |_| return;
3225 return self.getZigObject().?.deleteDeclExport(self, decl_index, name);3225 return self.getZigObject().?.deleteExport(self, exported, name);
3226}3226}
32273227
3228pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {3228pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {
...@@ -3239,7 +3239,7 @@ pub fn lowerAnonDecl(...@@ -3239,7 +3239,7 @@ pub fn lowerAnonDecl(
3239 self: *MachO,3239 self: *MachO,
3240 decl_val: InternPool.Index,3240 decl_val: InternPool.Index,
3241 explicit_alignment: InternPool.Alignment,3241 explicit_alignment: InternPool.Alignment,
3242 src_loc: Module.SrcLoc,3242 src_loc: Module.LazySrcLoc,
3243) !codegen.Result {3243) !codegen.Result {
3244 return self.getZigObject().?.lowerAnonDecl(self, decl_val, explicit_alignment, src_loc);3244 return self.getZigObject().?.lowerAnonDecl(self, decl_val, explicit_alignment, src_loc);
3245}3245}
src/link/MachO/DebugSymbols.zig+1-1
...@@ -459,4 +459,4 @@ const trace = @import("../../tracy.zig").trace;...@@ -459,4 +459,4 @@ const trace = @import("../../tracy.zig").trace;
459const Allocator = mem.Allocator;459const Allocator = mem.Allocator;
460const MachO = @import("../MachO.zig");460const MachO = @import("../MachO.zig");
461const StringTable = @import("../StringTable.zig");461const StringTable = @import("../StringTable.zig");
462const Type = @import("../../type.zig").Type;462const Type = @import("../../Type.zig");
src/link/MachO/ZigObject.zig+29-35
...@@ -572,7 +572,7 @@ pub fn lowerAnonDecl(...@@ -572,7 +572,7 @@ pub fn lowerAnonDecl(
572 macho_file: *MachO,572 macho_file: *MachO,
573 decl_val: InternPool.Index,573 decl_val: InternPool.Index,
574 explicit_alignment: Atom.Alignment,574 explicit_alignment: Atom.Alignment,
575 src_loc: Module.SrcLoc,575 src_loc: Module.LazySrcLoc,
576) !codegen.Result {576) !codegen.Result {
577 const gpa = macho_file.base.comp.gpa;577 const gpa = macho_file.base.comp.gpa;
578 const mod = macho_file.base.comp.module.?;578 const mod = macho_file.base.comp.module.?;
...@@ -682,7 +682,7 @@ pub fn updateFunc(...@@ -682,7 +682,7 @@ pub fn updateFunc(
682 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;682 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
683 const res = try codegen.generateFunction(683 const res = try codegen.generateFunction(
684 &macho_file.base,684 &macho_file.base,
685 decl.navSrcLoc(mod).upgrade(mod),685 decl.navSrcLoc(mod),
686 func_index,686 func_index,
687 air,687 air,
688 liveness,688 liveness,
...@@ -694,7 +694,7 @@ pub fn updateFunc(...@@ -694,7 +694,7 @@ pub fn updateFunc(
694 .ok => code_buffer.items,694 .ok => code_buffer.items,
695 .fail => |em| {695 .fail => |em| {
696 func.analysis(&mod.intern_pool).state = .codegen_failure;696 func.analysis(&mod.intern_pool).state = .codegen_failure;
697 try mod.failed_decls.put(mod.gpa, decl_index, em);697 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
698 return;698 return;
699 },699 },
700 };700 };
...@@ -713,9 +713,7 @@ pub fn updateFunc(...@@ -713,9 +713,7 @@ pub fn updateFunc(
713 );713 );
714 }714 }
715715
716 // Since we updated the vaddr and the size, each corresponding export716 // Exports will be updated by `Zcu.processExports` after the update.
717 // symbol also needs to be updated.
718 return self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
719}717}
720718
721pub fn updateDecl(719pub fn updateDecl(
...@@ -756,7 +754,7 @@ pub fn updateDecl(...@@ -756,7 +754,7 @@ pub fn updateDecl(
756754
757 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;755 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
758 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;756 const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none;
759 const res = try codegen.generateSymbol(&macho_file.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, dio, .{757 const res = try codegen.generateSymbol(&macho_file.base, decl.navSrcLoc(mod), decl_val, &code_buffer, dio, .{
760 .parent_atom_index = sym_index,758 .parent_atom_index = sym_index,
761 });759 });
762760
...@@ -764,7 +762,7 @@ pub fn updateDecl(...@@ -764,7 +762,7 @@ pub fn updateDecl(
764 .ok => code_buffer.items,762 .ok => code_buffer.items,
765 .fail => |em| {763 .fail => |em| {
766 decl.analysis = .codegen_failure;764 decl.analysis = .codegen_failure;
767 try mod.failed_decls.put(mod.gpa, decl_index, em);765 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
768 return;766 return;
769 },767 },
770 };768 };
...@@ -790,9 +788,7 @@ pub fn updateDecl(...@@ -790,9 +788,7 @@ pub fn updateDecl(
790 );788 );
791 }789 }
792790
793 // Since we updated the vaddr and the size, each corresponding export symbol also791 // Exports will be updated by `Zcu.processExports` after the update.
794 // needs to be updated.
795 try self.updateExports(macho_file, mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
796}792}
797793
798fn updateDeclCode(794fn updateDeclCode(
...@@ -1104,12 +1100,12 @@ pub fn lowerUnnamedConst(...@@ -1104,12 +1100,12 @@ pub fn lowerUnnamedConst(
1104 val,1100 val,
1105 val.typeOf(mod).abiAlignment(mod),1101 val.typeOf(mod).abiAlignment(mod),
1106 macho_file.zig_const_sect_index.?,1102 macho_file.zig_const_sect_index.?,
1107 decl.navSrcLoc(mod).upgrade(mod),1103 decl.navSrcLoc(mod),
1108 )) {1104 )) {
1109 .ok => |sym_index| sym_index,1105 .ok => |sym_index| sym_index,
1110 .fail => |em| {1106 .fail => |em| {
1111 decl.analysis = .codegen_failure;1107 decl.analysis = .codegen_failure;
1112 try mod.failed_decls.put(mod.gpa, decl_index, em);1108 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
1113 log.err("{s}", .{em.msg});1109 log.err("{s}", .{em.msg});
1114 return error.CodegenFail;1110 return error.CodegenFail;
1115 },1111 },
...@@ -1131,7 +1127,7 @@ fn lowerConst(...@@ -1131,7 +1127,7 @@ fn lowerConst(
1131 val: Value,1127 val: Value,
1132 required_alignment: Atom.Alignment,1128 required_alignment: Atom.Alignment,
1133 output_section_index: u8,1129 output_section_index: u8,
1134 src_loc: Module.SrcLoc,1130 src_loc: Module.LazySrcLoc,
1135) !LowerConstResult {1131) !LowerConstResult {
1136 const gpa = macho_file.base.comp.gpa;1132 const gpa = macho_file.base.comp.gpa;
11371133
...@@ -1187,7 +1183,7 @@ pub fn updateExports(...@@ -1187,7 +1183,7 @@ pub fn updateExports(
1187 macho_file: *MachO,1183 macho_file: *MachO,
1188 mod: *Module,1184 mod: *Module,
1189 exported: Module.Exported,1185 exported: Module.Exported,
1190 exports: []const *Module.Export,1186 export_indices: []const u32,
1191) link.File.UpdateExportsError!void {1187) link.File.UpdateExportsError!void {
1192 const tracy = trace(@src());1188 const tracy = trace(@src());
1193 defer tracy.end();1189 defer tracy.end();
...@@ -1199,15 +1195,15 @@ pub fn updateExports(...@@ -1199,15 +1195,15 @@ pub fn updateExports(
1199 break :blk self.decls.getPtr(decl_index).?;1195 break :blk self.decls.getPtr(decl_index).?;
1200 },1196 },
1201 .value => |value| self.anon_decls.getPtr(value) orelse blk: {1197 .value => |value| self.anon_decls.getPtr(value) orelse blk: {
1202 const first_exp = exports[0];1198 const first_exp = mod.all_exports.items[export_indices[0]];
1203 const res = try self.lowerAnonDecl(macho_file, value, .none, first_exp.getSrcLoc(mod));1199 const res = try self.lowerAnonDecl(macho_file, value, .none, first_exp.src);
1204 switch (res) {1200 switch (res) {
1205 .ok => {},1201 .ok => {},
1206 .fail => |em| {1202 .fail => |em| {
1207 // TODO maybe it's enough to return an error here and let Module.processExportsInner1203 // TODO maybe it's enough to return an error here and let Module.processExportsInner
1208 // handle the error?1204 // handle the error?
1209 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1205 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1210 mod.failed_exports.putAssumeCapacityNoClobber(first_exp, em);1206 mod.failed_exports.putAssumeCapacityNoClobber(export_indices[0], em);
1211 return;1207 return;
1212 },1208 },
1213 }1209 }
...@@ -1218,13 +1214,14 @@ pub fn updateExports(...@@ -1218,13 +1214,14 @@ pub fn updateExports(
1218 const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx;1214 const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx;
1219 const nlist = self.symtab.items(.nlist)[nlist_idx];1215 const nlist = self.symtab.items(.nlist)[nlist_idx];
12201216
1221 for (exports) |exp| {1217 for (export_indices) |export_idx| {
1218 const exp = mod.all_exports.items[export_idx];
1222 if (exp.opts.section.unwrap()) |section_name| {1219 if (exp.opts.section.unwrap()) |section_name| {
1223 if (!section_name.eqlSlice("__text", &mod.intern_pool)) {1220 if (!section_name.eqlSlice("__text", &mod.intern_pool)) {
1224 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);1221 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
1225 mod.failed_exports.putAssumeCapacityNoClobber(exp, try Module.ErrorMsg.create(1222 mod.failed_exports.putAssumeCapacityNoClobber(export_idx, try Module.ErrorMsg.create(
1226 gpa,1223 gpa,
1227 exp.getSrcLoc(mod),1224 exp.src,
1228 "Unimplemented: ExportOptions.section",1225 "Unimplemented: ExportOptions.section",
1229 .{},1226 .{},
1230 ));1227 ));
...@@ -1232,9 +1229,9 @@ pub fn updateExports(...@@ -1232,9 +1229,9 @@ pub fn updateExports(
1232 }1229 }
1233 }1230 }
1234 if (exp.opts.linkage == .link_once) {1231 if (exp.opts.linkage == .link_once) {
1235 try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create(1232 try mod.failed_exports.putNoClobber(mod.gpa, export_idx, try Module.ErrorMsg.create(
1236 gpa,1233 gpa,
1237 exp.getSrcLoc(mod),1234 exp.src,
1238 "Unimplemented: GlobalLinkage.link_once",1235 "Unimplemented: GlobalLinkage.link_once",
1239 .{},1236 .{},
1240 ));1237 ));
...@@ -1294,14 +1291,7 @@ fn updateLazySymbol(...@@ -1294,14 +1291,7 @@ fn updateLazySymbol(
1294 break :blk try self.strtab.insert(gpa, name);1291 break :blk try self.strtab.insert(gpa, name);
1295 };1292 };
12961293
1297 const src = if (lazy_sym.ty.srcLocOrNull(mod)) |src|1294 const src = lazy_sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded;
1298 src.upgrade(mod)
1299 else
1300 Module.SrcLoc{
1301 .file_scope = undefined,
1302 .base_node = undefined,
1303 .lazy = .unneeded,
1304 };
1305 const res = try codegen.generateLazySymbol(1295 const res = try codegen.generateLazySymbol(
1306 &macho_file.base,1296 &macho_file.base,
1307 src,1297 src,
...@@ -1364,15 +1354,18 @@ pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPo...@@ -1364,15 +1354,18 @@ pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPo
1364 }1354 }
1365}1355}
13661356
1367pub fn deleteDeclExport(1357pub fn deleteExport(
1368 self: *ZigObject,1358 self: *ZigObject,
1369 macho_file: *MachO,1359 macho_file: *MachO,
1370 decl_index: InternPool.DeclIndex,1360 exported: Zcu.Exported,
1371 name: InternPool.NullTerminatedString,1361 name: InternPool.NullTerminatedString,
1372) void {1362) void {
1373 const mod = macho_file.base.comp.module.?;1363 const mod = macho_file.base.comp.module.?;
13741364
1375 const metadata = self.decls.getPtr(decl_index) orelse return;1365 const metadata = switch (exported) {
1366 .decl_index => |decl_index| self.decls.getPtr(decl_index) orelse return,
1367 .value => |value| self.anon_decls.getPtr(value) orelse return,
1368 };
1376 const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return;1369 const nlist_index = metadata.@"export"(self, name.toSlice(&mod.intern_pool)) orelse return;
13771370
1378 log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)});1371 log.debug("deleting export '{}'", .{name.fmt(&mod.intern_pool)});
...@@ -1594,6 +1587,7 @@ const Object = @import("Object.zig");...@@ -1594,6 +1587,7 @@ const Object = @import("Object.zig");
1594const Relocation = @import("Relocation.zig");1587const Relocation = @import("Relocation.zig");
1595const Symbol = @import("Symbol.zig");1588const Symbol = @import("Symbol.zig");
1596const StringTable = @import("../StringTable.zig");1589const StringTable = @import("../StringTable.zig");
1597const Type = @import("../../type.zig").Type;1590const Type = @import("../../Type.zig");
1598const Value = @import("../../Value.zig");1591const Value = @import("../../Value.zig");
1592const AnalUnit = InternPool.AnalUnit;
1599const ZigObject = @This();1593const ZigObject = @This();
src/link/NvPtx.zig+2-2
...@@ -96,12 +96,12 @@ pub fn updateExports(...@@ -96,12 +96,12 @@ pub fn updateExports(
96 self: *NvPtx,96 self: *NvPtx,
97 module: *Module,97 module: *Module,
98 exported: Module.Exported,98 exported: Module.Exported,
99 exports: []const *Module.Export,99 export_indices: []const u32,
100) !void {100) !void {
101 if (build_options.skip_non_native and builtin.object_format != .nvptx)101 if (build_options.skip_non_native and builtin.object_format != .nvptx)
102 @panic("Attempted to compile for object format that was disabled by build configuration");102 @panic("Attempted to compile for object format that was disabled by build configuration");
103103
104 return self.llvm_object.updateExports(module, exported, exports);104 return self.llvm_object.updateExports(module, exported, export_indices);
105}105}
106106
107pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {107pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void {
src/link/Plan9.zig+55-39
...@@ -15,8 +15,9 @@ const File = link.File;...@@ -15,8 +15,9 @@ const File = link.File;
15const build_options = @import("build_options");15const build_options = @import("build_options");
16const Air = @import("../Air.zig");16const Air = @import("../Air.zig");
17const Liveness = @import("../Liveness.zig");17const Liveness = @import("../Liveness.zig");
18const Type = @import("../type.zig").Type;18const Type = @import("../Type.zig");
19const Value = @import("../Value.zig");19const Value = @import("../Value.zig");
20const AnalUnit = InternPool.AnalUnit;
2021
21const std = @import("std");22const std = @import("std");
22const builtin = @import("builtin");23const builtin = @import("builtin");
...@@ -60,6 +61,9 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged(...@@ -60,6 +61,9 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged(
60) = .{},61) = .{},
61/// the code is modified when relocated, so that is why it is mutable62/// the code is modified when relocated, so that is why it is mutable
62data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{},63data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{},
64/// When `updateExports` is called, we store the export indices here, to be used
65/// during flush.
66decl_exports: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u32) = .{},
6367
64/// Table of unnamed constants associated with a parent `Decl`.68/// Table of unnamed constants associated with a parent `Decl`.
65/// We store them here so that we can free the constants whenever the `Decl`69/// We store them here so that we can free the constants whenever the `Decl`
...@@ -435,7 +439,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:...@@ -435,7 +439,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
435439
436 const res = try codegen.generateFunction(440 const res = try codegen.generateFunction(
437 &self.base,441 &self.base,
438 decl.navSrcLoc(mod).upgrade(mod),442 decl.navSrcLoc(mod),
439 func_index,443 func_index,
440 air,444 air,
441 liveness,445 liveness,
...@@ -446,7 +450,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:...@@ -446,7 +450,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air:
446 .ok => try code_buffer.toOwnedSlice(),450 .ok => try code_buffer.toOwnedSlice(),
447 .fail => |em| {451 .fail => |em| {
448 func.analysis(&mod.intern_pool).state = .codegen_failure;452 func.analysis(&mod.intern_pool).state = .codegen_failure;
449 try mod.failed_decls.put(mod.gpa, decl_index, em);453 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
450 return;454 return;
451 },455 },
452 };456 };
...@@ -501,7 +505,7 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn...@@ -501,7 +505,7 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn
501 };505 };
502 self.syms.items[info.sym_index.?] = sym;506 self.syms.items[info.sym_index.?] = sym;
503507
504 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), val, &code_buffer, .{508 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod), val, &code_buffer, .{
505 .none = {},509 .none = {},
506 }, .{510 }, .{
507 .parent_atom_index = new_atom_idx,511 .parent_atom_index = new_atom_idx,
...@@ -510,7 +514,7 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn...@@ -510,7 +514,7 @@ pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIn
510 .ok => code_buffer.items,514 .ok => code_buffer.items,
511 .fail => |em| {515 .fail => |em| {
512 decl.analysis = .codegen_failure;516 decl.analysis = .codegen_failure;
513 try mod.failed_decls.put(mod.gpa, decl_index, em);517 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
514 log.err("{s}", .{em.msg});518 log.err("{s}", .{em.msg});
515 return error.CodegenFail;519 return error.CodegenFail;
516 },520 },
...@@ -540,14 +544,14 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex)...@@ -540,14 +544,14 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex)
540 defer code_buffer.deinit();544 defer code_buffer.deinit();
541 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;545 const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val;
542 // TODO we need the symbol index for symbol in the table of locals for the containing atom546 // TODO we need the symbol index for symbol in the table of locals for the containing atom
543 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod).upgrade(mod), decl_val, &code_buffer, .{ .none = {} }, .{547 const res = try codegen.generateSymbol(&self.base, decl.navSrcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{
544 .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)),548 .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)),
545 });549 });
546 const code = switch (res) {550 const code = switch (res) {
547 .ok => code_buffer.items,551 .ok => code_buffer.items,
548 .fail => |em| {552 .fail => |em| {
549 decl.analysis = .codegen_failure;553 decl.analysis = .codegen_failure;
550 try mod.failed_decls.put(mod.gpa, decl_index, em);554 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
551 return;555 return;
552 },556 },
553 };557 };
...@@ -770,8 +774,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node)...@@ -770,8 +774,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node)
770 mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());774 mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
771 }775 }
772 self.syms.items[atom.sym_index.?].value = off;776 self.syms.items[atom.sym_index.?].value = off;
773 if (mod.decl_exports.get(decl_index)) |exports| {777 if (self.decl_exports.get(decl_index)) |export_indices| {
774 try self.addDeclExports(mod, decl_index, exports.items);778 try self.addDeclExports(mod, decl_index, export_indices);
775 }779 }
776 }780 }
777 }781 }
...@@ -836,8 +840,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node)...@@ -836,8 +840,8 @@ pub fn flushModule(self: *Plan9, arena: Allocator, prog_node: std.Progress.Node)
836 mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());840 mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, target.cpu.arch.endian());
837 }841 }
838 self.syms.items[atom.sym_index.?].value = off;842 self.syms.items[atom.sym_index.?].value = off;
839 if (mod.decl_exports.get(decl_index)) |exports| {843 if (self.decl_exports.get(decl_index)) |export_indices| {
840 try self.addDeclExports(mod, decl_index, exports.items);844 try self.addDeclExports(mod, decl_index, export_indices);
841 }845 }
842 }846 }
843 // write the unnamed constants after the other data decls847 // write the unnamed constants after the other data decls
...@@ -1007,22 +1011,23 @@ fn addDeclExports(...@@ -1007,22 +1011,23 @@ fn addDeclExports(
1007 self: *Plan9,1011 self: *Plan9,
1008 mod: *Module,1012 mod: *Module,
1009 decl_index: InternPool.DeclIndex,1013 decl_index: InternPool.DeclIndex,
1010 exports: []const *Module.Export,1014 export_indices: []const u32,
1011) !void {1015) !void {
1012 const gpa = self.base.comp.gpa;1016 const gpa = self.base.comp.gpa;
1013 const metadata = self.decls.getPtr(decl_index).?;1017 const metadata = self.decls.getPtr(decl_index).?;
1014 const atom = self.getAtom(metadata.index);1018 const atom = self.getAtom(metadata.index);
10151019
1016 for (exports) |exp| {1020 for (export_indices) |export_idx| {
1021 const exp = mod.all_exports.items[export_idx];
1017 const exp_name = exp.opts.name.toSlice(&mod.intern_pool);1022 const exp_name = exp.opts.name.toSlice(&mod.intern_pool);
1018 // plan9 does not support custom sections1023 // plan9 does not support custom sections
1019 if (exp.opts.section.unwrap()) |section_name| {1024 if (exp.opts.section.unwrap()) |section_name| {
1020 if (!section_name.eqlSlice(".text", &mod.intern_pool) and1025 if (!section_name.eqlSlice(".text", &mod.intern_pool) and
1021 !section_name.eqlSlice(".data", &mod.intern_pool))1026 !section_name.eqlSlice(".data", &mod.intern_pool))
1022 {1027 {
1023 try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(1028 try mod.failed_exports.put(mod.gpa, export_idx, try Module.ErrorMsg.create(
1024 gpa,1029 gpa,
1025 mod.declPtr(decl_index).navSrcLoc(mod).upgrade(mod),1030 mod.declPtr(decl_index).navSrcLoc(mod),
1026 "plan9 does not support extra sections",1031 "plan9 does not support extra sections",
1027 .{},1032 .{},
1028 ));1033 ));
...@@ -1152,15 +1157,23 @@ pub fn updateExports(...@@ -1152,15 +1157,23 @@ pub fn updateExports(
1152 self: *Plan9,1157 self: *Plan9,
1153 module: *Module,1158 module: *Module,
1154 exported: Module.Exported,1159 exported: Module.Exported,
1155 exports: []const *Module.Export,1160 export_indices: []const u32,
1156) !void {1161) !void {
1162 const gpa = self.base.comp.gpa;
1157 switch (exported) {1163 switch (exported) {
1158 .value => @panic("TODO: plan9 updateExports handling values"),1164 .value => @panic("TODO: plan9 updateExports handling values"),
1159 .decl_index => |decl_index| _ = try self.seeDecl(decl_index),1165 .decl_index => |decl_index| {
1166 _ = try self.seeDecl(decl_index);
1167 if (self.decl_exports.fetchSwapRemove(decl_index)) |kv| {
1168 gpa.free(kv.value);
1169 }
1170 try self.decl_exports.ensureUnusedCapacity(gpa, 1);
1171 const duped_indices = try gpa.dupe(u32, export_indices);
1172 self.decl_exports.putAssumeCapacityNoClobber(decl_index, duped_indices);
1173 },
1160 }1174 }
1161 // we do all the things in flush1175 // all proper work is done in flush
1162 _ = module;1176 _ = module;
1163 _ = exports;
1164}1177}
11651178
1166pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index {1179pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index {
...@@ -1212,14 +1225,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind...@@ -1212,14 +1225,7 @@ fn updateLazySymbolAtom(self: *Plan9, sym: File.LazySymbol, atom_index: Atom.Ind
1212 self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol;1225 self.syms.items[self.getAtomPtr(atom_index).sym_index.?] = symbol;
12131226
1214 // generate the code1227 // generate the code
1215 const src = if (sym.ty.srcLocOrNull(mod)) |src|1228 const src = sym.ty.srcLocOrNull(mod) orelse Module.LazySrcLoc.unneeded;
1216 src.upgrade(mod)
1217 else
1218 Module.SrcLoc{
1219 .file_scope = undefined,
1220 .base_node = undefined,
1221 .lazy = .unneeded,
1222 };
1223 const res = try codegen.generateLazySymbol(1229 const res = try codegen.generateLazySymbol(
1224 &self.base,1230 &self.base,
1225 src,1231 src,
...@@ -1290,6 +1296,10 @@ pub fn deinit(self: *Plan9) void {...@@ -1290,6 +1296,10 @@ pub fn deinit(self: *Plan9) void {
1290 gpa.free(self.syms.items[sym_index].name);1296 gpa.free(self.syms.items[sym_index].name);
1291 }1297 }
1292 self.data_decl_table.deinit(gpa);1298 self.data_decl_table.deinit(gpa);
1299 for (self.decl_exports.values()) |export_indices| {
1300 gpa.free(export_indices);
1301 }
1302 self.decl_exports.deinit(gpa);
1293 self.syms.deinit(gpa);1303 self.syms.deinit(gpa);
1294 self.got_index_free_list.deinit(gpa);1304 self.got_index_free_list.deinit(gpa);
1295 self.syms_index_free_list.deinit(gpa);1305 self.syms_index_free_list.deinit(gpa);
...@@ -1395,10 +1405,13 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1395,10 +1405,13 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1395 const atom = self.getAtom(decl_metadata.index);1405 const atom = self.getAtom(decl_metadata.index);
1396 const sym = self.syms.items[atom.sym_index.?];1406 const sym = self.syms.items[atom.sym_index.?];
1397 try self.writeSym(writer, sym);1407 try self.writeSym(writer, sym);
1398 if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| {1408 if (self.decl_exports.get(decl_index)) |export_indices| {
1399 for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| {1409 for (export_indices) |export_idx| {
1400 try self.writeSym(writer, self.syms.items[exp_i]);1410 const exp = mod.all_exports.items[export_idx];
1401 };1411 if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
1412 try self.writeSym(writer, self.syms.items[exp_i]);
1413 }
1414 }
1402 }1415 }
1403 }1416 }
1404 }1417 }
...@@ -1442,13 +1455,16 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -1442,13 +1455,16 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1442 const atom = self.getAtom(decl_metadata.index);1455 const atom = self.getAtom(decl_metadata.index);
1443 const sym = self.syms.items[atom.sym_index.?];1456 const sym = self.syms.items[atom.sym_index.?];
1444 try self.writeSym(writer, sym);1457 try self.writeSym(writer, sym);
1445 if (self.base.comp.module.?.decl_exports.get(decl_index)) |exports| {1458 if (self.decl_exports.get(decl_index)) |export_indices| {
1446 for (exports.items) |e| if (decl_metadata.getExport(self, e.opts.name.toSlice(ip))) |exp_i| {1459 for (export_indices) |export_idx| {
1447 const s = self.syms.items[exp_i];1460 const exp = mod.all_exports.items[export_idx];
1448 if (mem.eql(u8, s.name, "_start"))1461 if (decl_metadata.getExport(self, exp.opts.name.toSlice(ip))) |exp_i| {
1449 self.entry_val = s.value;1462 const s = self.syms.items[exp_i];
1450 try self.writeSym(writer, s);1463 if (mem.eql(u8, s.name, "_start"))
1451 };1464 self.entry_val = s.value;
1465 try self.writeSym(writer, s);
1466 }
1467 }
1452 }1468 }
1453 }1469 }
1454 }1470 }
...@@ -1530,7 +1546,7 @@ pub fn lowerAnonDecl(...@@ -1530,7 +1546,7 @@ pub fn lowerAnonDecl(
1530 self: *Plan9,1546 self: *Plan9,
1531 decl_val: InternPool.Index,1547 decl_val: InternPool.Index,
1532 explicit_alignment: InternPool.Alignment,1548 explicit_alignment: InternPool.Alignment,
1533 src_loc: Module.SrcLoc,1549 src_loc: Module.LazySrcLoc,
1534) !codegen.Result {1550) !codegen.Result {
1535 _ = explicit_alignment;1551 _ = explicit_alignment;
1536 // This is basically the same as lowerUnnamedConst.1552 // This is basically the same as lowerUnnamedConst.
src/link/SpirV.zig+3-2
...@@ -152,7 +152,7 @@ pub fn updateExports(...@@ -152,7 +152,7 @@ pub fn updateExports(
152 self: *SpirV,152 self: *SpirV,
153 mod: *Module,153 mod: *Module,
154 exported: Module.Exported,154 exported: Module.Exported,
155 exports: []const *Module.Export,155 export_indices: []const u32,
156) !void {156) !void {
157 const decl_index = switch (exported) {157 const decl_index = switch (exported) {
158 .decl_index => |i| i,158 .decl_index => |i| i,
...@@ -177,7 +177,8 @@ pub fn updateExports(...@@ -177,7 +177,8 @@ pub fn updateExports(
177 if ((!is_vulkan and execution_model == .Kernel) or177 if ((!is_vulkan and execution_model == .Kernel) or
178 (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex)))178 (is_vulkan and (execution_model == .Fragment or execution_model == .Vertex)))
179 {179 {
180 for (exports) |exp| {180 for (export_indices) |export_idx| {
181 const exp = mod.all_exports.items[export_idx];
181 try self.object.spv.declareEntryPoint(182 try self.object.spv.declareEntryPoint(
182 spv_decl_index,183 spv_decl_index,
183 exp.opts.name.toSlice(&mod.intern_pool),184 exp.opts.name.toSlice(&mod.intern_pool),
src/link/Wasm.zig+8-8
...@@ -33,7 +33,7 @@ const Zcu = @import("../Zcu.zig");...@@ -33,7 +33,7 @@ const Zcu = @import("../Zcu.zig");
33const Module = Zcu;33const Module = Zcu;
34const Object = @import("Wasm/Object.zig");34const Object = @import("Wasm/Object.zig");
35const Symbol = @import("Wasm/Symbol.zig");35const Symbol = @import("Wasm/Symbol.zig");
36const Type = @import("../type.zig").Type;36const Type = @import("../Type.zig");
37const Value = @import("../Value.zig");37const Value = @import("../Value.zig");
38const ZigObject = @import("Wasm/ZigObject.zig");38const ZigObject = @import("Wasm/ZigObject.zig");
3939
...@@ -1533,7 +1533,7 @@ pub fn lowerAnonDecl(...@@ -1533,7 +1533,7 @@ pub fn lowerAnonDecl(
1533 wasm: *Wasm,1533 wasm: *Wasm,
1534 decl_val: InternPool.Index,1534 decl_val: InternPool.Index,
1535 explicit_alignment: Alignment,1535 explicit_alignment: Alignment,
1536 src_loc: Module.SrcLoc,1536 src_loc: Module.LazySrcLoc,
1537) !codegen.Result {1537) !codegen.Result {
1538 return wasm.zigObjectPtr().?.lowerAnonDecl(wasm, decl_val, explicit_alignment, src_loc);1538 return wasm.zigObjectPtr().?.lowerAnonDecl(wasm, decl_val, explicit_alignment, src_loc);
1539}1539}
...@@ -1542,26 +1542,26 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin...@@ -1542,26 +1542,26 @@ pub fn getAnonDeclVAddr(wasm: *Wasm, decl_val: InternPool.Index, reloc_info: lin
1542 return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info);1542 return wasm.zigObjectPtr().?.getAnonDeclVAddr(wasm, decl_val, reloc_info);
1543}1543}
15441544
1545pub fn deleteDeclExport(1545pub fn deleteExport(
1546 wasm: *Wasm,1546 wasm: *Wasm,
1547 decl_index: InternPool.DeclIndex,1547 exported: Zcu.Exported,
1548 name: InternPool.NullTerminatedString,1548 name: InternPool.NullTerminatedString,
1549) void {1549) void {
1550 if (wasm.llvm_object) |_| return;1550 if (wasm.llvm_object) |_| return;
1551 return wasm.zigObjectPtr().?.deleteDeclExport(wasm, decl_index, name);1551 return wasm.zigObjectPtr().?.deleteExport(wasm, exported, name);
1552}1552}
15531553
1554pub fn updateExports(1554pub fn updateExports(
1555 wasm: *Wasm,1555 wasm: *Wasm,
1556 mod: *Module,1556 mod: *Module,
1557 exported: Module.Exported,1557 exported: Module.Exported,
1558 exports: []const *Module.Export,1558 export_indices: []const u32,
1559) !void {1559) !void {
1560 if (build_options.skip_non_native and builtin.object_format != .wasm) {1560 if (build_options.skip_non_native and builtin.object_format != .wasm) {
1561 @panic("Attempted to compile for object format that was disabled by build configuration");1561 @panic("Attempted to compile for object format that was disabled by build configuration");
1562 }1562 }
1563 if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, exports);1563 if (wasm.llvm_object) |llvm_object| return llvm_object.updateExports(mod, exported, export_indices);
1564 return wasm.zigObjectPtr().?.updateExports(wasm, mod, exported, exports);1564 return wasm.zigObjectPtr().?.updateExports(wasm, mod, exported, export_indices);
1565}1565}
15661566
1567pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void {1567pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void {
src/link/Wasm/ZigObject.zig+23-17
...@@ -269,7 +269,7 @@ pub fn updateDecl(...@@ -269,7 +269,7 @@ pub fn updateDecl(
269269
270 const res = try codegen.generateSymbol(270 const res = try codegen.generateSymbol(
271 &wasm_file.base,271 &wasm_file.base,
272 decl.navSrcLoc(mod).upgrade(mod),272 decl.navSrcLoc(mod),
273 val,273 val,
274 &code_writer,274 &code_writer,
275 .none,275 .none,
...@@ -280,7 +280,7 @@ pub fn updateDecl(...@@ -280,7 +280,7 @@ pub fn updateDecl(
280 .ok => code_writer.items,280 .ok => code_writer.items,
281 .fail => |em| {281 .fail => |em| {
282 decl.analysis = .codegen_failure;282 decl.analysis = .codegen_failure;
283 try mod.failed_decls.put(mod.gpa, decl_index, em);283 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
284 return;284 return;
285 },285 },
286 };286 };
...@@ -308,7 +308,7 @@ pub fn updateFunc(...@@ -308,7 +308,7 @@ pub fn updateFunc(
308 defer code_writer.deinit();308 defer code_writer.deinit();
309 const result = try codegen.generateFunction(309 const result = try codegen.generateFunction(
310 &wasm_file.base,310 &wasm_file.base,
311 decl.navSrcLoc(mod).upgrade(mod),311 decl.navSrcLoc(mod),
312 func_index,312 func_index,
313 air,313 air,
314 liveness,314 liveness,
...@@ -320,7 +320,7 @@ pub fn updateFunc(...@@ -320,7 +320,7 @@ pub fn updateFunc(
320 .ok => code_writer.items,320 .ok => code_writer.items,
321 .fail => |em| {321 .fail => |em| {
322 decl.analysis = .codegen_failure;322 decl.analysis = .codegen_failure;
323 try mod.failed_decls.put(mod.gpa, decl_index, em);323 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
324 return;324 return;
325 },325 },
326 };326 };
...@@ -439,7 +439,7 @@ pub fn lowerAnonDecl(...@@ -439,7 +439,7 @@ pub fn lowerAnonDecl(
439 wasm_file: *Wasm,439 wasm_file: *Wasm,
440 decl_val: InternPool.Index,440 decl_val: InternPool.Index,
441 explicit_alignment: InternPool.Alignment,441 explicit_alignment: InternPool.Alignment,
442 src_loc: Module.SrcLoc,442 src_loc: Module.LazySrcLoc,
443) !codegen.Result {443) !codegen.Result {
444 const gpa = wasm_file.base.comp.gpa;444 const gpa = wasm_file.base.comp.gpa;
445 const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val);445 const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val);
...@@ -494,14 +494,14 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, d...@@ -494,14 +494,14 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, d
494 else494 else
495 decl.navSrcLoc(mod);495 decl.navSrcLoc(mod);
496496
497 switch (try zig_object.lowerConst(wasm_file, name, val, decl_src.upgrade(mod))) {497 switch (try zig_object.lowerConst(wasm_file, name, val, decl_src)) {
498 .ok => |atom_index| {498 .ok => |atom_index| {
499 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);499 try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index);
500 return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);500 return @intFromEnum(wasm_file.getAtom(atom_index).sym_index);
501 },501 },
502 .fail => |em| {502 .fail => |em| {
503 decl.analysis = .codegen_failure;503 decl.analysis = .codegen_failure;
504 try mod.failed_decls.put(mod.gpa, decl_index, em);504 try mod.failed_analysis.put(mod.gpa, AnalUnit.wrap(.{ .decl = decl_index }), em);
505 return error.CodegenFail;505 return error.CodegenFail;
506 },506 },
507 }507 }
...@@ -512,7 +512,7 @@ const LowerConstResult = union(enum) {...@@ -512,7 +512,7 @@ const LowerConstResult = union(enum) {
512 fail: *Module.ErrorMsg,512 fail: *Module.ErrorMsg,
513};513};
514514
515fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.SrcLoc) !LowerConstResult {515fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.LazySrcLoc) !LowerConstResult {
516 const gpa = wasm_file.base.comp.gpa;516 const gpa = wasm_file.base.comp.gpa;
517 const mod = wasm_file.base.comp.module.?;517 const mod = wasm_file.base.comp.module.?;
518518
...@@ -833,13 +833,17 @@ pub fn getAnonDeclVAddr(...@@ -833,13 +833,17 @@ pub fn getAnonDeclVAddr(
833 return target_symbol_index;833 return target_symbol_index;
834}834}
835835
836pub fn deleteDeclExport(836pub fn deleteExport(
837 zig_object: *ZigObject,837 zig_object: *ZigObject,
838 wasm_file: *Wasm,838 wasm_file: *Wasm,
839 decl_index: InternPool.DeclIndex,839 exported: Zcu.Exported,
840 name: InternPool.NullTerminatedString,840 name: InternPool.NullTerminatedString,
841) void {841) void {
842 const mod = wasm_file.base.comp.module.?;842 const mod = wasm_file.base.comp.module.?;
843 const decl_index = switch (exported) {
844 .decl_index => |decl_index| decl_index,
845 .value => @panic("TODO: implement Wasm linker code for exporting a constant value"),
846 };
843 const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return;847 const decl_info = zig_object.decls_map.getPtr(decl_index) orelse return;
844 if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| {848 if (decl_info.@"export"(zig_object, name.toSlice(&mod.intern_pool))) |sym_index| {
845 const sym = zig_object.symbol(sym_index);849 const sym = zig_object.symbol(sym_index);
...@@ -856,7 +860,7 @@ pub fn updateExports(...@@ -856,7 +860,7 @@ pub fn updateExports(
856 wasm_file: *Wasm,860 wasm_file: *Wasm,
857 mod: *Module,861 mod: *Module,
858 exported: Module.Exported,862 exported: Module.Exported,
859 exports: []const *Module.Export,863 export_indices: []const u32,
860) !void {864) !void {
861 const decl_index = switch (exported) {865 const decl_index = switch (exported) {
862 .decl_index => |i| i,866 .decl_index => |i| i,
...@@ -873,11 +877,12 @@ pub fn updateExports(...@@ -873,11 +877,12 @@ pub fn updateExports(
873 const gpa = mod.gpa;877 const gpa = mod.gpa;
874 log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)});878 log.debug("Updating exports for decl '{}'", .{decl.name.fmt(&mod.intern_pool)});
875879
876 for (exports) |exp| {880 for (export_indices) |export_idx| {
881 const exp = mod.all_exports.items[export_idx];
877 if (exp.opts.section.toSlice(&mod.intern_pool)) |section| {882 if (exp.opts.section.toSlice(&mod.intern_pool)) |section| {
878 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(883 try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create(
879 gpa,884 gpa,
880 decl.navSrcLoc(mod).upgrade(mod),885 decl.navSrcLoc(mod),
881 "Unimplemented: ExportOptions.section '{s}'",886 "Unimplemented: ExportOptions.section '{s}'",
882 .{section},887 .{section},
883 ));888 ));
...@@ -908,9 +913,9 @@ pub fn updateExports(...@@ -908,9 +913,9 @@ pub fn updateExports(
908 },913 },
909 .strong => {}, // symbols are strong by default914 .strong => {}, // symbols are strong by default
910 .link_once => {915 .link_once => {
911 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(916 try mod.failed_exports.putNoClobber(gpa, export_idx, try Module.ErrorMsg.create(
912 gpa,917 gpa,
913 decl.navSrcLoc(mod).upgrade(mod),918 decl.navSrcLoc(mod),
914 "Unimplemented: LinkOnce",919 "Unimplemented: LinkOnce",
915 .{},920 .{},
916 ));921 ));
...@@ -1247,7 +1252,8 @@ const Zcu = @import("../../Zcu.zig");...@@ -1247,7 +1252,8 @@ const Zcu = @import("../../Zcu.zig");
1247const Module = Zcu;1252const Module = Zcu;
1248const StringTable = @import("../StringTable.zig");1253const StringTable = @import("../StringTable.zig");
1249const Symbol = @import("Symbol.zig");1254const Symbol = @import("Symbol.zig");
1250const Type = @import("../../type.zig").Type;1255const Type = @import("../../Type.zig");
1251const Value = @import("../../Value.zig");1256const Value = @import("../../Value.zig");
1252const Wasm = @import("../Wasm.zig");1257const Wasm = @import("../Wasm.zig");
1258const AnalUnit = InternPool.AnalUnit;
1253const ZigObject = @This();1259const ZigObject = @This();
src/mutable_value.zig+1-1
...@@ -3,7 +3,7 @@ const assert = std.debug.assert;...@@ -3,7 +3,7 @@ const assert = std.debug.assert;
3const Allocator = std.mem.Allocator;3const Allocator = std.mem.Allocator;
4const Zcu = @import("Zcu.zig");4const Zcu = @import("Zcu.zig");
5const InternPool = @import("InternPool.zig");5const InternPool = @import("InternPool.zig");
6const Type = @import("type.zig").Type;6const Type = @import("Type.zig");
7const Value = @import("Value.zig");7const Value = @import("Value.zig");
88
9/// We use a tagged union here because while it wastes a few bytes for some tags, having a fixed9/// We use a tagged union here because while it wastes a few bytes for some tags, having a fixed
src/print_air.zig+1-1
...@@ -4,7 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin;...@@ -4,7 +4,7 @@ const fmtIntSizeBin = std.fmt.fmtIntSizeBin;
44
5const Zcu = @import("Zcu.zig");5const Zcu = @import("Zcu.zig");
6const Value = @import("Value.zig");6const Value = @import("Value.zig");
7const Type = @import("type.zig").Type;7const Type = @import("Type.zig");
8const Air = @import("Air.zig");8const Air = @import("Air.zig");
9const Liveness = @import("Liveness.zig");9const Liveness = @import("Liveness.zig");
10const InternPool = @import("InternPool.zig");10const InternPool = @import("InternPool.zig");
src/print_value.zig+5-5
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`.2//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`.
33
4const std = @import("std");4const std = @import("std");
5const Type = @import("type.zig").Type;5const Type = @import("Type.zig");
6const Value = @import("Value.zig");6const Value = @import("Value.zig");
7const Zcu = @import("Zcu.zig");7const Zcu = @import("Zcu.zig");
8/// Deprecated.8/// Deprecated.
...@@ -81,12 +81,12 @@ pub fn print(...@@ -81,12 +81,12 @@ pub fn print(
81 }),81 }),
82 .int => |int| switch (int.storage) {82 .int => |int| switch (int.storage) {
83 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),83 inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}),
84 .lazy_align => |ty| if (opt_sema) |sema| {84 .lazy_align => |ty| if (opt_sema != null) {
85 const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar;85 const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .sema)).scalar;
86 try writer.print("{}", .{a.toByteUnits() orelse 0});86 try writer.print("{}", .{a.toByteUnits() orelse 0});
87 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}),87 } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}),
88 .lazy_size => |ty| if (opt_sema) |sema| {88 .lazy_size => |ty| if (opt_sema != null) {
89 const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar;89 const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .sema)).scalar;
90 try writer.print("{}", .{s});90 try writer.print("{}", .{s});
91 } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(mod)}),91 } else try writer.print("@sizeOf({})", .{Type.fromInterned(ty).fmt(mod)}),
92 },92 },
src/register_manager.zig+1-1
...@@ -5,7 +5,7 @@ const assert = std.debug.assert;...@@ -5,7 +5,7 @@ const assert = std.debug.assert;
5const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
6const Air = @import("Air.zig");6const Air = @import("Air.zig");
7const StaticBitSet = std.bit_set.StaticBitSet;7const StaticBitSet = std.bit_set.StaticBitSet;
8const Type = @import("type.zig").Type;8const Type = @import("Type.zig");
9const Zcu = @import("Zcu.zig");9const Zcu = @import("Zcu.zig");
10/// Deprecated.10/// Deprecated.
11const Module = Zcu;11const Module = Zcu;
src/target.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const Type = @import("type.zig").Type;2const Type = @import("Type.zig");
3const AddressSpace = std.builtin.AddressSpace;3const AddressSpace = std.builtin.AddressSpace;
4const Alignment = @import("InternPool.zig").Alignment;4const Alignment = @import("InternPool.zig").Alignment;
5const Feature = @import("Zcu.zig").Feature;5const Feature = @import("Zcu.zig").Feature;
src/type.zig deleted-3617
...@@ -1,3617 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const Value = @import("Value.zig");
4const assert = std.debug.assert;
5const Target = std.Target;
6const Zcu = @import("Zcu.zig");
7/// Deprecated.
8const Module = Zcu;
9const log = std.log.scoped(.Type);
10const target_util = @import("target.zig");
11const Sema = @import("Sema.zig");
12const InternPool = @import("InternPool.zig");
13const Alignment = InternPool.Alignment;
14const Zir = std.zig.Zir;
15
16/// Both types and values are canonically represented by a single 32-bit integer
17/// which is an index into an `InternPool` data structure.
18/// This struct abstracts around this storage by providing methods only
19/// applicable to types rather than values in general.
20pub const Type = struct {
21 ip_index: InternPool.Index,
22
23 pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {
24 return ty.zigTypeTagOrPoison(mod) catch unreachable;
25 }
26
27 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
28 return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern());
29 }
30
31 pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {
32 return switch (self.zigTypeTag(mod)) {
33 .ErrorUnion => self.errorUnionPayload(mod).baseZigTypeTag(mod),
34 .Optional => {
35 return self.optionalChild(mod).baseZigTypeTag(mod);
36 },
37 else => |t| t,
38 };
39 }
40
41 pub fn isSelfComparable(ty: Type, mod: *const Module, is_equality_cmp: bool) bool {
42 return switch (ty.zigTypeTag(mod)) {
43 .Int,
44 .Float,
45 .ComptimeFloat,
46 .ComptimeInt,
47 => true,
48
49 .Vector => ty.elemType2(mod).isSelfComparable(mod, is_equality_cmp),
50
51 .Bool,
52 .Type,
53 .Void,
54 .ErrorSet,
55 .Fn,
56 .Opaque,
57 .AnyFrame,
58 .Enum,
59 .EnumLiteral,
60 => is_equality_cmp,
61
62 .NoReturn,
63 .Array,
64 .Struct,
65 .Undefined,
66 .Null,
67 .ErrorUnion,
68 .Union,
69 .Frame,
70 => false,
71
72 .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr(mod)),
73 .Optional => {
74 if (!is_equality_cmp) return false;
75 return ty.optionalChild(mod).isSelfComparable(mod, is_equality_cmp);
76 },
77 };
78 }
79
80 /// If it is a function pointer, returns the function type. Otherwise returns null.
81 pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {
82 if (ty.zigTypeTag(mod) != .Pointer) return null;
83 const elem_ty = ty.childType(mod);
84 if (elem_ty.zigTypeTag(mod) != .Fn) return null;
85 return elem_ty;
86 }
87
88 /// Asserts the type is a pointer.
89 pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {
90 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const;
91 }
92
93 pub const ArrayInfo = struct {
94 elem_type: Type,
95 sentinel: ?Value = null,
96 len: u64,
97 };
98
99 pub fn arrayInfo(self: Type, mod: *const Module) ArrayInfo {
100 return .{
101 .len = self.arrayLen(mod),
102 .sentinel = self.sentinel(mod),
103 .elem_type = self.childType(mod),
104 };
105 }
106
107 pub fn ptrInfo(ty: Type, mod: *const Module) InternPool.Key.PtrType {
108 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
109 .ptr_type => |p| p,
110 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
111 .ptr_type => |p| p,
112 else => unreachable,
113 },
114 else => unreachable,
115 };
116 }
117
118 pub fn eql(a: Type, b: Type, mod: *const Module) bool {
119 _ = mod; // TODO: remove this parameter
120 // The InternPool data structure hashes based on Key to make interned objects
121 // unique. An Index can be treated simply as u32 value for the
122 // purpose of Type/Value hashing and equality.
123 return a.toIntern() == b.toIntern();
124 }
125
126 pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
127 _ = ty;
128 _ = unused_fmt_string;
129 _ = options;
130 _ = writer;
131 @compileError("do not format types directly; use either ty.fmtDebug() or ty.fmt()");
132 }
133
134 pub const Formatter = std.fmt.Formatter(format2);
135
136 pub fn fmt(ty: Type, module: *Module) Formatter {
137 return .{ .data = .{
138 .ty = ty,
139 .module = module,
140 } };
141 }
142
143 const FormatContext = struct {
144 ty: Type,
145 module: *Module,
146 };
147
148 fn format2(
149 ctx: FormatContext,
150 comptime unused_format_string: []const u8,
151 options: std.fmt.FormatOptions,
152 writer: anytype,
153 ) !void {
154 comptime assert(unused_format_string.len == 0);
155 _ = options;
156 return print(ctx.ty, writer, ctx.module);
157 }
158
159 pub fn fmtDebug(ty: Type) std.fmt.Formatter(dump) {
160 return .{ .data = ty };
161 }
162
163 /// This is a debug function. In order to print types in a meaningful way
164 /// we also need access to the module.
165 pub fn dump(
166 start_type: Type,
167 comptime unused_format_string: []const u8,
168 options: std.fmt.FormatOptions,
169 writer: anytype,
170 ) @TypeOf(writer).Error!void {
171 _ = options;
172 comptime assert(unused_format_string.len == 0);
173 return writer.print("{any}", .{start_type.ip_index});
174 }
175
176 /// Prints a name suitable for `@typeName`.
177 /// TODO: take an `opt_sema` to pass to `fmtValue` when printing sentinels.
178 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
179 const ip = &mod.intern_pool;
180 switch (ip.indexToKey(ty.toIntern())) {
181 .int_type => |int_type| {
182 const sign_char: u8 = switch (int_type.signedness) {
183 .signed => 'i',
184 .unsigned => 'u',
185 };
186 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
187 },
188 .ptr_type => {
189 const info = ty.ptrInfo(mod);
190
191 if (info.sentinel != .none) switch (info.flags.size) {
192 .One, .C => unreachable,
193 .Many => try writer.print("[*:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod, null)}),
194 .Slice => try writer.print("[:{}]", .{Value.fromInterned(info.sentinel).fmtValue(mod, null)}),
195 } else switch (info.flags.size) {
196 .One => try writer.writeAll("*"),
197 .Many => try writer.writeAll("[*]"),
198 .C => try writer.writeAll("[*c]"),
199 .Slice => try writer.writeAll("[]"),
200 }
201 if (info.flags.alignment != .none or
202 info.packed_offset.host_size != 0 or
203 info.flags.vector_index != .none)
204 {
205 const alignment = if (info.flags.alignment != .none)
206 info.flags.alignment
207 else
208 Type.fromInterned(info.child).abiAlignment(mod);
209 try writer.print("align({d}", .{alignment.toByteUnits() orelse 0});
210
211 if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) {
212 try writer.print(":{d}:{d}", .{
213 info.packed_offset.bit_offset, info.packed_offset.host_size,
214 });
215 }
216 if (info.flags.vector_index == .runtime) {
217 try writer.writeAll(":?");
218 } else if (info.flags.vector_index != .none) {
219 try writer.print(":{d}", .{@intFromEnum(info.flags.vector_index)});
220 }
221 try writer.writeAll(") ");
222 }
223 if (info.flags.address_space != .generic) {
224 try writer.print("addrspace(.{s}) ", .{@tagName(info.flags.address_space)});
225 }
226 if (info.flags.is_const) try writer.writeAll("const ");
227 if (info.flags.is_volatile) try writer.writeAll("volatile ");
228 if (info.flags.is_allowzero and info.flags.size != .C) try writer.writeAll("allowzero ");
229
230 try print(Type.fromInterned(info.child), writer, mod);
231 return;
232 },
233 .array_type => |array_type| {
234 if (array_type.sentinel == .none) {
235 try writer.print("[{d}]", .{array_type.len});
236 try print(Type.fromInterned(array_type.child), writer, mod);
237 } else {
238 try writer.print("[{d}:{}]", .{
239 array_type.len,
240 Value.fromInterned(array_type.sentinel).fmtValue(mod, null),
241 });
242 try print(Type.fromInterned(array_type.child), writer, mod);
243 }
244 return;
245 },
246 .vector_type => |vector_type| {
247 try writer.print("@Vector({d}, ", .{vector_type.len});
248 try print(Type.fromInterned(vector_type.child), writer, mod);
249 try writer.writeAll(")");
250 return;
251 },
252 .opt_type => |child| {
253 try writer.writeByte('?');
254 return print(Type.fromInterned(child), writer, mod);
255 },
256 .error_union_type => |error_union_type| {
257 try print(Type.fromInterned(error_union_type.error_set_type), writer, mod);
258 try writer.writeByte('!');
259 if (error_union_type.payload_type == .generic_poison_type) {
260 try writer.writeAll("anytype");
261 } else {
262 try print(Type.fromInterned(error_union_type.payload_type), writer, mod);
263 }
264 return;
265 },
266 .inferred_error_set_type => |func_index| {
267 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
268 const owner_decl = mod.funcOwnerDeclPtr(func_index);
269 try owner_decl.renderFullyQualifiedName(mod, writer);
270 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
271 },
272 .error_set_type => |error_set_type| {
273 const names = error_set_type.names;
274 try writer.writeAll("error{");
275 for (names.get(ip), 0..) |name, i| {
276 if (i != 0) try writer.writeByte(',');
277 try writer.print("{}", .{name.fmt(ip)});
278 }
279 try writer.writeAll("}");
280 },
281 .simple_type => |s| switch (s) {
282 .f16,
283 .f32,
284 .f64,
285 .f80,
286 .f128,
287 .usize,
288 .isize,
289 .c_char,
290 .c_short,
291 .c_ushort,
292 .c_int,
293 .c_uint,
294 .c_long,
295 .c_ulong,
296 .c_longlong,
297 .c_ulonglong,
298 .c_longdouble,
299 .anyopaque,
300 .bool,
301 .void,
302 .type,
303 .anyerror,
304 .comptime_int,
305 .comptime_float,
306 .noreturn,
307 .adhoc_inferred_error_set,
308 => return writer.writeAll(@tagName(s)),
309
310 .null,
311 .undefined,
312 => try writer.print("@TypeOf({s})", .{@tagName(s)}),
313
314 .enum_literal => try writer.print("@TypeOf(.{s})", .{@tagName(s)}),
315 .atomic_order => try writer.writeAll("std.builtin.AtomicOrder"),
316 .atomic_rmw_op => try writer.writeAll("std.builtin.AtomicRmwOp"),
317 .calling_convention => try writer.writeAll("std.builtin.CallingConvention"),
318 .address_space => try writer.writeAll("std.builtin.AddressSpace"),
319 .float_mode => try writer.writeAll("std.builtin.FloatMode"),
320 .reduce_op => try writer.writeAll("std.builtin.ReduceOp"),
321 .call_modifier => try writer.writeAll("std.builtin.CallModifier"),
322 .prefetch_options => try writer.writeAll("std.builtin.PrefetchOptions"),
323 .export_options => try writer.writeAll("std.builtin.ExportOptions"),
324 .extern_options => try writer.writeAll("std.builtin.ExternOptions"),
325 .type_info => try writer.writeAll("std.builtin.Type"),
326
327 .generic_poison => unreachable,
328 },
329 .struct_type => {
330 const struct_type = ip.loadStructType(ty.toIntern());
331 if (struct_type.decl.unwrap()) |decl_index| {
332 const decl = mod.declPtr(decl_index);
333 try decl.renderFullyQualifiedName(mod, writer);
334 } else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| {
335 const namespace = mod.namespacePtr(namespace_index);
336 try namespace.renderFullyQualifiedName(mod, .empty, writer);
337 } else {
338 try writer.writeAll("@TypeOf(.{})");
339 }
340 },
341 .anon_struct_type => |anon_struct| {
342 if (anon_struct.types.len == 0) {
343 return writer.writeAll("@TypeOf(.{})");
344 }
345 try writer.writeAll("struct{");
346 for (anon_struct.types.get(ip), anon_struct.values.get(ip), 0..) |field_ty, val, i| {
347 if (i != 0) try writer.writeAll(", ");
348 if (val != .none) {
349 try writer.writeAll("comptime ");
350 }
351 if (anon_struct.names.len != 0) {
352 try writer.print("{}: ", .{anon_struct.names.get(ip)[i].fmt(&mod.intern_pool)});
353 }
354
355 try print(Type.fromInterned(field_ty), writer, mod);
356
357 if (val != .none) {
358 try writer.print(" = {}", .{Value.fromInterned(val).fmtValue(mod, null)});
359 }
360 }
361 try writer.writeAll("}");
362 },
363
364 .union_type => {
365 const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl);
366 try decl.renderFullyQualifiedName(mod, writer);
367 },
368 .opaque_type => {
369 const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl);
370 try decl.renderFullyQualifiedName(mod, writer);
371 },
372 .enum_type => {
373 const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl);
374 try decl.renderFullyQualifiedName(mod, writer);
375 },
376 .func_type => |fn_info| {
377 if (fn_info.is_noinline) {
378 try writer.writeAll("noinline ");
379 }
380 try writer.writeAll("fn (");
381 const param_types = fn_info.param_types.get(&mod.intern_pool);
382 for (param_types, 0..) |param_ty, i| {
383 if (i != 0) try writer.writeAll(", ");
384 if (std.math.cast(u5, i)) |index| {
385 if (fn_info.paramIsComptime(index)) {
386 try writer.writeAll("comptime ");
387 }
388 if (fn_info.paramIsNoalias(index)) {
389 try writer.writeAll("noalias ");
390 }
391 }
392 if (param_ty == .generic_poison_type) {
393 try writer.writeAll("anytype");
394 } else {
395 try print(Type.fromInterned(param_ty), writer, mod);
396 }
397 }
398 if (fn_info.is_var_args) {
399 if (param_types.len != 0) {
400 try writer.writeAll(", ");
401 }
402 try writer.writeAll("...");
403 }
404 try writer.writeAll(") ");
405 if (fn_info.cc != .Unspecified) {
406 try writer.writeAll("callconv(.");
407 try writer.writeAll(@tagName(fn_info.cc));
408 try writer.writeAll(") ");
409 }
410 if (fn_info.return_type == .generic_poison_type) {
411 try writer.writeAll("anytype");
412 } else {
413 try print(Type.fromInterned(fn_info.return_type), writer, mod);
414 }
415 },
416 .anyframe_type => |child| {
417 if (child == .none) return writer.writeAll("anyframe");
418 try writer.writeAll("anyframe->");
419 return print(Type.fromInterned(child), writer, mod);
420 },
421
422 // values, not types
423 .undef,
424 .simple_value,
425 .variable,
426 .extern_func,
427 .func,
428 .int,
429 .err,
430 .error_union,
431 .enum_literal,
432 .enum_tag,
433 .empty_enum_value,
434 .float,
435 .ptr,
436 .slice,
437 .opt,
438 .aggregate,
439 .un,
440 // memoization, not types
441 .memoized_call,
442 => unreachable,
443 }
444 }
445
446 pub fn fromInterned(i: InternPool.Index) Type {
447 assert(i != .none);
448 return .{ .ip_index = i };
449 }
450
451 pub fn toIntern(ty: Type) InternPool.Index {
452 assert(ty.ip_index != .none);
453 return ty.ip_index;
454 }
455
456 pub fn toValue(self: Type) Value {
457 return Value.fromInterned(self.toIntern());
458 }
459
460 const RuntimeBitsError = Module.CompileError || error{NeedLazy};
461
462 /// true if and only if the type takes up space in memory at runtime.
463 /// There are two reasons a type will return false:
464 /// * the type is a comptime-only type. For example, the type `type` itself.
465 /// - note, however, that a struct can have mixed fields and only the non-comptime-only
466 /// fields will count towards the ABI size. For example, `struct {T: type, x: i32}`
467 /// hasRuntimeBits()=true and abiSize()=4
468 /// * the type has only one possible value, making its ABI size 0.
469 /// - an enum with an explicit tag type has the ABI size of the integer tag type,
470 /// making it one-possible-value only if the integer tag type has 0 bits.
471 /// When `ignore_comptime_only` is true, then types that are comptime-only
472 /// may return false positives.
473 pub fn hasRuntimeBitsAdvanced(
474 ty: Type,
475 mod: *Module,
476 ignore_comptime_only: bool,
477 strat: AbiAlignmentAdvancedStrat,
478 ) RuntimeBitsError!bool {
479 const ip = &mod.intern_pool;
480 return switch (ty.toIntern()) {
481 // False because it is a comptime-only type.
482 .empty_struct_type => false,
483 else => switch (ip.indexToKey(ty.toIntern())) {
484 .int_type => |int_type| int_type.bits != 0,
485 .ptr_type => {
486 // Pointers to zero-bit types still have a runtime address; however, pointers
487 // to comptime-only types do not, with the exception of function pointers.
488 if (ignore_comptime_only) return true;
489 return switch (strat) {
490 .sema => |sema| !(try sema.typeRequiresComptime(ty)),
491 .eager => !comptimeOnly(ty, mod),
492 .lazy => error.NeedLazy,
493 };
494 },
495 .anyframe_type => true,
496 .array_type => |array_type| return array_type.lenIncludingSentinel() > 0 and
497 try Type.fromInterned(array_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
498 .vector_type => |vector_type| return vector_type.len > 0 and
499 try Type.fromInterned(vector_type.child).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
500 .opt_type => |child| {
501 const child_ty = Type.fromInterned(child);
502 if (child_ty.isNoReturn(mod)) {
503 // Then the optional is comptime-known to be null.
504 return false;
505 }
506 if (ignore_comptime_only) return true;
507 return switch (strat) {
508 .sema => |sema| !(try sema.typeRequiresComptime(child_ty)),
509 .eager => !comptimeOnly(child_ty, mod),
510 .lazy => error.NeedLazy,
511 };
512 },
513 .error_union_type,
514 .error_set_type,
515 .inferred_error_set_type,
516 => true,
517
518 // These are function *bodies*, not pointers.
519 // They return false here because they are comptime-only types.
520 // Special exceptions have to be made when emitting functions due to
521 // this returning false.
522 .func_type => false,
523
524 .simple_type => |t| switch (t) {
525 .f16,
526 .f32,
527 .f64,
528 .f80,
529 .f128,
530 .usize,
531 .isize,
532 .c_char,
533 .c_short,
534 .c_ushort,
535 .c_int,
536 .c_uint,
537 .c_long,
538 .c_ulong,
539 .c_longlong,
540 .c_ulonglong,
541 .c_longdouble,
542 .bool,
543 .anyerror,
544 .adhoc_inferred_error_set,
545 .anyopaque,
546 .atomic_order,
547 .atomic_rmw_op,
548 .calling_convention,
549 .address_space,
550 .float_mode,
551 .reduce_op,
552 .call_modifier,
553 .prefetch_options,
554 .export_options,
555 .extern_options,
556 => true,
557
558 // These are false because they are comptime-only types.
559 .void,
560 .type,
561 .comptime_int,
562 .comptime_float,
563 .noreturn,
564 .null,
565 .undefined,
566 .enum_literal,
567 .type_info,
568 => false,
569
570 .generic_poison => unreachable,
571 },
572 .struct_type => {
573 const struct_type = ip.loadStructType(ty.toIntern());
574 if (struct_type.assumeRuntimeBitsIfFieldTypesWip(ip)) {
575 // In this case, we guess that hasRuntimeBits() for this type is true,
576 // and then later if our guess was incorrect, we emit a compile error.
577 return true;
578 }
579 switch (strat) {
580 .sema => |sema| _ = try sema.resolveTypeFields(ty),
581 .eager => assert(struct_type.haveFieldTypes(ip)),
582 .lazy => if (!struct_type.haveFieldTypes(ip)) return error.NeedLazy,
583 }
584 for (0..struct_type.field_types.len) |i| {
585 if (struct_type.comptime_bits.getBit(ip, i)) continue;
586 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
587 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
588 return true;
589 } else {
590 return false;
591 }
592 },
593 .anon_struct_type => |tuple| {
594 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
595 if (val != .none) continue; // comptime field
596 if (try Type.fromInterned(field_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
597 }
598 return false;
599 },
600
601 .union_type => {
602 const union_type = ip.loadUnionType(ty.toIntern());
603 switch (union_type.flagsPtr(ip).runtime_tag) {
604 .none => {
605 if (union_type.flagsPtr(ip).status == .field_types_wip) {
606 // In this case, we guess that hasRuntimeBits() for this type is true,
607 // and then later if our guess was incorrect, we emit a compile error.
608 union_type.flagsPtr(ip).assumed_runtime_bits = true;
609 return true;
610 }
611 },
612 .safety, .tagged => {
613 const tag_ty = union_type.tagTypePtr(ip).*;
614 // tag_ty will be `none` if this union's tag type is not resolved yet,
615 // in which case we want control flow to continue down below.
616 if (tag_ty != .none and
617 try Type.fromInterned(tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
618 {
619 return true;
620 }
621 },
622 }
623 switch (strat) {
624 .sema => |sema| _ = try sema.resolveTypeFields(ty),
625 .eager => assert(union_type.flagsPtr(ip).status.haveFieldTypes()),
626 .lazy => if (!union_type.flagsPtr(ip).status.haveFieldTypes())
627 return error.NeedLazy,
628 }
629 for (0..union_type.field_types.len) |field_index| {
630 const field_ty = Type.fromInterned(union_type.field_types.get(ip)[field_index]);
631 if (try field_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
632 return true;
633 } else {
634 return false;
635 }
636 },
637
638 .opaque_type => true,
639 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
640
641 // values, not types
642 .undef,
643 .simple_value,
644 .variable,
645 .extern_func,
646 .func,
647 .int,
648 .err,
649 .error_union,
650 .enum_literal,
651 .enum_tag,
652 .empty_enum_value,
653 .float,
654 .ptr,
655 .slice,
656 .opt,
657 .aggregate,
658 .un,
659 // memoization, not types
660 .memoized_call,
661 => unreachable,
662 },
663 };
664 }
665
666 /// true if and only if the type has a well-defined memory layout
667 /// readFrom/writeToMemory are supported only for types with a well-
668 /// defined memory layout
669 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
670 const ip = &mod.intern_pool;
671 return switch (ip.indexToKey(ty.toIntern())) {
672 .int_type,
673 .vector_type,
674 => true,
675
676 .error_union_type,
677 .error_set_type,
678 .inferred_error_set_type,
679 .anon_struct_type,
680 .opaque_type,
681 .anyframe_type,
682 // These are function bodies, not function pointers.
683 .func_type,
684 => false,
685
686 .array_type => |array_type| Type.fromInterned(array_type.child).hasWellDefinedLayout(mod),
687 .opt_type => ty.isPtrLikeOptional(mod),
688 .ptr_type => |ptr_type| ptr_type.flags.size != .Slice,
689
690 .simple_type => |t| switch (t) {
691 .f16,
692 .f32,
693 .f64,
694 .f80,
695 .f128,
696 .usize,
697 .isize,
698 .c_char,
699 .c_short,
700 .c_ushort,
701 .c_int,
702 .c_uint,
703 .c_long,
704 .c_ulong,
705 .c_longlong,
706 .c_ulonglong,
707 .c_longdouble,
708 .bool,
709 .void,
710 => true,
711
712 .anyerror,
713 .adhoc_inferred_error_set,
714 .anyopaque,
715 .atomic_order,
716 .atomic_rmw_op,
717 .calling_convention,
718 .address_space,
719 .float_mode,
720 .reduce_op,
721 .call_modifier,
722 .prefetch_options,
723 .export_options,
724 .extern_options,
725 .type,
726 .comptime_int,
727 .comptime_float,
728 .noreturn,
729 .null,
730 .undefined,
731 .enum_literal,
732 .type_info,
733 .generic_poison,
734 => false,
735 },
736 .struct_type => {
737 const struct_type = ip.loadStructType(ty.toIntern());
738 // Struct with no fields have a well-defined layout of no bits.
739 return struct_type.layout != .auto or struct_type.field_types.len == 0;
740 },
741 .union_type => {
742 const union_type = ip.loadUnionType(ty.toIntern());
743 return switch (union_type.flagsPtr(ip).runtime_tag) {
744 .none, .safety => union_type.flagsPtr(ip).layout != .auto,
745 .tagged => false,
746 };
747 },
748 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
749 .auto => false,
750 .explicit, .nonexhaustive => true,
751 },
752
753 // values, not types
754 .undef,
755 .simple_value,
756 .variable,
757 .extern_func,
758 .func,
759 .int,
760 .err,
761 .error_union,
762 .enum_literal,
763 .enum_tag,
764 .empty_enum_value,
765 .float,
766 .ptr,
767 .slice,
768 .opt,
769 .aggregate,
770 .un,
771 // memoization, not types
772 .memoized_call,
773 => unreachable,
774 };
775 }
776
777 pub fn hasRuntimeBits(ty: Type, mod: *Module) bool {
778 return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable;
779 }
780
781 pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
782 return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable;
783 }
784
785 pub fn fnHasRuntimeBits(ty: Type, mod: *Module) bool {
786 return ty.fnHasRuntimeBitsAdvanced(mod, null) catch unreachable;
787 }
788
789 /// Determines whether a function type has runtime bits, i.e. whether a
790 /// function with this type can exist at runtime.
791 /// Asserts that `ty` is a function type.
792 /// If `opt_sema` is not provided, asserts that the return type is sufficiently resolved.
793 pub fn fnHasRuntimeBitsAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) Module.CompileError!bool {
794 const fn_info = mod.typeToFunc(ty).?;
795 if (fn_info.is_generic) return false;
796 if (fn_info.is_var_args) return true;
797 if (fn_info.cc == .Inline) return false;
798 return !try Type.fromInterned(fn_info.return_type).comptimeOnlyAdvanced(mod, opt_sema);
799 }
800
801 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
802 switch (ty.zigTypeTag(mod)) {
803 .Fn => return ty.fnHasRuntimeBits(mod),
804 else => return ty.hasRuntimeBits(mod),
805 }
806 }
807
808 /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.
809 pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
810 return switch (ty.zigTypeTag(mod)) {
811 .Fn => true,
812 else => return ty.hasRuntimeBitsIgnoreComptime(mod),
813 };
814 }
815
816 pub fn isNoReturn(ty: Type, mod: *Module) bool {
817 return mod.intern_pool.isNoReturn(ty.toIntern());
818 }
819
820 /// Returns `none` if the pointer is naturally aligned and the element type is 0-bit.
821 pub fn ptrAlignment(ty: Type, mod: *Module) Alignment {
822 return ptrAlignmentAdvanced(ty, mod, null) catch unreachable;
823 }
824
825 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !Alignment {
826 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
827 .ptr_type => |ptr_type| {
828 if (ptr_type.flags.alignment != .none)
829 return ptr_type.flags.alignment;
830
831 if (opt_sema) |sema| {
832 const res = try Type.fromInterned(ptr_type.child).abiAlignmentAdvanced(mod, .{ .sema = sema });
833 return res.scalar;
834 }
835
836 return (Type.fromInterned(ptr_type.child).abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
837 },
838 .opt_type => |child| Type.fromInterned(child).ptrAlignmentAdvanced(mod, opt_sema),
839 else => unreachable,
840 };
841 }
842
843 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
844 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
845 .ptr_type => |ptr_type| ptr_type.flags.address_space,
846 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
847 else => unreachable,
848 };
849 }
850
851 /// Never returns `none`. Asserts that all necessary type resolution is already done.
852 pub fn abiAlignment(ty: Type, mod: *Module) Alignment {
853 return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
854 }
855
856 /// May capture a reference to `ty`.
857 /// Returned value has type `comptime_int`.
858 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
859 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
860 .val => |val| return val,
861 .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits() orelse 0),
862 }
863 }
864
865 pub const AbiAlignmentAdvanced = union(enum) {
866 scalar: Alignment,
867 val: Value,
868 };
869
870 pub const AbiAlignmentAdvancedStrat = union(enum) {
871 eager,
872 lazy,
873 sema: *Sema,
874 };
875
876 /// If you pass `eager` you will get back `scalar` and assert the type is resolved.
877 /// In this case there will be no error, guaranteed.
878 /// If you pass `lazy` you may get back `scalar` or `val`.
879 /// If `val` is returned, a reference to `ty` has been captured.
880 /// If you pass `sema` you will get back `scalar` and resolve the type if
881 /// necessary, possibly returning a CompileError.
882 pub fn abiAlignmentAdvanced(
883 ty: Type,
884 mod: *Module,
885 strat: AbiAlignmentAdvancedStrat,
886 ) Module.CompileError!AbiAlignmentAdvanced {
887 const target = mod.getTarget();
888 const use_llvm = mod.comp.config.use_llvm;
889 const ip = &mod.intern_pool;
890
891 const opt_sema = switch (strat) {
892 .sema => |sema| sema,
893 else => null,
894 };
895
896 switch (ty.toIntern()) {
897 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = .@"1" },
898 else => switch (ip.indexToKey(ty.toIntern())) {
899 .int_type => |int_type| {
900 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
901 return .{ .scalar = intAbiAlignment(int_type.bits, target, use_llvm) };
902 },
903 .ptr_type, .anyframe_type => {
904 return .{ .scalar = ptrAbiAlignment(target) };
905 },
906 .array_type => |array_type| {
907 return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat);
908 },
909 .vector_type => |vector_type| {
910 if (vector_type.len == 0) return .{ .scalar = .@"1" };
911 switch (mod.comp.getZigBackend()) {
912 else => {
913 const elem_bits: u32 = @intCast(try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, opt_sema));
914 if (elem_bits == 0) return .{ .scalar = .@"1" };
915 const bytes = ((elem_bits * vector_type.len) + 7) / 8;
916 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
917 return .{ .scalar = Alignment.fromByteUnits(alignment) };
918 },
919 .stage2_c => {
920 return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat);
921 },
922 .stage2_x86_64 => {
923 if (vector_type.child == .bool_type) {
924 if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" };
925 if (vector_type.len > 128 and std.Target.x86.featureSetHas(target.cpu.features, .avx2)) return .{ .scalar = .@"32" };
926 if (vector_type.len > 64) return .{ .scalar = .@"16" };
927 const bytes = std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
928 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
929 return .{ .scalar = Alignment.fromByteUnits(alignment) };
930 }
931 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
932 if (elem_bytes == 0) return .{ .scalar = .@"1" };
933 const bytes = elem_bytes * vector_type.len;
934 if (bytes > 32 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" };
935 if (bytes > 16 and std.Target.x86.featureSetHas(target.cpu.features, .avx)) return .{ .scalar = .@"32" };
936 return .{ .scalar = .@"16" };
937 },
938 }
939 },
940
941 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
942 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, Type.fromInterned(info.payload_type)),
943
944 .error_set_type, .inferred_error_set_type => {
945 const bits = mod.errorSetBits();
946 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
947 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
948 },
949
950 // represents machine code; not a pointer
951 .func_type => return .{ .scalar = target_util.defaultFunctionAlignment(target) },
952
953 .simple_type => |t| switch (t) {
954 .bool,
955 .atomic_order,
956 .atomic_rmw_op,
957 .calling_convention,
958 .address_space,
959 .float_mode,
960 .reduce_op,
961 .call_modifier,
962 .prefetch_options,
963 .anyopaque,
964 => return .{ .scalar = .@"1" },
965
966 .usize,
967 .isize,
968 => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target, use_llvm) },
969
970 .export_options,
971 .extern_options,
972 .type_info,
973 => return .{ .scalar = ptrAbiAlignment(target) },
974
975 .c_char => return .{ .scalar = cTypeAlign(target, .char) },
976 .c_short => return .{ .scalar = cTypeAlign(target, .short) },
977 .c_ushort => return .{ .scalar = cTypeAlign(target, .ushort) },
978 .c_int => return .{ .scalar = cTypeAlign(target, .int) },
979 .c_uint => return .{ .scalar = cTypeAlign(target, .uint) },
980 .c_long => return .{ .scalar = cTypeAlign(target, .long) },
981 .c_ulong => return .{ .scalar = cTypeAlign(target, .ulong) },
982 .c_longlong => return .{ .scalar = cTypeAlign(target, .longlong) },
983 .c_ulonglong => return .{ .scalar = cTypeAlign(target, .ulonglong) },
984 .c_longdouble => return .{ .scalar = cTypeAlign(target, .longdouble) },
985
986 .f16 => return .{ .scalar = .@"2" },
987 .f32 => return .{ .scalar = cTypeAlign(target, .float) },
988 .f64 => switch (target.c_type_bit_size(.double)) {
989 64 => return .{ .scalar = cTypeAlign(target, .double) },
990 else => return .{ .scalar = .@"8" },
991 },
992 .f80 => switch (target.c_type_bit_size(.longdouble)) {
993 80 => return .{ .scalar = cTypeAlign(target, .longdouble) },
994 else => {
995 const u80_ty: Type = .{ .ip_index = .u80_type };
996 return .{ .scalar = abiAlignment(u80_ty, mod) };
997 },
998 },
999 .f128 => switch (target.c_type_bit_size(.longdouble)) {
1000 128 => return .{ .scalar = cTypeAlign(target, .longdouble) },
1001 else => return .{ .scalar = .@"16" },
1002 },
1003
1004 .anyerror, .adhoc_inferred_error_set => {
1005 const bits = mod.errorSetBits();
1006 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = .@"1" };
1007 return .{ .scalar = intAbiAlignment(bits, target, use_llvm) };
1008 },
1009
1010 .void,
1011 .type,
1012 .comptime_int,
1013 .comptime_float,
1014 .null,
1015 .undefined,
1016 .enum_literal,
1017 => return .{ .scalar = .@"1" },
1018
1019 .noreturn => unreachable,
1020 .generic_poison => unreachable,
1021 },
1022 .struct_type => {
1023 const struct_type = ip.loadStructType(ty.toIntern());
1024 if (struct_type.layout == .@"packed") {
1025 switch (strat) {
1026 .sema => |sema| try sema.resolveTypeLayout(ty),
1027 .lazy => if (struct_type.backingIntType(ip).* == .none) return .{
1028 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1029 .ty = .comptime_int_type,
1030 .storage = .{ .lazy_align = ty.toIntern() },
1031 } }))),
1032 },
1033 .eager => {},
1034 }
1035 return .{ .scalar = Type.fromInterned(struct_type.backingIntType(ip).*).abiAlignment(mod) };
1036 }
1037
1038 const flags = struct_type.flagsPtr(ip).*;
1039 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
1040
1041 return switch (strat) {
1042 .eager => unreachable, // struct alignment not resolved
1043 .sema => |sema| .{
1044 .scalar = try sema.resolveStructAlignment(ty.toIntern(), struct_type),
1045 },
1046 .lazy => .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1047 .ty = .comptime_int_type,
1048 .storage = .{ .lazy_align = ty.toIntern() },
1049 } }))) },
1050 };
1051 },
1052 .anon_struct_type => |tuple| {
1053 var big_align: Alignment = .@"1";
1054 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
1055 if (val != .none) continue; // comptime field
1056 switch (try Type.fromInterned(field_ty).abiAlignmentAdvanced(mod, strat)) {
1057 .scalar => |field_align| big_align = big_align.max(field_align),
1058 .val => switch (strat) {
1059 .eager => unreachable, // field type alignment not resolved
1060 .sema => unreachable, // passed to abiAlignmentAdvanced above
1061 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1062 .ty = .comptime_int_type,
1063 .storage = .{ .lazy_align = ty.toIntern() },
1064 } }))) },
1065 },
1066 }
1067 }
1068 return .{ .scalar = big_align };
1069 },
1070 .union_type => {
1071 const union_type = ip.loadUnionType(ty.toIntern());
1072 const flags = union_type.flagsPtr(ip).*;
1073 if (flags.alignment != .none) return .{ .scalar = flags.alignment };
1074
1075 if (!union_type.haveLayout(ip)) switch (strat) {
1076 .eager => unreachable, // union layout not resolved
1077 .sema => |sema| return .{ .scalar = try sema.resolveUnionAlignment(ty, union_type) },
1078 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1079 .ty = .comptime_int_type,
1080 .storage = .{ .lazy_align = ty.toIntern() },
1081 } }))) },
1082 };
1083
1084 return .{ .scalar = union_type.flagsPtr(ip).alignment };
1085 },
1086 .opaque_type => return .{ .scalar = .@"1" },
1087 .enum_type => return .{
1088 .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiAlignment(mod),
1089 },
1090
1091 // values, not types
1092 .undef,
1093 .simple_value,
1094 .variable,
1095 .extern_func,
1096 .func,
1097 .int,
1098 .err,
1099 .error_union,
1100 .enum_literal,
1101 .enum_tag,
1102 .empty_enum_value,
1103 .float,
1104 .ptr,
1105 .slice,
1106 .opt,
1107 .aggregate,
1108 .un,
1109 // memoization, not types
1110 .memoized_call,
1111 => unreachable,
1112 },
1113 }
1114 }
1115
1116 fn abiAlignmentAdvancedErrorUnion(
1117 ty: Type,
1118 mod: *Module,
1119 strat: AbiAlignmentAdvancedStrat,
1120 payload_ty: Type,
1121 ) Module.CompileError!AbiAlignmentAdvanced {
1122 // This code needs to be kept in sync with the equivalent switch prong
1123 // in abiSizeAdvanced.
1124 const code_align = abiAlignment(Type.anyerror, mod);
1125 switch (strat) {
1126 .eager, .sema => {
1127 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1128 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1129 .ty = .comptime_int_type,
1130 .storage = .{ .lazy_align = ty.toIntern() },
1131 } }))) },
1132 else => |e| return e,
1133 })) {
1134 return .{ .scalar = code_align };
1135 }
1136 return .{ .scalar = code_align.max(
1137 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,
1138 ) };
1139 },
1140 .lazy => {
1141 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {
1142 .scalar => |payload_align| return .{ .scalar = code_align.max(payload_align) },
1143 .val => {},
1144 }
1145 return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1146 .ty = .comptime_int_type,
1147 .storage = .{ .lazy_align = ty.toIntern() },
1148 } }))) };
1149 },
1150 }
1151 }
1152
1153 fn abiAlignmentAdvancedOptional(
1154 ty: Type,
1155 mod: *Module,
1156 strat: AbiAlignmentAdvancedStrat,
1157 ) Module.CompileError!AbiAlignmentAdvanced {
1158 const target = mod.getTarget();
1159 const child_type = ty.optionalChild(mod);
1160
1161 switch (child_type.zigTypeTag(mod)) {
1162 .Pointer => return .{ .scalar = ptrAbiAlignment(target) },
1163 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
1164 .NoReturn => return .{ .scalar = .@"1" },
1165 else => {},
1166 }
1167
1168 switch (strat) {
1169 .eager, .sema => {
1170 if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1171 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1172 .ty = .comptime_int_type,
1173 .storage = .{ .lazy_align = ty.toIntern() },
1174 } }))) },
1175 else => |e| return e,
1176 })) {
1177 return .{ .scalar = .@"1" };
1178 }
1179 return child_type.abiAlignmentAdvanced(mod, strat);
1180 },
1181 .lazy => switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
1182 .scalar => |x| return .{ .scalar = x.max(.@"1") },
1183 .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1184 .ty = .comptime_int_type,
1185 .storage = .{ .lazy_align = ty.toIntern() },
1186 } }))) },
1187 },
1188 }
1189 }
1190
1191 /// May capture a reference to `ty`.
1192 pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
1193 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
1194 .val => |val| return val,
1195 .scalar => |x| return mod.intValue(Type.comptime_int, x),
1196 }
1197 }
1198
1199 /// Asserts the type has the ABI size already resolved.
1200 /// Types that return false for hasRuntimeBits() return 0.
1201 pub fn abiSize(ty: Type, mod: *Module) u64 {
1202 return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar;
1203 }
1204
1205 const AbiSizeAdvanced = union(enum) {
1206 scalar: u64,
1207 val: Value,
1208 };
1209
1210 /// If you pass `eager` you will get back `scalar` and assert the type is resolved.
1211 /// In this case there will be no error, guaranteed.
1212 /// If you pass `lazy` you may get back `scalar` or `val`.
1213 /// If `val` is returned, a reference to `ty` has been captured.
1214 /// If you pass `sema` you will get back `scalar` and resolve the type if
1215 /// necessary, possibly returning a CompileError.
1216 pub fn abiSizeAdvanced(
1217 ty: Type,
1218 mod: *Module,
1219 strat: AbiAlignmentAdvancedStrat,
1220 ) Module.CompileError!AbiSizeAdvanced {
1221 const target = mod.getTarget();
1222 const use_llvm = mod.comp.config.use_llvm;
1223 const ip = &mod.intern_pool;
1224
1225 switch (ty.toIntern()) {
1226 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
1227
1228 else => switch (ip.indexToKey(ty.toIntern())) {
1229 .int_type => |int_type| {
1230 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1231 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target, use_llvm) };
1232 },
1233 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1234 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
1235 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1236 },
1237 .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1238
1239 .array_type => |array_type| {
1240 const len = array_type.lenIncludingSentinel();
1241 if (len == 0) return .{ .scalar = 0 };
1242 switch (try Type.fromInterned(array_type.child).abiSizeAdvanced(mod, strat)) {
1243 .scalar => |elem_size| return .{ .scalar = len * elem_size },
1244 .val => switch (strat) {
1245 .sema, .eager => unreachable,
1246 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1247 .ty = .comptime_int_type,
1248 .storage = .{ .lazy_size = ty.toIntern() },
1249 } }))) },
1250 },
1251 }
1252 },
1253 .vector_type => |vector_type| {
1254 const opt_sema = switch (strat) {
1255 .sema => |sema| sema,
1256 .eager => null,
1257 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1258 .ty = .comptime_int_type,
1259 .storage = .{ .lazy_size = ty.toIntern() },
1260 } }))) },
1261 };
1262 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
1263 .scalar => |x| x,
1264 .val => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1265 .ty = .comptime_int_type,
1266 .storage = .{ .lazy_size = ty.toIntern() },
1267 } }))) },
1268 };
1269 const total_bytes = switch (mod.comp.getZigBackend()) {
1270 else => total_bytes: {
1271 const elem_bits = try Type.fromInterned(vector_type.child).bitSizeAdvanced(mod, opt_sema);
1272 const total_bits = elem_bits * vector_type.len;
1273 break :total_bytes (total_bits + 7) / 8;
1274 },
1275 .stage2_c => total_bytes: {
1276 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
1277 break :total_bytes elem_bytes * vector_type.len;
1278 },
1279 .stage2_x86_64 => total_bytes: {
1280 if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable;
1281 const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar);
1282 break :total_bytes elem_bytes * vector_type.len;
1283 },
1284 };
1285 return AbiSizeAdvanced{ .scalar = alignment.forward(total_bytes) };
1286 },
1287
1288 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
1289
1290 .error_set_type, .inferred_error_set_type => {
1291 const bits = mod.errorSetBits();
1292 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1293 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1294 },
1295
1296 .error_union_type => |error_union_type| {
1297 const payload_ty = Type.fromInterned(error_union_type.payload_type);
1298 // This code needs to be kept in sync with the equivalent switch prong
1299 // in abiAlignmentAdvanced.
1300 const code_size = abiSize(Type.anyerror, mod);
1301 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1302 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1303 .ty = .comptime_int_type,
1304 .storage = .{ .lazy_size = ty.toIntern() },
1305 } }))) },
1306 else => |e| return e,
1307 })) {
1308 // Same as anyerror.
1309 return AbiSizeAdvanced{ .scalar = code_size };
1310 }
1311 const code_align = abiAlignment(Type.anyerror, mod);
1312 const payload_align = abiAlignment(payload_ty, mod);
1313 const payload_size = switch (try payload_ty.abiSizeAdvanced(mod, strat)) {
1314 .scalar => |elem_size| elem_size,
1315 .val => switch (strat) {
1316 .sema => unreachable,
1317 .eager => unreachable,
1318 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1319 .ty = .comptime_int_type,
1320 .storage = .{ .lazy_size = ty.toIntern() },
1321 } }))) },
1322 },
1323 };
1324
1325 var size: u64 = 0;
1326 if (code_align.compare(.gt, payload_align)) {
1327 size += code_size;
1328 size = payload_align.forward(size);
1329 size += payload_size;
1330 size = code_align.forward(size);
1331 } else {
1332 size += payload_size;
1333 size = code_align.forward(size);
1334 size += code_size;
1335 size = payload_align.forward(size);
1336 }
1337 return AbiSizeAdvanced{ .scalar = size };
1338 },
1339 .func_type => unreachable, // represents machine code; not a pointer
1340 .simple_type => |t| switch (t) {
1341 .bool,
1342 .atomic_order,
1343 .atomic_rmw_op,
1344 .calling_convention,
1345 .address_space,
1346 .float_mode,
1347 .reduce_op,
1348 .call_modifier,
1349 => return AbiSizeAdvanced{ .scalar = 1 },
1350
1351 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
1352 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
1353 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
1354 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
1355 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1356 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1357 else => {
1358 const u80_ty: Type = .{ .ip_index = .u80_type };
1359 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
1360 },
1361 },
1362
1363 .usize,
1364 .isize,
1365 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1366
1367 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
1368 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
1369 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
1370 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
1371 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
1372 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
1373 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
1374 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
1375 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
1376 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1377
1378 .anyopaque,
1379 .void,
1380 .type,
1381 .comptime_int,
1382 .comptime_float,
1383 .null,
1384 .undefined,
1385 .enum_literal,
1386 => return AbiSizeAdvanced{ .scalar = 0 },
1387
1388 .anyerror, .adhoc_inferred_error_set => {
1389 const bits = mod.errorSetBits();
1390 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1391 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target, use_llvm) };
1392 },
1393
1394 .prefetch_options => unreachable, // missing call to resolveTypeFields
1395 .export_options => unreachable, // missing call to resolveTypeFields
1396 .extern_options => unreachable, // missing call to resolveTypeFields
1397
1398 .type_info => unreachable,
1399 .noreturn => unreachable,
1400 .generic_poison => unreachable,
1401 },
1402 .struct_type => {
1403 const struct_type = ip.loadStructType(ty.toIntern());
1404 switch (strat) {
1405 .sema => |sema| try sema.resolveTypeLayout(ty),
1406 .lazy => switch (struct_type.layout) {
1407 .@"packed" => {
1408 if (struct_type.backingIntType(ip).* == .none) return .{
1409 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1410 .ty = .comptime_int_type,
1411 .storage = .{ .lazy_size = ty.toIntern() },
1412 } }))),
1413 };
1414 },
1415 .auto, .@"extern" => {
1416 if (!struct_type.haveLayout(ip)) return .{
1417 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1418 .ty = .comptime_int_type,
1419 .storage = .{ .lazy_size = ty.toIntern() },
1420 } }))),
1421 };
1422 },
1423 },
1424 .eager => {},
1425 }
1426 switch (struct_type.layout) {
1427 .@"packed" => return .{
1428 .scalar = Type.fromInterned(struct_type.backingIntType(ip).*).abiSize(mod),
1429 },
1430 .auto, .@"extern" => {
1431 assert(struct_type.haveLayout(ip));
1432 return .{ .scalar = struct_type.size(ip).* };
1433 },
1434 }
1435 },
1436 .anon_struct_type => |tuple| {
1437 switch (strat) {
1438 .sema => |sema| try sema.resolveTypeLayout(ty),
1439 .lazy, .eager => {},
1440 }
1441 const field_count = tuple.types.len;
1442 if (field_count == 0) {
1443 return AbiSizeAdvanced{ .scalar = 0 };
1444 }
1445 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
1446 },
1447
1448 .union_type => {
1449 const union_type = ip.loadUnionType(ty.toIntern());
1450 switch (strat) {
1451 .sema => |sema| try sema.resolveTypeLayout(ty),
1452 .lazy => if (!union_type.flagsPtr(ip).status.haveLayout()) return .{
1453 .val = Value.fromInterned((try mod.intern(.{ .int = .{
1454 .ty = .comptime_int_type,
1455 .storage = .{ .lazy_size = ty.toIntern() },
1456 } }))),
1457 },
1458 .eager => {},
1459 }
1460
1461 assert(union_type.haveLayout(ip));
1462 return .{ .scalar = union_type.size(ip).* };
1463 },
1464 .opaque_type => unreachable, // no size available
1465 .enum_type => return .{ .scalar = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).abiSize(mod) },
1466
1467 // values, not types
1468 .undef,
1469 .simple_value,
1470 .variable,
1471 .extern_func,
1472 .func,
1473 .int,
1474 .err,
1475 .error_union,
1476 .enum_literal,
1477 .enum_tag,
1478 .empty_enum_value,
1479 .float,
1480 .ptr,
1481 .slice,
1482 .opt,
1483 .aggregate,
1484 .un,
1485 // memoization, not types
1486 .memoized_call,
1487 => unreachable,
1488 },
1489 }
1490 }
1491
1492 fn abiSizeAdvancedOptional(
1493 ty: Type,
1494 mod: *Module,
1495 strat: AbiAlignmentAdvancedStrat,
1496 ) Module.CompileError!AbiSizeAdvanced {
1497 const child_ty = ty.optionalChild(mod);
1498
1499 if (child_ty.isNoReturn(mod)) {
1500 return AbiSizeAdvanced{ .scalar = 0 };
1501 }
1502
1503 if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1504 error.NeedLazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1505 .ty = .comptime_int_type,
1506 .storage = .{ .lazy_size = ty.toIntern() },
1507 } }))) },
1508 else => |e| return e,
1509 })) return AbiSizeAdvanced{ .scalar = 1 };
1510
1511 if (ty.optionalReprIsPayload(mod)) {
1512 return abiSizeAdvanced(child_ty, mod, strat);
1513 }
1514
1515 const payload_size = switch (try child_ty.abiSizeAdvanced(mod, strat)) {
1516 .scalar => |elem_size| elem_size,
1517 .val => switch (strat) {
1518 .sema => unreachable,
1519 .eager => unreachable,
1520 .lazy => return .{ .val = Value.fromInterned((try mod.intern(.{ .int = .{
1521 .ty = .comptime_int_type,
1522 .storage = .{ .lazy_size = ty.toIntern() },
1523 } }))) },
1524 },
1525 };
1526
1527 // Optional types are represented as a struct with the child type as the first
1528 // field and a boolean as the second. Since the child type's abi alignment is
1529 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1530 // to the child type's ABI alignment.
1531 return AbiSizeAdvanced{
1532 .scalar = (child_ty.abiAlignment(mod).toByteUnits() orelse 0) + payload_size,
1533 };
1534 }
1535
1536 pub fn ptrAbiAlignment(target: Target) Alignment {
1537 return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8));
1538 }
1539
1540 pub fn intAbiSize(bits: u16, target: Target, use_llvm: bool) u64 {
1541 return intAbiAlignment(bits, target, use_llvm).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8)));
1542 }
1543
1544 pub fn intAbiAlignment(bits: u16, target: Target, use_llvm: bool) Alignment {
1545 return switch (target.cpu.arch) {
1546 .x86 => switch (bits) {
1547 0 => .none,
1548 1...8 => .@"1",
1549 9...16 => .@"2",
1550 17...64 => .@"4",
1551 else => .@"16",
1552 },
1553 .x86_64 => switch (bits) {
1554 0 => .none,
1555 1...8 => .@"1",
1556 9...16 => .@"2",
1557 17...32 => .@"4",
1558 33...64 => .@"8",
1559 else => switch (target_util.zigBackend(target, use_llvm)) {
1560 .stage2_x86_64 => .@"8",
1561 else => .@"16",
1562 },
1563 },
1564 else => return Alignment.fromByteUnits(@min(
1565 std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))),
1566 maxIntAlignment(target, use_llvm),
1567 )),
1568 };
1569 }
1570
1571 pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
1572 return switch (target.cpu.arch) {
1573 .avr => 1,
1574 .msp430 => 2,
1575 .xcore => 4,
1576
1577 .arm,
1578 .armeb,
1579 .thumb,
1580 .thumbeb,
1581 .hexagon,
1582 .mips,
1583 .mipsel,
1584 .powerpc,
1585 .powerpcle,
1586 .r600,
1587 .amdgcn,
1588 .riscv32,
1589 .sparc,
1590 .sparcel,
1591 .s390x,
1592 .lanai,
1593 .wasm32,
1594 .wasm64,
1595 => 8,
1596
1597 // For these, LLVMABIAlignmentOfType(i128) reports 8. Note that 16
1598 // is a relevant number in three cases:
1599 // 1. Different machine code instruction when loading into SIMD register.
1600 // 2. The C ABI wants 16 for extern structs.
1601 // 3. 16-byte cmpxchg needs 16-byte alignment.
1602 // Same logic for powerpc64, mips64, sparc64.
1603 .powerpc64,
1604 .powerpc64le,
1605 .mips64,
1606 .mips64el,
1607 .sparc64,
1608 => switch (target.ofmt) {
1609 .c => 16,
1610 else => 8,
1611 },
1612
1613 .x86_64 => switch (target_util.zigBackend(target, use_llvm)) {
1614 .stage2_x86_64 => 8,
1615 else => 16,
1616 },
1617
1618 // Even LLVMABIAlignmentOfType(i128) agrees on these targets.
1619 .x86,
1620 .aarch64,
1621 .aarch64_be,
1622 .aarch64_32,
1623 .riscv64,
1624 .bpfel,
1625 .bpfeb,
1626 .nvptx,
1627 .nvptx64,
1628 => 16,
1629
1630 // Below this comment are unverified but based on the fact that C requires
1631 // int128_t to be 16 bytes aligned, it's a safe default.
1632 .spu_2,
1633 .csky,
1634 .arc,
1635 .m68k,
1636 .tce,
1637 .tcele,
1638 .le32,
1639 .amdil,
1640 .hsail,
1641 .spir,
1642 .kalimba,
1643 .renderscript32,
1644 .spirv,
1645 .spirv32,
1646 .shave,
1647 .le64,
1648 .amdil64,
1649 .hsail64,
1650 .spir64,
1651 .renderscript64,
1652 .ve,
1653 .spirv64,
1654 .dxil,
1655 .loongarch32,
1656 .loongarch64,
1657 .xtensa,
1658 => 16,
1659 };
1660 }
1661
1662 pub fn bitSize(ty: Type, mod: *Module) u64 {
1663 return bitSizeAdvanced(ty, mod, null) catch unreachable;
1664 }
1665
1666 /// If you pass `opt_sema`, any recursive type resolutions will happen if
1667 /// necessary, possibly returning a CompileError. Passing `null` instead asserts
1668 /// the type is fully resolved, and there will be no error, guaranteed.
1669 pub fn bitSizeAdvanced(
1670 ty: Type,
1671 mod: *Module,
1672 opt_sema: ?*Sema,
1673 ) Module.CompileError!u64 {
1674 const target = mod.getTarget();
1675 const ip = &mod.intern_pool;
1676
1677 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
1678
1679 switch (ip.indexToKey(ty.toIntern())) {
1680 .int_type => |int_type| return int_type.bits,
1681 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1682 .Slice => return target.ptrBitWidth() * 2,
1683 else => return target.ptrBitWidth(),
1684 },
1685 .anyframe_type => return target.ptrBitWidth(),
1686
1687 .array_type => |array_type| {
1688 const len = array_type.lenIncludingSentinel();
1689 if (len == 0) return 0;
1690 const elem_ty = Type.fromInterned(array_type.child);
1691 const elem_size = @max(
1692 (try elem_ty.abiAlignmentAdvanced(mod, strat)).scalar.toByteUnits() orelse 0,
1693 (try elem_ty.abiSizeAdvanced(mod, strat)).scalar,
1694 );
1695 if (elem_size == 0) return 0;
1696 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
1697 return (len - 1) * 8 * elem_size + elem_bit_size;
1698 },
1699 .vector_type => |vector_type| {
1700 const child_ty = Type.fromInterned(vector_type.child);
1701 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
1702 return elem_bit_size * vector_type.len;
1703 },
1704 .opt_type => {
1705 // Optionals and error unions are not packed so their bitsize
1706 // includes padding bits.
1707 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
1708 },
1709
1710 .error_set_type, .inferred_error_set_type => return mod.errorSetBits(),
1711
1712 .error_union_type => {
1713 // Optionals and error unions are not packed so their bitsize
1714 // includes padding bits.
1715 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
1716 },
1717 .func_type => unreachable, // represents machine code; not a pointer
1718 .simple_type => |t| switch (t) {
1719 .f16 => return 16,
1720 .f32 => return 32,
1721 .f64 => return 64,
1722 .f80 => return 80,
1723 .f128 => return 128,
1724
1725 .usize,
1726 .isize,
1727 => return target.ptrBitWidth(),
1728
1729 .c_char => return target.c_type_bit_size(.char),
1730 .c_short => return target.c_type_bit_size(.short),
1731 .c_ushort => return target.c_type_bit_size(.ushort),
1732 .c_int => return target.c_type_bit_size(.int),
1733 .c_uint => return target.c_type_bit_size(.uint),
1734 .c_long => return target.c_type_bit_size(.long),
1735 .c_ulong => return target.c_type_bit_size(.ulong),
1736 .c_longlong => return target.c_type_bit_size(.longlong),
1737 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
1738 .c_longdouble => return target.c_type_bit_size(.longdouble),
1739
1740 .bool => return 1,
1741 .void => return 0,
1742
1743 .anyerror,
1744 .adhoc_inferred_error_set,
1745 => return mod.errorSetBits(),
1746
1747 .anyopaque => unreachable,
1748 .type => unreachable,
1749 .comptime_int => unreachable,
1750 .comptime_float => unreachable,
1751 .noreturn => unreachable,
1752 .null => unreachable,
1753 .undefined => unreachable,
1754 .enum_literal => unreachable,
1755 .generic_poison => unreachable,
1756
1757 .atomic_order => unreachable,
1758 .atomic_rmw_op => unreachable,
1759 .calling_convention => unreachable,
1760 .address_space => unreachable,
1761 .float_mode => unreachable,
1762 .reduce_op => unreachable,
1763 .call_modifier => unreachable,
1764 .prefetch_options => unreachable,
1765 .export_options => unreachable,
1766 .extern_options => unreachable,
1767 .type_info => unreachable,
1768 },
1769 .struct_type => {
1770 const struct_type = ip.loadStructType(ty.toIntern());
1771 const is_packed = struct_type.layout == .@"packed";
1772 if (opt_sema) |sema| {
1773 try sema.resolveTypeFields(ty);
1774 if (is_packed) try sema.resolveTypeLayout(ty);
1775 }
1776 if (is_packed) {
1777 return try Type.fromInterned(struct_type.backingIntType(ip).*).bitSizeAdvanced(mod, opt_sema);
1778 }
1779 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
1780 },
1781
1782 .anon_struct_type => {
1783 if (opt_sema) |sema| try sema.resolveTypeFields(ty);
1784 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
1785 },
1786
1787 .union_type => {
1788 const union_type = ip.loadUnionType(ty.toIntern());
1789 const is_packed = ty.containerLayout(mod) == .@"packed";
1790 if (opt_sema) |sema| {
1791 try sema.resolveTypeFields(ty);
1792 if (is_packed) try sema.resolveTypeLayout(ty);
1793 }
1794 if (!is_packed) {
1795 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
1796 }
1797 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
1798
1799 var size: u64 = 0;
1800 for (0..union_type.field_types.len) |field_index| {
1801 const field_ty = union_type.field_types.get(ip)[field_index];
1802 size = @max(size, try bitSizeAdvanced(Type.fromInterned(field_ty), mod, opt_sema));
1803 }
1804
1805 return size;
1806 },
1807 .opaque_type => unreachable,
1808 .enum_type => return bitSizeAdvanced(Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty), mod, opt_sema),
1809
1810 // values, not types
1811 .undef,
1812 .simple_value,
1813 .variable,
1814 .extern_func,
1815 .func,
1816 .int,
1817 .err,
1818 .error_union,
1819 .enum_literal,
1820 .enum_tag,
1821 .empty_enum_value,
1822 .float,
1823 .ptr,
1824 .slice,
1825 .opt,
1826 .aggregate,
1827 .un,
1828 // memoization, not types
1829 .memoized_call,
1830 => unreachable,
1831 }
1832 }
1833
1834 /// Returns true if the type's layout is already resolved and it is safe
1835 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
1836 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
1837 const ip = &mod.intern_pool;
1838 return switch (ip.indexToKey(ty.toIntern())) {
1839 .struct_type => ip.loadStructType(ty.toIntern()).haveLayout(ip),
1840 .union_type => ip.loadUnionType(ty.toIntern()).haveLayout(ip),
1841 .array_type => |array_type| {
1842 if (array_type.lenIncludingSentinel() == 0) return true;
1843 return Type.fromInterned(array_type.child).layoutIsResolved(mod);
1844 },
1845 .opt_type => |child| Type.fromInterned(child).layoutIsResolved(mod),
1846 .error_union_type => |k| Type.fromInterned(k.payload_type).layoutIsResolved(mod),
1847 else => true,
1848 };
1849 }
1850
1851 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1852 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1853 .ptr_type => |ptr_info| ptr_info.flags.size == .One,
1854 else => false,
1855 };
1856 }
1857
1858 /// Asserts `ty` is a pointer.
1859 pub fn ptrSize(ty: Type, mod: *const Module) std.builtin.Type.Pointer.Size {
1860 return ptrSizeOrNull(ty, mod).?;
1861 }
1862
1863 /// Returns `null` if `ty` is not a pointer.
1864 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1865 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1866 .ptr_type => |ptr_info| ptr_info.flags.size,
1867 else => null,
1868 };
1869 }
1870
1871 pub fn isSlice(ty: Type, mod: *const Module) bool {
1872 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1873 .ptr_type => |ptr_type| ptr_type.flags.size == .Slice,
1874 else => false,
1875 };
1876 }
1877
1878 pub fn slicePtrFieldType(ty: Type, mod: *const Module) Type {
1879 return Type.fromInterned(mod.intern_pool.slicePtrType(ty.toIntern()));
1880 }
1881
1882 pub fn isConstPtr(ty: Type, mod: *const Module) bool {
1883 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1884 .ptr_type => |ptr_type| ptr_type.flags.is_const,
1885 else => false,
1886 };
1887 }
1888
1889 pub fn isVolatilePtr(ty: Type, mod: *const Module) bool {
1890 return isVolatilePtrIp(ty, &mod.intern_pool);
1891 }
1892
1893 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
1894 return switch (ip.indexToKey(ty.toIntern())) {
1895 .ptr_type => |ptr_type| ptr_type.flags.is_volatile,
1896 else => false,
1897 };
1898 }
1899
1900 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
1901 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1902 .ptr_type => |ptr_type| ptr_type.flags.is_allowzero,
1903 .opt_type => true,
1904 else => false,
1905 };
1906 }
1907
1908 pub fn isCPtr(ty: Type, mod: *const Module) bool {
1909 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1910 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1911 else => false,
1912 };
1913 }
1914
1915 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
1916 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1917 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1918 .Slice => false,
1919 .One, .Many, .C => true,
1920 },
1921 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1922 .ptr_type => |p| switch (p.flags.size) {
1923 .Slice, .C => false,
1924 .Many, .One => !p.flags.is_allowzero,
1925 },
1926 else => false,
1927 },
1928 else => false,
1929 };
1930 }
1931
1932 /// For pointer-like optionals, returns true, otherwise returns the allowzero property
1933 /// of pointers.
1934 pub fn ptrAllowsZero(ty: Type, mod: *const Module) bool {
1935 if (ty.isPtrLikeOptional(mod)) {
1936 return true;
1937 }
1938 return ty.ptrInfo(mod).flags.is_allowzero;
1939 }
1940
1941 /// See also `isPtrLikeOptional`.
1942 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
1943 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1944 .opt_type => |child_type| child_type == .anyerror_type or switch (mod.intern_pool.indexToKey(child_type)) {
1945 .ptr_type => |ptr_type| ptr_type.flags.size != .C and !ptr_type.flags.is_allowzero,
1946 .error_set_type, .inferred_error_set_type => true,
1947 else => false,
1948 },
1949 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1950 else => false,
1951 };
1952 }
1953
1954 /// Returns true if the type is optional and would be lowered to a single pointer
1955 /// address value, using 0 for null. Note that this returns true for C pointers.
1956 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
1957 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
1958 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1959 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1960 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1961 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1962 .Slice, .C => false,
1963 .Many, .One => !ptr_type.flags.is_allowzero,
1964 },
1965 else => false,
1966 },
1967 else => false,
1968 };
1969 }
1970
1971 /// For *[N]T, returns [N]T.
1972 /// For *T, returns T.
1973 /// For [*]T, returns T.
1974 pub fn childType(ty: Type, mod: *const Module) Type {
1975 return childTypeIp(ty, &mod.intern_pool);
1976 }
1977
1978 pub fn childTypeIp(ty: Type, ip: *const InternPool) Type {
1979 return Type.fromInterned(ip.childType(ty.toIntern()));
1980 }
1981
1982 /// For *[N]T, returns T.
1983 /// For ?*T, returns T.
1984 /// For ?*[N]T, returns T.
1985 /// For ?[*]T, returns T.
1986 /// For *T, returns T.
1987 /// For [*]T, returns T.
1988 /// For [N]T, returns T.
1989 /// For []T, returns T.
1990 /// For anyframe->T, returns T.
1991 pub fn elemType2(ty: Type, mod: *const Module) Type {
1992 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1993 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1994 .One => Type.fromInterned(ptr_type.child).shallowElemType(mod),
1995 .Many, .C, .Slice => Type.fromInterned(ptr_type.child),
1996 },
1997 .anyframe_type => |child| {
1998 assert(child != .none);
1999 return Type.fromInterned(child);
2000 },
2001 .vector_type => |vector_type| Type.fromInterned(vector_type.child),
2002 .array_type => |array_type| Type.fromInterned(array_type.child),
2003 .opt_type => |child| Type.fromInterned(mod.intern_pool.childType(child)),
2004 else => unreachable,
2005 };
2006 }
2007
2008 fn shallowElemType(child_ty: Type, mod: *const Module) Type {
2009 return switch (child_ty.zigTypeTag(mod)) {
2010 .Array, .Vector => child_ty.childType(mod),
2011 else => child_ty,
2012 };
2013 }
2014
2015 /// For vectors, returns the element type. Otherwise returns self.
2016 pub fn scalarType(ty: Type, mod: *Module) Type {
2017 return switch (ty.zigTypeTag(mod)) {
2018 .Vector => ty.childType(mod),
2019 else => ty,
2020 };
2021 }
2022
2023 /// Asserts that the type is an optional.
2024 /// Note that for C pointers this returns the type unmodified.
2025 pub fn optionalChild(ty: Type, mod: *const Module) Type {
2026 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2027 .opt_type => |child| Type.fromInterned(child),
2028 .ptr_type => |ptr_type| b: {
2029 assert(ptr_type.flags.size == .C);
2030 break :b ty;
2031 },
2032 else => unreachable,
2033 };
2034 }
2035
2036 /// Returns the tag type of a union, if the type is a union and it has a tag type.
2037 /// Otherwise, returns `null`.
2038 pub fn unionTagType(ty: Type, mod: *Module) ?Type {
2039 const ip = &mod.intern_pool;
2040 switch (ip.indexToKey(ty.toIntern())) {
2041 .union_type => {},
2042 else => return null,
2043 }
2044 const union_type = ip.loadUnionType(ty.toIntern());
2045 switch (union_type.flagsPtr(ip).runtime_tag) {
2046 .tagged => {
2047 assert(union_type.flagsPtr(ip).status.haveFieldTypes());
2048 return Type.fromInterned(union_type.enum_tag_ty);
2049 },
2050 else => return null,
2051 }
2052 }
2053
2054 /// Same as `unionTagType` but includes safety tag.
2055 /// Codegen should use this version.
2056 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
2057 const ip = &mod.intern_pool;
2058 return switch (ip.indexToKey(ty.toIntern())) {
2059 .union_type => {
2060 const union_type = ip.loadUnionType(ty.toIntern());
2061 if (!union_type.hasTag(ip)) return null;
2062 assert(union_type.haveFieldTypes(ip));
2063 return Type.fromInterned(union_type.enum_tag_ty);
2064 },
2065 else => null,
2066 };
2067 }
2068
2069 /// Asserts the type is a union; returns the tag type, even if the tag will
2070 /// not be stored at runtime.
2071 pub fn unionTagTypeHypothetical(ty: Type, mod: *Module) Type {
2072 const union_obj = mod.typeToUnion(ty).?;
2073 return Type.fromInterned(union_obj.enum_tag_ty);
2074 }
2075
2076 pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) ?Type {
2077 const ip = &mod.intern_pool;
2078 const union_obj = mod.typeToUnion(ty).?;
2079 const union_fields = union_obj.field_types.get(ip);
2080 const index = mod.unionTagFieldIndex(union_obj, enum_tag) orelse return null;
2081 return Type.fromInterned(union_fields[index]);
2082 }
2083
2084 pub fn unionFieldTypeByIndex(ty: Type, index: usize, mod: *Module) Type {
2085 const ip = &mod.intern_pool;
2086 const union_obj = mod.typeToUnion(ty).?;
2087 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
2088 }
2089
2090 pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
2091 const union_obj = mod.typeToUnion(ty).?;
2092 return mod.unionTagFieldIndex(union_obj, enum_tag);
2093 }
2094
2095 pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool {
2096 const ip = &mod.intern_pool;
2097 const union_obj = mod.typeToUnion(ty).?;
2098 for (union_obj.field_types.get(ip)) |field_ty| {
2099 if (Type.fromInterned(field_ty).hasRuntimeBits(mod)) return false;
2100 }
2101 return true;
2102 }
2103
2104 /// Returns the type used for backing storage of this union during comptime operations.
2105 /// Asserts the type is either an extern or packed union.
2106 pub fn unionBackingType(ty: Type, mod: *Module) !Type {
2107 return switch (ty.containerLayout(mod)) {
2108 .@"extern" => try mod.arrayType(.{ .len = ty.abiSize(mod), .child = .u8_type }),
2109 .@"packed" => try mod.intType(.unsigned, @intCast(ty.bitSize(mod))),
2110 .auto => unreachable,
2111 };
2112 }
2113
2114 pub fn unionGetLayout(ty: Type, mod: *Module) Module.UnionLayout {
2115 const ip = &mod.intern_pool;
2116 const union_obj = ip.loadUnionType(ty.toIntern());
2117 return mod.getUnionLayout(union_obj);
2118 }
2119
2120 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
2121 const ip = &mod.intern_pool;
2122 return switch (ip.indexToKey(ty.toIntern())) {
2123 .struct_type => ip.loadStructType(ty.toIntern()).layout,
2124 .anon_struct_type => .auto,
2125 .union_type => ip.loadUnionType(ty.toIntern()).flagsPtr(ip).layout,
2126 else => unreachable,
2127 };
2128 }
2129
2130 /// Asserts that the type is an error union.
2131 pub fn errorUnionPayload(ty: Type, mod: *Module) Type {
2132 return Type.fromInterned(mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.payload_type);
2133 }
2134
2135 /// Asserts that the type is an error union.
2136 pub fn errorUnionSet(ty: Type, mod: *Module) Type {
2137 return Type.fromInterned(mod.intern_pool.errorUnionSet(ty.toIntern()));
2138 }
2139
2140 /// Returns false for unresolved inferred error sets.
2141 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
2142 const ip = &mod.intern_pool;
2143 return switch (ty.toIntern()) {
2144 .anyerror_type, .adhoc_inferred_error_set_type => false,
2145 else => switch (ip.indexToKey(ty.toIntern())) {
2146 .error_set_type => |error_set_type| error_set_type.names.len == 0,
2147 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2148 .none, .anyerror_type => false,
2149 else => |t| ip.indexToKey(t).error_set_type.names.len == 0,
2150 },
2151 else => unreachable,
2152 },
2153 };
2154 }
2155
2156 /// Returns true if it is an error set that includes anyerror, false otherwise.
2157 /// Note that the result may be a false negative if the type did not get error set
2158 /// resolution prior to this call.
2159 pub fn isAnyError(ty: Type, mod: *Module) bool {
2160 const ip = &mod.intern_pool;
2161 return switch (ty.toIntern()) {
2162 .anyerror_type => true,
2163 .adhoc_inferred_error_set_type => false,
2164 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2165 .inferred_error_set_type => |i| ip.funcIesResolved(i).* == .anyerror_type,
2166 else => false,
2167 },
2168 };
2169 }
2170
2171 pub fn isError(ty: Type, mod: *const Module) bool {
2172 return switch (ty.zigTypeTag(mod)) {
2173 .ErrorUnion, .ErrorSet => true,
2174 else => false,
2175 };
2176 }
2177
2178 /// Returns whether ty, which must be an error set, includes an error `name`.
2179 /// Might return a false negative if `ty` is an inferred error set and not fully
2180 /// resolved yet.
2181 pub fn errorSetHasFieldIp(
2182 ip: *const InternPool,
2183 ty: InternPool.Index,
2184 name: InternPool.NullTerminatedString,
2185 ) bool {
2186 return switch (ty) {
2187 .anyerror_type => true,
2188 else => switch (ip.indexToKey(ty)) {
2189 .error_set_type => |error_set_type| error_set_type.nameIndex(ip, name) != null,
2190 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2191 .anyerror_type => true,
2192 .none => false,
2193 else => |t| ip.indexToKey(t).error_set_type.nameIndex(ip, name) != null,
2194 },
2195 else => unreachable,
2196 },
2197 };
2198 }
2199
2200 /// Returns whether ty, which must be an error set, includes an error `name`.
2201 /// Might return a false negative if `ty` is an inferred error set and not fully
2202 /// resolved yet.
2203 pub fn errorSetHasField(ty: Type, name: []const u8, mod: *Module) bool {
2204 const ip = &mod.intern_pool;
2205 return switch (ty.toIntern()) {
2206 .anyerror_type => true,
2207 else => switch (ip.indexToKey(ty.toIntern())) {
2208 .error_set_type => |error_set_type| {
2209 // If the string is not interned, then the field certainly is not present.
2210 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2211 return error_set_type.nameIndex(ip, field_name_interned) != null;
2212 },
2213 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
2214 .anyerror_type => true,
2215 .none => false,
2216 else => |t| {
2217 // If the string is not interned, then the field certainly is not present.
2218 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2219 return ip.indexToKey(t).error_set_type.nameIndex(ip, field_name_interned) != null;
2220 },
2221 },
2222 else => unreachable,
2223 },
2224 };
2225 }
2226
2227 /// Asserts the type is an array or vector or struct.
2228 pub fn arrayLen(ty: Type, mod: *const Module) u64 {
2229 return ty.arrayLenIp(&mod.intern_pool);
2230 }
2231
2232 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
2233 return ip.aggregateTypeLen(ty.toIntern());
2234 }
2235
2236 pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
2237 return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern());
2238 }
2239
2240 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
2241 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2242 .vector_type => |vector_type| vector_type.len,
2243 .anon_struct_type => |tuple| @intCast(tuple.types.len),
2244 else => unreachable,
2245 };
2246 }
2247
2248 /// Asserts the type is an array, pointer or vector.
2249 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
2250 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2251 .vector_type,
2252 .struct_type,
2253 .anon_struct_type,
2254 => null,
2255
2256 .array_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,
2257 .ptr_type => |t| if (t.sentinel != .none) Value.fromInterned(t.sentinel) else null,
2258
2259 else => unreachable,
2260 };
2261 }
2262
2263 /// Returns true if and only if the type is a fixed-width integer.
2264 pub fn isInt(self: Type, mod: *const Module) bool {
2265 return self.toIntern() != .comptime_int_type and
2266 mod.intern_pool.isIntegerType(self.toIntern());
2267 }
2268
2269 /// Returns true if and only if the type is a fixed-width, signed integer.
2270 pub fn isSignedInt(ty: Type, mod: *const Module) bool {
2271 return switch (ty.toIntern()) {
2272 .c_char_type => mod.getTarget().charSignedness() == .signed,
2273 .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
2274 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2275 .int_type => |int_type| int_type.signedness == .signed,
2276 else => false,
2277 },
2278 };
2279 }
2280
2281 /// Returns true if and only if the type is a fixed-width, unsigned integer.
2282 pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
2283 return switch (ty.toIntern()) {
2284 .c_char_type => mod.getTarget().charSignedness() == .unsigned,
2285 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
2286 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2287 .int_type => |int_type| int_type.signedness == .unsigned,
2288 else => false,
2289 },
2290 };
2291 }
2292
2293 /// Returns true for integers, enums, error sets, and packed structs.
2294 /// If this function returns true, then intInfo() can be called on the type.
2295 pub fn isAbiInt(ty: Type, mod: *Module) bool {
2296 return switch (ty.zigTypeTag(mod)) {
2297 .Int, .Enum, .ErrorSet => true,
2298 .Struct => ty.containerLayout(mod) == .@"packed",
2299 else => false,
2300 };
2301 }
2302
2303 /// Asserts the type is an integer, enum, error set, or vector of one of them.
2304 pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType {
2305 const ip = &mod.intern_pool;
2306 const target = mod.getTarget();
2307 var ty = starting_ty;
2308
2309 while (true) switch (ty.toIntern()) {
2310 .anyerror_type, .adhoc_inferred_error_set_type => {
2311 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2312 },
2313 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
2314 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
2315 .c_char_type => return .{ .signedness = mod.getTarget().charSignedness(), .bits = target.c_type_bit_size(.char) },
2316 .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
2317 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
2318 .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
2319 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
2320 .c_long_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
2321 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
2322 .c_longlong_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
2323 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
2324 else => switch (ip.indexToKey(ty.toIntern())) {
2325 .int_type => |int_type| return int_type,
2326 .struct_type => ty = Type.fromInterned(ip.loadStructType(ty.toIntern()).backingIntType(ip).*),
2327 .enum_type => ty = Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
2328 .vector_type => |vector_type| ty = Type.fromInterned(vector_type.child),
2329
2330 .error_set_type, .inferred_error_set_type => {
2331 return .{ .signedness = .unsigned, .bits = mod.errorSetBits() };
2332 },
2333
2334 .anon_struct_type => unreachable,
2335
2336 .ptr_type => unreachable,
2337 .anyframe_type => unreachable,
2338 .array_type => unreachable,
2339
2340 .opt_type => unreachable,
2341 .error_union_type => unreachable,
2342 .func_type => unreachable,
2343 .simple_type => unreachable, // handled via Index enum tag above
2344
2345 .union_type => unreachable,
2346 .opaque_type => unreachable,
2347
2348 // values, not types
2349 .undef,
2350 .simple_value,
2351 .variable,
2352 .extern_func,
2353 .func,
2354 .int,
2355 .err,
2356 .error_union,
2357 .enum_literal,
2358 .enum_tag,
2359 .empty_enum_value,
2360 .float,
2361 .ptr,
2362 .slice,
2363 .opt,
2364 .aggregate,
2365 .un,
2366 // memoization, not types
2367 .memoized_call,
2368 => unreachable,
2369 },
2370 };
2371 }
2372
2373 pub fn isNamedInt(ty: Type) bool {
2374 return switch (ty.toIntern()) {
2375 .usize_type,
2376 .isize_type,
2377 .c_char_type,
2378 .c_short_type,
2379 .c_ushort_type,
2380 .c_int_type,
2381 .c_uint_type,
2382 .c_long_type,
2383 .c_ulong_type,
2384 .c_longlong_type,
2385 .c_ulonglong_type,
2386 => true,
2387
2388 else => false,
2389 };
2390 }
2391
2392 /// Returns `false` for `comptime_float`.
2393 pub fn isRuntimeFloat(ty: Type) bool {
2394 return switch (ty.toIntern()) {
2395 .f16_type,
2396 .f32_type,
2397 .f64_type,
2398 .f80_type,
2399 .f128_type,
2400 .c_longdouble_type,
2401 => true,
2402
2403 else => false,
2404 };
2405 }
2406
2407 /// Returns `true` for `comptime_float`.
2408 pub fn isAnyFloat(ty: Type) bool {
2409 return switch (ty.toIntern()) {
2410 .f16_type,
2411 .f32_type,
2412 .f64_type,
2413 .f80_type,
2414 .f128_type,
2415 .c_longdouble_type,
2416 .comptime_float_type,
2417 => true,
2418
2419 else => false,
2420 };
2421 }
2422
2423 /// Asserts the type is a fixed-size float or comptime_float.
2424 /// Returns 128 for comptime_float types.
2425 pub fn floatBits(ty: Type, target: Target) u16 {
2426 return switch (ty.toIntern()) {
2427 .f16_type => 16,
2428 .f32_type => 32,
2429 .f64_type => 64,
2430 .f80_type => 80,
2431 .f128_type, .comptime_float_type => 128,
2432 .c_longdouble_type => target.c_type_bit_size(.longdouble),
2433
2434 else => unreachable,
2435 };
2436 }
2437
2438 /// Asserts the type is a function or a function pointer.
2439 pub fn fnReturnType(ty: Type, mod: *Module) Type {
2440 return Type.fromInterned(mod.intern_pool.funcTypeReturnType(ty.toIntern()));
2441 }
2442
2443 /// Asserts the type is a function.
2444 pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
2445 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.cc;
2446 }
2447
2448 pub fn isValidParamType(self: Type, mod: *const Module) bool {
2449 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
2450 .Opaque, .NoReturn => false,
2451 else => true,
2452 };
2453 }
2454
2455 pub fn isValidReturnType(self: Type, mod: *const Module) bool {
2456 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
2457 .Opaque => false,
2458 else => true,
2459 };
2460 }
2461
2462 /// Asserts the type is a function.
2463 pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
2464 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.is_var_args;
2465 }
2466
2467 pub fn isNumeric(ty: Type, mod: *const Module) bool {
2468 return switch (ty.toIntern()) {
2469 .f16_type,
2470 .f32_type,
2471 .f64_type,
2472 .f80_type,
2473 .f128_type,
2474 .c_longdouble_type,
2475 .comptime_int_type,
2476 .comptime_float_type,
2477 .usize_type,
2478 .isize_type,
2479 .c_char_type,
2480 .c_short_type,
2481 .c_ushort_type,
2482 .c_int_type,
2483 .c_uint_type,
2484 .c_long_type,
2485 .c_ulong_type,
2486 .c_longlong_type,
2487 .c_ulonglong_type,
2488 => true,
2489
2490 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2491 .int_type => true,
2492 else => false,
2493 },
2494 };
2495 }
2496
2497 /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
2498 /// resolves field types rather than asserting they are already resolved.
2499 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
2500 var ty = starting_type;
2501 const ip = &mod.intern_pool;
2502 while (true) switch (ty.toIntern()) {
2503 .empty_struct_type => return Value.empty_struct,
2504
2505 else => switch (ip.indexToKey(ty.toIntern())) {
2506 .int_type => |int_type| {
2507 if (int_type.bits == 0) {
2508 return try mod.intValue(ty, 0);
2509 } else {
2510 return null;
2511 }
2512 },
2513
2514 .ptr_type,
2515 .error_union_type,
2516 .func_type,
2517 .anyframe_type,
2518 .error_set_type,
2519 .inferred_error_set_type,
2520 => return null,
2521
2522 inline .array_type, .vector_type => |seq_type, seq_tag| {
2523 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
2524 if (seq_type.len + @intFromBool(has_sentinel) == 0) return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2525 .ty = ty.toIntern(),
2526 .storage = .{ .elems = &.{} },
2527 } })));
2528 if (try Type.fromInterned(seq_type.child).onePossibleValue(mod)) |opv| {
2529 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2530 .ty = ty.toIntern(),
2531 .storage = .{ .repeated_elem = opv.toIntern() },
2532 } })));
2533 }
2534 return null;
2535 },
2536 .opt_type => |child| {
2537 if (child == .noreturn_type) {
2538 return try mod.nullValue(ty);
2539 } else {
2540 return null;
2541 }
2542 },
2543
2544 .simple_type => |t| switch (t) {
2545 .f16,
2546 .f32,
2547 .f64,
2548 .f80,
2549 .f128,
2550 .usize,
2551 .isize,
2552 .c_char,
2553 .c_short,
2554 .c_ushort,
2555 .c_int,
2556 .c_uint,
2557 .c_long,
2558 .c_ulong,
2559 .c_longlong,
2560 .c_ulonglong,
2561 .c_longdouble,
2562 .anyopaque,
2563 .bool,
2564 .type,
2565 .anyerror,
2566 .comptime_int,
2567 .comptime_float,
2568 .enum_literal,
2569 .atomic_order,
2570 .atomic_rmw_op,
2571 .calling_convention,
2572 .address_space,
2573 .float_mode,
2574 .reduce_op,
2575 .call_modifier,
2576 .prefetch_options,
2577 .export_options,
2578 .extern_options,
2579 .type_info,
2580 .adhoc_inferred_error_set,
2581 => return null,
2582
2583 .void => return Value.void,
2584 .noreturn => return Value.@"unreachable",
2585 .null => return Value.null,
2586 .undefined => return Value.undef,
2587
2588 .generic_poison => unreachable,
2589 },
2590 .struct_type => {
2591 const struct_type = ip.loadStructType(ty.toIntern());
2592 assert(struct_type.haveFieldTypes(ip));
2593 if (struct_type.knownNonOpv(ip))
2594 return null;
2595 const field_vals = try mod.gpa.alloc(InternPool.Index, struct_type.field_types.len);
2596 defer mod.gpa.free(field_vals);
2597 for (field_vals, 0..) |*field_val, i_usize| {
2598 const i: u32 = @intCast(i_usize);
2599 if (struct_type.fieldIsComptime(ip, i)) {
2600 assert(struct_type.haveFieldInits(ip));
2601 field_val.* = struct_type.field_inits.get(ip)[i];
2602 continue;
2603 }
2604 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]);
2605 if (try field_ty.onePossibleValue(mod)) |field_opv| {
2606 field_val.* = field_opv.toIntern();
2607 } else return null;
2608 }
2609
2610 // In this case the struct has no runtime-known fields and
2611 // therefore has one possible value.
2612 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2613 .ty = ty.toIntern(),
2614 .storage = .{ .elems = field_vals },
2615 } })));
2616 },
2617
2618 .anon_struct_type => |tuple| {
2619 for (tuple.values.get(ip)) |val| {
2620 if (val == .none) return null;
2621 }
2622 // In this case the struct has all comptime-known fields and
2623 // therefore has one possible value.
2624 // TODO: write something like getCoercedInts to avoid needing to dupe
2625 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values.get(ip));
2626 defer mod.gpa.free(duped_values);
2627 return Value.fromInterned((try mod.intern(.{ .aggregate = .{
2628 .ty = ty.toIntern(),
2629 .storage = .{ .elems = duped_values },
2630 } })));
2631 },
2632
2633 .union_type => {
2634 const union_obj = ip.loadUnionType(ty.toIntern());
2635 const tag_val = (try Type.fromInterned(union_obj.enum_tag_ty).onePossibleValue(mod)) orelse
2636 return null;
2637 if (union_obj.field_types.len == 0) {
2638 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2639 return Value.fromInterned(only);
2640 }
2641 const only_field_ty = union_obj.field_types.get(ip)[0];
2642 const val_val = (try Type.fromInterned(only_field_ty).onePossibleValue(mod)) orelse
2643 return null;
2644 const only = try mod.intern(.{ .un = .{
2645 .ty = ty.toIntern(),
2646 .tag = tag_val.toIntern(),
2647 .val = val_val.toIntern(),
2648 } });
2649 return Value.fromInterned(only);
2650 },
2651 .opaque_type => return null,
2652 .enum_type => {
2653 const enum_type = ip.loadEnumType(ty.toIntern());
2654 switch (enum_type.tag_mode) {
2655 .nonexhaustive => {
2656 if (enum_type.tag_ty == .comptime_int_type) return null;
2657
2658 if (try Type.fromInterned(enum_type.tag_ty).onePossibleValue(mod)) |int_opv| {
2659 const only = try mod.intern(.{ .enum_tag = .{
2660 .ty = ty.toIntern(),
2661 .int = int_opv.toIntern(),
2662 } });
2663 return Value.fromInterned(only);
2664 }
2665
2666 return null;
2667 },
2668 .auto, .explicit => {
2669 if (Type.fromInterned(enum_type.tag_ty).hasRuntimeBits(mod)) return null;
2670
2671 switch (enum_type.names.len) {
2672 0 => {
2673 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2674 return Value.fromInterned(only);
2675 },
2676 1 => {
2677 if (enum_type.values.len == 0) {
2678 const only = try mod.intern(.{ .enum_tag = .{
2679 .ty = ty.toIntern(),
2680 .int = try mod.intern(.{ .int = .{
2681 .ty = enum_type.tag_ty,
2682 .storage = .{ .u64 = 0 },
2683 } }),
2684 } });
2685 return Value.fromInterned(only);
2686 } else {
2687 return Value.fromInterned(enum_type.values.get(ip)[0]);
2688 }
2689 },
2690 else => return null,
2691 }
2692 },
2693 }
2694 },
2695
2696 // values, not types
2697 .undef,
2698 .simple_value,
2699 .variable,
2700 .extern_func,
2701 .func,
2702 .int,
2703 .err,
2704 .error_union,
2705 .enum_literal,
2706 .enum_tag,
2707 .empty_enum_value,
2708 .float,
2709 .ptr,
2710 .slice,
2711 .opt,
2712 .aggregate,
2713 .un,
2714 // memoization, not types
2715 .memoized_call,
2716 => unreachable,
2717 },
2718 };
2719 }
2720
2721 /// During semantic analysis, instead call `Sema.typeRequiresComptime` which
2722 /// resolves field types rather than asserting they are already resolved.
2723 pub fn comptimeOnly(ty: Type, mod: *Module) bool {
2724 return ty.comptimeOnlyAdvanced(mod, null) catch unreachable;
2725 }
2726
2727 /// `generic_poison` will return false.
2728 /// May return false negatives when structs and unions are having their field types resolved.
2729 /// If `opt_sema` is not provided, asserts that the type is sufficiently resolved.
2730 pub fn comptimeOnlyAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) Module.CompileError!bool {
2731 const ip = &mod.intern_pool;
2732 return switch (ty.toIntern()) {
2733 .empty_struct_type => false,
2734
2735 else => switch (ip.indexToKey(ty.toIntern())) {
2736 .int_type => false,
2737 .ptr_type => |ptr_type| {
2738 const child_ty = Type.fromInterned(ptr_type.child);
2739 switch (child_ty.zigTypeTag(mod)) {
2740 .Fn => return !try child_ty.fnHasRuntimeBitsAdvanced(mod, opt_sema),
2741 .Opaque => return false,
2742 else => return child_ty.comptimeOnlyAdvanced(mod, opt_sema),
2743 }
2744 },
2745 .anyframe_type => |child| {
2746 if (child == .none) return false;
2747 return Type.fromInterned(child).comptimeOnlyAdvanced(mod, opt_sema);
2748 },
2749 .array_type => |array_type| return Type.fromInterned(array_type.child).comptimeOnlyAdvanced(mod, opt_sema),
2750 .vector_type => |vector_type| return Type.fromInterned(vector_type.child).comptimeOnlyAdvanced(mod, opt_sema),
2751 .opt_type => |child| return Type.fromInterned(child).comptimeOnlyAdvanced(mod, opt_sema),
2752 .error_union_type => |error_union_type| return Type.fromInterned(error_union_type.payload_type).comptimeOnlyAdvanced(mod, opt_sema),
2753
2754 .error_set_type,
2755 .inferred_error_set_type,
2756 => false,
2757
2758 // These are function bodies, not function pointers.
2759 .func_type => true,
2760
2761 .simple_type => |t| switch (t) {
2762 .f16,
2763 .f32,
2764 .f64,
2765 .f80,
2766 .f128,
2767 .usize,
2768 .isize,
2769 .c_char,
2770 .c_short,
2771 .c_ushort,
2772 .c_int,
2773 .c_uint,
2774 .c_long,
2775 .c_ulong,
2776 .c_longlong,
2777 .c_ulonglong,
2778 .c_longdouble,
2779 .anyopaque,
2780 .bool,
2781 .void,
2782 .anyerror,
2783 .adhoc_inferred_error_set,
2784 .noreturn,
2785 .generic_poison,
2786 .atomic_order,
2787 .atomic_rmw_op,
2788 .calling_convention,
2789 .address_space,
2790 .float_mode,
2791 .reduce_op,
2792 .call_modifier,
2793 .prefetch_options,
2794 .export_options,
2795 .extern_options,
2796 => false,
2797
2798 .type,
2799 .comptime_int,
2800 .comptime_float,
2801 .null,
2802 .undefined,
2803 .enum_literal,
2804 .type_info,
2805 => true,
2806 },
2807 .struct_type => {
2808 const struct_type = ip.loadStructType(ty.toIntern());
2809 // packed structs cannot be comptime-only because they have a well-defined
2810 // memory layout and every field has a well-defined bit pattern.
2811 if (struct_type.layout == .@"packed")
2812 return false;
2813
2814 // A struct with no fields is not comptime-only.
2815 return switch (struct_type.flagsPtr(ip).requires_comptime) {
2816 .no, .wip => false,
2817 .yes => true,
2818 .unknown => {
2819 // The type is not resolved; assert that we have a Sema.
2820 const sema = opt_sema.?;
2821
2822 if (struct_type.flagsPtr(ip).field_types_wip)
2823 return false;
2824
2825 struct_type.flagsPtr(ip).requires_comptime = .wip;
2826 errdefer struct_type.flagsPtr(ip).requires_comptime = .unknown;
2827
2828 try sema.resolveTypeFieldsStruct(ty.toIntern(), struct_type);
2829
2830 for (0..struct_type.field_types.len) |i_usize| {
2831 const i: u32 = @intCast(i_usize);
2832 if (struct_type.fieldIsComptime(ip, i)) continue;
2833 const field_ty = struct_type.field_types.get(ip)[i];
2834 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
2835 // Note that this does not cause the layout to
2836 // be considered resolved. Comptime-only types
2837 // still maintain a layout of their
2838 // runtime-known fields.
2839 struct_type.flagsPtr(ip).requires_comptime = .yes;
2840 return true;
2841 }
2842 }
2843
2844 struct_type.flagsPtr(ip).requires_comptime = .no;
2845 return false;
2846 },
2847 };
2848 },
2849
2850 .anon_struct_type => |tuple| {
2851 for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, val| {
2852 const have_comptime_val = val != .none;
2853 if (!have_comptime_val and try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) return true;
2854 }
2855 return false;
2856 },
2857
2858 .union_type => {
2859 const union_type = ip.loadUnionType(ty.toIntern());
2860 switch (union_type.flagsPtr(ip).requires_comptime) {
2861 .no, .wip => return false,
2862 .yes => return true,
2863 .unknown => {
2864 // The type is not resolved; assert that we have a Sema.
2865 const sema = opt_sema.?;
2866
2867 if (union_type.flagsPtr(ip).status == .field_types_wip)
2868 return false;
2869
2870 union_type.flagsPtr(ip).requires_comptime = .wip;
2871 errdefer union_type.flagsPtr(ip).requires_comptime = .unknown;
2872
2873 try sema.resolveTypeFieldsUnion(ty, union_type);
2874
2875 for (0..union_type.field_types.len) |field_idx| {
2876 const field_ty = union_type.field_types.get(ip)[field_idx];
2877 if (try Type.fromInterned(field_ty).comptimeOnlyAdvanced(mod, opt_sema)) {
2878 union_type.flagsPtr(ip).requires_comptime = .yes;
2879 return true;
2880 }
2881 }
2882
2883 union_type.flagsPtr(ip).requires_comptime = .no;
2884 return false;
2885 },
2886 }
2887 },
2888
2889 .opaque_type => false,
2890
2891 .enum_type => return Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty).comptimeOnlyAdvanced(mod, opt_sema),
2892
2893 // values, not types
2894 .undef,
2895 .simple_value,
2896 .variable,
2897 .extern_func,
2898 .func,
2899 .int,
2900 .err,
2901 .error_union,
2902 .enum_literal,
2903 .enum_tag,
2904 .empty_enum_value,
2905 .float,
2906 .ptr,
2907 .slice,
2908 .opt,
2909 .aggregate,
2910 .un,
2911 // memoization, not types
2912 .memoized_call,
2913 => unreachable,
2914 },
2915 };
2916 }
2917
2918 pub fn isVector(ty: Type, mod: *const Module) bool {
2919 return ty.zigTypeTag(mod) == .Vector;
2920 }
2921
2922 /// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len.
2923 pub fn totalVectorBits(ty: Type, zcu: *Zcu) u64 {
2924 if (!ty.isVector(zcu)) return 0;
2925 const v = zcu.intern_pool.indexToKey(ty.toIntern()).vector_type;
2926 return v.len * Type.fromInterned(v.child).bitSize(zcu);
2927 }
2928
2929 pub fn isArrayOrVector(ty: Type, mod: *const Module) bool {
2930 return switch (ty.zigTypeTag(mod)) {
2931 .Array, .Vector => true,
2932 else => false,
2933 };
2934 }
2935
2936 pub fn isIndexable(ty: Type, mod: *Module) bool {
2937 return switch (ty.zigTypeTag(mod)) {
2938 .Array, .Vector => true,
2939 .Pointer => switch (ty.ptrSize(mod)) {
2940 .Slice, .Many, .C => true,
2941 .One => switch (ty.childType(mod).zigTypeTag(mod)) {
2942 .Array, .Vector => true,
2943 .Struct => ty.childType(mod).isTuple(mod),
2944 else => false,
2945 },
2946 },
2947 .Struct => ty.isTuple(mod),
2948 else => false,
2949 };
2950 }
2951
2952 pub fn indexableHasLen(ty: Type, mod: *Module) bool {
2953 return switch (ty.zigTypeTag(mod)) {
2954 .Array, .Vector => true,
2955 .Pointer => switch (ty.ptrSize(mod)) {
2956 .Many, .C => false,
2957 .Slice => true,
2958 .One => switch (ty.childType(mod).zigTypeTag(mod)) {
2959 .Array, .Vector => true,
2960 .Struct => ty.childType(mod).isTuple(mod),
2961 else => false,
2962 },
2963 },
2964 .Struct => ty.isTuple(mod),
2965 else => false,
2966 };
2967 }
2968
2969 /// Asserts that the type can have a namespace.
2970 pub fn getNamespaceIndex(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex {
2971 return ty.getNamespace(zcu).?;
2972 }
2973
2974 /// Returns null if the type has no namespace.
2975 pub fn getNamespace(ty: Type, zcu: *Zcu) ?InternPool.OptionalNamespaceIndex {
2976 const ip = &zcu.intern_pool;
2977 return switch (ip.indexToKey(ty.toIntern())) {
2978 .opaque_type => ip.loadOpaqueType(ty.toIntern()).namespace,
2979 .struct_type => ip.loadStructType(ty.toIntern()).namespace,
2980 .union_type => ip.loadUnionType(ty.toIntern()).namespace,
2981 .enum_type => ip.loadEnumType(ty.toIntern()).namespace,
2982
2983 .anon_struct_type => .none,
2984 .simple_type => |s| switch (s) {
2985 .anyopaque,
2986 .atomic_order,
2987 .atomic_rmw_op,
2988 .calling_convention,
2989 .address_space,
2990 .float_mode,
2991 .reduce_op,
2992 .call_modifier,
2993 .prefetch_options,
2994 .export_options,
2995 .extern_options,
2996 .type_info,
2997 => .none,
2998 else => null,
2999 },
3000
3001 else => null,
3002 };
3003 }
3004
3005 // Works for vectors and vectors of integers.
3006 pub fn minInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
3007 const scalar = try minIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
3008 return if (ty.zigTypeTag(mod) == .Vector) Value.fromInterned((try mod.intern(.{ .aggregate = .{
3009 .ty = dest_ty.toIntern(),
3010 .storage = .{ .repeated_elem = scalar.toIntern() },
3011 } }))) else scalar;
3012 }
3013
3014 /// Asserts that the type is an integer.
3015 pub fn minIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
3016 const info = ty.intInfo(mod);
3017 if (info.signedness == .unsigned) return mod.intValue(dest_ty, 0);
3018 if (info.bits == 0) return mod.intValue(dest_ty, -1);
3019
3020 if (std.math.cast(u6, info.bits - 1)) |shift| {
3021 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
3022 return mod.intValue(dest_ty, n);
3023 }
3024
3025 var res = try std.math.big.int.Managed.init(mod.gpa);
3026 defer res.deinit();
3027
3028 try res.setTwosCompIntLimit(.min, info.signedness, info.bits);
3029
3030 return mod.intValue_big(dest_ty, res.toConst());
3031 }
3032
3033 // Works for vectors and vectors of integers.
3034 /// The returned Value will have type dest_ty.
3035 pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
3036 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
3037 return if (ty.zigTypeTag(mod) == .Vector) Value.fromInterned((try mod.intern(.{ .aggregate = .{
3038 .ty = dest_ty.toIntern(),
3039 .storage = .{ .repeated_elem = scalar.toIntern() },
3040 } }))) else scalar;
3041 }
3042
3043 /// The returned Value will have type dest_ty.
3044 pub fn maxIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
3045 const info = ty.intInfo(mod);
3046
3047 switch (info.bits) {
3048 0 => return switch (info.signedness) {
3049 .signed => try mod.intValue(dest_ty, -1),
3050 .unsigned => try mod.intValue(dest_ty, 0),
3051 },
3052 1 => return switch (info.signedness) {
3053 .signed => try mod.intValue(dest_ty, 0),
3054 .unsigned => try mod.intValue(dest_ty, 1),
3055 },
3056 else => {},
3057 }
3058
3059 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
3060 .signed => {
3061 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);
3062 return mod.intValue(dest_ty, n);
3063 },
3064 .unsigned => {
3065 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);
3066 return mod.intValue(dest_ty, n);
3067 },
3068 };
3069
3070 var res = try std.math.big.int.Managed.init(mod.gpa);
3071 defer res.deinit();
3072
3073 try res.setTwosCompIntLimit(.max, info.signedness, info.bits);
3074
3075 return mod.intValue_big(dest_ty, res.toConst());
3076 }
3077
3078 /// Asserts the type is an enum or a union.
3079 pub fn intTagType(ty: Type, mod: *Module) Type {
3080 const ip = &mod.intern_pool;
3081 return switch (ip.indexToKey(ty.toIntern())) {
3082 .union_type => Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty).intTagType(mod),
3083 .enum_type => Type.fromInterned(ip.loadEnumType(ty.toIntern()).tag_ty),
3084 else => unreachable,
3085 };
3086 }
3087
3088 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
3089 const ip = &mod.intern_pool;
3090 return switch (ip.indexToKey(ty.toIntern())) {
3091 .enum_type => switch (ip.loadEnumType(ty.toIntern()).tag_mode) {
3092 .nonexhaustive => true,
3093 .auto, .explicit => false,
3094 },
3095 else => false,
3096 };
3097 }
3098
3099 // Asserts that `ty` is an error set and not `anyerror`.
3100 // Asserts that `ty` is resolved if it is an inferred error set.
3101 pub fn errorSetNames(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
3102 const ip = &mod.intern_pool;
3103 return switch (ip.indexToKey(ty.toIntern())) {
3104 .error_set_type => |x| x.names,
3105 .inferred_error_set_type => |i| switch (ip.funcIesResolved(i).*) {
3106 .none => unreachable, // unresolved inferred error set
3107 .anyerror_type => unreachable,
3108 else => |t| ip.indexToKey(t).error_set_type.names,
3109 },
3110 else => unreachable,
3111 };
3112 }
3113
3114 pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice {
3115 return mod.intern_pool.loadEnumType(ty.toIntern()).names;
3116 }
3117
3118 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
3119 return mod.intern_pool.loadEnumType(ty.toIntern()).names.len;
3120 }
3121
3122 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
3123 const ip = &mod.intern_pool;
3124 return ip.loadEnumType(ty.toIntern()).names.get(ip)[field_index];
3125 }
3126
3127 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
3128 const ip = &mod.intern_pool;
3129 const enum_type = ip.loadEnumType(ty.toIntern());
3130 return enum_type.nameIndex(ip, field_name);
3131 }
3132
3133 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
3134 /// an integer which represents the enum value. Returns the field index in
3135 /// declaration order, or `null` if `enum_tag` does not match any field.
3136 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
3137 const ip = &mod.intern_pool;
3138 const enum_type = ip.loadEnumType(ty.toIntern());
3139 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
3140 .int => enum_tag.toIntern(),
3141 .enum_tag => |info| info.int,
3142 else => unreachable,
3143 };
3144 assert(ip.typeOf(int_tag) == enum_type.tag_ty);
3145 return enum_type.tagValueIndex(ip, int_tag);
3146 }
3147
3148 /// Returns none in the case of a tuple which uses the integer index as the field name.
3149 pub fn structFieldName(ty: Type, index: usize, mod: *Module) InternPool.OptionalNullTerminatedString {
3150 const ip = &mod.intern_pool;
3151 return switch (ip.indexToKey(ty.toIntern())) {
3152 .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index),
3153 .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index),
3154 else => unreachable,
3155 };
3156 }
3157
3158 pub fn structFieldCount(ty: Type, mod: *Module) u32 {
3159 const ip = &mod.intern_pool;
3160 return switch (ip.indexToKey(ty.toIntern())) {
3161 .struct_type => ip.loadStructType(ty.toIntern()).field_types.len,
3162 .anon_struct_type => |anon_struct| anon_struct.types.len,
3163 else => unreachable,
3164 };
3165 }
3166
3167 /// Supports structs and unions.
3168 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
3169 const ip = &mod.intern_pool;
3170 return switch (ip.indexToKey(ty.toIntern())) {
3171 .struct_type => Type.fromInterned(ip.loadStructType(ty.toIntern()).field_types.get(ip)[index]),
3172 .union_type => {
3173 const union_obj = ip.loadUnionType(ty.toIntern());
3174 return Type.fromInterned(union_obj.field_types.get(ip)[index]);
3175 },
3176 .anon_struct_type => |anon_struct| Type.fromInterned(anon_struct.types.get(ip)[index]),
3177 else => unreachable,
3178 };
3179 }
3180
3181 pub fn structFieldAlign(ty: Type, index: usize, zcu: *Zcu) Alignment {
3182 return ty.structFieldAlignAdvanced(index, zcu, null) catch unreachable;
3183 }
3184
3185 pub fn structFieldAlignAdvanced(ty: Type, index: usize, zcu: *Zcu, opt_sema: ?*Sema) !Alignment {
3186 const ip = &zcu.intern_pool;
3187 switch (ip.indexToKey(ty.toIntern())) {
3188 .struct_type => {
3189 const struct_type = ip.loadStructType(ty.toIntern());
3190 assert(struct_type.layout != .@"packed");
3191 const explicit_align = struct_type.fieldAlign(ip, index);
3192 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[index]);
3193 if (opt_sema) |sema| {
3194 return sema.structFieldAlignment(explicit_align, field_ty, struct_type.layout);
3195 } else {
3196 return zcu.structFieldAlignment(explicit_align, field_ty, struct_type.layout);
3197 }
3198 },
3199 .anon_struct_type => |anon_struct| {
3200 return (try Type.fromInterned(anon_struct.types.get(ip)[index]).abiAlignmentAdvanced(zcu, if (opt_sema) |sema| .{ .sema = sema } else .eager)).scalar;
3201 },
3202 .union_type => {
3203 const union_obj = ip.loadUnionType(ty.toIntern());
3204 if (opt_sema) |sema| {
3205 return sema.unionFieldAlignment(union_obj, @intCast(index));
3206 } else {
3207 return zcu.unionFieldNormalAlignment(union_obj, @intCast(index));
3208 }
3209 },
3210 else => unreachable,
3211 }
3212 }
3213
3214 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
3215 const ip = &mod.intern_pool;
3216 switch (ip.indexToKey(ty.toIntern())) {
3217 .struct_type => {
3218 const struct_type = ip.loadStructType(ty.toIntern());
3219 const val = struct_type.fieldInit(ip, index);
3220 // TODO: avoid using `unreachable` to indicate this.
3221 if (val == .none) return Value.@"unreachable";
3222 return Value.fromInterned(val);
3223 },
3224 .anon_struct_type => |anon_struct| {
3225 const val = anon_struct.values.get(ip)[index];
3226 // TODO: avoid using `unreachable` to indicate this.
3227 if (val == .none) return Value.@"unreachable";
3228 return Value.fromInterned(val);
3229 },
3230 else => unreachable,
3231 }
3232 }
3233
3234 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
3235 const ip = &mod.intern_pool;
3236 switch (ip.indexToKey(ty.toIntern())) {
3237 .struct_type => {
3238 const struct_type = ip.loadStructType(ty.toIntern());
3239 if (struct_type.fieldIsComptime(ip, index)) {
3240 assert(struct_type.haveFieldInits(ip));
3241 return Value.fromInterned(struct_type.field_inits.get(ip)[index]);
3242 } else {
3243 return Type.fromInterned(struct_type.field_types.get(ip)[index]).onePossibleValue(mod);
3244 }
3245 },
3246 .anon_struct_type => |tuple| {
3247 const val = tuple.values.get(ip)[index];
3248 if (val == .none) {
3249 return Type.fromInterned(tuple.types.get(ip)[index]).onePossibleValue(mod);
3250 } else {
3251 return Value.fromInterned(val);
3252 }
3253 },
3254 else => unreachable,
3255 }
3256 }
3257
3258 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
3259 const ip = &mod.intern_pool;
3260 return switch (ip.indexToKey(ty.toIntern())) {
3261 .struct_type => ip.loadStructType(ty.toIntern()).fieldIsComptime(ip, index),
3262 .anon_struct_type => |anon_struct| anon_struct.values.get(ip)[index] != .none,
3263 else => unreachable,
3264 };
3265 }
3266
3267 pub const FieldOffset = struct {
3268 field: usize,
3269 offset: u64,
3270 };
3271
3272 /// Supports structs and unions.
3273 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
3274 const ip = &mod.intern_pool;
3275 switch (ip.indexToKey(ty.toIntern())) {
3276 .struct_type => {
3277 const struct_type = ip.loadStructType(ty.toIntern());
3278 assert(struct_type.haveLayout(ip));
3279 assert(struct_type.layout != .@"packed");
3280 return struct_type.offsets.get(ip)[index];
3281 },
3282
3283 .anon_struct_type => |tuple| {
3284 var offset: u64 = 0;
3285 var big_align: Alignment = .none;
3286
3287 for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| {
3288 if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(mod)) {
3289 // comptime field
3290 if (i == index) return offset;
3291 continue;
3292 }
3293
3294 const field_align = Type.fromInterned(field_ty).abiAlignment(mod);
3295 big_align = big_align.max(field_align);
3296 offset = field_align.forward(offset);
3297 if (i == index) return offset;
3298 offset += Type.fromInterned(field_ty).abiSize(mod);
3299 }
3300 offset = big_align.max(.@"1").forward(offset);
3301 return offset;
3302 },
3303
3304 .union_type => {
3305 const union_type = ip.loadUnionType(ty.toIntern());
3306 if (!union_type.hasTag(ip))
3307 return 0;
3308 const layout = mod.getUnionLayout(union_type);
3309 if (layout.tag_align.compare(.gte, layout.payload_align)) {
3310 // {Tag, Payload}
3311 return layout.payload_align.forward(layout.tag_size);
3312 } else {
3313 // {Payload, Tag}
3314 return 0;
3315 }
3316 },
3317
3318 else => unreachable,
3319 }
3320 }
3321
3322 pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex {
3323 return ty.getOwnerDeclOrNull(mod) orelse unreachable;
3324 }
3325
3326 pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?InternPool.DeclIndex {
3327 const ip = &mod.intern_pool;
3328 return switch (ip.indexToKey(ty.toIntern())) {
3329 .struct_type => ip.loadStructType(ty.toIntern()).decl.unwrap(),
3330 .union_type => ip.loadUnionType(ty.toIntern()).decl,
3331 .opaque_type => ip.loadOpaqueType(ty.toIntern()).decl,
3332 .enum_type => ip.loadEnumType(ty.toIntern()).decl,
3333 else => null,
3334 };
3335 }
3336
3337 pub fn srcLocOrNull(ty: Type, zcu: *Zcu) ?Module.LazySrcLoc {
3338 const ip = &zcu.intern_pool;
3339 return .{
3340 .base_node_inst = switch (ip.indexToKey(ty.toIntern())) {
3341 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
3342 .declared => |d| d.zir_index,
3343 .reified => |r| r.zir_index,
3344 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3345 .empty_struct => return null,
3346 },
3347 else => return null,
3348 },
3349 .offset = Module.LazySrcLoc.Offset.nodeOffset(0),
3350 };
3351 }
3352
3353 pub fn srcLoc(ty: Type, zcu: *Zcu) Module.LazySrcLoc {
3354 return ty.srcLocOrNull(zcu).?;
3355 }
3356
3357 pub fn isGenericPoison(ty: Type) bool {
3358 return ty.toIntern() == .generic_poison_type;
3359 }
3360
3361 pub fn isTuple(ty: Type, mod: *Module) bool {
3362 const ip = &mod.intern_pool;
3363 return switch (ip.indexToKey(ty.toIntern())) {
3364 .struct_type => {
3365 const struct_type = ip.loadStructType(ty.toIntern());
3366 if (struct_type.layout == .@"packed") return false;
3367 if (struct_type.decl == .none) return false;
3368 return struct_type.flagsPtr(ip).is_tuple;
3369 },
3370 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
3371 else => false,
3372 };
3373 }
3374
3375 pub fn isAnonStruct(ty: Type, mod: *Module) bool {
3376 if (ty.toIntern() == .empty_struct_type) return true;
3377 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3378 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
3379 else => false,
3380 };
3381 }
3382
3383 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3384 const ip = &mod.intern_pool;
3385 return switch (ip.indexToKey(ty.toIntern())) {
3386 .struct_type => {
3387 const struct_type = ip.loadStructType(ty.toIntern());
3388 if (struct_type.layout == .@"packed") return false;
3389 if (struct_type.decl == .none) return false;
3390 return struct_type.flagsPtr(ip).is_tuple;
3391 },
3392 .anon_struct_type => true,
3393 else => false,
3394 };
3395 }
3396
3397 pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
3398 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3399 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
3400 else => false,
3401 };
3402 }
3403
3404 pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3405 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3406 .anon_struct_type => true,
3407 else => false,
3408 };
3409 }
3410
3411 /// Traverses optional child types and error union payloads until the type
3412 /// is not a pointer. For `E!?u32`, returns `u32`; for `*u8`, returns `*u8`.
3413 pub fn optEuBaseType(ty: Type, mod: *Module) Type {
3414 var cur = ty;
3415 while (true) switch (cur.zigTypeTag(mod)) {
3416 .Optional => cur = cur.optionalChild(mod),
3417 .ErrorUnion => cur = cur.errorUnionPayload(mod),
3418 else => return cur,
3419 };
3420 }
3421
3422 pub fn toUnsigned(ty: Type, mod: *Module) !Type {
3423 return switch (ty.zigTypeTag(mod)) {
3424 .Int => mod.intType(.unsigned, ty.intInfo(mod).bits),
3425 .Vector => try mod.vectorType(.{
3426 .len = ty.vectorLen(mod),
3427 .child = (try ty.childType(mod).toUnsigned(mod)).toIntern(),
3428 }),
3429 else => unreachable,
3430 };
3431 }
3432
3433 pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
3434 const ip = &zcu.intern_pool;
3435 return switch (ip.indexToKey(ty.toIntern())) {
3436 .struct_type => ip.loadStructType(ty.toIntern()).zir_index.unwrap(),
3437 .union_type => ip.loadUnionType(ty.toIntern()).zir_index,
3438 .enum_type => ip.loadEnumType(ty.toIntern()).zir_index.unwrap(),
3439 .opaque_type => ip.loadOpaqueType(ty.toIntern()).zir_index,
3440 else => null,
3441 };
3442 }
3443
3444 pub fn typeDeclSrcLine(ty: Type, zcu: *const Zcu) ?u32 {
3445 const ip = &zcu.intern_pool;
3446 const tracked = switch (ip.indexToKey(ty.toIntern())) {
3447 .struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {
3448 .declared => |d| d.zir_index,
3449 .reified => |r| r.zir_index,
3450 .generated_tag => |gt| ip.loadUnionType(gt.union_type).zir_index,
3451 .empty_struct => return null,
3452 },
3453 else => return null,
3454 };
3455 const info = tracked.resolveFull(&zcu.intern_pool);
3456 const file = zcu.import_table.values()[zcu.path_digest_map.getIndex(info.path_digest).?];
3457 assert(file.zir_loaded);
3458 const zir = file.zir;
3459 const inst = zir.instructions.get(@intFromEnum(info.inst));
3460 assert(inst.tag == .extended);
3461 return switch (inst.data.extended.opcode) {
3462 .struct_decl => zir.extraData(Zir.Inst.StructDecl, inst.data.extended.operand).data.src_line,
3463 .union_decl => zir.extraData(Zir.Inst.UnionDecl, inst.data.extended.operand).data.src_line,
3464 .enum_decl => zir.extraData(Zir.Inst.EnumDecl, inst.data.extended.operand).data.src_line,
3465 .opaque_decl => zir.extraData(Zir.Inst.OpaqueDecl, inst.data.extended.operand).data.src_line,
3466 .reify => zir.extraData(Zir.Inst.Reify, inst.data.extended.operand).data.src_line,
3467 else => unreachable,
3468 };
3469 }
3470
3471 /// Given a namespace type, returns its list of caotured values.
3472 pub fn getCaptures(ty: Type, zcu: *const Zcu) InternPool.CaptureValue.Slice {
3473 const ip = &zcu.intern_pool;
3474 return switch (ip.indexToKey(ty.toIntern())) {
3475 .struct_type => ip.loadStructType(ty.toIntern()).captures,
3476 .union_type => ip.loadUnionType(ty.toIntern()).captures,
3477 .enum_type => ip.loadEnumType(ty.toIntern()).captures,
3478 .opaque_type => ip.loadOpaqueType(ty.toIntern()).captures,
3479 else => unreachable,
3480 };
3481 }
3482
3483 pub fn arrayBase(ty: Type, zcu: *const Zcu) struct { Type, u64 } {
3484 var cur_ty: Type = ty;
3485 var cur_len: u64 = 1;
3486 while (cur_ty.zigTypeTag(zcu) == .Array) {
3487 cur_len *= cur_ty.arrayLenIncludingSentinel(zcu);
3488 cur_ty = cur_ty.childType(zcu);
3489 }
3490 return .{ cur_ty, cur_len };
3491 }
3492
3493 pub fn packedStructFieldPtrInfo(struct_ty: Type, parent_ptr_ty: Type, field_idx: u32, zcu: *Zcu) union(enum) {
3494 /// The result is a bit-pointer with the same value and a new packed offset.
3495 bit_ptr: InternPool.Key.PtrType.PackedOffset,
3496 /// The result is a standard pointer.
3497 byte_ptr: struct {
3498 /// The byte offset of the field pointer from the parent pointer value.
3499 offset: u64,
3500 /// The alignment of the field pointer type.
3501 alignment: InternPool.Alignment,
3502 },
3503 } {
3504 comptime assert(Type.packed_struct_layout_version == 2);
3505
3506 const parent_ptr_info = parent_ptr_ty.ptrInfo(zcu);
3507 const field_ty = struct_ty.structFieldType(field_idx, zcu);
3508
3509 var bit_offset: u16 = 0;
3510 var running_bits: u16 = 0;
3511 for (0..struct_ty.structFieldCount(zcu)) |i| {
3512 const f_ty = struct_ty.structFieldType(i, zcu);
3513 if (i == field_idx) {
3514 bit_offset = running_bits;
3515 }
3516 running_bits += @intCast(f_ty.bitSize(zcu));
3517 }
3518
3519 const res_host_size: u16, const res_bit_offset: u16 = if (parent_ptr_info.packed_offset.host_size != 0)
3520 .{ parent_ptr_info.packed_offset.host_size, parent_ptr_info.packed_offset.bit_offset + bit_offset }
3521 else
3522 .{ (running_bits + 7) / 8, bit_offset };
3523
3524 // If the field happens to be byte-aligned, simplify the pointer type.
3525 // We can only do this if the pointee's bit size matches its ABI byte size,
3526 // so that loads and stores do not interfere with surrounding packed bits.
3527 //
3528 // TODO: we do not attempt this with big-endian targets yet because of nested
3529 // structs and floats. I need to double-check the desired behavior for big endian
3530 // targets before adding the necessary complications to this code. This will not
3531 // cause miscompilations; it only means the field pointer uses bit masking when it
3532 // might not be strictly necessary.
3533 if (res_bit_offset % 8 == 0 and field_ty.bitSize(zcu) == field_ty.abiSize(zcu) * 8 and zcu.getTarget().cpu.arch.endian() == .little) {
3534 const byte_offset = res_bit_offset / 8;
3535 const new_align = Alignment.fromLog2Units(@ctz(byte_offset | parent_ptr_ty.ptrAlignment(zcu).toByteUnits().?));
3536 return .{ .byte_ptr = .{
3537 .offset = byte_offset,
3538 .alignment = new_align,
3539 } };
3540 }
3541
3542 return .{ .bit_ptr = .{
3543 .host_size = res_host_size,
3544 .bit_offset = res_bit_offset,
3545 } };
3546 }
3547
3548 pub const @"u1": Type = .{ .ip_index = .u1_type };
3549 pub const @"u8": Type = .{ .ip_index = .u8_type };
3550 pub const @"u16": Type = .{ .ip_index = .u16_type };
3551 pub const @"u29": Type = .{ .ip_index = .u29_type };
3552 pub const @"u32": Type = .{ .ip_index = .u32_type };
3553 pub const @"u64": Type = .{ .ip_index = .u64_type };
3554 pub const @"u128": Type = .{ .ip_index = .u128_type };
3555
3556 pub const @"i8": Type = .{ .ip_index = .i8_type };
3557 pub const @"i16": Type = .{ .ip_index = .i16_type };
3558 pub const @"i32": Type = .{ .ip_index = .i32_type };
3559 pub const @"i64": Type = .{ .ip_index = .i64_type };
3560 pub const @"i128": Type = .{ .ip_index = .i128_type };
3561
3562 pub const @"f16": Type = .{ .ip_index = .f16_type };
3563 pub const @"f32": Type = .{ .ip_index = .f32_type };
3564 pub const @"f64": Type = .{ .ip_index = .f64_type };
3565 pub const @"f80": Type = .{ .ip_index = .f80_type };
3566 pub const @"f128": Type = .{ .ip_index = .f128_type };
3567
3568 pub const @"bool": Type = .{ .ip_index = .bool_type };
3569 pub const @"usize": Type = .{ .ip_index = .usize_type };
3570 pub const @"isize": Type = .{ .ip_index = .isize_type };
3571 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type };
3572 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type };
3573 pub const @"void": Type = .{ .ip_index = .void_type };
3574 pub const @"type": Type = .{ .ip_index = .type_type };
3575 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type };
3576 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type };
3577 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type };
3578 pub const @"null": Type = .{ .ip_index = .null_type };
3579 pub const @"undefined": Type = .{ .ip_index = .undefined_type };
3580 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type };
3581
3582 pub const @"c_char": Type = .{ .ip_index = .c_char_type };
3583 pub const @"c_short": Type = .{ .ip_index = .c_short_type };
3584 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type };
3585 pub const @"c_int": Type = .{ .ip_index = .c_int_type };
3586 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type };
3587 pub const @"c_long": Type = .{ .ip_index = .c_long_type };
3588 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type };
3589 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
3590 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
3591 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
3592
3593 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
3594 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
3595 pub const single_const_pointer_to_comptime_int: Type = .{
3596 .ip_index = .single_const_pointer_to_comptime_int_type,
3597 };
3598 pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
3599 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
3600
3601 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
3602
3603 pub fn smallestUnsignedBits(max: u64) u16 {
3604 if (max == 0) return 0;
3605 const base = std.math.log2(max);
3606 const upper = (@as(u64, 1) << @as(u6, @intCast(base))) - 1;
3607 return @as(u16, @intCast(base + @intFromBool(upper < max)));
3608 }
3609
3610 /// This is only used for comptime asserts. Bump this number when you make a change
3611 /// to packed struct layout to find out all the places in the codebase you need to edit!
3612 pub const packed_struct_layout_version = 2;
3613};
3614
3615fn cTypeAlign(target: Target, c_type: Target.CType) Alignment {
3616 return Alignment.fromByteUnits(target.c_type_alignment(c_type));
3617}
test/cases/compile_errors/compileLog_of_tagged_enum_doesnt_crash_the_compiler.zig+1
...@@ -16,6 +16,7 @@ pub export fn entry() void {...@@ -16,6 +16,7 @@ pub export fn entry() void {
16// target=native16// target=native
17//17//
18// :6:5: error: found compile log statement18// :6:5: error: found compile log statement
19// :6:5: note: also here
19//20//
20// Compile Log Output:21// Compile Log Output:
21// @as(tmp.Bar, .{ .X = 123 })22// @as(tmp.Bar, .{ .X = 123 })
test/cases/compile_errors/compile_log.zig+1
...@@ -18,6 +18,7 @@ export fn baz() void {...@@ -18,6 +18,7 @@ export fn baz() void {
18//18//
19// :6:5: error: found compile log statement19// :6:5: error: found compile log statement
20// :12:5: note: also here20// :12:5: note: also here
21// :6:5: note: also here
21//22//
22// Compile Log Output:23// Compile Log Output:
23// @as(*const [5:0]u8, "begin")24// @as(*const [5:0]u8, "begin")
test/cases/compile_errors/direct_struct_loop.zig-1
...@@ -10,4 +10,3 @@ export fn entry() usize {...@@ -10,4 +10,3 @@ export fn entry() usize {
10// target=native10// target=native
11//11//
12// :1:11: error: struct 'tmp.A' depends on itself12// :1:11: error: struct 'tmp.A' depends on itself
13// :2:5: note: while checking this field
test/cases/compile_errors/indirect_struct_loop.zig-3
...@@ -16,6 +16,3 @@ export fn entry() usize {...@@ -16,6 +16,3 @@ export fn entry() usize {
16// target=native16// target=native
17//17//
18// :1:11: error: struct 'tmp.A' depends on itself18// :1:11: error: struct 'tmp.A' depends on itself
19// :8:5: note: while checking this field
20// :5:5: note: while checking this field
21// :2:5: note: while checking this field
test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_struct_that_contains_itself.zig-1
...@@ -13,4 +13,3 @@ export fn entry() usize {...@@ -13,4 +13,3 @@ export fn entry() usize {
13// target=native13// target=native
14//14//
15// :1:13: error: struct 'tmp.Foo' depends on itself15// :1:13: error: struct 'tmp.Foo' depends on itself
16// :2:5: note: while checking this field
test/cases/compile_errors/instantiating_an_undefined_value_for_an_invalid_union_that_contains_itself.zig-1
...@@ -13,4 +13,3 @@ export fn entry() usize {...@@ -13,4 +13,3 @@ export fn entry() usize {
13// target=native13// target=native
14//14//
15// :1:13: error: union 'tmp.Foo' depends on itself15// :1:13: error: union 'tmp.Foo' depends on itself
16// :2:5: note: while checking this field
test/cases/compile_errors/invalid_dependency_on_struct_size.zig-1
...@@ -16,4 +16,3 @@ comptime {...@@ -16,4 +16,3 @@ comptime {
16// target=native16// target=native
17//17//
18// :6:21: error: struct layout depends on it having runtime bits18// :6:21: error: struct layout depends on it having runtime bits
19// :4:13: note: while checking this field
test/cases/compile_errors/struct_depends_on_itself_via_optional_field.zig-2
...@@ -15,5 +15,3 @@ export fn entry() void {...@@ -15,5 +15,3 @@ export fn entry() void {
15// target=native15// target=native
16//16//
17// :1:17: error: struct 'tmp.LhsExpr' depends on itself17// :1:17: error: struct 'tmp.LhsExpr' depends on itself
18// :5:5: note: while checking this field
19// :2:5: note: while checking this field
test/cases/compile_errors/struct_type_returned_from_non-generic_function.zig+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1pub export fn entry(param: usize) usize {1pub export fn entry(param: usize) usize {
2 return struct { param };2 return struct { @TypeOf(param) };
3}3}
44
5// error5// error
test/src/Cases.zig+33-670
...@@ -395,10 +395,7 @@ fn addFromDirInner(...@@ -395,10 +395,7 @@ fn addFromDirInner(
395 if (entry.kind != .file) continue;395 if (entry.kind != .file) continue;
396396
397 // Ignore stuff such as .swp files397 // Ignore stuff such as .swp files
398 switch (Compilation.classifyFileExt(entry.basename)) {398 if (!knownFileExtension(entry.basename)) continue;
399 .unknown => continue,
400 else => {},
401 }
402 try filenames.append(try ctx.arena.dupe(u8, entry.path));399 try filenames.append(try ctx.arena.dupe(u8, entry.path));
403 }400 }
404401
...@@ -623,8 +620,6 @@ pub fn lowerToBuildSteps(...@@ -623,8 +620,6 @@ pub fn lowerToBuildSteps(
623 b: *std.Build,620 b: *std.Build,
624 parent_step: *std.Build.Step,621 parent_step: *std.Build.Step,
625 test_filters: []const []const u8,622 test_filters: []const []const u8,
626 cases_dir_path: []const u8,
627 incremental_exe: *std.Build.Step.Compile,
628) void {623) void {
629 const host = std.zig.system.resolveTargetQuery(.{}) catch |err|624 const host = std.zig.system.resolveTargetQuery(.{}) catch |err|
630 std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)});625 std.debug.panic("unable to detect native host: {s}\n", .{@errorName(err)});
...@@ -637,20 +632,11 @@ pub fn lowerToBuildSteps(...@@ -637,20 +632,11 @@ pub fn lowerToBuildSteps(
637 // compilation is in a happier state.632 // compilation is in a happier state.
638 continue;633 continue;
639 }634 }
640 for (test_filters) |test_filter| {635 // TODO: the logic for running these was bad, so I've ripped it out. Rewrite this
641 if (std.mem.indexOf(u8, incr_case.base_path, test_filter)) |_| break;636 // in a way that actually spawns the compiler, communicating with it over the
642 } else if (test_filters.len > 0) continue;637 // compiler server protocol.
643 const case_base_path_with_dir = std.fs.path.join(b.allocator, &.{638 _ = incr_case;
644 cases_dir_path, incr_case.base_path,639 @panic("TODO implement incremental test case executor");
645 }) catch @panic("OOM");
646 const run = b.addRunArtifact(incremental_exe);
647 run.setName(incr_case.base_path);
648 run.addArgs(&.{
649 case_base_path_with_dir,
650 b.graph.zig_exe,
651 });
652 run.expectStdOutEqual("");
653 parent_step.dependOn(&run.step);
654 }640 }
655641
656 for (self.cases.items) |case| {642 for (self.cases.items) |case| {
...@@ -1236,192 +1222,6 @@ const assert = std.debug.assert;...@@ -1236,192 +1222,6 @@ const assert = std.debug.assert;
1236const Allocator = std.mem.Allocator;1222const Allocator = std.mem.Allocator;
1237const getExternalExecutor = std.zig.system.getExternalExecutor;1223const getExternalExecutor = std.zig.system.getExternalExecutor;
12381224
1239const Compilation = @import("../../src/Compilation.zig");
1240const zig_h = @import("../../src/link.zig").File.C.zig_h;
1241const introspect = @import("../../src/introspect.zig");
1242const ThreadPool = std.Thread.Pool;
1243const WaitGroup = std.Thread.WaitGroup;
1244const build_options = @import("build_options");
1245const Package = @import("../../src/Package.zig");
1246
1247pub const std_options = .{
1248 .log_level = .err,
1249};
1250
1251var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{
1252 .stack_trace_frames = build_options.mem_leak_frames,
1253}){};
1254
1255// TODO: instead of embedding the compiler in this process, spawn the compiler
1256// as a sub-process and communicate the updates using the compiler protocol.
1257pub fn main() !void {
1258 const use_gpa = build_options.force_gpa or !builtin.link_libc;
1259 const gpa = gpa: {
1260 if (use_gpa) {
1261 break :gpa general_purpose_allocator.allocator();
1262 }
1263 // We would prefer to use raw libc allocator here, but cannot
1264 // use it if it won't support the alignment we need.
1265 if (@alignOf(std.c.max_align_t) < @alignOf(i128)) {
1266 break :gpa std.heap.c_allocator;
1267 }
1268 break :gpa std.heap.raw_c_allocator;
1269 };
1270
1271 var single_threaded_arena = std.heap.ArenaAllocator.init(gpa);
1272 defer single_threaded_arena.deinit();
1273
1274 var thread_safe_arena: std.heap.ThreadSafeAllocator = .{
1275 .child_allocator = single_threaded_arena.allocator(),
1276 };
1277 const arena = thread_safe_arena.allocator();
1278
1279 const args = try std.process.argsAlloc(arena);
1280 const case_file_path = args[1];
1281 const zig_exe_path = args[2];
1282
1283 var filenames = std.ArrayList([]const u8).init(arena);
1284
1285 const case_dirname = std.fs.path.dirname(case_file_path).?;
1286 var iterable_dir = try std.fs.cwd().openDir(case_dirname, .{ .iterate = true });
1287 defer iterable_dir.close();
1288
1289 if (std.mem.endsWith(u8, case_file_path, ".0.zig")) {
1290 const stem = case_file_path[case_dirname.len + 1 .. case_file_path.len - "0.zig".len];
1291 var it = iterable_dir.iterate();
1292 while (try it.next()) |entry| {
1293 if (entry.kind != .file) continue;
1294 if (!std.mem.startsWith(u8, entry.name, stem)) continue;
1295 try filenames.append(try std.fs.path.join(arena, &.{ case_dirname, entry.name }));
1296 }
1297 } else {
1298 try filenames.append(case_file_path);
1299 }
1300
1301 if (filenames.items.len == 0) {
1302 std.debug.print("failed to find the input source file(s) from '{s}'\n", .{
1303 case_file_path,
1304 });
1305 std.process.exit(1);
1306 }
1307
1308 // Sort filenames, so that incremental tests are contiguous and in-order
1309 sortTestFilenames(filenames.items);
1310
1311 var ctx = Cases.init(gpa, arena);
1312
1313 var test_it = TestIterator{ .filenames = filenames.items };
1314 while (try test_it.next()) |batch| {
1315 const strategy: TestStrategy = if (batch.len > 1) .incremental else .independent;
1316 var cases = std.ArrayList(usize).init(arena);
1317
1318 for (batch) |filename| {
1319 const max_file_size = 10 * 1024 * 1024;
1320 const src = try iterable_dir.readFileAllocOptions(arena, filename, max_file_size, null, 1, 0);
1321
1322 // Parse the manifest
1323 var manifest = try TestManifest.parse(arena, src);
1324
1325 if (cases.items.len == 0) {
1326 const backends = try manifest.getConfigForKeyAlloc(arena, "backend", Backend);
1327 const targets = try manifest.getConfigForKeyAlloc(arena, "target", std.Target.Query);
1328 const c_frontends = try manifest.getConfigForKeyAlloc(ctx.arena, "c_frontend", CFrontend);
1329 const is_test = try manifest.getConfigForKeyAssertSingle("is_test", bool);
1330 const link_libc = try manifest.getConfigForKeyAssertSingle("link_libc", bool);
1331 const output_mode = try manifest.getConfigForKeyAssertSingle("output_mode", std.builtin.OutputMode);
1332
1333 if (manifest.type == .translate_c) {
1334 for (c_frontends) |c_frontend| {
1335 for (targets) |target_query| {
1336 const output = try manifest.trailingLinesSplit(ctx.arena);
1337 try ctx.translate.append(.{
1338 .name = std.fs.path.stem(filename),
1339 .c_frontend = c_frontend,
1340 .target = resolveTargetQuery(target_query),
1341 .is_test = is_test,
1342 .link_libc = link_libc,
1343 .input = src,
1344 .kind = .{ .translate = output },
1345 });
1346 }
1347 }
1348 continue;
1349 }
1350 if (manifest.type == .run_translated_c) {
1351 for (c_frontends) |c_frontend| {
1352 for (targets) |target_query| {
1353 const output = try manifest.trailingSplit(ctx.arena);
1354 try ctx.translate.append(.{
1355 .name = std.fs.path.stem(filename),
1356 .c_frontend = c_frontend,
1357 .target = resolveTargetQuery(target_query),
1358 .is_test = is_test,
1359 .link_libc = link_libc,
1360 .output = output,
1361 .input = src,
1362 .kind = .{ .run = output },
1363 });
1364 }
1365 }
1366 continue;
1367 }
1368
1369 // Cross-product to get all possible test combinations
1370 for (backends) |backend| {
1371 for (targets) |target| {
1372 const next = ctx.cases.items.len;
1373 try ctx.cases.append(.{
1374 .name = std.fs.path.stem(filename),
1375 .target = target,
1376 .backend = backend,
1377 .updates = std.ArrayList(Cases.Update).init(ctx.cases.allocator),
1378 .is_test = is_test,
1379 .output_mode = output_mode,
1380 .link_libc = backend == .llvm,
1381 .deps = std.ArrayList(DepModule).init(ctx.cases.allocator),
1382 });
1383 try cases.append(next);
1384 }
1385 }
1386 }
1387
1388 for (cases.items) |case_index| {
1389 const case = &ctx.cases.items[case_index];
1390 if (strategy == .incremental and case.backend == .stage2 and case.target.getCpuArch() == .x86_64 and !case.link_libc and case.target.getOsTag() != .plan9) {
1391 // https://github.com/ziglang/zig/issues/15174
1392 continue;
1393 }
1394
1395 switch (manifest.type) {
1396 .compile => {
1397 case.addCompile(src);
1398 },
1399 .@"error" => {
1400 const errors = try manifest.trailingLines(arena);
1401 switch (strategy) {
1402 .independent => {
1403 case.addError(src, errors);
1404 },
1405 .incremental => {
1406 case.addErrorNamed("update", src, errors);
1407 },
1408 }
1409 },
1410 .run => {
1411 const output = try manifest.trailingSplit(ctx.arena);
1412 case.addCompareOutput(src, output);
1413 },
1414 .translate_c => @panic("c_frontend specified for compile case"),
1415 .run_translated_c => @panic("c_frontend specified for compile case"),
1416 .cli => @panic("TODO cli tests"),
1417 }
1418 }
1419 }
1420 }
1421
1422 return runCases(&ctx, zig_exe_path);
1423}
1424
1425fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget {1225fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget {
1426 return .{1226 return .{
1427 .query = query,1227 .query = query,
...@@ -1430,470 +1230,33 @@ fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget {...@@ -1430,470 +1230,33 @@ fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget {
1430 };1230 };
1431}1231}
14321232
1433fn runCases(self: *Cases, zig_exe_path: []const u8) !void {1233fn knownFileExtension(filename: []const u8) bool {
1434 const host = try std.zig.system.resolveTargetQuery(.{});1234 // List taken from `Compilation.classifyFileExt` in the compiler.
14351235 for ([_][]const u8{
1436 var progress = std.Progress{};1236 ".c", ".C", ".cc", ".cpp",
1437 const root_node = progress.start("compiler", self.cases.items.len);1237 ".cxx", ".stub", ".m", ".mm",
1438 progress.terminal = null;1238 ".ll", ".bc", ".s", ".S",
1439 defer root_node.end();1239 ".h", ".zig", ".so", ".dll",
14401240 ".dylib", ".tbd", ".a", ".lib",
1441 var zig_lib_directory = try introspect.findZigLibDirFromSelfExe(self.gpa, zig_exe_path);1241 ".o", ".obj", ".cu", ".def",
1442 defer zig_lib_directory.handle.close();1242 ".rc", ".res", ".manifest",
1443 defer self.gpa.free(zig_lib_directory.path.?);1243 }) |ext| {
14441244 if (std.mem.endsWith(u8, filename, ext)) return true;
1445 var aux_thread_pool: ThreadPool = undefined;
1446 try aux_thread_pool.init(.{ .allocator = self.gpa });
1447 defer aux_thread_pool.deinit();
1448
1449 // Use the same global cache dir for all the tests, such that we for example don't have to
1450 // rebuild musl libc for every case (when LLVM backend is enabled).
1451 var global_tmp = std.testing.tmpDir(.{});
1452 defer global_tmp.cleanup();
1453
1454 var cache_dir = try global_tmp.dir.makeOpenPath(".zig-cache", .{});
1455 defer cache_dir.close();
1456 const tmp_dir_path = try std.fs.path.join(self.gpa, &[_][]const u8{ ".", ".zig-cache", "tmp", &global_tmp.sub_path });
1457 defer self.gpa.free(tmp_dir_path);
1458
1459 const global_cache_directory: Compilation.Directory = .{
1460 .handle = cache_dir,
1461 .path = try std.fs.path.join(self.gpa, &[_][]const u8{ tmp_dir_path, ".zig-cache" }),
1462 };
1463 defer self.gpa.free(global_cache_directory.path.?);
1464
1465 {
1466 for (self.cases.items) |*case| {
1467 if (build_options.skip_non_native) {
1468 if (case.target.getCpuArch() != builtin.cpu.arch)
1469 continue;
1470 if (case.target.getObjectFormat() != builtin.object_format)
1471 continue;
1472 }
1473
1474 // Skip tests that require LLVM backend when it is not available
1475 if (!build_options.have_llvm and case.backend == .llvm)
1476 continue;
1477
1478 assert(case.backend != .stage1);
1479
1480 for (build_options.test_filters) |test_filter| {
1481 if (std.mem.indexOf(u8, case.name, test_filter)) |_| break;
1482 } else if (build_options.test_filters.len > 0) continue;
1483
1484 var prg_node = root_node.start(case.name, case.updates.items.len);
1485 prg_node.activate();
1486 defer prg_node.end();
1487
1488 try runOneCase(
1489 self.gpa,
1490 &prg_node,
1491 case.*,
1492 zig_lib_directory,
1493 zig_exe_path,
1494 &aux_thread_pool,
1495 global_cache_directory,
1496 host,
1497 );
1498 }
1499
1500 for (self.translate.items) |*case| {
1501 _ = case;
1502 @panic("TODO is this even used?");
1503 }
1504 }
1505}
1506
1507fn runOneCase(
1508 allocator: Allocator,
1509 root_node: *std.Progress.Node,
1510 case: Case,
1511 zig_lib_directory: Compilation.Directory,
1512 zig_exe_path: []const u8,
1513 thread_pool: *ThreadPool,
1514 global_cache_directory: Compilation.Directory,
1515 host: std.Target,
1516) !void {
1517 const tmp_src_path = "tmp.zig";
1518 const enable_rosetta = build_options.enable_rosetta;
1519 const enable_qemu = build_options.enable_qemu;
1520 const enable_wine = build_options.enable_wine;
1521 const enable_wasmtime = build_options.enable_wasmtime;
1522 const enable_darling = build_options.enable_darling;
1523 const glibc_runtimes_dir: ?[]const u8 = build_options.glibc_runtimes_dir;
1524
1525 const target = try std.zig.system.resolveTargetQuery(case.target);
1526
1527 var arena_allocator = std.heap.ArenaAllocator.init(allocator);
1528 defer arena_allocator.deinit();
1529 const arena = arena_allocator.allocator();
1530
1531 var tmp = std.testing.tmpDir(.{});
1532 defer tmp.cleanup();
1533
1534 var cache_dir = try tmp.dir.makeOpenPath(".zig-cache", .{});
1535 defer cache_dir.close();
1536
1537 const tmp_dir_path = try std.fs.path.join(
1538 arena,
1539 &[_][]const u8{ ".", ".zig-cache", "tmp", &tmp.sub_path },
1540 );
1541 const local_cache_path = try std.fs.path.join(
1542 arena,
1543 &[_][]const u8{ tmp_dir_path, ".zig-cache" },
1544 );
1545
1546 const zig_cache_directory: Compilation.Directory = .{
1547 .handle = cache_dir,
1548 .path = local_cache_path,
1549 };
1550
1551 var main_pkg: Package = .{
1552 .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir },
1553 .root_src_path = tmp_src_path,
1554 };
1555 defer {
1556 var it = main_pkg.table.iterator();
1557 while (it.next()) |kv| {
1558 allocator.free(kv.key_ptr.*);
1559 kv.value_ptr.*.destroy(allocator);
1560 }
1561 main_pkg.table.deinit(allocator);
1562 }
1563
1564 for (case.deps.items) |dep| {
1565 var pkg = try Package.create(
1566 allocator,
1567 tmp_dir_path,
1568 dep.path,
1569 );
1570 errdefer pkg.destroy(allocator);
1571 try main_pkg.add(allocator, dep.name, pkg);
1572 }1245 }
15731246 // Final check for .so.X, .so.X.Y, .so.X.Y.Z.
1574 const bin_name = try std.zig.binNameAlloc(arena, .{1247 // From `Compilation.hasSharedLibraryExt`.
1575 .root_name = "test_case",1248 var it = std.mem.splitScalar(u8, filename, '.');
1576 .target = target,1249 _ = it.first();
1577 .output_mode = case.output_mode,1250 var so_txt = it.next() orelse return false;
1578 });1251 while (!std.mem.eql(u8, so_txt, "so")) {
15791252 so_txt = it.next() orelse return false;
1580 const emit_directory: Compilation.Directory = .{
1581 .path = tmp_dir_path,
1582 .handle = tmp.dir,
1583 };
1584 const emit_bin: Compilation.EmitLoc = .{
1585 .directory = emit_directory,
1586 .basename = bin_name,
1587 };
1588 const emit_h: ?Compilation.EmitLoc = if (case.emit_h) .{
1589 .directory = emit_directory,
1590 .basename = "test_case.h",
1591 } else null;
1592 const use_llvm: bool = switch (case.backend) {
1593 .llvm => true,
1594 else => false,
1595 };
1596 const comp = try Compilation.create(allocator, .{
1597 .local_cache_directory = zig_cache_directory,
1598 .global_cache_directory = global_cache_directory,
1599 .zig_lib_directory = zig_lib_directory,
1600 .thread_pool = thread_pool,
1601 .root_name = "test_case",
1602 .target = target,
1603 // TODO: support tests for object file building, and library builds
1604 // and linking. This will require a rework to support multi-file
1605 // tests.
1606 .output_mode = case.output_mode,
1607 .is_test = case.is_test,
1608 .optimize_mode = case.optimize_mode,
1609 .emit_bin = emit_bin,
1610 .emit_h = emit_h,
1611 .main_pkg = &main_pkg,
1612 .keep_source_files_loaded = true,
1613 .is_native_os = case.target.isNativeOs(),
1614 .is_native_abi = case.target.isNativeAbi(),
1615 .dynamic_linker = target.dynamic_linker.get(),
1616 .link_libc = case.link_libc,
1617 .use_llvm = use_llvm,
1618 .self_exe_path = zig_exe_path,
1619 // TODO instead of turning off color, pass in a std.Progress.Node
1620 .color = .off,
1621 .reference_trace = 0,
1622 // TODO: force self-hosted linkers with stage2 backend to avoid LLD creeping in
1623 // until the auto-select mechanism deems them worthy
1624 .use_lld = switch (case.backend) {
1625 .stage2 => false,
1626 else => null,
1627 },
1628 });
1629 defer comp.destroy();
1630
1631 update: for (case.updates.items, 0..) |update, update_index| {
1632 var update_node = root_node.start(update.name, 3);
1633 update_node.activate();
1634 defer update_node.end();
1635
1636 var sync_node = update_node.start("write", 0);
1637 sync_node.activate();
1638 for (update.files.items) |file| {
1639 try tmp.dir.writeFile(.{ .sub_path = file.path, .data = file.src });
1640 }
1641 sync_node.end();
1642
1643 var module_node = update_node.start("parse/analysis/codegen", 0);
1644 module_node.activate();
1645 try comp.makeBinFileWritable();
1646 try comp.update(&module_node);
1647 module_node.end();
1648
1649 if (update.case != .Error) {
1650 var all_errors = try comp.getAllErrorsAlloc();
1651 defer all_errors.deinit(allocator);
1652 if (all_errors.errorMessageCount() > 0) {
1653 all_errors.renderToStdErr(.{
1654 .ttyconf = std.io.tty.detectConfig(std.io.getStdErr()),
1655 });
1656 // TODO print generated C code
1657 return error.UnexpectedCompileErrors;
1658 }
1659 }
1660
1661 switch (update.case) {
1662 .Header => |expected_output| {
1663 var file = try tmp.dir.openFile("test_case.h", .{ .mode = .read_only });
1664 defer file.close();
1665 const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024);
1666
1667 try std.testing.expectEqualStrings(expected_output, out);
1668 },
1669 .CompareObjectFile => |expected_output| {
1670 var file = try tmp.dir.openFile(bin_name, .{ .mode = .read_only });
1671 defer file.close();
1672 const out = try file.reader().readAllAlloc(arena, 5 * 1024 * 1024);
1673
1674 try std.testing.expectEqualStrings(expected_output, out);
1675 },
1676 .Compile => {},
1677 .Error => |expected_errors| {
1678 var test_node = update_node.start("assert", 0);
1679 test_node.activate();
1680 defer test_node.end();
1681
1682 var error_bundle = try comp.getAllErrorsAlloc();
1683 defer error_bundle.deinit(allocator);
1684
1685 if (error_bundle.errorMessageCount() == 0) {
1686 return error.ExpectedCompilationErrors;
1687 }
1688
1689 var actual_stderr = std.ArrayList(u8).init(arena);
1690 try error_bundle.renderToWriter(.{
1691 .ttyconf = .no_color,
1692 .include_reference_trace = false,
1693 .include_source_line = false,
1694 }, actual_stderr.writer());
1695
1696 // Render the expected lines into a string that we can compare verbatim.
1697 var expected_generated = std.ArrayList(u8).init(arena);
1698
1699 var actual_line_it = std.mem.splitScalar(u8, actual_stderr.items, '\n');
1700 for (expected_errors) |expect_line| {
1701 const actual_line = actual_line_it.next() orelse {
1702 try expected_generated.appendSlice(expect_line);
1703 try expected_generated.append('\n');
1704 continue;
1705 };
1706 if (std.mem.endsWith(u8, actual_line, expect_line)) {
1707 try expected_generated.appendSlice(actual_line);
1708 try expected_generated.append('\n');
1709 continue;
1710 }
1711 if (std.mem.startsWith(u8, expect_line, ":?:?: ")) {
1712 if (std.mem.endsWith(u8, actual_line, expect_line[":?:?: ".len..])) {
1713 try expected_generated.appendSlice(actual_line);
1714 try expected_generated.append('\n');
1715 continue;
1716 }
1717 }
1718 try expected_generated.appendSlice(expect_line);
1719 try expected_generated.append('\n');
1720 }
1721
1722 try std.testing.expectEqualStrings(expected_generated.items, actual_stderr.items);
1723 },
1724 .Execution => |expected_stdout| {
1725 if (!std.process.can_spawn) {
1726 std.debug.print("Unable to spawn child processes on {s}, skipping test.\n", .{@tagName(builtin.os.tag)});
1727 continue :update; // Pass test.
1728 }
1729
1730 update_node.setEstimatedTotalItems(4);
1731
1732 var argv = std.ArrayList([]const u8).init(allocator);
1733 defer argv.deinit();
1734
1735 const exec_result = x: {
1736 var exec_node = update_node.start("execute", 0);
1737 exec_node.activate();
1738 defer exec_node.end();
1739
1740 // We go out of our way here to use the unique temporary directory name in
1741 // the exe_path so that it makes its way into the cache hash, avoiding
1742 // cache collisions from multiple threads doing `zig run` at the same time
1743 // on the same test_case.c input filename.
1744 const ss = std.fs.path.sep_str;
1745 const exe_path = try std.fmt.allocPrint(
1746 arena,
1747 ".." ++ ss ++ "{s}" ++ ss ++ "{s}",
1748 .{ &tmp.sub_path, bin_name },
1749 );
1750 if (case.target.ofmt != null and case.target.ofmt.? == .c) {
1751 if (getExternalExecutor(host, &target, .{ .link_libc = true }) != .native) {
1752 // We wouldn't be able to run the compiled C code.
1753 continue :update; // Pass test.
1754 }
1755 try argv.appendSlice(&[_][]const u8{
1756 zig_exe_path,
1757 "run",
1758 "-cflags",
1759 "-std=c99",
1760 "-pedantic",
1761 "-Werror",
1762 "-Wno-incompatible-library-redeclaration", // https://github.com/ziglang/zig/issues/875
1763 "--",
1764 "-lc",
1765 exe_path,
1766 });
1767 if (zig_lib_directory.path) |p| {
1768 try argv.appendSlice(&.{ "-I", p });
1769 }
1770 } else switch (getExternalExecutor(host, &target, .{ .link_libc = case.link_libc })) {
1771 .native => {
1772 if (case.backend == .stage2 and case.target.getCpuArch().isArmOrThumb()) {
1773 // https://github.com/ziglang/zig/issues/13623
1774 continue :update; // Pass test.
1775 }
1776 try argv.append(exe_path);
1777 },
1778 .bad_dl, .bad_os_or_cpu => continue :update, // Pass test.
1779
1780 .rosetta => if (enable_rosetta) {
1781 try argv.append(exe_path);
1782 } else {
1783 continue :update; // Rosetta not available, pass test.
1784 },
1785
1786 .qemu => |qemu_bin_name| if (enable_qemu) {
1787 const need_cross_glibc = target.isGnuLibC() and case.link_libc;
1788 const glibc_dir_arg: ?[]const u8 = if (need_cross_glibc)
1789 glibc_runtimes_dir orelse continue :update // glibc dir not available; pass test
1790 else
1791 null;
1792 try argv.append(qemu_bin_name);
1793 if (glibc_dir_arg) |dir| {
1794 const linux_triple = try target.linuxTriple(arena);
1795 const full_dir = try std.fs.path.join(arena, &[_][]const u8{
1796 dir,
1797 linux_triple,
1798 });
1799
1800 try argv.append("-L");
1801 try argv.append(full_dir);
1802 }
1803 try argv.append(exe_path);
1804 } else {
1805 continue :update; // QEMU not available; pass test.
1806 },
1807
1808 .wine => |wine_bin_name| if (enable_wine) {
1809 try argv.append(wine_bin_name);
1810 try argv.append(exe_path);
1811 } else {
1812 continue :update; // Wine not available; pass test.
1813 },
1814
1815 .wasmtime => |wasmtime_bin_name| if (enable_wasmtime) {
1816 try argv.append(wasmtime_bin_name);
1817 try argv.append("--dir=.");
1818 try argv.append(exe_path);
1819 } else {
1820 continue :update; // wasmtime not available; pass test.
1821 },
1822
1823 .darling => |darling_bin_name| if (enable_darling) {
1824 try argv.append(darling_bin_name);
1825 // Since we use relative to cwd here, we invoke darling with
1826 // "shell" subcommand.
1827 try argv.append("shell");
1828 try argv.append(exe_path);
1829 } else {
1830 continue :update; // Darling not available; pass test.
1831 },
1832 }
1833
1834 try comp.makeBinFileExecutable();
1835
1836 while (true) {
1837 break :x std.process.Child.run(.{
1838 .allocator = allocator,
1839 .argv = argv.items,
1840 .cwd_dir = tmp.dir,
1841 .cwd = tmp_dir_path,
1842 }) catch |err| switch (err) {
1843 error.FileBusy => {
1844 // There is a fundamental design flaw in Unix systems with how
1845 // ETXTBSY interacts with fork+exec.
1846 // https://github.com/golang/go/issues/22315
1847 // https://bugs.openjdk.org/browse/JDK-8068370
1848 // Unfortunately, this could be a real error, but we can't
1849 // tell the difference here.
1850 continue;
1851 },
1852 else => {
1853 std.debug.print("\n{s}.{d} The following command failed with {s}:\n", .{
1854 case.name, update_index, @errorName(err),
1855 });
1856 dumpArgs(argv.items);
1857 return error.ChildProcessExecution;
1858 },
1859 };
1860 }
1861 };
1862 var test_node = update_node.start("test", 0);
1863 test_node.activate();
1864 defer test_node.end();
1865 defer allocator.free(exec_result.stdout);
1866 defer allocator.free(exec_result.stderr);
1867 switch (exec_result.term) {
1868 .Exited => |code| {
1869 if (code != 0) {
1870 std.debug.print("\n{s}\n{s}: execution exited with code {d}:\n", .{
1871 exec_result.stderr, case.name, code,
1872 });
1873 dumpArgs(argv.items);
1874 return error.ChildProcessExecution;
1875 }
1876 },
1877 else => {
1878 std.debug.print("\n{s}\n{s}: execution crashed:\n", .{
1879 exec_result.stderr, case.name,
1880 });
1881 dumpArgs(argv.items);
1882 return error.ChildProcessExecution;
1883 },
1884 }
1885 try std.testing.expectEqualStrings(expected_stdout, exec_result.stdout);
1886 // We allow stderr to have garbage in it because wasmtime prints a
1887 // warning about --invoke even though we don't pass it.
1888 //std.testing.expectEqualStrings("", exec_result.stderr);
1889 },
1890 }
1891 }
1892}
1893
1894fn dumpArgs(argv: []const []const u8) void {
1895 for (argv) |arg| {
1896 std.debug.print("{s} ", .{arg});
1897 }1253 }
1898 std.debug.print("\n", .{});1254 const n1 = it.next() orelse return false;
1255 const n2 = it.next();
1256 const n3 = it.next();
1257 _ = std.fmt.parseInt(u32, n1, 10) catch return false;
1258 if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
1259 if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
1260 if (it.next() != null) return false;
1261 return false;
1899}1262}
test/tests.zig-4
...@@ -1250,7 +1250,6 @@ pub fn addCases(...@@ -1250,7 +1250,6 @@ pub fn addCases(
1250 b: *std.Build,1250 b: *std.Build,
1251 parent_step: *Step,1251 parent_step: *Step,
1252 test_filters: []const []const u8,1252 test_filters: []const []const u8,
1253 check_case_exe: *std.Build.Step.Compile,
1254 target: std.Build.ResolvedTarget,1253 target: std.Build.ResolvedTarget,
1255 translate_c_options: @import("src/Cases.zig").TranslateCOptions,1254 translate_c_options: @import("src/Cases.zig").TranslateCOptions,
1256 build_options: @import("cases.zig").BuildOptions,1255 build_options: @import("cases.zig").BuildOptions,
...@@ -1268,12 +1267,9 @@ pub fn addCases(...@@ -1268,12 +1267,9 @@ pub fn addCases(
12681267
1269 cases.lowerToTranslateCSteps(b, parent_step, test_filters, target, translate_c_options);1268 cases.lowerToTranslateCSteps(b, parent_step, test_filters, target, translate_c_options);
12701269
1271 const cases_dir_path = try b.build_root.join(b.allocator, &.{ "test", "cases" });
1272 cases.lowerToBuildSteps(1270 cases.lowerToBuildSteps(
1273 b,1271 b,
1274 parent_step,1272 parent_step,
1275 test_filters,1273 test_filters,
1276 cases_dir_path,
1277 check_case_exe,
1278 );1274 );
1279}1275}