| author | |
| committer | |
| log | 790b8428a26457e7ed9ea20485b9d3085011b989 |
| tree | 3d27f81e31d73af526e8a972504325fa1cb0d9e1 |
| parent | de61540c2d049b0774dd9c5e14aa8f65ed1c25ed |
| parent | cda6f552d5d4a996df69981dac7c9d9b3c066537 |
| signature |
refactors ad infinitum71 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.zig | 522 | src/Sema.zig |
| 523 | src/Sema/bitcast.zig | 523 | src/Sema/bitcast.zig |
| 524 | src/Sema/comptime_ptr_access.zig | 524 | src/Sema/comptime_ptr_access.zig |
| 525 | src/Type.zig | ||
| 525 | src/Value.zig | 526 | src/Value.zig |
| 526 | src/Zcu.zig | 527 | src/Zcu.zig |
| 527 | src/arch/aarch64/CodeGen.zig | 528 | src/arch/aarch64/CodeGen.zig |
| ... | @@ -673,7 +674,6 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -673,7 +674,6 @@ set(ZIG_STAGE2_SOURCES |
| 673 | src/target.zig | 674 | src/target.zig |
| 674 | src/tracy.zig | 675 | src/tracy.zig |
| 675 | src/translate_c.zig | 676 | src/translate_c.zig |
| 676 | src/type.zig | ||
| 677 | src/wasi_libc.zig | 677 | src/wasi_libc.zig |
| 678 | ) | 678 | ) |
| 679 | 679 |
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); |
| 84 | 84 | ||
| 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 | } |
| 227 | 217 | ||
| 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 { |
| 245 | 235 | ||
| 246 | if (link_libc) { | 236 | if (link_libc) { |
| 247 | exe.linkLibC(); | 237 | exe.linkLibC(); |
| 248 | check_case_exe.linkLibC(); | ||
| 249 | } | 238 | } |
| 250 | 239 | ||
| 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 | } |
| 340 | 329 | ||
| 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"); | ||
| 352 | 338 | ||
| 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 | } |
| 359 | 344 | ||
| ... | @@ -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{}; |
| 395 | 380 | ||
| 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); | ||
| 398 | 382 | ||
| 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); |
| 459 | 443 | ||
| 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 | }; |
| 22 | 25 | ||
| 23 | inner: InnerType, | 26 | inner: InnerType, |
| 24 | 27 | ||
| 25 | pub const Error = ElfDynLib.Error || DlDynLib.Error || WindowsDynLib.Error; | 28 | pub const Error = ElfDynLibError || DlDynLibError || WindowsDynLibError; |
| 26 | 29 | ||
| 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 | } |
| 124 | 127 | ||
| 128 | /// Separated to avoid referencing `ElfDynLib`, because its field types may not | ||
| 129 | /// be valid on other targets. | ||
| 130 | const ElfDynLibError = error{ | ||
| 131 | FileTooBig, | ||
| 132 | NotElfFile, | ||
| 133 | NotDynamicLibrary, | ||
| 134 | MissingDynamicLinkingInformation, | ||
| 135 | ElfStringSectionNotFound, | ||
| 136 | ElfSymSectionNotFound, | ||
| 137 | ElfHashTableNotFound, | ||
| 138 | } || posix.OpenError || posix.MMapError; | ||
| 139 | |||
| 125 | pub const ElfDynLib = struct { | 140 | pub 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, |
| 132 | 147 | ||
| 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; | ||
| 142 | 149 | ||
| 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 | } |
| 352 | 359 | ||
| 360 | /// Separated to avoid referencing `WindowsDynLib`, because its field types may not | ||
| 361 | /// be valid on other targets. | ||
| 362 | const WindowsDynLibError = error{ | ||
| 363 | FileNotFound, | ||
| 364 | InvalidPath, | ||
| 365 | } || windows.LoadLibraryError; | ||
| 366 | |||
| 353 | pub const WindowsDynLib = struct { | 367 | pub const WindowsDynLib = struct { |
| 354 | pub const Error = error{ | 368 | pub const Error = WindowsDynLibError; |
| 355 | FileNotFound, | ||
| 356 | InvalidPath, | ||
| 357 | } || windows.LoadLibraryError; | ||
| 358 | 369 | ||
| 359 | dll: windows.HMODULE, | 370 | dll: windows.HMODULE, |
| 360 | 371 | ||
| ... | @@ -413,8 +424,12 @@ pub const WindowsDynLib = struct { | ... | @@ -413,8 +424,12 @@ pub const WindowsDynLib = struct { |
| 413 | } | 424 | } |
| 414 | }; | 425 | }; |
| 415 | 426 | ||
| 427 | /// Separated to avoid referencing `DlDynLib`, because its field types may not | ||
| 428 | /// be valid on other targets. | ||
| 429 | const DlDynLibError = error{ FileNotFound, NameTooLong }; | ||
| 430 | |||
| 416 | pub const DlDynLib = struct { | 431 | pub const DlDynLib = struct { |
| 417 | pub const Error = error{ FileNotFound, NameTooLong }; | 432 | pub const Error = DlDynLibError; |
| 418 | 433 | ||
| 419 | handle: *anyopaque, | 434 | handle: *anyopaque, |
| 420 | 435 |
lib/std/http.zig+6-6| ... | @@ -311,13 +311,13 @@ const builtin = @import("builtin"); | ... | @@ -311,13 +311,13 @@ const builtin = @import("builtin"); |
| 311 | const std = @import("std.zig"); | 311 | const std = @import("std.zig"); |
| 312 | 312 | ||
| 313 | test { | 313 | test { |
| 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 | }; |
| 1931 | 1931 | ||
| 1932 | test { | 1932 | test { |
| 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 | #endif | 208 | #endif |
| 209 | 209 | ||
| 210 | #define zig_mangled_tentative zig_mangled | ||
| 211 | #define zig_mangled_final zig_mangled | ||
| 210 | #if _MSC_VER | 212 | #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; |
| 9 | 9 | ||
| 10 | const Air = @This(); | 10 | const Air = @This(); |
| 11 | const Value = @import("Value.zig"); | 11 | const Value = @import("Value.zig"); |
| 12 | const Type = @import("type.zig").Type; | 12 | const Type = @import("Type.zig"); |
| 13 | const InternPool = @import("InternPool.zig"); | 13 | const InternPool = @import("InternPool.zig"); |
| 14 | const Zcu = @import("Zcu.zig"); | 14 | const 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 | |||
| 1805 | pub const typesFullyResolved = @import("Air/types_resolved.zig").typesFullyResolved; |
src/Air/types_resolved.zig created+521| ... | @@ -0,0 +1,521 @@ | ||
| 1 | const Air = @import("../Air.zig"); | ||
| 2 | const Zcu = @import("../Zcu.zig"); | ||
| 3 | const Type = @import("../Type.zig"); | ||
| 4 | const Value = @import("../Value.zig"); | ||
| 5 | const 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. | ||
| 9 | pub fn typesFullyResolved(air: Air, zcu: *Zcu) bool { | ||
| 10 | return checkBody(air, air.getMainBody(), zcu); | ||
| 11 | } | ||
| 12 | |||
| 13 | fn 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 | |||
| 437 | fn 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 | |||
| 447 | fn 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 | |||
| 461 | fn 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; |
| 12 | const ErrorBundle = std.zig.ErrorBundle; | 12 | const ErrorBundle = std.zig.ErrorBundle; |
| 13 | 13 | ||
| 14 | const Value = @import("Value.zig"); | 14 | const Value = @import("Value.zig"); |
| 15 | const Type = @import("type.zig").Type; | 15 | const Type = @import("Type.zig"); |
| 16 | const target_util = @import("target.zig"); | 16 | const target_util = @import("target.zig"); |
| 17 | const Package = @import("Package.zig"); | 17 | const Package = @import("Package.zig"); |
| 18 | const link = @import("link.zig"); | 18 | const link = @import("link.zig"); |
| ... | @@ -31,11 +31,13 @@ const clangMain = @import("main.zig").clangMain; | ... | @@ -31,11 +31,13 @@ const clangMain = @import("main.zig").clangMain; |
| 31 | const Zcu = @import("Zcu.zig"); | 31 | const Zcu = @import("Zcu.zig"); |
| 32 | /// Deprecated; use `Zcu`. | 32 | /// Deprecated; use `Zcu`. |
| 33 | const Module = Zcu; | 33 | const Module = Zcu; |
| 34 | const Sema = @import("Sema.zig"); | ||
| 34 | const InternPool = @import("InternPool.zig"); | 35 | const InternPool = @import("InternPool.zig"); |
| 35 | const Cache = std.Build.Cache; | 36 | const Cache = std.Build.Cache; |
| 36 | const c_codegen = @import("codegen/c.zig"); | 37 | const c_codegen = @import("codegen/c.zig"); |
| 37 | const libtsan = @import("libtsan.zig"); | 38 | const libtsan = @import("libtsan.zig"); |
| 38 | const Zir = std.zig.Zir; | 39 | const Zir = std.zig.Zir; |
| 40 | const Air = @import("Air.zig"); | ||
| 39 | const Builtin = @import("Builtin.zig"); | 41 | const Builtin = @import("Builtin.zig"); |
| 40 | const LlvmObject = @import("codegen/llvm.zig").Object; | 42 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 41 | 43 | ||
| ... | @@ -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 determined | 329 | /// 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 the | 336 | /// 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, | ||
| 330 | 343 | ||
| 331 | /// one of the glibc static objects | 344 | /// 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 { |
| 2660 | 2678 | ||
| 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 | } |
| 2833 | 2854 | ||
| 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(); |
| 2837 | 2858 | ||
| 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 for | 2872 | // When a parse error is introduced, we keep all the semantic analysis for |
| 2852 | // the previous parse success, including compile errors, but we cannot | 2873 | // 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 | } |
| 2869 | 2894 | ||
| 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 { |
| 2882 | 2907 | ||
| 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 | } |
| 2889 | 2914 | ||
| ... | @@ -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 | } |
| 2990 | 3023 | ||
| 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 | } |
| 3042 | 3075 | ||
| 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); |
| 3054 | 3090 | ||
| 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 | } |
| 3061 | 3097 | ||
| 3062 | try addModuleErrorMsg(zcu, &bundle, err_msg); | 3098 | try addModuleErrorMsg(zcu, &bundle, err_msg, &all_references); |
| 3063 | } | 3099 | } |
| 3064 | } | 3100 | } |
| 3065 | 3101 | ||
| ... | @@ -3115,11 +3151,17 @@ pub const ErrorNoteHashContext = struct { | ... | @@ -3115,11 +3151,17 @@ pub const ErrorNoteHashContext = struct { |
| 3115 | } | 3151 | } |
| 3116 | }; | 3152 | }; |
| 3117 | 3153 | ||
| 3118 | pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void { | 3154 | pub 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); |
| 3135 | 3177 | ||
| 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); |
| 3138 | 3180 | ||
| 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)); | ||
| 3149 | 3216 | ||
| 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 | ); | ||
| 3172 | 3224 | ||
| 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 | 0 | 3233 | 0 |
| 3182 | else | 3234 | 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); |
| 3195 | 3247 | ||
| 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); |
| 3202 | 3255 | ||
| 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(); |
| 3400 | 3453 | ||
| 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); |
| 3410 | 3474 | ||
| ... | @@ -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( |
| 4364 | 4440 | ||
| 4365 | file.status = .retryable_failure; | 4441 | file.status = .retryable_failure; |
| 4366 | 4442 | ||
| 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), |
| 4375 | 4450 | .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 | }; |
| 4383 | 4453 |
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 entries | 82 | /// 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. |
| 84 | first_dependency: std.AutoArrayHashMapUnmanaged(AnalSubject, DepEntry.Index) = .{}, | 84 | first_dependency: std.AutoArrayHashMapUnmanaged(AnalUnit, DepEntry.Index) = .{}, |
| 85 | 85 | ||
| 86 | /// Stores dependency information. The hashmaps declared above are used to look | 86 | /// 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 that | 87 | /// 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 | } |
| 134 | 134 | ||
| 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. |
| 139 | pub const AnalSubject = packed struct(u32) { | 139 | pub 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 | }; |
| 180 | 180 | ||
| 181 | pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalSubject) void { | 181 | pub 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(); |
| 183 | 183 | ||
| 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: |
| 207 | pub const DependencyIterator = struct { | 207 | pub 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 | } |
| 238 | 238 | ||
| 239 | pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalSubject, dependee: Dependee) Allocator.Error!void { | 239 | pub 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 not | 300 | /// 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 in | 301 | /// 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; |
| 3 | const Order = std.math.Order; | 3 | const Order = std.math.Order; |
| 4 | 4 | ||
| 5 | const InternPool = @import("InternPool.zig"); | 5 | const InternPool = @import("InternPool.zig"); |
| 6 | const Type = @import("type.zig").Type; | 6 | const Type = @import("Type.zig"); |
| 7 | const Value = @import("Value.zig"); | 7 | const Value = @import("Value.zig"); |
| 8 | const Zcu = @import("Zcu.zig"); | 8 | const 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 the | 64 | /// instantiation can point back to the instantiation site in addition to the |
| 65 | /// declaration site. | 65 | /// declaration site. |
| 66 | generic_call_src: LazySrcLoc = LazySrcLoc.unneeded, | 66 | generic_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. | ||
| 74 | types_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, because | 68 | /// 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 means | 69 | /// 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. |
| 118 | comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{}, | 110 | comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{}, |
| 119 | 111 | ||
| 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`. | ||
| 114 | exports: 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. | ||
| 119 | references: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, | ||
| 120 | |||
| 120 | const MaybeComptimeAlloc = struct { | 121 | const 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); |
| 167 | const Sema = @This(); | 168 | const Sema = @This(); |
| 168 | const Value = @import("Value.zig"); | 169 | const Value = @import("Value.zig"); |
| 169 | const MutableValue = @import("mutable_value.zig").MutableValue; | 170 | const MutableValue = @import("mutable_value.zig").MutableValue; |
| 170 | const Type = @import("type.zig").Type; | 171 | const Type = @import("Type.zig"); |
| 171 | const Air = @import("Air.zig"); | 172 | const Air = @import("Air.zig"); |
| 172 | const Zir = std.zig.Zir; | 173 | const Zir = std.zig.Zir; |
| 173 | const Zcu = @import("Zcu.zig"); | 174 | const Zcu = @import("Zcu.zig"); |
| ... | @@ -186,6 +187,7 @@ const build_options = @import("build_options"); | ... | @@ -186,6 +187,7 @@ const build_options = @import("build_options"); |
| 186 | const Compilation = @import("Compilation.zig"); | 187 | const Compilation = @import("Compilation.zig"); |
| 187 | const InternPool = @import("InternPool.zig"); | 188 | const InternPool = @import("InternPool.zig"); |
| 188 | const Alignment = InternPool.Alignment; | 189 | const Alignment = InternPool.Alignment; |
| 190 | const AnalUnit = InternPool.AnalUnit; | ||
| 189 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; | 191 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; |
| 190 | 192 | ||
| 191 | pub const default_branch_quota = 1000; | 193 | pub 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 | } |
| 880 | 883 | ||
| ... | @@ -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)); |
| 2068 | 2071 | ||
| 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)); |
| 2073 | 2076 | ||
| 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 | } |
| 2420 | 2422 | ||
| 2421 | fn addFieldErrNote( | 2423 | fn 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 | } |
| 2448 | 2450 | ||
| 2449 | pub fn fail( | 2451 | pub 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; | ||
| 2469 | 2472 | ||
| 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 | } | ||
| 2472 | 2483 | ||
| 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 | } | ||
| 2482 | 2496 | ||
| 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) { |
| 2485 | 2499 | 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 | }; | ||
| 2504 | 2501 | ||
| 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 | else | 2504 | // 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 { |
| 2511 | 2508 | 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 | } |
| 2552 | 2524 | ||
| ... | @@ -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); |
| 2566 | 2537 | ||
| 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 | }; |
| 2574 | 2545 | ||
| 2575 | msg.src_loc = resolved_src; | 2546 | msg.src_loc = src; |
| 2576 | msg.msg = msg_str; | 2547 | msg.msg = msg_str; |
| 2577 | } | 2548 | } |
| 2578 | 2549 | ||
| ... | @@ -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 | } |
| 2654 | 2625 | ||
| 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; |
| 2736 | 2707 | ||
| 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) or | 2710 | 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 | } |
| 2854 | 2825 | ||
| 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 | } |
| 2858 | 2831 | ||
| ... | @@ -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 | } |
| 3354 | 3327 | ||
| 3355 | try mod.finalizeAnonDecl(new_decl_index); | 3328 | try mod.finalizeAnonDecl(new_decl_index); |
| 3356 | 3329 | 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 | } |
| 3359 | 3333 | ||
| ... | @@ -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(); |
| 3479 | 3453 | ||
| 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 | } |
| 3484 | 3458 | ||
| 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 in | 3467 | // 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 | } |
| 3498 | 3471 | ||
| ... | @@ -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( |
| 4081 | fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { | 4054 | fn 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 | } |
| 4086 | 4059 | ||
| 4087 | fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { | 4060 | fn 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 | } |
| 4158 | 4129 | ||
| ... | @@ -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); |
| 4249 | 4221 | ||
| 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 produces | 4239 | // Unless the block is comptime, `alloc_inferred` always produces |
| 4268 | // a runtime constant. The final inferred type needs to be | 4240 | // 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); |
| 4271 | 4243 | ||
| 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 | } |
| 4281 | 4253 | ||
| 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 and | 4901 | 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 implicit | 4905 | // 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; |
| 4941 | 4911 | ||
| 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); |
| 4990 | 4960 | ||
| 4991 | try sema.resolveStructFieldInits(struct_ty); | 4961 | try struct_ty.resolveStructFieldInits(mod); |
| 4992 | 4962 | ||
| 4993 | // We collect the comptime field values in case the struct initialization | 4963 | // 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); |
| 5151 | 5121 | ||
| 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); |
| 5194 | 5164 | ||
| 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( |
| 5261 | 5231 | ||
| 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 { |
| 5708 | 5678 | ||
| 5709 | fn refValue(sema: *Sema, val: InternPool.Index) CompileError!InternPool.Index { | 5679 | fn 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", .{}); |
| 5819 | 5789 | ||
| 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", .{}); |
| 5976 | 5942 | ||
| 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 | } |
| 6425 | 6392 | ||
| 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; |
| 6447 | 6413 | ||
| 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 | } |
| 6469 | 6436 | ||
| 6470 | try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); | 6437 | try sema.maybeQueueFuncBodyAnalysis(src, exported_decl_index); |
| 6471 | 6438 | ||
| 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 | } |
| 6480 | 6446 | ||
| 6481 | fn 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 | |||
| 6512 | fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { | 6447 | fn 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; |
| 6702 | 6637 | ||
| 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 | } |
| 6736 | 6668 | ||
| 6737 | fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 6669 | fn 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 |
| 6888 | 6820 | ||
| 6889 | if (!block.ownerModule().error_tracing) return .none; | 6821 | if (!block.ownerModule().error_tracing) return .none; |
| 6890 | 6822 | ||
| 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.), or | 6861 | // 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. |
| 6937 | 6863 | ||
| 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); |
| 6962 | 6888 | ||
| 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 only | 7014 | // 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); |
| 7095 | 7021 | ||
| ... | @@ -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( |
| 7550 | 7472 | ||
| 7551 | const gpa = sema.gpa; | 7473 | const gpa = sema.gpa; |
| 7552 | 7474 | ||
| 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 | } |
| 7573 | 7490 | ||
| ... | @@ -7927,13 +7844,13 @@ fn analyzeCall( | ... | @@ -7927,13 +7844,13 @@ fn analyzeCall( |
| 7927 | 7844 | ||
| 7928 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); | 7845 | if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); |
| 7929 | 7846 | ||
| 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 | } |
| 7934 | 7850 | ||
| 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); |
| 8372 | 8288 | ||
| 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 | } |
| 8389 | 8303 | ||
| 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); |
| 8393 | 8305 | ||
| 8394 | if (sema.owner_func_index != .none and | 8306 | 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 | } |
| 8399 | 8311 | ||
| 8312 | try sema.addReferenceEntry(call_src, AnalUnit.wrap(.{ .func = callee_index })); | ||
| 8400 | try mod.ensureFuncBodyAnalysisQueued(callee_index); | 8313 | try mod.ensureFuncBodyAnalysisQueued(callee_index); |
| 8401 | 8314 | ||
| 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); |
| 8413 | 8326 | ||
| 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 instruction | 8396 | 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); |
| 8741 | 8657 | ||
| 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 | } |
| 8987 | 8903 | ||
| 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 | } |
| 9022 | 8938 | ||
| ... | @@ -9059,7 +8975,7 @@ fn zirOptionalPayload( | ... | @@ -9059,7 +8975,7 @@ fn zirOptionalPayload( |
| 9059 | // TODO https://github.com/ziglang/zig/issues/6597 | 8975 | // 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( |
| 9177 | 9093 | ||
| 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 | } |
| 9214 | 9130 | ||
| ... | @@ -9656,17 +9572,8 @@ fn funcCommon( | ... | @@ -9656,17 +9572,8 @@ fn funcCommon( |
| 9656 | } | 9572 | } |
| 9657 | } | 9573 | } |
| 9658 | 9574 | ||
| 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; |
| 9671 | 9578 | ||
| 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 can | 9922 | // 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 | } |
| 10020 | 9927 | ||
| 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 | }; |
| 10076 | 9983 | ||
| 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; | ||
| 10092 | 9985 | ||
| 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 { |
| 11239 | 11132 | ||
| 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 | } |
| 11245 | 11138 | ||
| ... | @@ -11452,7 +11345,7 @@ fn switchCond( | ... | @@ -11452,7 +11345,7 @@ fn switchCond( |
| 11452 | }, | 11345 | }, |
| 11453 | 11346 | ||
| 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 | } |
| 13746 | 13639 | ||
| 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); |
| 13756 | 13649 | ||
| 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; |
| 13824 | 13717 | ||
| 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 | } |
| 13936 | 13829 | ||
| 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); |
| 14636 | 14529 | ||
| 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 | } |
| 14966 | 14859 | ||
| 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 directly | 15072 | // 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 directly | 15208 | // 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 directly | 15375 | // 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)) and | 15736 | 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( |
| 16247 | 16140 | ||
| 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( |
| 16881 | 16774 | ||
| 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; |
| 16896 | 16789 | ||
| ... | @@ -16903,7 +16796,7 @@ fn analyzePtrArithmetic( | ... | @@ -16903,7 +16796,7 @@ fn analyzePtrArithmetic( |
| 16903 | )); | 16796 | )); |
| 16904 | assert(new_align != .none); | 16797 | assert(new_align != .none); |
| 16905 | 16798 | ||
| 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); |
| 16924 | 16817 | ||
| 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 | } |
| 17069 | 16960 | ||
| ... | @@ -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 | } |
| 17446 | 17334 | ||
| ... | @@ -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 | } |
| 17486 | 17374 | ||
| ... | @@ -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 | }; |
| 17512 | 17400 | ||
| 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 | }; |
| 17668 | 17556 | ||
| 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).?; |
| 17695 | 17583 | ||
| 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 | } }); |
| 17803 | 17691 | ||
| 17804 | const callconv_ty = try sema.getBuiltinType("CallingConvention"); | 17692 | const callconv_ty = try mod.getBuiltinType("CallingConvention"); |
| 17805 | 17693 | ||
| 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(); |
| 17837 | 17725 | ||
| 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 | else | 17771 | else |
| 17884 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); | 17772 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); |
| 17885 | 17773 | ||
| 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 | }; |
| 18039 | 17927 | ||
| 18040 | try sema.queueFullTypeResolution(error_field_ty); | ||
| 18041 | |||
| 18042 | // Build our list of Error values | 17928 | // Build our list of Error values |
| 18043 | // Optional value is only null if anyerror | 17929 | // Optional value is only null if anyerror |
| 18044 | // Value can be zero-length slice otherwise | 17930 | // 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 | }; |
| 18090 | 17976 | ||
| 18091 | // Build our ?[]const Error value | 17977 | // 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 | }; |
| 18317 | 18203 | ||
| 18318 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 18204 | 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 | }; |
| 18352 | 18238 | ||
| 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 | }; |
| 18357 | 18243 | ||
| ... | @@ -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 | }; |
| 18467 | 18353 | ||
| 18468 | try sema.resolveTypeLayout(ty); // Getting alignment requires type layout | 18354 | try ty.resolveLayout(mod); // Getting alignment requires type layout |
| 18469 | 18355 | ||
| 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 | }; |
| 18507 | 18393 | ||
| 18508 | try sema.resolveTypeLayout(Type.fromInterned(field_ty)); | 18394 | try Type.fromInterned(field_ty).resolveLayout(mod); |
| 18509 | 18395 | ||
| 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); |
| 18536 | 18422 | ||
| 18537 | try sema.resolveStructFieldInits(ty); | 18423 | try ty.resolveStructFieldInits(mod); |
| 18538 | 18424 | ||
| 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 | }; |
| 18582 | 18469 | ||
| ... | @@ -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 | }; |
| 18690 | 18577 | ||
| 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)); |
| 18693 | 18580 | ||
| 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); | ||
| 18734 | 18620 | ||
| 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 |
| 19348 | 19234 | ||
| 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}; |
| 19590 | 19476 | ||
| 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 | } |
| 19790 | 19676 | ||
| 19791 | try sema.resolveTypeLayout(sema.fn_ret_ty); | 19677 | try sema.fn_ret_ty.resolveLayout(mod); |
| 19792 | 19678 | ||
| 19793 | try sema.validateRuntimeValue(block, operand_src, operand); | 19679 | try sema.validateRuntimeValue(block, operand_src, operand); |
| 19794 | 19680 | ||
| ... | @@ -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; |
| 19876 | 19762 | ||
| ... | @@ -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 | } |
| 19947 | 19833 | ||
| 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); |
| 20040 | 19926 | ||
| 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( |
| 20107 | 19993 | ||
| 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 | } |
| 20113 | 19998 | ||
| ... | @@ -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); |
| 20140 | 20025 | ||
| 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( |
| 20250 | 20135 | ||
| 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 | } |
| 20265 | 20150 | ||
| 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 | } |
| 20343 | 20227 | ||
| 20344 | try sema.resolveStructFieldInits(struct_ty); | 20228 | try struct_ty.resolveStructFieldInits(mod); |
| 20345 | 20229 | ||
| 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 | } |
| 20412 | 20296 | ||
| 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( |
| 20543 | 20426 | ||
| 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; |
| 20559 | 20442 | ||
| 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); | ||
| 20698 | 20580 | ||
| 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( |
| 20707 | 20589 | ||
| 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 | } |
| 20722 | 20604 | ||
| 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( |
| 20808 | 20690 | ||
| 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 { |
| 20936 | fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref { | 20818 | fn 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()); |
| 20943 | 20825 | ||
| ... | @@ -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 | } |
| 20979 | 20858 | ||
| ... | @@ -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; |
| 21150 | 21029 | ||
| 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 | ); |
| 21259 | 21138 | ||
| 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 | ).?); |
| 21275 | 21154 | ||
| 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(); |
| 21278 | 21157 | ||
| 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 | ).?); |
| 21293 | 21172 | ||
| 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 | } |
| 21343 | 21222 | ||
| 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( |
| 21349 | 21228 | ||
| 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 | } |
| 21354 | 21233 | ||
| 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 | } |
| 21395 | 21274 | ||
| 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 | ).?); |
| 21424 | 21303 | ||
| 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); |
| 21530 | 21409 | ||
| 21531 | // Decls | 21410 | // 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 | } |
| 21535 | 21414 | ||
| ... | @@ -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 | ).?); |
| 21564 | 21443 | ||
| 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 | } |
| 21568 | 21447 | ||
| ... | @@ -21580,7 +21459,7 @@ fn zirReify( | ... | @@ -21580,7 +21459,7 @@ fn zirReify( |
| 21580 | ).?); | 21459 | ).?); |
| 21581 | 21460 | ||
| 21582 | // Decls | 21461 | // 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 | } |
| 21586 | 21465 | ||
| ... | @@ -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 | ).?); |
| 21630 | 21509 | ||
| 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( |
| 21987 | 21866 | ||
| 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 location | 21871 | // 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( |
| 22032 | 21911 | ||
| 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 location | 21916 | // 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; |
| 22090 | 21969 | ||
| 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 | } |
| 22094 | 21975 | ||
| ... | @@ -22162,7 +22043,7 @@ fn reifyStruct( | ... | @@ -22162,7 +22043,7 @@ fn reifyStruct( |
| 22162 | 22043 | ||
| 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 | } |
| 22247 | 22128 | ||
| 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 | } |
| 22354 | 22235 | ||
| 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 | } |
| 22358 | 22241 | ||
| 22359 | fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) CompileError!Air.Inst.Ref { | 22242 | fn 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); |
| 22362 | 22245 | ||
| 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); |
| 22397 | 22280 | ||
| 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"); |
| 22400 | 22283 | ||
| 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 |
| 22416 | fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { | 22299 | fn 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)); |
| 22418 | 22301 | ||
| 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); |
| 22551 | 22434 | ||
| 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); |
| 22599 | 22482 | ||
| 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); |
| 22602 | 22485 | ||
| 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); |
| 22897 | 22780 | ||
| 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); |
| 22900 | 22783 | ||
| 22901 | const src_slice_like = src_info.flags.size == .Slice or | 22784 | 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 first | 23027 | // 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 instructions | 23112 | // 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; |
| 23287 | 23170 | ||
| 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 |
| 23576 | 23459 | ||
| 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; |
| 23831 | 23714 | ||
| 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); |
| 23834 | 23717 | ||
| 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); |
| 24012 | 23895 | ||
| ... | @@ -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); |
| 24832 | 24715 | ||
| 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); |
| 24938 | 24821 | ||
| 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 | else | 24881 | 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 | } |
| 25025 | 24909 | ||
| 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); |
| 25029 | 24913 | ||
| 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; |
| 25608 | 25491 | ||
| 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; |
| 25619 | 25502 | ||
| 25620 | // ok1: dest >= src + len | 25503 | // 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; |
| 25959 | 25842 | ||
| 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); |
| 26175 | 26058 | ||
| 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( |
| 26194 | 26077 | ||
| 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); |
| 26247 | 26130 | ||
| 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); |
| 26495 | 26378 | ||
| 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 | } |
| 26499 | 26382 | ||
| ... | @@ -26620,7 +26503,7 @@ const ExternPosition = enum { | ... | @@ -26620,7 +26503,7 @@ const ExternPosition = enum { |
| 26620 | 26503 | ||
| 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. |
| 26624 | fn validateExternType( | 26507 | fn 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 | } |
| 26851 | 26734 | ||
| 26852 | fn prepareSimplePanic(sema: *Sema, block: *Block) !void { | 26735 | fn prepareSimplePanic(sema: *Sema) !void { |
| 26853 | const mod = sema.mod; | 26736 | const mod = sema.mod; |
| 26854 | 26737 | ||
| 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 actually | 26740 | // 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 | } |
| 26867 | 26750 | ||
| 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; |
| 26893 | 26776 | ||
| 26894 | try sema.prepareSimplePanic(block); | 26777 | try sema.prepareSimplePanic(); |
| 26895 | 26778 | ||
| 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 | } |
| 27001 | 26884 | ||
| 27002 | try sema.prepareSimplePanic(block); | 26885 | try sema.prepareSimplePanic(); |
| 27003 | 26886 | ||
| 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); |
| 27465 | 27348 | ||
| 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 | }); |
| 27474 | 27357 | ||
| 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); |
| 27479 | 27362 | ||
| ... | @@ -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 | }); |
| 27492 | 27375 | ||
| 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); |
| 27497 | 27380 | ||
| ... | @@ -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) orelse | 27542 | 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)) orelse | 27584 | const decl_idx = (try sema.namespaceLookup(block, src, namespace, field_name)) orelse |
| 27702 | break :found_decl null; | 27585 | break :found_decl null; |
| 27703 | 27586 | ||
| 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 | } |
| 27810 | 27692 | ||
| 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 | } |
| 27863 | 27744 | ||
| 27864 | fn namespaceLookupVal( | 27745 | fn 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); |
| 27888 | 27769 | ||
| 27889 | try sema.resolveTypeFields(struct_ty); | 27770 | try struct_ty.resolveFields(mod); |
| 27890 | try sema.resolveStructLayout(struct_ty); | 27771 | try struct_ty.resolveLayout(mod); |
| 27891 | 27772 | ||
| 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 | } |
| 27927 | 27808 | ||
| 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 | } |
| 27932 | 27813 | ||
| ... | @@ -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_align | 27861 | 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 | } |
| 27983 | 27865 | ||
| 27984 | const ptr_field_ty = try sema.ptrType(ptr_ty_data); | 27866 | const ptr_field_ty = try mod.ptrTypeSema(ptr_ty_data); |
| 27985 | 27867 | ||
| 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); |
| 28012 | 27894 | ||
| 28013 | try sema.resolveTypeFields(struct_ty); | 27895 | try struct_ty.resolveFields(mod); |
| 28014 | 27896 | ||
| 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) orelse | 27903 | 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 | } |
| 28027 | 27909 | ||
| ... | @@ -28038,7 +27920,7 @@ fn structFieldVal( | ... | @@ -28038,7 +27920,7 @@ fn structFieldVal( |
| 28038 | } | 27920 | } |
| 28039 | 27921 | ||
| 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); |
| 28106 | 27988 | ||
| 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 | } |
| 28127 | 28009 | ||
| 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 | } |
| 28132 | 28014 | ||
| ... | @@ -28147,11 +28029,11 @@ fn unionFieldPtr( | ... | @@ -28147,11 +28029,11 @@ fn unionFieldPtr( |
| 28147 | 28029 | ||
| 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.alignment | 28044 | union_ptr_info.flags.alignment |
| 28163 | else | 28045 | 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 | } |
| 28224 | 28106 | ||
| ... | @@ -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); |
| 28255 | 28137 | ||
| 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 | } |
| 28317 | 28199 | ||
| ... | @@ -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); |
| 28388 | 28270 | ||
| 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 checkIndexable | 28286 | 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); |
| 28527 | 28409 | ||
| 28528 | if (field_count == 0) { | 28410 | if (field_count == 0) { |
| ... | @@ -28536,7 +28418,7 @@ fn tupleFieldPtr( | ... | @@ -28536,7 +28418,7 @@ fn tupleFieldPtr( |
| 28536 | } | 28418 | } |
| 28537 | 28419 | ||
| 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 | }); |
| 28547 | 28429 | ||
| 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); |
| 28550 | 28432 | ||
| 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 | } |
| 28558 | 28440 | ||
| 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 | } |
| 28563 | 28445 | ||
| ... | @@ -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); |
| 28584 | 28466 | ||
| 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); |
| 28596 | 28478 | ||
| 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 field | 28482 | 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); |
| 28609 | 28491 | ||
| 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 | } |
| 28614 | 28496 | ||
| ... | @@ -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); |
| 28639 | 28521 | ||
| 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()); |
| 28677 | 28559 | ||
| 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 | } |
| 28682 | 28563 | ||
| ... | @@ -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; |
| 28715 | 28596 | ||
| 28716 | const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset); | 28597 | const elem_ptr_ty = try array_ptr_ty.elemPtrType(offset, mod); |
| 28717 | 28598 | ||
| 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( |
| 28765 | 28646 | ||
| 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 | else | 28675 | 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 | } |
| 28802 | 28682 | ||
| ... | @@ -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; |
| 28823 | 28703 | ||
| 28824 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset); | 28704 | const elem_ptr_ty = try slice_ty.elemPtrType(offset, mod); |
| 28825 | 28705 | ||
| 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 location | 28797 | 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 | } |
| 29002 | 28881 | ||
| ... | @@ -29227,7 +29106,7 @@ fn coerceExtra( | ... | @@ -29227,7 +29106,7 @@ fn coerceExtra( |
| 29227 | // empty tuple to zero-length slice | 29106 | // 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 error | 29255 | // 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 | } |
| 30705 | 30584 | ||
| 30706 | try sema.requireRuntimeBlock(block, src, runtime_src); | 30585 | try sema.requireRuntimeBlock(block, src, runtime_src); |
| 30707 | try sema.queueFullTypeResolution(elem_ty); | ||
| 30708 | 30586 | ||
| 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); |
| 30930 | 30808 | ||
| 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); |
| 30933 | 30811 | ||
| 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( |
| 31111 | 30989 | ||
| 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); |
| 31529 | 31407 | ||
| 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 | } |
| 31792 | 31669 | ||
| 31793 | fn addReferencedBy( | 31670 | fn 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 fixed | 31677 | 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 | } |
| 31806 | 31683 | ||
| 31807 | pub fn ensureDeclAnalyzed(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!void { | 31684 | pub 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 | } |
| 31853 | 31730 | ||
| 31854 | fn analyzeDeclRef(sema: *Sema, decl_index: InternPool.DeclIndex) CompileError!Air.Inst.Ref { | 31731 | fn 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 | } |
| 31857 | 31734 | ||
| 31858 | /// Analyze a reference to the decl at the given index. Ensures the underlying decl is analyzed, but | 31735 | /// 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 a | 31736 | /// 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` wraps | 31737 | /// 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. |
| 31862 | fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn_body: bool) CompileError!Air.Inst.Ref { | 31739 | fn 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); |
| 31865 | 31743 | ||
| 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 type | 31751 | // 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 | } |
| 31892 | 31770 | ||
| 31893 | fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void { | 31771 | fn 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 | } |
| 31901 | 31780 | ||
| ... | @@ -31910,22 +31789,22 @@ fn analyzeRef( | ... | @@ -31910,22 +31789,22 @@ fn analyzeRef( |
| 31910 | 31789 | ||
| 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 | } |
| 31918 | 31797 | ||
| 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; |
| 32406 | 32285 | ||
| 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( |
| 32558 | 32437 | ||
| 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; |
| 32622 | 32501 | ||
| 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); |
| 32625 | 32504 | ||
| 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 | } |
| 32687 | 32566 | ||
| 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 the | 32593 | // we don't need to add one for sentinels because the |
| 32715 | // underlying value data includes the sentinel | 32594 | // 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 | } |
| 32718 | 32597 | ||
| 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_true | 32688 | .bool_true |
| 32810 | else | 32689 | 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 | else | 32757 | 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 | else | 32761 | 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 | } |
| 33196 | 33074 | ||
| ... | @@ -33993,7 +33871,7 @@ fn resolvePeerTypesInner( | ... | @@ -33993,7 +33871,7 @@ fn resolvePeerTypesInner( |
| 33993 | 33871 | ||
| 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 | }, |
| 33998 | 33876 | ||
| 33999 | .ptr => { | 33877 | .ptr => { |
| ... | @@ -34303,7 +34181,7 @@ fn resolvePeerTypesInner( | ... | @@ -34303,7 +34181,7 @@ fn resolvePeerTypesInner( |
| 34303 | }, | 34181 | }, |
| 34304 | } | 34182 | } |
| 34305 | 34183 | ||
| 34306 | return .{ .success = try sema.ptrType(opt_ptr_info.?) }; | 34184 | return .{ .success = try mod.ptrTypeSema(opt_ptr_info.?) }; |
| 34307 | }, | 34185 | }, |
| 34308 | 34186 | ||
| 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); |
| 34664 | 34542 | ||
| 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).?; |
| 34798 | 34676 | ||
| 34799 | try sema.resolveTypeFully(Type.fromInterned(fn_ty_info.return_type)); | 34677 | try Type.fromInterned(fn_ty_info.return_type).resolveFully(mod); |
| 34800 | 34678 | ||
| 34801 | if (mod.comp.config.any_error_tracing and | 34679 | 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 | } |
| 34807 | 34685 | ||
| 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 | } |
| 34812 | 34690 | ||
| 34813 | /// Make it so that calling hash() and eql() on `val` will not assert due | ||
| 34814 | /// to a type not having its layout resolved. | ||
| 34815 | fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { | 34691 | fn 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 | |||
| 34932 | pub 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 | } |
| 34975 | 34694 | ||
| 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(); |
| 34986 | 34705 | ||
| 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"); |
| 34989 | 34710 | ||
| ... | @@ -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 | } |
| 34999 | 34720 | ||
| 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); |
| 35012 | 34733 | ||
| ... | @@ -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 | } |
| 35026 | 34748 | ||
| 35027 | struct_type.flagsPtr(ip).alignment = result; | 34749 | struct_type.flagsPtr(ip).alignment = result; |
| 35028 | return result; | ||
| 35029 | } | 34750 | } |
| 35030 | 34751 | ||
| 35031 | fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void { | 34752 | pub 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; |
| 35035 | 34756 | ||
| 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; |
| 35038 | 34761 | ||
| 35039 | try sema.resolveTypeFields(ty); | 34762 | try ty.resolveFields(zcu); |
| 35040 | 34763 | ||
| 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 | } |
| 35045 | 34771 | ||
| ... | @@ -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 | } |
| 35267 | 34996 | ||
| 35268 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | 34997 | fn 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(); |
| 35329 | 35058 | ||
| 35059 | assert(sema.ownerUnit().unwrap().decl == union_type.decl); | ||
| 35060 | |||
| 35330 | assert(!union_type.haveLayout(ip)); | 35061 | assert(!union_type.haveLayout(ip)); |
| 35331 | 35062 | ||
| 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 | } |
| 35341 | 35072 | ||
| 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 | } |
| 35357 | 35088 | ||
| 35358 | union_type.flagsPtr(ip).alignment = max_align; | 35089 | union_type.flagsPtr(ip).alignment = max_align; |
| 35359 | return max_align; | ||
| 35360 | } | 35090 | } |
| 35361 | 35091 | ||
| 35362 | /// This logic must be kept in sync with `Module.getUnionLayout`. | 35092 | /// This logic must be kept in sync with `Module.getUnionLayout`. |
| 35363 | fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void { | 35093 | pub 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; |
| 35366 | 35096 | ||
| ... | @@ -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); |
| 35371 | 35101 | ||
| 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 { |
| 35477 | 35209 | ||
| 35478 | /// Returns `error.AnalysisFail` if any of the types (recursively) failed to | 35210 | /// Returns `error.AnalysisFail` if any of the types (recursively) failed to |
| 35479 | /// be resolved. | 35211 | /// be resolved. |
| 35480 | pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void { | 35212 | pub 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 | |||
| 35520 | fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { | ||
| 35521 | try sema.resolveStructLayout(ty); | 35213 | try sema.resolveStructLayout(ty); |
| 35522 | 35214 | ||
| 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).?; |
| 35526 | 35218 | ||
| 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); |
| 35529 | 35223 | ||
| ... | @@ -35533,16 +35227,19 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { | ... | @@ -35533,16 +35227,19 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void { |
| 35533 | 35227 | ||
| 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 | } |
| 35539 | 35233 | ||
| 35540 | fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void { | 35234 | pub fn resolveUnionFully(sema: *Sema, ty: Type) SemaError!void { |
| 35541 | try sema.resolveUnionLayout(ty); | 35235 | try sema.resolveUnionLayout(ty); |
| 35542 | 35236 | ||
| 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 | } |
| 35569 | 35266 | ||
| 35570 | pub 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. | ||
| 35670 | fn 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 | |||
| 35689 | pub fn resolveTypeFieldsStruct( | 35267 | pub 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; |
| 35698 | 35276 | ||
| 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 | } |
| 35732 | 35313 | ||
| 35733 | pub fn resolveStructFieldInits(sema: *Sema, ty: Type) CompileError!void { | 35314 | pub 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; |
| 35738 | 35319 | ||
| 35320 | assert(sema.ownerUnit().unwrap().decl == owner_decl); | ||
| 35321 | |||
| 35739 | // Inits can start as resolved | 35322 | // Inits can start as resolved |
| 35740 | if (struct_type.haveFieldInits(ip)) return; | 35323 | if (struct_type.haveFieldInits(ip)) return; |
| 35741 | 35324 | ||
| ... | @@ -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 | } |
| 35765 | 35349 | ||
| 35766 | pub fn resolveTypeFieldsUnion(sema: *Sema, ty: Type, union_type: InternPool.LoadedUnionType) CompileError!void { | 35350 | pub 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 that | 35449 | // 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 | } |
| 35865 | 35454 | ||
| ... | @@ -36225,6 +35814,8 @@ fn semaStructFields( | ... | @@ -36225,6 +35814,8 @@ fn semaStructFields( |
| 36225 | 35814 | ||
| 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 | } |
| 36229 | 35820 | ||
| 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 | } |
| 36369 | 35962 | ||
| 36370 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { | 35963 | fn 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 | } |
| 36742 | 36337 | ||
| 36743 | fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Type, tag_ref: Air.Inst.Ref) CompileError!Value { | 36338 | fn 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 | } |
| 36848 | 36443 | ||
| 36849 | fn 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 | |||
| 36882 | fn 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 | |||
| 36911 | fn 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 one | 36444 | /// There is another implementation of this in `Type.onePossibleValue`. This one |
| 36950 | /// in `Sema` is for calling during semantic analysis, and performs field resolution | 36445 | /// 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 asserts | 36446 | /// 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 | }, |
| 37150 | 36645 | ||
| 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); | ||
| 37154 | 36652 | ||
| 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 and | 36654 | // 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 | }, |
| 37209 | 36698 | ||
| 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).*))) orelse | 36705 | 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)) orelse | 36712 | 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); |
| 37345 | 36828 | ||
| 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 { |
| 37530 | 37013 | ||
| 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. |
| 37533 | pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool { | 37016 | pub fn typeRequiresComptime(sema: *Sema, ty: Type) SemaError!bool { |
| 37534 | return ty.comptimeOnlyAdvanced(sema.mod, sema); | 37017 | return ty.comptimeOnlyAdvanced(sema.mod, .sema); |
| 37535 | } | 37018 | } |
| 37536 | 37019 | ||
| 37537 | pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { | 37020 | pub 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 | } |
| 37544 | 37026 | ||
| 37545 | pub fn typeAbiSize(sema: *Sema, ty: Type) !u64 { | 37027 | pub 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 | } |
| 37549 | 37031 | ||
| 37550 | pub fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!Alignment { | 37032 | pub 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`. | ||
| 37556 | pub 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`. | ||
| 37567 | pub 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 | } |
| 37588 | 37035 | ||
| 37589 | pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { | 37036 | pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool { |
| 37590 | return ty.fnHasRuntimeBitsAdvanced(sema.mod, sema); | 37037 | return ty.fnHasRuntimeBitsAdvanced(sema.mod, .sema); |
| 37591 | } | 37038 | } |
| 37592 | 37039 | ||
| 37593 | fn unionFieldIndex( | 37040 | fn 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) orelse | 37051 | 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 | } |
| 37648 | 37095 | ||
| 37649 | fn 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, setting | 37096 | /// 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). |
| 37655 | fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value { | 37098 | fn 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( |
| 37881 | 37324 | ||
| 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( |
| 38069 | 37512 | ||
| 38070 | fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool { | 37513 | fn 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( |
| 38139 | 37582 | ||
| 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 | } |
| 38200 | 37643 | ||
| ... | @@ -38230,80 +37673,6 @@ fn compareVector( | ... | @@ -38230,80 +37673,6 @@ fn compareVector( |
| 38230 | } }))); | 37673 | } }))); |
| 38231 | } | 37674 | } |
| 38232 | 37675 | ||
| 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`. | ||
| 38242 | pub 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. |
| 38309 | fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type { | 37678 | fn 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 | } |
| 38346 | 37715 | ||
| 38347 | pub 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 | |||
| 38354 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | 37716 | pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 38355 | if (!sema.mod.comp.debug_incremental) return; | 37717 | if (!sema.mod.comp.debug_incremental) return; |
| 38356 | 37718 | ||
| ... | @@ -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 | } |
| 38364 | 37726 | ||
| 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 | else | 37730 | 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 | } |
| 38496 | 37858 | ||
| 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. | ||
| 37862 | pub 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 | |||
| 37902 | pub 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 | |||
| 38497 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; | 37910 | pub const bitCastVal = @import("Sema/bitcast.zig").bitCast; |
| 38498 | pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; | 37911 | pub const bitCastSpliceVal = @import("Sema/bitcast.zig").bitCastSplice; |
| 38499 | 37912 |
src/Sema/bitcast.zig+5-5| ... | @@ -78,8 +78,8 @@ fn bitCastInner( | ... | @@ -78,8 +78,8 @@ fn bitCastInner( |
| 78 | 78 | ||
| 79 | const val_ty = val.typeOf(zcu); | 79 | const val_ty = val.typeOf(zcu); |
| 80 | 80 | ||
| 81 | try sema.resolveTypeLayout(val_ty); | 81 | try val_ty.resolveLayout(zcu); |
| 82 | try sema.resolveTypeLayout(dest_ty); | 82 | try dest_ty.resolveLayout(zcu); |
| 83 | 83 | ||
| 84 | assert(val_ty.hasWellDefinedLayout(zcu)); | 84 | assert(val_ty.hasWellDefinedLayout(zcu)); |
| 85 | 85 | ||
| ... | @@ -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); |
| 138 | 138 | ||
| 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); |
| 141 | 141 | ||
| 142 | const splice_bits = splice_val_ty.bitSize(zcu); | 142 | const splice_bits = splice_val_ty.bitSize(zcu); |
| 143 | 143 | ||
| ... | @@ -767,6 +767,6 @@ const assert = std.debug.assert; | ... | @@ -767,6 +767,6 @@ const assert = std.debug.assert; |
| 767 | const Sema = @import("../Sema.zig"); | 767 | const Sema = @import("../Sema.zig"); |
| 768 | const Zcu = @import("../Zcu.zig"); | 768 | const Zcu = @import("../Zcu.zig"); |
| 769 | const InternPool = @import("../InternPool.zig"); | 769 | const InternPool = @import("../InternPool.zig"); |
| 770 | const Type = @import("../type.zig").Type; | 770 | const Type = @import("../Type.zig"); |
| 771 | const Value = @import("../Value.zig"); | 771 | const Value = @import("../Value.zig"); |
| 772 | const CompileError = Zcu.CompileError; | 772 | const 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; |
| 1054 | const Sema = @import("../Sema.zig"); | 1054 | const Sema = @import("../Sema.zig"); |
| 1055 | const Block = Sema.Block; | 1055 | const Block = Sema.Block; |
| 1056 | const MutableValue = @import("../mutable_value.zig").MutableValue; | 1056 | const MutableValue = @import("../mutable_value.zig").MutableValue; |
| 1057 | const Type = @import("../type.zig").Type; | 1057 | const Type = @import("../Type.zig"); |
| 1058 | const Value = @import("../Value.zig"); | 1058 | const Value = @import("../Value.zig"); |
| 1059 | const Zcu = @import("../Zcu.zig"); | 1059 | const Zcu = @import("../Zcu.zig"); |
| 1060 | const LazySrcLoc = Zcu.LazySrcLoc; | 1060 | const 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 | |||
| 6 | const std = @import("std"); | ||
| 7 | const builtin = @import("builtin"); | ||
| 8 | const Allocator = std.mem.Allocator; | ||
| 9 | const Value = @import("Value.zig"); | ||
| 10 | const assert = std.debug.assert; | ||
| 11 | const Target = std.Target; | ||
| 12 | const Zcu = @import("Zcu.zig"); | ||
| 13 | /// Deprecated. | ||
| 14 | const Module = Zcu; | ||
| 15 | const log = std.log.scoped(.Type); | ||
| 16 | const target_util = @import("target.zig"); | ||
| 17 | const Sema = @import("Sema.zig"); | ||
| 18 | const InternPool = @import("InternPool.zig"); | ||
| 19 | const Alignment = InternPool.Alignment; | ||
| 20 | const Zir = std.zig.Zir; | ||
| 21 | const Type = @This(); | ||
| 22 | const SemaError = Zcu.SemaError; | ||
| 23 | |||
| 24 | ip_index: InternPool.Index, | ||
| 25 | |||
| 26 | pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId { | ||
| 27 | return ty.zigTypeTagOrPoison(mod) catch unreachable; | ||
| 28 | } | ||
| 29 | |||
| 30 | pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId { | ||
| 31 | return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern()); | ||
| 32 | } | ||
| 33 | |||
| 34 | pub 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 | |||
| 44 | pub 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. | ||
| 84 | pub 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. | ||
| 92 | pub fn ptrIsMutable(ty: Type, mod: *const Module) bool { | ||
| 93 | return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const; | ||
| 94 | } | ||
| 95 | |||
| 96 | pub const ArrayInfo = struct { | ||
| 97 | elem_type: Type, | ||
| 98 | sentinel: ?Value = null, | ||
| 99 | len: u64, | ||
| 100 | }; | ||
| 101 | |||
| 102 | pub 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 | |||
| 110 | pub 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 | |||
| 121 | pub 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 | |||
| 129 | pub 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 | |||
| 137 | pub const Formatter = std.fmt.Formatter(format2); | ||
| 138 | |||
| 139 | pub fn fmt(ty: Type, module: *Module) Formatter { | ||
| 140 | return .{ .data = .{ | ||
| 141 | .ty = ty, | ||
| 142 | .module = module, | ||
| 143 | } }; | ||
| 144 | } | ||
| 145 | |||
| 146 | const FormatContext = struct { | ||
| 147 | ty: Type, | ||
| 148 | module: *Module, | ||
| 149 | }; | ||
| 150 | |||
| 151 | fn 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 | |||
| 162 | pub 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. | ||
| 168 | pub 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. | ||
| 181 | pub 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 | |||
| 449 | pub fn fromInterned(i: InternPool.Index) Type { | ||
| 450 | assert(i != .none); | ||
| 451 | return .{ .ip_index = i }; | ||
| 452 | } | ||
| 453 | |||
| 454 | pub fn toIntern(ty: Type) InternPool.Index { | ||
| 455 | assert(ty.ip_index != .none); | ||
| 456 | return ty.ip_index; | ||
| 457 | } | ||
| 458 | |||
| 459 | pub fn toValue(self: Type) Value { | ||
| 460 | return Value.fromInterned(self.toIntern()); | ||
| 461 | } | ||
| 462 | |||
| 463 | const 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. | ||
| 476 | pub 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 | ||
| 672 | pub 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 | |||
| 780 | pub fn hasRuntimeBits(ty: Type, mod: *Module) bool { | ||
| 781 | return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable; | ||
| 782 | } | ||
| 783 | |||
| 784 | pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool { | ||
| 785 | return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable; | ||
| 786 | } | ||
| 787 | |||
| 788 | pub 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. | ||
| 795 | pub 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 | |||
| 803 | pub 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. | ||
| 811 | pub 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 | |||
| 818 | pub 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. | ||
| 823 | pub fn ptrAlignment(ty: Type, mod: *Module) Alignment { | ||
| 824 | return ptrAlignmentAdvanced(ty, mod, .normal) catch unreachable; | ||
| 825 | } | ||
| 826 | |||
| 827 | pub 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 | |||
| 845 | pub 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. | ||
| 854 | pub 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`. | ||
| 860 | pub 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 | |||
| 867 | pub const AbiAlignmentAdvanced = union(enum) { | ||
| 868 | scalar: Alignment, | ||
| 869 | val: Value, | ||
| 870 | }; | ||
| 871 | |||
| 872 | pub 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. | ||
| 886 | pub 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. | ||
| 908 | pub 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 | |||
| 1132 | fn 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 | |||
| 1169 | fn 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`. | ||
| 1208 | pub 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. | ||
| 1217 | pub fn abiSize(ty: Type, mod: *Module) u64 { | ||
| 1218 | return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar; | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | const 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. | ||
| 1232 | pub 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 | |||
| 1508 | fn 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 | |||
| 1552 | pub fn ptrAbiAlignment(target: Target) Alignment { | ||
| 1553 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | pub 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 | |||
| 1560 | pub 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 | |||
| 1587 | pub 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 | |||
| 1678 | pub fn bitSize(ty: Type, mod: *Module) u64 { | ||
| 1679 | return bitSizeAdvanced(ty, mod, .normal) catch unreachable; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | pub 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. | ||
| 1849 | pub 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 | |||
| 1864 | pub 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. | ||
| 1872 | pub 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. | ||
| 1877 | pub 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 | |||
| 1884 | pub 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 | |||
| 1891 | pub fn slicePtrFieldType(ty: Type, mod: *const Module) Type { | ||
| 1892 | return Type.fromInterned(mod.intern_pool.slicePtrType(ty.toIntern())); | ||
| 1893 | } | ||
| 1894 | |||
| 1895 | pub 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 | |||
| 1902 | pub fn isVolatilePtr(ty: Type, mod: *const Module) bool { | ||
| 1903 | return isVolatilePtrIp(ty, &mod.intern_pool); | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | pub 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 | |||
| 1913 | pub 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 | |||
| 1921 | pub 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 | |||
| 1928 | pub 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. | ||
| 1947 | pub 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`. | ||
| 1955 | pub 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`. | ||
| 1970 | pub 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. | ||
| 1987 | pub fn childType(ty: Type, mod: *const Module) Type { | ||
| 1988 | return childTypeIp(ty, &mod.intern_pool); | ||
| 1989 | } | ||
| 1990 | |||
| 1991 | pub 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. | ||
| 2004 | pub 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 | |||
| 2021 | fn 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. | ||
| 2029 | pub 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. | ||
| 2038 | pub 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`. | ||
| 2051 | pub 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. | ||
| 2069 | pub 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. | ||
| 2084 | pub 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 | |||
| 2089 | pub 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 | |||
| 2097 | pub 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 | |||
| 2103 | pub 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 | |||
| 2108 | pub 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. | ||
| 2119 | pub 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 | |||
| 2127 | pub 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 | |||
| 2133 | pub 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. | ||
| 2144 | pub 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. | ||
| 2149 | pub 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. | ||
| 2154 | pub 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. | ||
| 2172 | pub 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 | |||
| 2184 | pub 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. | ||
| 2194 | pub 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. | ||
| 2216 | pub 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. | ||
| 2241 | pub fn arrayLen(ty: Type, mod: *const Module) u64 { | ||
| 2242 | return ty.arrayLenIp(&mod.intern_pool); | ||
| 2243 | } | ||
| 2244 | |||
| 2245 | pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 { | ||
| 2246 | return ip.aggregateTypeLen(ty.toIntern()); | ||
| 2247 | } | ||
| 2248 | |||
| 2249 | pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 { | ||
| 2250 | return mod.intern_pool.aggregateTypeLenIncludingSentinel(ty.toIntern()); | ||
| 2251 | } | ||
| 2252 | |||
| 2253 | pub 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. | ||
| 2262 | pub 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. | ||
| 2277 | pub 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. | ||
| 2283 | pub 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. | ||
| 2295 | pub 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. | ||
| 2308 | pub 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. | ||
| 2317 | pub 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 | |||
| 2386 | pub 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`. | ||
| 2406 | pub 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`. | ||
| 2421 | pub 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. | ||
| 2438 | pub 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. | ||
| 2452 | pub 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. | ||
| 2457 | pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention { | ||
| 2458 | return mod.intern_pool.indexToKey(ty.toIntern()).func_type.cc; | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | pub 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 | |||
| 2468 | pub 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. | ||
| 2476 | pub fn fnIsVarArgs(ty: Type, mod: *Module) bool { | ||
| 2477 | return mod.intern_pool.indexToKey(ty.toIntern()).func_type.is_var_args; | ||
| 2478 | } | ||
| 2479 | |||
| 2480 | pub 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. | ||
| 2512 | pub 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. | ||
| 2736 | pub 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. | ||
| 2742 | pub 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 | |||
| 2928 | pub 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. | ||
| 2933 | pub 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 | |||
| 2939 | pub fn isArrayOrVector(ty: Type, mod: *const Module) bool { | ||
| 2940 | return switch (ty.zigTypeTag(mod)) { | ||
| 2941 | .Array, .Vector => true, | ||
| 2942 | else => false, | ||
| 2943 | }; | ||
| 2944 | } | ||
| 2945 | |||
| 2946 | pub 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 | |||
| 2962 | pub 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. | ||
| 2980 | pub fn getNamespaceIndex(ty: Type, zcu: *Zcu) InternPool.OptionalNamespaceIndex { | ||
| 2981 | return ty.getNamespace(zcu).?; | ||
| 2982 | } | ||
| 2983 | |||
| 2984 | /// Returns null if the type has no namespace. | ||
| 2985 | pub 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. | ||
| 3016 | pub 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. | ||
| 3025 | pub 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. | ||
| 3045 | pub 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. | ||
| 3054 | pub 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. | ||
| 3089 | pub 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 | |||
| 3098 | pub 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. | ||
| 3111 | pub 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 | |||
| 3124 | pub fn enumFields(ty: Type, mod: *Module) InternPool.NullTerminatedString.Slice { | ||
| 3125 | return mod.intern_pool.loadEnumType(ty.toIntern()).names; | ||
| 3126 | } | ||
| 3127 | |||
| 3128 | pub fn enumFieldCount(ty: Type, mod: *Module) usize { | ||
| 3129 | return mod.intern_pool.loadEnumType(ty.toIntern()).names.len; | ||
| 3130 | } | ||
| 3131 | |||
| 3132 | pub 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 | |||
| 3137 | pub 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. | ||
| 3146 | pub 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. | ||
| 3159 | pub 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 | |||
| 3168 | pub 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. | ||
| 3178 | pub 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 | |||
| 3191 | pub fn structFieldAlign(ty: Type, index: usize, zcu: *Zcu) Alignment { | ||
| 3192 | return ty.structFieldAlignAdvanced(index, zcu, .normal) catch unreachable; | ||
| 3193 | } | ||
| 3194 | |||
| 3195 | pub 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 | |||
| 3216 | pub 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 | |||
| 3236 | pub 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 | |||
| 3260 | pub 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 | |||
| 3269 | pub const FieldOffset = struct { | ||
| 3270 | field: usize, | ||
| 3271 | offset: u64, | ||
| 3272 | }; | ||
| 3273 | |||
| 3274 | /// Supports structs and unions. | ||
| 3275 | pub 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 | |||
| 3324 | pub fn getOwnerDecl(ty: Type, mod: *Module) InternPool.DeclIndex { | ||
| 3325 | return ty.getOwnerDeclOrNull(mod) orelse unreachable; | ||
| 3326 | } | ||
| 3327 | |||
| 3328 | pub 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 | |||
| 3339 | pub 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 | |||
| 3355 | pub fn srcLoc(ty: Type, zcu: *Zcu) Module.LazySrcLoc { | ||
| 3356 | return ty.srcLocOrNull(zcu).?; | ||
| 3357 | } | ||
| 3358 | |||
| 3359 | pub fn isGenericPoison(ty: Type) bool { | ||
| 3360 | return ty.toIntern() == .generic_poison_type; | ||
| 3361 | } | ||
| 3362 | |||
| 3363 | pub 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 | |||
| 3377 | pub 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 | |||
| 3385 | pub 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 | |||
| 3399 | pub 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 | |||
| 3406 | pub 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`. | ||
| 3415 | pub 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 | |||
| 3424 | pub 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 | |||
| 3435 | pub 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 | |||
| 3446 | pub 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. | ||
| 3474 | pub 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 | |||
| 3485 | pub 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 | |||
| 3495 | pub 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 | |||
| 3550 | pub 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 | |||
| 3596 | pub 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 | |||
| 3694 | pub 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 | |||
| 3748 | pub 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 | |||
| 3754 | pub fn resolveStructAlignment(ty: Type, zcu: *Zcu) SemaError!void { | ||
| 3755 | return ty.resolveStructInner(zcu, .alignment); | ||
| 3756 | } | ||
| 3757 | |||
| 3758 | pub fn resolveUnionAlignment(ty: Type, zcu: *Zcu) SemaError!void { | ||
| 3759 | return ty.resolveUnionInner(zcu, .alignment); | ||
| 3760 | } | ||
| 3761 | |||
| 3762 | /// `ty` must be a struct. | ||
| 3763 | fn 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. | ||
| 3805 | fn 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. | ||
| 3848 | fn 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`. | ||
| 3877 | pub 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 | |||
| 3941 | pub const @"u1": Type = .{ .ip_index = .u1_type }; | ||
| 3942 | pub const @"u8": Type = .{ .ip_index = .u8_type }; | ||
| 3943 | pub const @"u16": Type = .{ .ip_index = .u16_type }; | ||
| 3944 | pub const @"u29": Type = .{ .ip_index = .u29_type }; | ||
| 3945 | pub const @"u32": Type = .{ .ip_index = .u32_type }; | ||
| 3946 | pub const @"u64": Type = .{ .ip_index = .u64_type }; | ||
| 3947 | pub const @"u128": Type = .{ .ip_index = .u128_type }; | ||
| 3948 | |||
| 3949 | pub const @"i8": Type = .{ .ip_index = .i8_type }; | ||
| 3950 | pub const @"i16": Type = .{ .ip_index = .i16_type }; | ||
| 3951 | pub const @"i32": Type = .{ .ip_index = .i32_type }; | ||
| 3952 | pub const @"i64": Type = .{ .ip_index = .i64_type }; | ||
| 3953 | pub const @"i128": Type = .{ .ip_index = .i128_type }; | ||
| 3954 | |||
| 3955 | pub const @"f16": Type = .{ .ip_index = .f16_type }; | ||
| 3956 | pub const @"f32": Type = .{ .ip_index = .f32_type }; | ||
| 3957 | pub const @"f64": Type = .{ .ip_index = .f64_type }; | ||
| 3958 | pub const @"f80": Type = .{ .ip_index = .f80_type }; | ||
| 3959 | pub const @"f128": Type = .{ .ip_index = .f128_type }; | ||
| 3960 | |||
| 3961 | pub const @"bool": Type = .{ .ip_index = .bool_type }; | ||
| 3962 | pub const @"usize": Type = .{ .ip_index = .usize_type }; | ||
| 3963 | pub const @"isize": Type = .{ .ip_index = .isize_type }; | ||
| 3964 | pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type }; | ||
| 3965 | pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type }; | ||
| 3966 | pub const @"void": Type = .{ .ip_index = .void_type }; | ||
| 3967 | pub const @"type": Type = .{ .ip_index = .type_type }; | ||
| 3968 | pub const @"anyerror": Type = .{ .ip_index = .anyerror_type }; | ||
| 3969 | pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type }; | ||
| 3970 | pub const @"anyframe": Type = .{ .ip_index = .anyframe_type }; | ||
| 3971 | pub const @"null": Type = .{ .ip_index = .null_type }; | ||
| 3972 | pub const @"undefined": Type = .{ .ip_index = .undefined_type }; | ||
| 3973 | pub const @"noreturn": Type = .{ .ip_index = .noreturn_type }; | ||
| 3974 | |||
| 3975 | pub const @"c_char": Type = .{ .ip_index = .c_char_type }; | ||
| 3976 | pub const @"c_short": Type = .{ .ip_index = .c_short_type }; | ||
| 3977 | pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type }; | ||
| 3978 | pub const @"c_int": Type = .{ .ip_index = .c_int_type }; | ||
| 3979 | pub const @"c_uint": Type = .{ .ip_index = .c_uint_type }; | ||
| 3980 | pub const @"c_long": Type = .{ .ip_index = .c_long_type }; | ||
| 3981 | pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type }; | ||
| 3982 | pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type }; | ||
| 3983 | pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type }; | ||
| 3984 | pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type }; | ||
| 3985 | |||
| 3986 | pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; | ||
| 3987 | pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type }; | ||
| 3988 | pub const single_const_pointer_to_comptime_int: Type = .{ | ||
| 3989 | .ip_index = .single_const_pointer_to_comptime_int_type, | ||
| 3990 | }; | ||
| 3991 | pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; | ||
| 3992 | pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type }; | ||
| 3993 | |||
| 3994 | pub const generic_poison: Type = .{ .ip_index = .generic_poison_type }; | ||
| 3995 | |||
| 3996 | pub 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! | ||
| 4005 | pub const packed_struct_layout_version = 2; | ||
| 4006 | |||
| 4007 | fn 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 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const Type = @import("type.zig").Type; | 3 | const Type = @import("Type.zig"); |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const BigIntConst = std.math.big.int.Const; | 5 | const BigIntConst = std.math.big.int.Const; |
| 6 | const BigIntMutable = std.math.big.int.Mutable; | 6 | const 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 | } |
| 163 | 163 | ||
| 164 | pub const ResolveStrat = Type.ResolveStrat; | ||
| 165 | |||
| 164 | /// Asserts the value is an integer. | 166 | /// Asserts the value is an integer. |
| 165 | pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst { | 167 | pub 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 | } |
| 168 | 170 | ||
| 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. |
| 230 | pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 { | 232 | pub 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 | } |
| 233 | 235 | ||
| 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. |
| 236 | pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 { | 238 | pub 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 0 | 250 | .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 | } |
| 274 | 270 | ||
| 275 | /// Asserts the value is an integer and it fits in a u64 | 271 | /// Asserts the value is an integer and it fits in a u64 |
| 276 | pub fn toUnsignedInt(val: Value, mod: *Module) u64 { | 272 | pub fn toUnsignedInt(val: Value, zcu: *Zcu) u64 { |
| 277 | return getUnsignedInt(val, mod).?; | 273 | return getUnsignedInt(val, zcu).?; |
| 278 | } | 274 | } |
| 279 | 275 | ||
| 280 | /// Asserts the value is an integer and it fits in a u64 | 276 | /// Asserts the value is an integer and it fits in a u64 |
| 281 | pub fn toUnsignedIntAdvanced(val: Value, sema: *Sema) !u64 { | 277 | pub fn toUnsignedIntSema(val: Value, zcu: *Zcu) !u64 { |
| 282 | return (try getUnsignedIntAdvanced(val, sema.mod, sema)).?; | 278 | return (try getUnsignedIntAdvanced(val, zcu, .sema)).?; |
| 283 | } | 279 | } |
| 284 | 280 | ||
| 285 | /// Asserts the value is an integer and it fits in a i64 | 281 | /// 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 | } |
| 1029 | 1025 | ||
| 1030 | pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order { | 1026 | pub 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 | } |
| 1033 | 1029 | ||
| 1034 | pub fn orderAgainstZeroAdvanced( | 1030 | pub 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( |
| 1069 | 1065 | ||
| 1070 | /// Asserts the value is comparable. | 1066 | /// Asserts the value is comparable. |
| 1071 | pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order { | 1067 | pub 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 | } |
| 1074 | 1070 | ||
| 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. | 1072 | pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, strat: ResolveStrat) !std.math.Order { |
| 1077 | pub 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 |
| 1096 | 1091 | ||
| 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 | } |
| 1103 | 1098 | ||
| 1104 | /// Asserts the value is comparable. Does not take a type parameter because it supports | 1099 | /// Asserts the value is comparable. Does not take a type parameter because it supports |
| 1105 | /// comparisons between heterogeneous types. | 1100 | /// comparisons between heterogeneous types. |
| 1106 | pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool { | 1101 | pub 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 | } |
| 1109 | 1104 | ||
| 1110 | pub fn compareHeteroAdvanced( | 1105 | pub 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 | } |
| 1140 | 1135 | ||
| 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, ...)` |
| 1178 | pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator, mod: *Module) bool { | 1173 | pub 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 | } |
| 1181 | 1176 | ||
| 1182 | pub fn compareAllWithZeroAdvanced( | 1177 | pub 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 | } |
| 1189 | 1184 | ||
| 1190 | pub fn compareAllWithZeroAdvancedExtra( | 1185 | pub 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 | } |
| 1223 | 1218 | ||
| 1224 | pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool { | 1219 | pub 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 | } |
| 1280 | 1275 | ||
| 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. |
| 1283 | pub fn sliceLen(val: Value, sema: *Sema) !u64 { | 1278 | pub 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 | } |
| 1286 | 1281 | ||
| 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 | } |
| 1483 | 1478 | ||
| 1484 | pub fn floatFromInt(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module) !Value { | 1479 | pub 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 | } |
| 1490 | 1485 | ||
| 1491 | pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { | 1486 | pub 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 | } |
| 1506 | 1501 | ||
| 1507 | pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value { | 1502 | pub 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; |
| 3616 | 3603 | ||
| 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. |
| 3620 | pub fn ptrOptPayload(parent_ptr: Value, sema: *Sema) !Value { | 3607 | pub 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); |
| 3625 | 3610 | ||
| 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); |
| 3628 | 3613 | ||
| 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 same | 3616 | // 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 { |
| 3651 | 3636 | ||
| 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. |
| 3655 | pub fn ptrEuPayload(parent_ptr: Value, sema: *Sema) !Value { | 3640 | pub 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); |
| 3660 | 3643 | ||
| 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); |
| 3663 | 3646 | ||
| 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 a | 3649 | // 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. |
| 3686 | pub fn ptrField(parent_ptr: Value, field_idx: u32, sema: *Sema) !Value { | 3669 | pub 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); |
| 3691 | 3672 | ||
| ... | @@ -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 a | 3744 | // 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 | }; |
| 3806 | 3787 | ||
| 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; |
| 3814 | 3795 | ||
| 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 { |
| 3834 | 3815 | ||
| 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. |
| 3838 | pub fn ptrElem(orig_parent_ptr: Value, field_idx: u64, sema: *Sema) !Value { | 3819 | pub 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 { |
| 3845 | 3824 | ||
| 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); |
| 3849 | 3828 | ||
| 3850 | if (parent_ptr.isUndef(zcu)) return zcu.undefValue(result_ty); | 3829 | if (parent_ptr.isUndef(zcu)) return zcu.undefValue(result_ty); |
| 3851 | 3830 | ||
| ... | @@ -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 { |
| 3862 | 3841 | ||
| 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 | }, |
| 3875 | 3854 | ||
| 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 | else | 3857 | else |
| 3879 | .{ .offset = field_idx * try sema.typeAbiSize(elem_ty) }, | 3858 | .{ .offset = field_idx * (try elem_ty.abiSizeAdvanced(zcu, .sema)).scalar }, |
| 3880 | 3859 | ||
| 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) { |
| 4014 | pub fn pointerDerivation(ptr_val: Value, arena: Allocator, zcu: *Zcu) Allocator.Error!PointerDeriveStep { | 3993 | pub 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 | } |
| 4024 | 3999 | ||
| ... | @@ -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 | |||
| 4248 | pub 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(); |
| 20 | const Compilation = @import("Compilation.zig"); | 20 | const Compilation = @import("Compilation.zig"); |
| 21 | const Cache = std.Build.Cache; | 21 | const Cache = std.Build.Cache; |
| 22 | const Value = @import("Value.zig"); | 22 | const Value = @import("Value.zig"); |
| 23 | const Type = @import("type.zig").Type; | 23 | const Type = @import("Type.zig"); |
| 24 | const Package = @import("Package.zig"); | 24 | const Package = @import("Package.zig"); |
| 25 | const link = @import("link.zig"); | 25 | const link = @import("link.zig"); |
| 26 | const Air = @import("Air.zig"); | 26 | const Air = @import("Air.zig"); |
| ... | @@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir; | ... | @@ -35,6 +35,7 @@ const isUpDir = @import("introspect.zig").isUpDir; |
| 35 | const clang = @import("clang.zig"); | 35 | const clang = @import("clang.zig"); |
| 36 | const InternPool = @import("InternPool.zig"); | 36 | const InternPool = @import("InternPool.zig"); |
| 37 | const Alignment = InternPool.Alignment; | 37 | const Alignment = InternPool.Alignment; |
| 38 | const AnalUnit = InternPool.AnalUnit; | ||
| 38 | const BuiltinFn = std.zig.BuiltinFn; | 39 | const BuiltinFn = std.zig.BuiltinFn; |
| 39 | const LlvmObject = @import("codegen/llvm.zig").Object; | 40 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 40 | 41 | ||
| ... | @@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined, | ... | @@ -71,18 +72,22 @@ codegen_prog_node: std.Progress.Node = undefined, |
| 71 | global_zir_cache: Compilation.Directory, | 72 | global_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. |
| 73 | local_zir_cache: Compilation.Directory, | 74 | local_zir_cache: Compilation.Directory, |
| 74 | /// It's rare for a decl to be exported, so we save memory by having a sparse | 75 | /// 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 itself | 77 | all_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 |
| 78 | decl_exports: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{}, | 79 | /// future semantic analysis. |
| 79 | /// Same as `decl_exports` but for exported constant values. | 80 | free_exports: ArrayListUnmanaged(u32) = .{}, |
| 80 | value_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 Decl | 82 | /// 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 that | 83 | /// whose analysis triggered the export. |
| 83 | /// is performing the export of another Decl. | 84 | single_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, |
| 84 | /// This table owns the Export memory. | 85 | /// Like `single_exports`, but for `AnalUnit`s which perform multiple exports. |
| 85 | export_owners: std.AutoArrayHashMapUnmanaged(Decl.Index, ArrayListUnmanaged(*Export)) = .{}, | 86 | /// The exports are `all_exports.items[index..][0..len]`. |
| 87 | multi_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 order | 91 | /// 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 when | 92 | /// 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. |
| 104 | intern_pool: InternPool = .{}, | 109 | intern_pool: InternPool = .{}, |
| 105 | 110 | ||
| 106 | /// We optimize memory usage for a compilation with no compile errors by storing the | 111 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| 107 | /// error messages and mapping outside of `Decl`. | 112 | failed_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. | ||
| 111 | failed_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`. |
| 114 | compile_log_decls: std.AutoArrayHashMapUnmanaged(Decl.Index, extern struct { | 115 | compile_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 { |
| 126 | failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, | 127 | failed_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. |
| 128 | failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{}, | 129 | failed_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. | 131 | failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{}, |
| 131 | failed_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. |
| 134 | cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, std.zig.ErrorBundle) = .{}, | 134 | cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .{}, |
| 135 | 135 | ||
| 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. |
| 137 | global_error_set: GlobalErrorSet = .{}, | 137 | global_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-limit | 139 | /// Maximum amount of distinct error values, set by --error-limit |
| 140 | error_limit: ErrorInt, | 140 | error_limit: ErrorInt, |
| 141 | 141 | ||
| 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. |
| 143 | potentially_outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, u32) = .{}, | 143 | potentially_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. |
| 146 | outdated: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, u32) = .{}, | 146 | outdated: 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. |
| 150 | outdated_ready: std.AutoArrayHashMapUnmanaged(InternPool.AnalSubject, void) = .{}, | 150 | outdated_ready: std.AutoArrayHashMapUnmanaged(AnalUnit, void) = .{}, |
| 151 | /// This contains a set of Decls which may not be in `outdated`, but are the | 151 | /// 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 preserved | 153 | /// 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`, the | 154 | /// (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. |
| 156 | outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | 156 | outdated_file_root: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 157 | /// This contains a list of AnalSubject whose analysis or codegen failed, but the | 157 | /// 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 may | 158 | /// 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 of | 159 | /// succeed. On the next update, we will flush this list, marking all members of |
| 160 | /// it as outdated. | 160 | /// it as outdated. |
| 161 | retryable_failures: std.ArrayListUnmanaged(InternPool.AnalSubject) = .{}, | 161 | retryable_failures: std.ArrayListUnmanaged(AnalUnit) = .{}, |
| 162 | 162 | ||
| 163 | stage1_flags: packed struct { | 163 | stage1_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, |
| 176 | 176 | ||
| 177 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, | 177 | test_functions: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{}, |
| 178 | 178 | ||
| 179 | /// TODO: the key here will be a `Cau.Index`. | ||
| 179 | global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{}, | 180 | global_assembly: std.AutoArrayHashMapUnmanaged(Decl.Index, []u8) = .{}, |
| 180 | 181 | ||
| 181 | reference_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`. | ||
| 187 | reference_table: std.AutoArrayHashMapUnmanaged(AnalUnit, u32) = .{}, | ||
| 188 | all_references: std.ArrayListUnmanaged(Reference) = .{}, | ||
| 189 | /// Freelist of indices in `all_references`. | ||
| 190 | free_references: std.ArrayListUnmanaged(u32) = .{}, | ||
| 185 | 191 | ||
| 186 | panic_messages: [PanicId.len]Decl.OptionalIndex = .{.none} ** PanicId.len, | 192 | panic_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 | }; |
| 266 | 286 | ||
| 267 | pub const Export = struct { | 287 | pub 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 | }; |
| 293 | 307 | ||
| 294 | const ValueArena = struct { | 308 | pub 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, |
| 297 | 311 | /// 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 instance | 312 | /// `std.math.maxInt(u32)` is the sentinel. |
| 299 | prev: ?*ValueArena = null, | 313 | next: u32, |
| 300 | 314 | /// The source location of the reference. | |
| 301 | /// Returns an allocator backed by either promoting `state`, or by the existing ArenaAllocator | 315 | 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 | }; |
| 333 | 317 | ||
| 334 | pub const Decl = struct { | 318 | pub 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 has | 360 | /// Sematic analysis and constant value codegen of this Decl has |
| 377 | /// succeeded. However, the Decl may be outdated due to an in-progress | 361 | /// 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, |
| 765 | 749 | ||
| ... | @@ -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 | } |
| 927 | 914 | ||
| 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 the | 917 | // 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 more | 930 | // 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 speed | 931 | // 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), |
| 947 | 934 | ||
| 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 | } |
| 951 | 938 | ||
| 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 | } |
| 958 | 945 | ||
| 959 | /// Mark this file and every file referenced by it as multi_pkg and report an | 946 | /// 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 | }; |
| 998 | 985 | ||
| 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 they | 987 | /// 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. | ||
| 1007 | pub const ErrorMsg = struct { | 989 | pub 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 | }; | ||
| 1018 | 994 | ||
| 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 { |
| 1038 | 1014 | ||
| 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 | } |
| 2407 | 2379 | ||
| 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(); |
| 2473 | 2442 | ||
| 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); |
| 2478 | 2447 | ||
| 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); |
| 2507 | 2476 | ||
| 2508 | zcu.compile_log_decls.deinit(gpa); | 2477 | zcu.compile_log_sources.deinit(gpa); |
| 2509 | 2478 | ||
| 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); | ||
| 2524 | 2483 | ||
| 2525 | zcu.global_error_set.deinit(gpa); | 2484 | zcu.global_error_set.deinit(gpa); |
| 2526 | 2485 | ||
| ... | @@ -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); |
| 2539 | 2498 | ||
| 2540 | zcu.reference_table.deinit(gpa); | 2499 | zcu.reference_table.deinit(gpa); |
| 2500 | zcu.all_references.deinit(gpa); | ||
| 2501 | zcu.free_references.deinit(gpa); | ||
| 2541 | 2502 | ||
| 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 | } |
| 2592 | 2553 | ||
| 2593 | fn 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/8643 | 2554 | // TODO https://github.com/ziglang/zig/issues/8643 |
| 2599 | const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; | 2555 | const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8; |
| 2600 | const HackDataLayout = extern struct { | 2556 | const 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 | } |
| 3139 | 3095 | ||
| 3140 | /// Given a AnalSubject which is newly outdated or PO, mark all AnalSubjects which may | 3096 | /// 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. |
| 3142 | fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: InternPool.AnalSubject) !void { | 3098 | fn 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 introduced | 3100 | .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 | } |
| 3168 | 3124 | ||
| 3169 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?InternPool.AnalSubject { | 3125 | pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { |
| 3170 | if (!zcu.comp.debug_incremental) return null; | 3126 | if (!zcu.comp.debug_incremental) return null; |
| 3171 | 3127 | ||
| 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 | } |
| 3176 | 3132 | ||
| 3177 | // Our goal is to find an outdated AnalSubject which itself has no outdated or | 3133 | // 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 track | 3134 | // 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 not | 3135 | // them in the `outdated_ready` set for efficiency. However, this is not |
| 3180 | // necessarily the case, since the Decl dependency graph may contain loops | 3136 | // 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 this | 3153 | // `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 have | 3158 | // 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 | } |
| 3215 | 3171 | ||
| 3216 | // There is no single AnalSubject which is ready for re-analysis. Instead, we | 3172 | // 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 the | 3173 | // 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 dependency | 3175 | // 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 |
| 3221 | 3177 | ||
| 3222 | // The choice of this Decl could have a big impact on how much total | 3178 | // 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 avoid | 3180 | // 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 a | 3182 | // 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 | }); |
| 3273 | 3229 | ||
| 3274 | return InternPool.AnalSubject.wrap(.{ .decl = chosen_decl_idx.? }); | 3230 | return AnalUnit.wrap(.{ .decl = chosen_decl_idx.? }); |
| 3275 | } | 3231 | } |
| 3276 | 3232 | ||
| 3277 | /// During an incremental update, before semantic analysis, call this to flush all values from | 3233 | /// 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 as | 3245 | // 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 listed | 3412 | // 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. |
| 3458 | 3414 | ||
| 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) or | 3416 | 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); |
| 3462 | 3418 | ||
| ... | @@ -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 here | 3441 | // 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 | } |
| 3490 | 3447 | ||
| 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 | } |
| 3609 | 3566 | ||
| 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) or | 3568 | 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); |
| 3613 | 3570 | ||
| 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 | } |
| 3617 | 3577 | ||
| 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); |
| 3651 | 3611 | ||
| 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); |
| 3670 | 3630 | ||
| 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 | } |
| 3674 | 3635 | ||
| 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. | ||
| 3644 | pub 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); |
| 3677 | 3660 | ||
| 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 | } |
| 3684 | 3667 | ||
| 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(); |
| 3715 | 3698 | ||
| 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) |
| 3773 | 3759 | ||
| 3774 | assert(decl.has_tv); | 3760 | assert(decl.has_tv); |
| 3775 | 3761 | ||
| 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) or | 3763 | 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); |
| 3779 | 3765 | ||
| ... | @@ -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) |
| 3792 | 3778 | ||
| 3793 | // Decl itself is safely analyzed, and body analysis is not yet queued | 3779 | // Decl itself is safely analyzed, and body analysis is not yet queued |
| 3794 | 3780 | ||
| 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 changed | 3783 | // TODO: we ideally only want to do this if the function's type changed |
| 3798 | // since the last update | 3784 | // 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; |
| 3870 | 3856 | ||
| 3871 | try zcu.scanNamespace(namespace_index, decls, decl); | 3857 | try zcu.scanNamespace(namespace_index, decls, decl); |
| 3872 | 3858 | 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 | } |
| 3875 | 3861 | ||
| ... | @@ -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 { |
| 3906 | 3892 | ||
| 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 | }; |
| 4099 | 4085 | ||
| 4100 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalSubject.wrap(.{ .decl = decl_index })); | 4086 | mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .decl = decl_index })); |
| 4101 | 4087 | ||
| 4102 | decl.analysis = .in_progress; | 4088 | decl.analysis = .in_progress; |
| 4103 | 4089 | ||
| ... | @@ -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 Decl | 4146 | // 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); |
| 4164 | 4150 | ||
| 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 the | 4264 | // 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); |
| 4281 | 4267 | ||
| 4282 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); | 4268 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| 4283 | 4269 | ||
| ... | @@ -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 | } |
| 4295 | 4281 | ||
| 4282 | try sema.flushExports(); | ||
| 4283 | |||
| 4296 | return result; | 4284 | return result; |
| 4297 | } | 4285 | } |
| 4298 | 4286 | ||
| ... | @@ -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; |
| 4531 | 4519 | ||
| ... | @@ -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 | } |
| 4951 | 4939 | ||
| 4952 | /// Delete all the Export objects that are caused by this Decl. Re-analysis of | 4940 | /// 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). |
| 4954 | fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { | 4942 | pub 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; |
| 4956 | 4944 | ||
| 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. | ||
| 4982 | fn 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 | |||
| 4998 | pub 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 | } |
| 5010 | 5020 | ||
| 5011 | pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocator) SemaError!Air { | 5021 | pub 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(); |
| 5028 | 5038 | ||
| 5029 | mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalSubject.wrap(.{ .func = func_index })); | 5039 | mod.intern_pool.removeDependenciesForDepender(gpa, AnalUnit.wrap(.{ .func = func_index })); |
| 5030 | 5040 | ||
| 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 | }; |
| 5247 | 5257 | ||
| 5248 | // Similarly, resolve any queued up types that were requested to be resolved for | 5258 | 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 | } | ||
| 5264 | 5259 | ||
| 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 | } |
| 5343 | 5338 | ||
| 5344 | pub fn errNoteNonLazy( | 5339 | pub 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); |
| 5357 | 5348 | ||
| ... | @@ -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 before | 5383 | /// Called from `Compilation.update`, after everything is done, just before |
| 5393 | /// reporting compile errors. In this function we emit exported symbol collision | 5384 | /// 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. |
| 5395 | pub fn processExports(mod: *Module) !void { | 5386 | pub 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); |
| 5399 | 5445 | ||
| 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 | } |
| 5404 | 5450 | ||
| 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 | } |
| 5410 | 5456 | ||
| 5411 | const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export); | 5457 | const SymbolExports = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, u32); |
| 5412 | 5458 | ||
| 5413 | fn processExportsInner( | 5459 | fn 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; |
| 5420 | 5466 | ||
| 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 | } |
| 5447 | 5492 | ||
| 5448 | fn handleUpdateExports( | 5493 | fn 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 | } |
| 5686 | 5727 | ||
| 5687 | pub 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 | |||
| 5695 | pub const Feature = enum { | 5728 | pub 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 | } |
| 5788 | 5821 | ||
| 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. | ||
| 5825 | pub 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 | |||
| 5789 | pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type { | 5832 | pub 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 | } |
| 6363 | 6406 | ||
| 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`. | 6408 | pub 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; |
| 6367 | pub 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. | ||
| 6414 | pub 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 | } |
| 6374 | 6423 | ||
| 6375 | /// Returns the index of the active field, given the current tag value | 6424 | /// 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 | } |
| 6382 | 6431 | ||
| 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. | ||
| 6386 | pub fn structFieldAlignment( | 6433 | pub 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. | ||
| 6444 | pub 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 |
| 6406 | 6460 | 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. | ||
| 6409 | pub 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 | } |
| 6420 | 6465 | ||
| ... | @@ -6440,3 +6485,62 @@ pub fn structPackedFieldBitOffset( | ... | @@ -6440,3 +6485,62 @@ pub fn structPackedFieldBitOffset( |
| 6440 | } | 6485 | } |
| 6441 | unreachable; // index out of bounds | 6486 | unreachable; // index out of bounds |
| 6442 | } | 6487 | } |
| 6488 | |||
| 6489 | pub 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. | ||
| 6497 | pub 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 | |||
| 6522 | pub 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 | |||
| 6528 | pub 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 | |||
| 6541 | pub 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"); |
| 8 | const Mir = @import("Mir.zig"); | 8 | const Mir = @import("Mir.zig"); |
| 9 | const Emit = @import("Emit.zig"); | 9 | const Emit = @import("Emit.zig"); |
| 10 | const Liveness = @import("../../Liveness.zig"); | 10 | const Liveness = @import("../../Liveness.zig"); |
| 11 | const Type = @import("../../type.zig").Type; | 11 | const Type = @import("../../Type.zig"); |
| 12 | const Value = @import("../../Value.zig"); | 12 | const Value = @import("../../Value.zig"); |
| 13 | const link = @import("../../link.zig"); | 13 | const link = @import("../../link.zig"); |
| 14 | const Zcu = @import("../../Zcu.zig"); | 14 | const Zcu = @import("../../Zcu.zig"); |
| ... | @@ -59,7 +59,7 @@ args: []MCValue, | ... | @@ -59,7 +59,7 @@ args: []MCValue, |
| 59 | ret_mcv: MCValue, | 59 | ret_mcv: MCValue, |
| 60 | fn_type: Type, | 60 | fn_type: Type, |
| 61 | arg_index: u32, | 61 | arg_index: u32, |
| 62 | src_loc: Module.SrcLoc, | 62 | src_loc: Module.LazySrcLoc, |
| 63 | stack_align: u32, | 63 | stack_align: u32, |
| 64 | 64 | ||
| 65 | /// MIR Instructions | 65 | /// MIR Instructions |
| ... | @@ -331,7 +331,7 @@ const Self = @This(); | ... | @@ -331,7 +331,7 @@ const Self = @This(); |
| 331 | 331 | ||
| 332 | pub fn generate( | 332 | pub 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, |
| 22 | debug_output: DebugInfoOutput, | 22 | debug_output: DebugInfoOutput, |
| 23 | target: *const std.Target, | 23 | target: *const std.Target, |
| 24 | err_msg: ?*ErrorMsg = null, | 24 | err_msg: ?*ErrorMsg = null, |
| 25 | src_loc: Module.SrcLoc, | 25 | src_loc: Module.LazySrcLoc, |
| 26 | code: *std.ArrayList(u8), | 26 | code: *std.ArrayList(u8), |
| 27 | 27 | ||
| 28 | prev_di_line: u32, | 28 | prev_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"); |
| 3 | const bits = @import("bits.zig"); | 3 | const bits = @import("bits.zig"); |
| 4 | const Register = bits.Register; | 4 | const Register = bits.Register; |
| 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 6 | const Type = @import("../../type.zig").Type; | 6 | const Type = @import("../../Type.zig"); |
| 7 | const Zcu = @import("../../Zcu.zig"); | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | /// Deprecated. | 8 | /// Deprecated. |
| 9 | const Module = Zcu; | 9 | const 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"); |
| 8 | const Mir = @import("Mir.zig"); | 8 | const Mir = @import("Mir.zig"); |
| 9 | const Emit = @import("Emit.zig"); | 9 | const Emit = @import("Emit.zig"); |
| 10 | const Liveness = @import("../../Liveness.zig"); | 10 | const Liveness = @import("../../Liveness.zig"); |
| 11 | const Type = @import("../../type.zig").Type; | 11 | const Type = @import("../../Type.zig"); |
| 12 | const Value = @import("../../Value.zig"); | 12 | const Value = @import("../../Value.zig"); |
| 13 | const link = @import("../../link.zig"); | 13 | const link = @import("../../link.zig"); |
| 14 | const Zcu = @import("../../Zcu.zig"); | 14 | const Zcu = @import("../../Zcu.zig"); |
| ... | @@ -59,7 +59,7 @@ args: []MCValue, | ... | @@ -59,7 +59,7 @@ args: []MCValue, |
| 59 | ret_mcv: MCValue, | 59 | ret_mcv: MCValue, |
| 60 | fn_type: Type, | 60 | fn_type: Type, |
| 61 | arg_index: u32, | 61 | arg_index: u32, |
| 62 | src_loc: Module.SrcLoc, | 62 | src_loc: Module.LazySrcLoc, |
| 63 | stack_align: u32, | 63 | stack_align: u32, |
| 64 | 64 | ||
| 65 | /// MIR Instructions | 65 | /// MIR Instructions |
| ... | @@ -338,7 +338,7 @@ const Self = @This(); | ... | @@ -338,7 +338,7 @@ const Self = @This(); |
| 338 | 338 | ||
| 339 | pub fn generate( | 339 | pub 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"); |
| 11 | const Zcu = @import("../../Zcu.zig"); | 11 | const Zcu = @import("../../Zcu.zig"); |
| 12 | /// Deprecated. | 12 | /// Deprecated. |
| 13 | const Module = Zcu; | 13 | const Module = Zcu; |
| 14 | const Type = @import("../../type.zig").Type; | 14 | const Type = @import("../../Type.zig"); |
| 15 | const ErrorMsg = Module.ErrorMsg; | 15 | const ErrorMsg = Module.ErrorMsg; |
| 16 | const Target = std.Target; | 16 | const Target = std.Target; |
| 17 | const assert = std.debug.assert; | 17 | const assert = std.debug.assert; |
| ... | @@ -26,7 +26,7 @@ bin_file: *link.File, | ... | @@ -26,7 +26,7 @@ bin_file: *link.File, |
| 26 | debug_output: DebugInfoOutput, | 26 | debug_output: DebugInfoOutput, |
| 27 | target: *const std.Target, | 27 | target: *const std.Target, |
| 28 | err_msg: ?*ErrorMsg = null, | 28 | err_msg: ?*ErrorMsg = null, |
| 29 | src_loc: Module.SrcLoc, | 29 | src_loc: Module.LazySrcLoc, |
| 30 | code: *std.ArrayList(u8), | 30 | code: *std.ArrayList(u8), |
| 31 | 31 | ||
| 32 | prev_di_line: u32, | 32 | prev_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; |
| 3 | const bits = @import("bits.zig"); | 3 | const bits = @import("bits.zig"); |
| 4 | const Register = bits.Register; | 4 | const Register = bits.Register; |
| 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 5 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 6 | const Type = @import("../../type.zig").Type; | 6 | const Type = @import("../../Type.zig"); |
| 7 | const Zcu = @import("../../Zcu.zig"); | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | /// Deprecated. | 8 | /// Deprecated. |
| 9 | const Module = Zcu; | 9 | const 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"); |
| 7 | const Mir = @import("Mir.zig"); | 7 | const Mir = @import("Mir.zig"); |
| 8 | const Emit = @import("Emit.zig"); | 8 | const Emit = @import("Emit.zig"); |
| 9 | const Liveness = @import("../../Liveness.zig"); | 9 | const Liveness = @import("../../Liveness.zig"); |
| 10 | const Type = @import("../../type.zig").Type; | 10 | const Type = @import("../../Type.zig"); |
| 11 | const Value = @import("../../Value.zig"); | 11 | const Value = @import("../../Value.zig"); |
| 12 | const link = @import("../../link.zig"); | 12 | const link = @import("../../link.zig"); |
| 13 | const Zcu = @import("../../Zcu.zig"); | 13 | const Zcu = @import("../../Zcu.zig"); |
| ... | @@ -59,7 +59,7 @@ args: []MCValue, | ... | @@ -59,7 +59,7 @@ args: []MCValue, |
| 59 | ret_mcv: InstTracking, | 59 | ret_mcv: InstTracking, |
| 60 | fn_type: Type, | 60 | fn_type: Type, |
| 61 | arg_index: usize, | 61 | arg_index: usize, |
| 62 | src_loc: Zcu.SrcLoc, | 62 | src_loc: Zcu.LazySrcLoc, |
| 63 | 63 | ||
| 64 | /// MIR Instructions | 64 | /// MIR Instructions |
| 65 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, | 65 | mir_instructions: std.MultiArrayList(Mir.Inst) = .{}, |
| ... | @@ -696,7 +696,7 @@ const CallView = enum(u1) { | ... | @@ -696,7 +696,7 @@ const CallView = enum(u1) { |
| 696 | 696 | ||
| 697 | pub fn generate( | 697 | pub 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, |
| 8 | mir: Mir, | 8 | mir: Mir, |
| 9 | cc: std.builtin.CallingConvention, | 9 | cc: std.builtin.CallingConvention, |
| 10 | err_msg: ?*ErrorMsg = null, | 10 | err_msg: ?*ErrorMsg = null, |
| 11 | src_loc: Zcu.SrcLoc, | 11 | src_loc: Zcu.LazySrcLoc, |
| 12 | result_insts_len: u8 = undefined, | 12 | result_insts_len: u8 = undefined, |
| 13 | result_relocs_len: u8 = undefined, | 13 | result_relocs_len: u8 = undefined, |
| 14 | result_insts: [ | 14 | result_insts: [ |
src/arch/riscv64/Mir.zig+1-1| ... | @@ -431,7 +431,7 @@ pub const RegisterList = struct { | ... | @@ -431,7 +431,7 @@ pub const RegisterList = struct { |
| 431 | const Mir = @This(); | 431 | const Mir = @This(); |
| 432 | const std = @import("std"); | 432 | const std = @import("std"); |
| 433 | const builtin = @import("builtin"); | 433 | const builtin = @import("builtin"); |
| 434 | const Type = @import("../../type.zig").Type; | 434 | const Type = @import("../../Type.zig"); |
| 435 | 435 | ||
| 436 | const assert = std.debug.assert; | 436 | const assert = std.debug.assert; |
| 437 | 437 |
src/arch/riscv64/abi.zig+1-1| ... | @@ -2,7 +2,7 @@ const std = @import("std"); | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | const bits = @import("bits.zig"); | 2 | const bits = @import("bits.zig"); |
| 3 | const Register = bits.Register; | 3 | const Register = bits.Register; |
| 4 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 4 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 5 | const Type = @import("../../type.zig").Type; | 5 | const Type = @import("../../Type.zig"); |
| 6 | const InternPool = @import("../../InternPool.zig"); | 6 | const InternPool = @import("../../InternPool.zig"); |
| 7 | const Zcu = @import("../../Zcu.zig"); | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | const assert = std.debug.assert; | 8 | const 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"); |
| 21 | const Mir = @import("Mir.zig"); | 21 | const Mir = @import("Mir.zig"); |
| 22 | const Emit = @import("Emit.zig"); | 22 | const Emit = @import("Emit.zig"); |
| 23 | const Liveness = @import("../../Liveness.zig"); | 23 | const Liveness = @import("../../Liveness.zig"); |
| 24 | const Type = @import("../../type.zig").Type; | 24 | const Type = @import("../../Type.zig"); |
| 25 | const CodeGenError = codegen.CodeGenError; | 25 | const CodeGenError = codegen.CodeGenError; |
| 26 | const Result = @import("../../codegen.zig").Result; | 26 | const Result = @import("../../codegen.zig").Result; |
| 27 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; | 27 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| ... | @@ -64,7 +64,7 @@ args: []MCValue, | ... | @@ -64,7 +64,7 @@ args: []MCValue, |
| 64 | ret_mcv: MCValue, | 64 | ret_mcv: MCValue, |
| 65 | fn_type: Type, | 65 | fn_type: Type, |
| 66 | arg_index: usize, | 66 | arg_index: usize, |
| 67 | src_loc: Module.SrcLoc, | 67 | src_loc: Module.LazySrcLoc, |
| 68 | stack_align: Alignment, | 68 | stack_align: Alignment, |
| 69 | 69 | ||
| 70 | /// MIR Instructions | 70 | /// MIR Instructions |
| ... | @@ -263,7 +263,7 @@ const BigTomb = struct { | ... | @@ -263,7 +263,7 @@ const BigTomb = struct { |
| 263 | 263 | ||
| 264 | pub fn generate( | 264 | pub 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, |
| 24 | debug_output: DebugInfoOutput, | 24 | debug_output: DebugInfoOutput, |
| 25 | target: *const std.Target, | 25 | target: *const std.Target, |
| 26 | err_msg: ?*ErrorMsg = null, | 26 | err_msg: ?*ErrorMsg = null, |
| 27 | src_loc: Module.SrcLoc, | 27 | src_loc: Module.LazySrcLoc, |
| 28 | code: *std.ArrayList(u8), | 28 | code: *std.ArrayList(u8), |
| 29 | 29 | ||
| 30 | prev_di_line: u32, | 30 | prev_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"); |
| 13 | const Zcu = @import("../../Zcu.zig"); | 13 | const Zcu = @import("../../Zcu.zig"); |
| 14 | const InternPool = @import("../../InternPool.zig"); | 14 | const InternPool = @import("../../InternPool.zig"); |
| 15 | const Decl = Zcu.Decl; | 15 | const Decl = Zcu.Decl; |
| 16 | const Type = @import("../../type.zig").Type; | 16 | const Type = @import("../../Type.zig"); |
| 17 | const Value = @import("../../Value.zig"); | 17 | const Value = @import("../../Value.zig"); |
| 18 | const Compilation = @import("../../Compilation.zig"); | 18 | const Compilation = @import("../../Compilation.zig"); |
| 19 | const link = @import("../../link.zig"); | 19 | const 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.zig | 765 | /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig |
| 766 | fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError { | 766 | fn 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( |
| 1202 | 1202 | ||
| 1203 | pub fn generate( | 1203 | pub 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 | } |
| 3163 | 3163 | ||
| 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 | } |
| 263 | 263 |
src/arch/wasm/abi.zig+1-1| ... | @@ -8,7 +8,7 @@ const std = @import("std"); | ... | @@ -8,7 +8,7 @@ const std = @import("std"); |
| 8 | const Target = std.Target; | 8 | const Target = std.Target; |
| 9 | const assert = std.debug.assert; | 9 | const assert = std.debug.assert; |
| 10 | 10 | ||
| 11 | const Type = @import("../../type.zig").Type; | 11 | const Type = @import("../../Type.zig"); |
| 12 | const Zcu = @import("../../Zcu.zig"); | 12 | const Zcu = @import("../../Zcu.zig"); |
| 13 | 13 | ||
| 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; |
| 32 | const InternPool = @import("../../InternPool.zig"); | 32 | const InternPool = @import("../../InternPool.zig"); |
| 33 | const Alignment = InternPool.Alignment; | 33 | const Alignment = InternPool.Alignment; |
| 34 | const Target = std.Target; | 34 | const Target = std.Target; |
| 35 | const Type = @import("../../type.zig").Type; | 35 | const Type = @import("../../Type.zig"); |
| 36 | const Value = @import("../../Value.zig"); | 36 | const Value = @import("../../Value.zig"); |
| 37 | const Instruction = @import("encoder.zig").Instruction; | 37 | const Instruction = @import("encoder.zig").Instruction; |
| 38 | 38 | ||
| ... | @@ -74,7 +74,7 @@ va_info: union { | ... | @@ -74,7 +74,7 @@ va_info: union { |
| 74 | ret_mcv: InstTracking, | 74 | ret_mcv: InstTracking, |
| 75 | fn_type: Type, | 75 | fn_type: Type, |
| 76 | arg_index: u32, | 76 | arg_index: u32, |
| 77 | src_loc: Module.SrcLoc, | 77 | src_loc: Module.LazySrcLoc, |
| 78 | 78 | ||
| 79 | eflags_inst: ?Air.Inst.Index = null, | 79 | eflags_inst: ?Air.Inst.Index = null, |
| 80 | 80 | ||
| ... | @@ -795,7 +795,7 @@ const Self = @This(); | ... | @@ -795,7 +795,7 @@ const Self = @This(); |
| 795 | 795 | ||
| 796 | pub fn generate( | 796 | pub 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( |
| 971 | 971 | ||
| 972 | pub fn generateLazy( | 972 | pub 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, |
| 8 | mir: Mir, | 8 | mir: Mir, |
| 9 | cc: std.builtin.CallingConvention, | 9 | cc: std.builtin.CallingConvention, |
| 10 | err_msg: ?*ErrorMsg = null, | 10 | err_msg: ?*ErrorMsg = null, |
| 11 | src_loc: Module.SrcLoc, | 11 | src_loc: Module.LazySrcLoc, |
| 12 | result_insts_len: u8 = undefined, | 12 | result_insts_len: u8 = undefined, |
| 13 | result_relocs_len: u8 = undefined, | 13 | result_relocs_len: u8 = undefined, |
| 14 | result_insts: [ | 14 | result_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; |
| 537 | const InternPool = @import("../../InternPool.zig"); | 537 | const InternPool = @import("../../InternPool.zig"); |
| 538 | const Register = @import("bits.zig").Register; | 538 | const Register = @import("bits.zig").Register; |
| 539 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; | 539 | const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; |
| 540 | const Type = @import("../../type.zig").Type; | 540 | const Type = @import("../../Type.zig"); |
| 541 | const Value = @import("../../Value.zig"); | 541 | const Value = @import("../../Value.zig"); |
| 542 | const Zcu = @import("../../Zcu.zig"); | 542 | const 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. |
| 21 | const Module = Zcu; | 21 | const Module = Zcu; |
| 22 | const Target = std.Target; | 22 | const Target = std.Target; |
| 23 | const Type = @import("type.zig").Type; | 23 | const Type = @import("Type.zig"); |
| 24 | const Value = @import("Value.zig"); | 24 | const Value = @import("Value.zig"); |
| 25 | const Zir = std.zig.Zir; | 25 | const Zir = std.zig.Zir; |
| 26 | const Alignment = InternPool.Alignment; | 26 | const Alignment = InternPool.Alignment; |
| ... | @@ -47,7 +47,7 @@ pub const DebugInfoOutput = union(enum) { | ... | @@ -47,7 +47,7 @@ pub const DebugInfoOutput = union(enum) { |
| 47 | 47 | ||
| 48 | pub fn generateFunction( | 48 | pub 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( |
| 79 | 79 | ||
| 80 | pub fn generateLazyFunction( | 80 | pub 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 |
| 105 | 105 | ||
| 106 | pub fn generateLazySymbol( | 106 | pub 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 instead | 110 | // 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( |
| 171 | 171 | ||
| 172 | pub fn generateSymbol( | 172 | pub 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( |
| 618 | 618 | ||
| 619 | fn lowerPtr( | 619 | fn 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 { |
| 683 | 683 | ||
| 684 | fn lowerAnonDeclRef( | 684 | fn 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( |
| 730 | 730 | ||
| 731 | fn lowerDeclRef( | 731 | fn 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) { |
| 814 | 814 | ||
| 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) { |
| 825 | 825 | ||
| 826 | fn genDeclRef( | 826 | fn 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( |
| 931 | 931 | ||
| 932 | fn genUnnamedConst( | 932 | fn 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( |
| 970 | 970 | ||
| 971 | pub fn genTypedValue( | 971 | pub 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"); |
| 9 | const Module = @import("../Package/Module.zig"); | 9 | const Module = @import("../Package/Module.zig"); |
| 10 | const Compilation = @import("../Compilation.zig"); | 10 | const Compilation = @import("../Compilation.zig"); |
| 11 | const Value = @import("../Value.zig"); | 11 | const Value = @import("../Value.zig"); |
| 12 | const Type = @import("../type.zig").Type; | 12 | const Type = @import("../Type.zig"); |
| 13 | const C = link.File.C; | 13 | const C = link.File.C; |
| 14 | const Decl = Zcu.Decl; | 14 | const Decl = Zcu.Decl; |
| 15 | const trace = @import("../tracy.zig").trace; | 15 | const 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); |
| 733 | 733 | ||
| 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 call | 734 | // 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 function | 735 | // them). The analysis until now should ensure that the C function |
| 738 | // pointers are compatible. If they are not, then there is a bug | 736 | // 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 | } |
| 754 | 752 | ||
| ... | @@ -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; |
| 1778 | 1780 | ||
| 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); |
| 1782 | 1783 | ||
| 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 "); |
| 1794 | 1795 | ||
| ... | @@ -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 | } |
| 1801 | 1802 | ||
| 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 | } |
| 1819 | 1809 | ||
| 1820 | try renderTypeSuffix( | 1810 | try renderTypeSuffix( |
| ... | @@ -1833,44 +1823,30 @@ pub const DeclGen = struct { | ... | @@ -1833,44 +1823,30 @@ pub const DeclGen = struct { |
| 1833 | 1823 | ||
| 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.name | 1831 | 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 | } |
| 2087 | 2063 | ||
| 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 | } |
| 2237 | 2181 | ||
| 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); |
| 2242 | 2186 | ||
| 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 | } |
| 2763 | 2701 | ||
| 2764 | fn 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 | |||
| 2827 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void { | 2702 | pub 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); |
| 2887 | 2762 | ||
| 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"); |
| 2894 | 2769 | ||
| 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(); |
| 2923 | 2798 | ||
| 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( |
| 2927 | 2802 | 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"); | ||
| 2933 | 2809 | ||
| 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(' '); |
| 2940 | 2820 | ||
| 2941 | // In case we need to use the header, populate it with a copy of the function | 2821 | // 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 { |
| 2949 | 2829 | ||
| 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(); |
| 2954 | 2833 | ||
| 2955 | // Take advantage of the free_locals map to bucket locals per type. All | 2834 | // 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 { |
| 3007 | 2886 | ||
| 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); | ||
| 3018 | 2904 | ||
| 3019 | if (variable.is_extern) return; | 2905 | if (variable.is_extern) return; |
| 3020 | 2906 | ||
| 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 | } |
| 3040 | 2923 | ||
| 3041 | pub fn genDeclValue( | 2924 | pub 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); |
| 3053 | 2933 | ||
| 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); | ||
| 3072 | 2938 | ||
| 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 | } |
| 3082 | 2947 | ||
| 3083 | pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { | 2948 | pub 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(); | ||
| 3091 | 2952 | ||
| 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 | } |
| 3101 | 3017 | ||
| ... | @@ -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; |
| 2583 | const CType = @This(); | 2583 | const CType = @This(); |
| 2584 | const Module = @import("../../Package/Module.zig"); | 2584 | const Module = @import("../../Package/Module.zig"); |
| 2585 | const std = @import("std"); | 2585 | const std = @import("std"); |
| 2586 | const Type = @import("../../type.zig").Type; | 2586 | const Type = @import("../../Type.zig"); |
| 2587 | const Zcu = @import("../../Zcu.zig"); | 2587 | const Zcu = @import("../../Zcu.zig"); |
| 2588 | const DeclIndex = @import("../../InternPool.zig").DeclIndex; | 2588 | const 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"); |
| 22 | const Air = @import("../Air.zig"); | 22 | const Air = @import("../Air.zig"); |
| 23 | const Liveness = @import("../Liveness.zig"); | 23 | const Liveness = @import("../Liveness.zig"); |
| 24 | const Value = @import("../Value.zig"); | 24 | const Value = @import("../Value.zig"); |
| 25 | const Type = @import("../type.zig").Type; | 25 | const Type = @import("../Type.zig"); |
| 26 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); | 26 | const x86_64_abi = @import("../arch/x86_64/abi.zig"); |
| 27 | const wasm_c_abi = @import("../arch/wasm/abi.zig"); | 27 | const wasm_c_abi = @import("../arch/wasm/abi.zig"); |
| 28 | const aarch64_c_abi = @import("../arch/aarch64/abi.zig"); | 28 | const 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 in | 848 | /// 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), | ||
| 855 | 851 | ||
| 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 | } |
| 1123 | 1117 | ||
| 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 { |
| 1193 | 1132 | ||
| 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); |
| 1699 | 1637 | ||
| 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 and | 1639 | 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)); |
| 1704 | 1641 | ||
| 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 | }; |
| 1761 | 1698 | ||
| 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 | } |
| 1766 | 1701 | ||
| 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 | } |
| 1786 | 1720 | ||
| 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 call | 1732 | 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 | }; | ||
| 1815 | 1735 | ||
| 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 | } |
| 1864 | 1747 | ||
| ... | @@ -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 | } |
| 1899 | 1782 | ||
| 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/13265 | 1844 | // The planned solution to this is https://github.com/ziglang/zig/issues/13265 |
| 1937 | // Until then we iterate over existing aliases and make them point | 1845 | // 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; |
| 2689 | 2604 | ||
| 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 | }; | ||
| 2692 | 2610 | ||
| 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); |
| 4764 | 4682 | ||
| 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); | ||
| 4767 | 4693 | ||
| 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; |
| 4770 | 4696 | ||
| 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 | ); | ||
| 4772 | 4710 | ||
| 4773 | const debug_file = try o.getDebugFile(namespace.file_scope); | 4711 | const debug_expression = try o.builder.debugExpression(&.{}); |
| 4774 | 4712 | ||
| 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)), // Name | 4714 | debug_global_var, |
| 4777 | try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name | 4715 | debug_expression, |
| 4778 | debug_file, // File | 4716 | ); |
| 4779 | debug_file, // Scope | ||
| 4780 | line_number, | ||
| 4781 | try o.lowerDebugType(decl.typeOf(zcu)), | ||
| 4782 | variable_index, | ||
| 4783 | .{ .local = is_internal_linkage }, | ||
| 4784 | ); | ||
| 4785 | 4717 | ||
| 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 | } | ||
| 4787 | 4722 | ||
| 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 | ); | ||
| 4792 | 4725 | ||
| 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 { |
| 5193 | 5152 | ||
| 5194 | const fqn = try decl.fullyQualifiedName(zcu); | 5153 | const fqn = try decl.fullyQualifiedName(zcu); |
| 5195 | 5154 | ||
| 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. |
| 10 | const Module = Zcu; | 10 | const Module = Zcu; |
| 11 | const Decl = Module.Decl; | 11 | const Decl = Module.Decl; |
| 12 | const Type = @import("../type.zig").Type; | 12 | const Type = @import("../Type.zig"); |
| 13 | const Value = @import("../Value.zig"); | 13 | const Value = @import("../Value.zig"); |
| 14 | const Air = @import("../Air.zig"); | 14 | const Air = @import("../Air.zig"); |
| 15 | const Liveness = @import("../Liveness.zig"); | 15 | const Liveness = @import("../Liveness.zig"); |
| ... | @@ -218,7 +218,7 @@ pub const Object = struct { | ... | @@ -218,7 +218,7 @@ pub const Object = struct { |
| 218 | 218 | ||
| 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_msg | 224 | // 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); |
| 6445 | 6445 |
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. |
| 19 | const Module = Zcu; | 19 | const Module = Zcu; |
| 20 | const InternPool = @import("InternPool.zig"); | 20 | const InternPool = @import("InternPool.zig"); |
| 21 | const Type = @import("type.zig").Type; | 21 | const Type = @import("Type.zig"); |
| 22 | const Value = @import("Value.zig"); | 22 | const Value = @import("Value.zig"); |
| 23 | const LlvmObject = @import("codegen/llvm.zig").Object; | 23 | const LlvmObject = @import("codegen/llvm.zig").Object; |
| 24 | const lldMain = @import("main.zig").lldMain; | 24 | const 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 | } |
| 673 | 673 | ||
| 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 | => {}, |
| 686 | 685 | ||
| 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"); |
| 14 | const codegen = @import("../codegen/c.zig"); | 14 | const codegen = @import("../codegen/c.zig"); |
| 15 | const link = @import("../link.zig"); | 15 | const link = @import("../link.zig"); |
| 16 | const trace = @import("../tracy.zig").trace; | 16 | const trace = @import("../tracy.zig").trace; |
| 17 | const Type = @import("../type.zig").Type; | 17 | const Type = @import("../Type.zig"); |
| 18 | const Value = @import("../Value.zig"); | 18 | const Value = @import("../Value.zig"); |
| 19 | const Air = @import("../Air.zig"); | 19 | const Air = @import("../Air.zig"); |
| 20 | const Liveness = @import("../Liveness.zig"); | 20 | const 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`. |
| 40 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, | 40 | aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment) = .{}, |
| 41 | 41 | ||
| 42 | exported_decls: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, ExportedBlock) = .{}, | ||
| 43 | exported_values: std.AutoArrayHashMapUnmanaged(InternPool.Index, ExportedBlock) = .{}, | ||
| 44 | |||
| 42 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new | 45 | /// Optimization, `updateDecl` reuses this buffer rather than creating a new |
| 43 | /// one with every call. | 46 | /// one with every call. |
| 44 | fwd_decl_buf: std.ArrayListUnmanaged(u8) = .{}, | 47 | fwd_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 | }; |
| 82 | 85 | ||
| 86 | /// Per-exported-symbol data. | ||
| 87 | pub const ExportedBlock = struct { | ||
| 88 | fwd_decl: String = String.empty, | ||
| 89 | }; | ||
| 90 | |||
| 83 | pub fn getString(this: C, s: String) []const u8 { | 91 | pub 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 | } |
| 240 | 248 | ||
| 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 { |
| 288 | 300 | ||
| 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 | } |
| 353 | 365 | ||
| 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, {}); |
| 457 | 473 | } | |
| 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 | } |
| 461 | 480 | ||
| 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 | } |
| 470 | 506 | ||
| ... | @@ -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; |
| 498 | 534 | ||
| 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 | ); | ||
| 506 | 557 | ||
| 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 | } |
| 534 | 585 | ||
| 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 | } |
| 736 | 798 | ||
| 737 | pub fn flushEmitH(zcu: *Zcu) !void { | 799 | pub 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 | |||
| 891 | pub 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: |
| 1144 | 1144 | ||
| 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 | }; |
| 1162 | 1162 | ||
| 1163 | try self.updateDeclCode(decl_index, code, .FUNCTION); | 1163 | try self.updateDeclCode(decl_index, code, .FUNCTION); |
| 1164 | 1164 | ||
| 1165 | // Since we updated the vaddr and the size, each corresponding export | 1165 | // 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 | } |
| 1169 | 1167 | ||
| 1170 | pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 { | 1168 | pub 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 | }; |
| 1201 | 1199 | ||
| 1202 | fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { | 1200 | fn 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; |
| 1204 | 1202 | ||
| 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(); |
| 1273 | 1271 | ||
| 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 | }; |
| 1286 | 1284 | ||
| 1287 | try self.updateDeclCode(decl_index, code, .NULL); | 1285 | try self.updateDeclCode(decl_index, code, .NULL); |
| 1288 | 1286 | ||
| 1289 | // Since we updated the vaddr and the size, each corresponding export | 1287 | // 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 | } |
| 1293 | 1289 | ||
| 1294 | fn updateLazySymbolAtom( | 1290 | fn 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().?; |
| 1315 | 1311 | ||
| 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 to | 1512 | // 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 | } |
| 1554 | 1544 | ||
| 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); |
| 1556 | 1546 | ||
| 1557 | const gpa = comp.gpa; | 1547 | const gpa = comp.gpa; |
| 1558 | 1548 | ||
| ... | @@ -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.processExportsInner | 1560 | // 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); |
| 1582 | 1572 | ||
| 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)}); |
| 1585 | 1576 | ||
| 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 | } |
| 1597 | 1588 | ||
| 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 | } |
| 1643 | 1634 | ||
| 1644 | pub fn deleteDeclExport( | 1635 | pub 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"); |
| 2748 | const Relocation = @import("Coff/Relocation.zig"); | 2742 | const Relocation = @import("Coff/Relocation.zig"); |
| 2749 | const TableSection = @import("table_section.zig").TableSection; | 2743 | const TableSection = @import("table_section.zig").TableSection; |
| 2750 | const StringTable = @import("StringTable.zig"); | 2744 | const StringTable = @import("StringTable.zig"); |
| 2751 | const Type = @import("../type.zig").Type; | 2745 | const Type = @import("../Type.zig"); |
| 2752 | const Value = @import("../Value.zig"); | 2746 | const Value = @import("../Value.zig"); |
| 2747 | const AnalUnit = InternPool.AnalUnit; | ||
| 2753 | 2748 | ||
| 2754 | pub const base_tag: link.File.Tag = .coff; | 2749 | pub const base_tag: link.File.Tag = .coff; |
| 2755 | 2750 |
src/link/Dwarf.zig+1-1| ... | @@ -2969,5 +2969,5 @@ const Zcu = @import("../Zcu.zig"); | ... | @@ -2969,5 +2969,5 @@ const Zcu = @import("../Zcu.zig"); |
| 2969 | const Module = Zcu; | 2969 | const Module = Zcu; |
| 2970 | const InternPool = @import("../InternPool.zig"); | 2970 | const InternPool = @import("../InternPool.zig"); |
| 2971 | const StringTable = @import("StringTable.zig"); | 2971 | const StringTable = @import("StringTable.zig"); |
| 2972 | const Type = @import("../type.zig").Type; | 2972 | const Type = @import("../Type.zig"); |
| 2973 | const Value = @import("../Value.zig"); | 2973 | const 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 | } |
| 3022 | 3022 | ||
| 3023 | pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void { | 3023 | pub 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 | } |
| 3027 | 3027 | ||
| 3028 | pub fn deleteDeclExport( | 3028 | pub 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 | } |
| 3036 | 3036 | ||
| 3037 | fn addLinkerDefinedSymbols(self: *Elf) !void { | 3037 | fn 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 | else | 1084 | 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 | } |
| 1117 | 1117 | ||
| 1118 | // Since we updated the vaddr and the size, each corresponding export | 1118 | // 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 | } |
| 1122 | 1120 | ||
| 1123 | pub fn updateDecl( | 1121 | pub fn updateDecl( |
| ... | @@ -1158,13 +1156,13 @@ pub fn updateDecl( | ... | @@ -1158,13 +1156,13 @@ pub fn updateDecl( |
| 1158 | // TODO implement .debug_info for global variables | 1156 | // 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 | else | 1164 | 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 | }); |
| 1170 | 1168 | ||
| ... | @@ -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 | } |
| 1196 | 1194 | ||
| 1197 | // Since we updated the vaddr and the size, each corresponding export | 1195 | // 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 | } |
| 1201 | 1197 | ||
| 1202 | fn updateLazySymbol( | 1198 | fn 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 | }; |
| 1223 | 1219 | ||
| 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; |
| 1339 | 1328 | ||
| ... | @@ -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.processExportsInner | 1395 | // 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]; |
| 1420 | 1409 | ||
| 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 | } |
| 1489 | 1479 | ||
| 1490 | pub fn deleteDeclExport( | 1480 | pub 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; |
| 1654 | const Object = @import("Object.zig"); | 1647 | const Object = @import("Object.zig"); |
| 1655 | const Symbol = @import("Symbol.zig"); | 1648 | const Symbol = @import("Symbol.zig"); |
| 1656 | const StringTable = @import("../StringTable.zig"); | 1649 | const StringTable = @import("../StringTable.zig"); |
| 1657 | const Type = @import("../../type.zig").Type; | 1650 | const Type = @import("../../Type.zig"); |
| 1658 | const Value = @import("../../Value.zig"); | 1651 | const Value = @import("../../Value.zig"); |
| 1652 | const AnalUnit = InternPool.AnalUnit; | ||
| 1659 | const ZigObject = @This(); | 1653 | const 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 | } |
| 3218 | 3218 | ||
| 3219 | pub fn deleteDeclExport( | 3219 | pub 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 | } |
| 3227 | 3227 | ||
| 3228 | pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void { | 3228 | pub 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; |
| 459 | const Allocator = mem.Allocator; | 459 | const Allocator = mem.Allocator; |
| 460 | const MachO = @import("../MachO.zig"); | 460 | const MachO = @import("../MachO.zig"); |
| 461 | const StringTable = @import("../StringTable.zig"); | 461 | const StringTable = @import("../StringTable.zig"); |
| 462 | const Type = @import("../../type.zig").Type; | 462 | const 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 | } |
| 715 | 715 | ||
| 716 | // Since we updated the vaddr and the size, each corresponding export | 716 | // 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 | } |
| 720 | 718 | ||
| 721 | pub fn updateDecl( | 719 | pub fn updateDecl( |
| ... | @@ -756,7 +754,7 @@ pub fn updateDecl( | ... | @@ -756,7 +754,7 @@ pub fn updateDecl( |
| 756 | 754 | ||
| 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 | }); |
| 762 | 760 | ||
| ... | @@ -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 | } |
| 792 | 790 | ||
| 793 | // Since we updated the vaddr and the size, each corresponding export symbol also | 791 | // 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 | } |
| 797 | 793 | ||
| 798 | fn updateDeclCode( | 794 | fn 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; |
| 1137 | 1133 | ||
| ... | @@ -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.processExportsInner | 1203 | // 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]; |
| 1220 | 1216 | ||
| 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 | }; |
| 1296 | 1293 | ||
| 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 | } |
| 1366 | 1356 | ||
| 1367 | pub fn deleteDeclExport( | 1357 | pub 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.?; |
| 1374 | 1364 | ||
| 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; |
| 1377 | 1370 | ||
| 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"); |
| 1594 | const Relocation = @import("Relocation.zig"); | 1587 | const Relocation = @import("Relocation.zig"); |
| 1595 | const Symbol = @import("Symbol.zig"); | 1588 | const Symbol = @import("Symbol.zig"); |
| 1596 | const StringTable = @import("../StringTable.zig"); | 1589 | const StringTable = @import("../StringTable.zig"); |
| 1597 | const Type = @import("../../type.zig").Type; | 1590 | const Type = @import("../../Type.zig"); |
| 1598 | const Value = @import("../../Value.zig"); | 1591 | const Value = @import("../../Value.zig"); |
| 1592 | const AnalUnit = InternPool.AnalUnit; | ||
| 1599 | const ZigObject = @This(); | 1593 | const 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"); |
| 103 | 103 | ||
| 104 | return self.llvm_object.updateExports(module, exported, exports); | 104 | return self.llvm_object.updateExports(module, exported, export_indices); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | pub fn freeDecl(self: *NvPtx, decl_index: InternPool.DeclIndex) void { | 107 | pub 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; |
| 15 | const build_options = @import("build_options"); | 15 | const build_options = @import("build_options"); |
| 16 | const Air = @import("../Air.zig"); | 16 | const Air = @import("../Air.zig"); |
| 17 | const Liveness = @import("../Liveness.zig"); | 17 | const Liveness = @import("../Liveness.zig"); |
| 18 | const Type = @import("../type.zig").Type; | 18 | const Type = @import("../Type.zig"); |
| 19 | const Value = @import("../Value.zig"); | 19 | const Value = @import("../Value.zig"); |
| 20 | const AnalUnit = InternPool.AnalUnit; | ||
| 20 | 21 | ||
| 21 | const std = @import("std"); | 22 | const std = @import("std"); |
| 22 | const builtin = @import("builtin"); | 23 | const 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 mutable | 62 | /// the code is modified when relocated, so that is why it is mutable |
| 62 | data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{}, | 63 | data_decl_table: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u8) = .{}, |
| 64 | /// When `updateExports` is called, we store the export indices here, to be used | ||
| 65 | /// during flush. | ||
| 66 | decl_exports: std.AutoArrayHashMapUnmanaged(InternPool.DeclIndex, []u32) = .{}, | ||
| 63 | 67 | ||
| 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: |
| 435 | 439 | ||
| 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; |
| 503 | 507 | ||
| 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 atom | 546 | // 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 decls | 847 | // 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); |
| 1015 | 1019 | ||
| 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 sections | 1023 | // 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) and | 1025 | 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 flush | 1175 | // all proper work is done in flush |
| 1162 | _ = module; | 1176 | _ = module; |
| 1163 | _ = exports; | ||
| 1164 | } | 1177 | } |
| 1165 | 1178 | ||
| 1166 | pub fn getOrCreateAtomForLazySymbol(self: *Plan9, sym: File.LazySymbol) !Atom.Index { | 1179 | pub 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; |
| 1213 | 1226 | ||
| 1214 | // generate the code | 1227 | // 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) or | 177 | 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"); |
| 33 | const Module = Zcu; | 33 | const Module = Zcu; |
| 34 | const Object = @import("Wasm/Object.zig"); | 34 | const Object = @import("Wasm/Object.zig"); |
| 35 | const Symbol = @import("Wasm/Symbol.zig"); | 35 | const Symbol = @import("Wasm/Symbol.zig"); |
| 36 | const Type = @import("../type.zig").Type; | 36 | const Type = @import("../Type.zig"); |
| 37 | const Value = @import("../Value.zig"); | 37 | const Value = @import("../Value.zig"); |
| 38 | const ZigObject = @import("Wasm/ZigObject.zig"); | 38 | const ZigObject = @import("Wasm/ZigObject.zig"); |
| 39 | 39 | ||
| ... | @@ -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 | } |
| 1544 | 1544 | ||
| 1545 | pub fn deleteDeclExport( | 1545 | pub 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 | } |
| 1553 | 1553 | ||
| 1554 | pub fn updateExports( | 1554 | pub 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 | } |
| 1566 | 1566 | ||
| 1567 | pub fn freeDecl(wasm: *Wasm, decl_index: InternPool.DeclIndex) void { | 1567 | pub 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( |
| 269 | 269 | ||
| 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 | else | 494 | else |
| 495 | decl.navSrcLoc(mod); | 495 | decl.navSrcLoc(mod); |
| 496 | 496 | ||
| 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 | }; |
| 514 | 514 | ||
| 515 | fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.SrcLoc) !LowerConstResult { | 515 | fn 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.?; |
| 518 | 518 | ||
| ... | @@ -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 | } |
| 835 | 835 | ||
| 836 | pub fn deleteDeclExport( | 836 | pub 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)}); |
| 875 | 879 | ||
| 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 default | 914 | .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"); |
| 1247 | const Module = Zcu; | 1252 | const Module = Zcu; |
| 1248 | const StringTable = @import("../StringTable.zig"); | 1253 | const StringTable = @import("../StringTable.zig"); |
| 1249 | const Symbol = @import("Symbol.zig"); | 1254 | const Symbol = @import("Symbol.zig"); |
| 1250 | const Type = @import("../../type.zig").Type; | 1255 | const Type = @import("../../Type.zig"); |
| 1251 | const Value = @import("../../Value.zig"); | 1256 | const Value = @import("../../Value.zig"); |
| 1252 | const Wasm = @import("../Wasm.zig"); | 1257 | const Wasm = @import("../Wasm.zig"); |
| 1258 | const AnalUnit = InternPool.AnalUnit; | ||
| 1253 | const ZigObject = @This(); | 1259 | const 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; |
| 3 | const Allocator = std.mem.Allocator; | 3 | const Allocator = std.mem.Allocator; |
| 4 | const Zcu = @import("Zcu.zig"); | 4 | const Zcu = @import("Zcu.zig"); |
| 5 | const InternPool = @import("InternPool.zig"); | 5 | const InternPool = @import("InternPool.zig"); |
| 6 | const Type = @import("type.zig").Type; | 6 | const Type = @import("Type.zig"); |
| 7 | const Value = @import("Value.zig"); | 7 | const Value = @import("Value.zig"); |
| 8 | 8 | ||
| 9 | /// We use a tagged union here because while it wastes a few bytes for some tags, having a fixed | 9 | /// 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; |
| 4 | 4 | ||
| 5 | const Zcu = @import("Zcu.zig"); | 5 | const Zcu = @import("Zcu.zig"); |
| 6 | const Value = @import("Value.zig"); | 6 | const Value = @import("Value.zig"); |
| 7 | const Type = @import("type.zig").Type; | 7 | const Type = @import("Type.zig"); |
| 8 | const Air = @import("Air.zig"); | 8 | const Air = @import("Air.zig"); |
| 9 | const Liveness = @import("Liveness.zig"); | 9 | const Liveness = @import("Liveness.zig"); |
| 10 | const InternPool = @import("InternPool.zig"); | 10 | const 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`. |
| 3 | 3 | ||
| 4 | const std = @import("std"); | 4 | const std = @import("std"); |
| 5 | const Type = @import("type.zig").Type; | 5 | const Type = @import("Type.zig"); |
| 6 | const Value = @import("Value.zig"); | 6 | const Value = @import("Value.zig"); |
| 7 | const Zcu = @import("Zcu.zig"); | 7 | const 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; |
| 5 | const Allocator = std.mem.Allocator; | 5 | const Allocator = std.mem.Allocator; |
| 6 | const Air = @import("Air.zig"); | 6 | const Air = @import("Air.zig"); |
| 7 | const StaticBitSet = std.bit_set.StaticBitSet; | 7 | const StaticBitSet = std.bit_set.StaticBitSet; |
| 8 | const Type = @import("type.zig").Type; | 8 | const Type = @import("Type.zig"); |
| 9 | const Zcu = @import("Zcu.zig"); | 9 | const Zcu = @import("Zcu.zig"); |
| 10 | /// Deprecated. | 10 | /// Deprecated. |
| 11 | const Module = Zcu; | 11 | const Module = Zcu; |
src/target.zig+1-1| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Type = @import("type.zig").Type; | 2 | const Type = @import("Type.zig"); |
| 3 | const AddressSpace = std.builtin.AddressSpace; | 3 | const AddressSpace = std.builtin.AddressSpace; |
| 4 | const Alignment = @import("InternPool.zig").Alignment; | 4 | const Alignment = @import("InternPool.zig").Alignment; |
| 5 | const Feature = @import("Zcu.zig").Feature; | 5 | const Feature = @import("Zcu.zig").Feature; |
src/type.zig deleted-3617| ... | @@ -1,3617 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const Value = @import("Value.zig"); | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | const Target = std.Target; | ||
| 6 | const Zcu = @import("Zcu.zig"); | ||
| 7 | /// Deprecated. | ||
| 8 | const Module = Zcu; | ||
| 9 | const log = std.log.scoped(.Type); | ||
| 10 | const target_util = @import("target.zig"); | ||
| 11 | const Sema = @import("Sema.zig"); | ||
| 12 | const InternPool = @import("InternPool.zig"); | ||
| 13 | const Alignment = InternPool.Alignment; | ||
| 14 | const 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. | ||
| 20 | pub 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 | |||
| 3615 | fn 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=native | 16 | // target=native |
| 17 | // | 17 | // |
| 18 | // :6:5: error: found compile log statement | 18 | // :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 statement | 19 | // :6:5: error: found compile log statement |
| 20 | // :12:5: note: also here | 20 | // :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=native | 10 | // target=native |
| 11 | // | 11 | // |
| 12 | // :1:11: error: struct 'tmp.A' depends on itself | 12 | // :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=native | 16 | // target=native |
| 17 | // | 17 | // |
| 18 | // :1:11: error: struct 'tmp.A' depends on itself | 18 | // :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=native | 13 | // target=native |
| 14 | // | 14 | // |
| 15 | // :1:13: error: struct 'tmp.Foo' depends on itself | 15 | // :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=native | 13 | // target=native |
| 14 | // | 14 | // |
| 15 | // :1:13: error: union 'tmp.Foo' depends on itself | 15 | // :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=native | 16 | // target=native |
| 17 | // | 17 | // |
| 18 | // :6:21: error: struct layout depends on it having runtime bits | 18 | // :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=native | 15 | // target=native |
| 16 | // | 16 | // |
| 17 | // :1:17: error: struct 'tmp.LhsExpr' depends on itself | 17 | // :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 @@ |
| 1 | pub export fn entry(param: usize) usize { | 1 | pub export fn entry(param: usize) usize { |
| 2 | return struct { param }; | 2 | return struct { @TypeOf(param) }; |
| 3 | } | 3 | } |
| 4 | 4 | ||
| 5 | // error | 5 | // 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; |
| 396 | 396 | ||
| 397 | // Ignore stuff such as .swp files | 397 | // 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 | } |
| 404 | 401 | ||
| ... | @@ -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 | } |
| 655 | 641 | ||
| 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; |
| 1236 | const Allocator = std.mem.Allocator; | 1222 | const Allocator = std.mem.Allocator; |
| 1237 | const getExternalExecutor = std.zig.system.getExternalExecutor; | 1223 | const getExternalExecutor = std.zig.system.getExternalExecutor; |
| 1238 | 1224 | ||
| 1239 | const Compilation = @import("../../src/Compilation.zig"); | ||
| 1240 | const zig_h = @import("../../src/link.zig").File.C.zig_h; | ||
| 1241 | const introspect = @import("../../src/introspect.zig"); | ||
| 1242 | const ThreadPool = std.Thread.Pool; | ||
| 1243 | const WaitGroup = std.Thread.WaitGroup; | ||
| 1244 | const build_options = @import("build_options"); | ||
| 1245 | const Package = @import("../../src/Package.zig"); | ||
| 1246 | |||
| 1247 | pub const std_options = .{ | ||
| 1248 | .log_level = .err, | ||
| 1249 | }; | ||
| 1250 | |||
| 1251 | var 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. | ||
| 1257 | pub 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 | |||
| 1425 | fn resolveTargetQuery(query: std.Target.Query) std.Build.ResolvedTarget { | 1225 | fn 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 | } |
| 1432 | 1232 | ||
| 1433 | fn runCases(self: *Cases, zig_exe_path: []const u8) !void { | 1233 | fn knownFileExtension(filename: []const u8) bool { |
| 1434 | const host = try std.zig.system.resolveTargetQuery(.{}); | 1234 | // List taken from `Compilation.classifyFileExt` in the compiler. |
| 1435 | 1235 | 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", |
| 1440 | 1240 | ".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| { |
| 1444 | 1244 | 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 | |||
| 1507 | fn 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 | } |
| 1573 | 1246 | // 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")) { |
| 1579 | 1252 | 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 | |||
| 1894 | fn 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( |
| 1268 | 1267 | ||
| 1269 | cases.lowerToTranslateCSteps(b, parent_step, test_filters, target, translate_c_options); | 1268 | cases.lowerToTranslateCSteps(b, parent_step, test_filters, target, translate_c_options); |
| 1270 | 1269 | ||
| 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 | } |