| author | |
| committer | |
| log | 5a41704f7ec2c472897f955ecfe1feafa697ff68 |
| tree | 62984e96e61c367ce7ad304fc532051c10e6921d |
| parent | 6f10b11658c002b26341bff10e1dd522f2465b5a |
Closes #1490445 files changed, 3658 insertions(+), 3604 deletions(-)
CMakeLists.txt+1-1| ... | @@ -564,7 +564,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -564,7 +564,7 @@ set(ZIG_STAGE2_SOURCES |
| 564 | "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig" | 564 | "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig" |
| 565 | "${CMAKE_SOURCE_DIR}/src/codegen.zig" | 565 | "${CMAKE_SOURCE_DIR}/src/codegen.zig" |
| 566 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" | 566 | "${CMAKE_SOURCE_DIR}/src/codegen/c.zig" |
| 567 | "${CMAKE_SOURCE_DIR}/src/codegen/c/type.zig" | 567 | "${CMAKE_SOURCE_DIR}/src/codegen/c/Type.zig" |
| 568 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" | 568 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" |
| 569 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" | 569 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" |
| 570 | "${CMAKE_SOURCE_DIR}/src/glibc.zig" | 570 | "${CMAKE_SOURCE_DIR}/src/glibc.zig" |
build.zig+1-3| ... | @@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void { | ... | @@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void { |
| 16 | const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; | 16 | const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false; |
| 17 | const target = t: { | 17 | const target = t: { |
| 18 | var default_target: std.zig.CrossTarget = .{}; | 18 | var default_target: std.zig.CrossTarget = .{}; |
| 19 | if (only_c) { | 19 | default_target.ofmt = b.option(std.Target.ObjectFormat, "ofmt", "Object format to target") orelse if (only_c) .c else null; |
| 20 | default_target.ofmt = .c; | ||
| 21 | } | ||
| 22 | break :t b.standardTargetOptions(.{ .default_target = default_target }); | 20 | break :t b.standardTargetOptions(.{ .default_target = default_target }); |
| 23 | }; | 21 | }; |
| 24 | 22 |
lib/std/c/darwin.zig+2-2| ... | @@ -1150,8 +1150,8 @@ pub const siginfo_t = extern struct { | ... | @@ -1150,8 +1150,8 @@ pub const siginfo_t = extern struct { |
| 1150 | 1150 | ||
| 1151 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. | 1151 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 1152 | pub const Sigaction = extern struct { | 1152 | pub const Sigaction = extern struct { |
| 1153 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 1153 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 1154 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 1154 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 1155 | 1155 | ||
| 1156 | handler: extern union { | 1156 | handler: extern union { |
| 1157 | handler: ?handler_fn, | 1157 | handler: ?handler_fn, |
lib/std/c/dragonfly.zig+3-3| ... | @@ -690,8 +690,8 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; | ... | @@ -690,8 +690,8 @@ pub const empty_sigset = sigset_t{ .__bits = [_]c_uint{0} ** _SIG_WORDS }; |
| 690 | pub const sig_atomic_t = c_int; | 690 | pub const sig_atomic_t = c_int; |
| 691 | 691 | ||
| 692 | pub const Sigaction = extern struct { | 692 | pub const Sigaction = extern struct { |
| 693 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 693 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 694 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 694 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 695 | 695 | ||
| 696 | /// signal handler | 696 | /// signal handler |
| 697 | handler: extern union { | 697 | handler: extern union { |
| ... | @@ -702,7 +702,7 @@ pub const Sigaction = extern struct { | ... | @@ -702,7 +702,7 @@ pub const Sigaction = extern struct { |
| 702 | mask: sigset_t, | 702 | mask: sigset_t, |
| 703 | }; | 703 | }; |
| 704 | 704 | ||
| 705 | pub const sig_t = *const fn (c_int) callconv(.C) void; | 705 | pub const sig_t = *const fn (i32) callconv(.C) void; |
| 706 | 706 | ||
| 707 | pub const SOCK = struct { | 707 | pub const SOCK = struct { |
| 708 | pub const STREAM = 1; | 708 | pub const STREAM = 1; |
lib/std/c/freebsd.zig+2-2| ... | @@ -1171,8 +1171,8 @@ const NSIG = 32; | ... | @@ -1171,8 +1171,8 @@ const NSIG = 32; |
| 1171 | 1171 | ||
| 1172 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 1172 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 1173 | pub const Sigaction = extern struct { | 1173 | pub const Sigaction = extern struct { |
| 1174 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 1174 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 1175 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 1175 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 1176 | 1176 | ||
| 1177 | /// signal handler | 1177 | /// signal handler |
| 1178 | handler: extern union { | 1178 | handler: extern union { |
lib/std/c/haiku.zig+1-1| ... | @@ -501,7 +501,7 @@ pub const siginfo_t = extern struct { | ... | @@ -501,7 +501,7 @@ pub const siginfo_t = extern struct { |
| 501 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 501 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 502 | pub const Sigaction = extern struct { | 502 | pub const Sigaction = extern struct { |
| 503 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | 503 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 504 | pub const sigaction_fn = *const fn (c_int, *allowzero anyopaque, ?*anyopaque) callconv(.C) void; | 504 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 505 | 505 | ||
| 506 | /// signal handler | 506 | /// signal handler |
| 507 | handler: extern union { | 507 | handler: extern union { |
lib/std/c/netbsd.zig+2-2| ... | @@ -864,8 +864,8 @@ pub const SIG = struct { | ... | @@ -864,8 +864,8 @@ pub const SIG = struct { |
| 864 | 864 | ||
| 865 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 865 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 866 | pub const Sigaction = extern struct { | 866 | pub const Sigaction = extern struct { |
| 867 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 867 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 868 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 868 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 869 | 869 | ||
| 870 | /// signal handler | 870 | /// signal handler |
| 871 | handler: extern union { | 871 | handler: extern union { |
lib/std/c/openbsd.zig+2-2| ... | @@ -842,8 +842,8 @@ pub const SIG = struct { | ... | @@ -842,8 +842,8 @@ pub const SIG = struct { |
| 842 | 842 | ||
| 843 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 843 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 844 | pub const Sigaction = extern struct { | 844 | pub const Sigaction = extern struct { |
| 845 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 845 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 846 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 846 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 847 | 847 | ||
| 848 | /// signal handler | 848 | /// signal handler |
| 849 | handler: extern union { | 849 | handler: extern union { |
lib/std/c/solaris.zig+2-2| ... | @@ -874,8 +874,8 @@ pub const SIG = struct { | ... | @@ -874,8 +874,8 @@ pub const SIG = struct { |
| 874 | 874 | ||
| 875 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 875 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 876 | pub const Sigaction = extern struct { | 876 | pub const Sigaction = extern struct { |
| 877 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 877 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 878 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 878 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 879 | 879 | ||
| 880 | /// signal options | 880 | /// signal options |
| 881 | flags: c_uint, | 881 | flags: c_uint, |
lib/std/debug.zig+1-1| ... | @@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void { | ... | @@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void { |
| 2570 | updateSegfaultHandler(&act) catch {}; | 2570 | updateSegfaultHandler(&act) catch {}; |
| 2571 | } | 2571 | } |
| 2572 | 2572 | ||
| 2573 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 2573 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) noreturn { |
| 2574 | // Reset to the default handler so that if a segfault happens in this handler it will crash | 2574 | // Reset to the default handler so that if a segfault happens in this handler it will crash |
| 2575 | // the process. Also when this handler returns, the original instruction will be repeated | 2575 | // the process. Also when this handler returns, the original instruction will be repeated |
| 2576 | // and the resulting segfault will crash the process rather than continually dump stack traces. | 2576 | // and the resulting segfault will crash the process rather than continually dump stack traces. |
lib/std/os/emscripten.zig+2-2| ... | @@ -695,8 +695,8 @@ pub const SIG = struct { | ... | @@ -695,8 +695,8 @@ pub const SIG = struct { |
| 695 | }; | 695 | }; |
| 696 | 696 | ||
| 697 | pub const Sigaction = extern struct { | 697 | pub const Sigaction = extern struct { |
| 698 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 698 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 699 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 699 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 700 | 700 | ||
| 701 | handler: extern union { | 701 | handler: extern union { |
| 702 | handler: ?handler_fn, | 702 | handler: ?handler_fn, |
lib/std/os/linux.zig+3-3| ... | @@ -4301,7 +4301,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l | ... | @@ -4301,7 +4301,7 @@ pub const all_mask: sigset_t = [_]u32{0xffffffff} ** @typeInfo(sigset_t).Array.l |
| 4301 | pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; | 4301 | pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; |
| 4302 | 4302 | ||
| 4303 | const k_sigaction_funcs = struct { | 4303 | const k_sigaction_funcs = struct { |
| 4304 | const handler = ?*align(1) const fn (c_int) callconv(.C) void; | 4304 | const handler = ?*align(1) const fn (i32) callconv(.C) void; |
| 4305 | const restorer = *const fn () callconv(.C) void; | 4305 | const restorer = *const fn () callconv(.C) void; |
| 4306 | }; | 4306 | }; |
| 4307 | 4307 | ||
| ... | @@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) { | ... | @@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) { |
| 4328 | 4328 | ||
| 4329 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. | 4329 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 4330 | pub const Sigaction = extern struct { | 4330 | pub const Sigaction = extern struct { |
| 4331 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | 4331 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; |
| 4332 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 4332 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 4333 | 4333 | ||
| 4334 | handler: extern union { | 4334 | handler: extern union { |
| 4335 | handler: ?handler_fn, | 4335 | handler: ?handler_fn, |
lib/std/os/plan9.zig+2-2| ... | @@ -186,8 +186,8 @@ pub const empty_sigset = 0; | ... | @@ -186,8 +186,8 @@ pub const empty_sigset = 0; |
| 186 | pub const siginfo_t = c_long; | 186 | pub const siginfo_t = c_long; |
| 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible. | 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible. |
| 188 | pub const Sigaction = extern struct { | 188 | pub const Sigaction = extern struct { |
| 189 | pub const handler_fn = *const fn (c_int) callconv(.C) void; | 189 | pub const handler_fn = *const fn (i32) callconv(.C) void; |
| 190 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | 190 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; |
| 191 | 191 | ||
| 192 | handler: extern union { | 192 | handler: extern union { |
| 193 | handler: ?handler_fn, | 193 | handler: ?handler_fn, |
lib/std/start.zig+1-1| ... | @@ -597,4 +597,4 @@ fn maybeIgnoreSigpipe() void { | ... | @@ -597,4 +597,4 @@ fn maybeIgnoreSigpipe() void { |
| 597 | } | 597 | } |
| 598 | } | 598 | } |
| 599 | 599 | ||
| 600 | fn noopSigHandler(_: c_int) callconv(.C) void {} | 600 | fn noopSigHandler(_: i32) callconv(.C) void {} |
src/Compilation.zig+7-6| ... | @@ -3457,14 +3457,18 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3457,14 +3457,18 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3457 | .pass = .{ .decl = decl_index }, | 3457 | .pass = .{ .decl = decl_index }, |
| 3458 | .is_naked_fn = false, | 3458 | .is_naked_fn = false, |
| 3459 | .fwd_decl = fwd_decl.toManaged(gpa), | 3459 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3460 | .ctypes = .{}, | 3460 | .ctype_pool = c_codegen.CType.Pool.empty, |
| 3461 | .scratch = .{}, | ||
| 3461 | .anon_decl_deps = .{}, | 3462 | .anon_decl_deps = .{}, |
| 3462 | .aligned_anon_decls = .{}, | 3463 | .aligned_anon_decls = .{}, |
| 3463 | }; | 3464 | }; |
| 3464 | defer { | 3465 | defer { |
| 3465 | dg.ctypes.deinit(gpa); | 3466 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); |
| 3466 | dg.fwd_decl.deinit(); | 3467 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); |
| 3468 | dg.ctype_pool.deinit(gpa); | ||
| 3469 | dg.scratch.deinit(gpa); | ||
| 3467 | } | 3470 | } |
| 3471 | try dg.ctype_pool.init(gpa); | ||
| 3468 | 3472 | ||
| 3469 | c_codegen.genHeader(&dg) catch |err| switch (err) { | 3473 | c_codegen.genHeader(&dg) catch |err| switch (err) { |
| 3470 | error.AnalysisFail => { | 3474 | error.AnalysisFail => { |
| ... | @@ -3473,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v | ... | @@ -3473,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3473 | }, | 3477 | }, |
| 3474 | else => |e| return e, | 3478 | else => |e| return e, |
| 3475 | }; | 3479 | }; |
| 3476 | |||
| 3477 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | ||
| 3478 | fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len); | ||
| 3479 | }, | 3480 | }, |
| 3480 | } | 3481 | } |
| 3481 | }, | 3482 | }, |
src/InternPool.zig+2-9| ... | @@ -712,7 +712,7 @@ pub const Key = union(enum) { | ... | @@ -712,7 +712,7 @@ pub const Key = union(enum) { |
| 712 | pub fn fieldName( | 712 | pub fn fieldName( |
| 713 | self: AnonStructType, | 713 | self: AnonStructType, |
| 714 | ip: *const InternPool, | 714 | ip: *const InternPool, |
| 715 | index: u32, | 715 | index: usize, |
| 716 | ) OptionalNullTerminatedString { | 716 | ) OptionalNullTerminatedString { |
| 717 | if (self.names.len == 0) | 717 | if (self.names.len == 0) |
| 718 | return .none; | 718 | return .none; |
| ... | @@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) { | ... | @@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) { |
| 3879 | none = std.math.maxInt(u6), | 3879 | none = std.math.maxInt(u6), |
| 3880 | _, | 3880 | _, |
| 3881 | 3881 | ||
| 3882 | pub fn toByteUnitsOptional(a: Alignment) ?u64 { | 3882 | pub fn toByteUnits(a: Alignment) ?u64 { |
| 3883 | return switch (a) { | 3883 | return switch (a) { |
| 3884 | .none => null, | 3884 | .none => null, |
| 3885 | else => @as(u64, 1) << @intFromEnum(a), | 3885 | else => @as(u64, 1) << @intFromEnum(a), |
| 3886 | }; | 3886 | }; |
| 3887 | } | 3887 | } |
| 3888 | 3888 | ||
| 3889 | pub fn toByteUnits(a: Alignment, default: u64) u64 { | ||
| 3890 | return switch (a) { | ||
| 3891 | .none => default, | ||
| 3892 | else => @as(u64, 1) << @intFromEnum(a), | ||
| 3893 | }; | ||
| 3894 | } | ||
| 3895 | |||
| 3896 | pub fn fromByteUnits(n: u64) Alignment { | 3889 | pub fn fromByteUnits(n: u64) Alignment { |
| 3897 | if (n == 0) return .none; | 3890 | if (n == 0) return .none; |
| 3898 | assert(std.math.isPowerOfTwo(n)); | 3891 | assert(std.math.isPowerOfTwo(n)); |
src/Module.zig+1-1| ... | @@ -5846,7 +5846,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { | ... | @@ -5846,7 +5846,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 { |
| 5846 | return @as(u16, @intCast(big.bitCountTwosComp())); | 5846 | return @as(u16, @intCast(big.bitCountTwosComp())); |
| 5847 | }, | 5847 | }, |
| 5848 | .lazy_align => |lazy_ty| { | 5848 | .lazy_align => |lazy_ty| { |
| 5849 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(mod).toByteUnits(0)) + @intFromBool(sign); | 5849 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiAlignment(mod).toByteUnits() orelse 0) + @intFromBool(sign); |
| 5850 | }, | 5850 | }, |
| 5851 | .lazy_size => |lazy_ty| { | 5851 | .lazy_size => |lazy_ty| { |
| 5852 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(mod)) + @intFromBool(sign); | 5852 | return Type.smallestUnsignedBits(Type.fromInterned(lazy_ty).abiSize(mod)) + @intFromBool(sign); |
src/Sema.zig+14-14| ... | @@ -6508,7 +6508,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -6508,7 +6508,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 6508 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); | 6508 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); |
| 6509 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { | 6509 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { |
| 6510 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ | 6510 | return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ |
| 6511 | alignment.toByteUnitsOptional().?, | 6511 | alignment.toByteUnits().?, |
| 6512 | }); | 6512 | }); |
| 6513 | } | 6513 | } |
| 6514 | 6514 | ||
| ... | @@ -17804,7 +17804,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -17804,7 +17804,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 17804 | }, | 17804 | }, |
| 17805 | .Pointer => { | 17805 | .Pointer => { |
| 17806 | const info = ty.ptrInfo(mod); | 17806 | const info = ty.ptrInfo(mod); |
| 17807 | const alignment = if (info.flags.alignment.toByteUnitsOptional()) |alignment| | 17807 | const alignment = if (info.flags.alignment.toByteUnits()) |alignment| |
| 17808 | try mod.intValue(Type.comptime_int, alignment) | 17808 | try mod.intValue(Type.comptime_int, alignment) |
| 17809 | else | 17809 | else |
| 17810 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); | 17810 | try Type.fromInterned(info.child).lazyAbiAlignment(mod); |
| ... | @@ -18279,7 +18279,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18279,7 +18279,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18279 | // type: type, | 18279 | // type: type, |
| 18280 | field_ty, | 18280 | field_ty, |
| 18281 | // alignment: comptime_int, | 18281 | // alignment: comptime_int, |
| 18282 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits(0))).toIntern(), | 18282 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), |
| 18283 | }; | 18283 | }; |
| 18284 | field_val.* = try mod.intern(.{ .aggregate = .{ | 18284 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18285 | .ty = union_field_ty.toIntern(), | 18285 | .ty = union_field_ty.toIntern(), |
| ... | @@ -18436,7 +18436,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18436,7 +18436,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18436 | // is_comptime: bool, | 18436 | // is_comptime: bool, |
| 18437 | Value.makeBool(is_comptime).toIntern(), | 18437 | Value.makeBool(is_comptime).toIntern(), |
| 18438 | // alignment: comptime_int, | 18438 | // alignment: comptime_int, |
| 18439 | (try mod.intValue(Type.comptime_int, Type.fromInterned(field_ty).abiAlignment(mod).toByteUnits(0))).toIntern(), | 18439 | (try mod.intValue(Type.comptime_int, Type.fromInterned(field_ty).abiAlignment(mod).toByteUnits() orelse 0)).toIntern(), |
| 18440 | }; | 18440 | }; |
| 18441 | struct_field_val.* = try mod.intern(.{ .aggregate = .{ | 18441 | struct_field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18442 | .ty = struct_field_ty.toIntern(), | 18442 | .ty = struct_field_ty.toIntern(), |
| ... | @@ -18505,7 +18505,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -18505,7 +18505,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18505 | // is_comptime: bool, | 18505 | // is_comptime: bool, |
| 18506 | Value.makeBool(field_is_comptime).toIntern(), | 18506 | Value.makeBool(field_is_comptime).toIntern(), |
| 18507 | // alignment: comptime_int, | 18507 | // alignment: comptime_int, |
| 18508 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits(0))).toIntern(), | 18508 | (try mod.intValue(Type.comptime_int, alignment.toByteUnits() orelse 0)).toIntern(), |
| 18509 | }; | 18509 | }; |
| 18510 | field_val.* = try mod.intern(.{ .aggregate = .{ | 18510 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18511 | .ty = struct_field_ty.toIntern(), | 18511 | .ty = struct_field_ty.toIntern(), |
| ... | @@ -22552,7 +22552,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -22552,7 +22552,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22552 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 22552 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22553 | } | 22553 | } |
| 22554 | if (ptr_align.compare(.gt, .@"1")) { | 22554 | if (ptr_align.compare(.gt, .@"1")) { |
| 22555 | const align_bytes_minus_1 = ptr_align.toByteUnitsOptional().? - 1; | 22555 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; |
| 22556 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 22556 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22557 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); | 22557 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); |
| 22558 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 22558 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| ... | @@ -22572,7 +22572,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -22572,7 +22572,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22572 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); | 22572 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22573 | } | 22573 | } |
| 22574 | if (ptr_align.compare(.gt, .@"1")) { | 22574 | if (ptr_align.compare(.gt, .@"1")) { |
| 22575 | const align_bytes_minus_1 = ptr_align.toByteUnitsOptional().? - 1; | 22575 | const align_bytes_minus_1 = ptr_align.toByteUnits().? - 1; |
| 22576 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 22576 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22577 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); | 22577 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); |
| 22578 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); | 22578 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| ... | @@ -22970,10 +22970,10 @@ fn ptrCastFull( | ... | @@ -22970,10 +22970,10 @@ fn ptrCastFull( |
| 22970 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); | 22970 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); |
| 22971 | errdefer msg.destroy(sema.gpa); | 22971 | errdefer msg.destroy(sema.gpa); |
| 22972 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ | 22972 | try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ |
| 22973 | operand_ty.fmt(mod), src_align.toByteUnits(0), | 22973 | operand_ty.fmt(mod), src_align.toByteUnits() orelse 0, |
| 22974 | }); | 22974 | }); |
| 22975 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ | 22975 | try sema.errNote(block, src, msg, "'{}' has alignment '{d}'", .{ |
| 22976 | dest_ty.fmt(mod), dest_align.toByteUnits(0), | 22976 | dest_ty.fmt(mod), dest_align.toByteUnits() orelse 0, |
| 22977 | }); | 22977 | }); |
| 22978 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); | 22978 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); |
| 22979 | break :msg msg; | 22979 | break :msg msg; |
| ... | @@ -23067,7 +23067,7 @@ fn ptrCastFull( | ... | @@ -23067,7 +23067,7 @@ fn ptrCastFull( |
| 23067 | if (!dest_align.check(addr)) { | 23067 | if (!dest_align.check(addr)) { |
| 23068 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ | 23068 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ |
| 23069 | addr, | 23069 | addr, |
| 23070 | dest_align.toByteUnitsOptional().?, | 23070 | dest_align.toByteUnits().?, |
| 23071 | }); | 23071 | }); |
| 23072 | } | 23072 | } |
| 23073 | } | 23073 | } |
| ... | @@ -23110,7 +23110,7 @@ fn ptrCastFull( | ... | @@ -23110,7 +23110,7 @@ fn ptrCastFull( |
| 23110 | dest_align.compare(.gt, src_align) and | 23110 | dest_align.compare(.gt, src_align) and |
| 23111 | try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child))) | 23111 | try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child))) |
| 23112 | { | 23112 | { |
| 23113 | const align_bytes_minus_1 = dest_align.toByteUnitsOptional().? - 1; | 23113 | const align_bytes_minus_1 = dest_align.toByteUnits().? - 1; |
| 23114 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); | 23114 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 23115 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); | 23115 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); |
| 23116 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); | 23116 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); |
| ... | @@ -27837,7 +27837,7 @@ fn structFieldPtrByIndex( | ... | @@ -27837,7 +27837,7 @@ fn structFieldPtrByIndex( |
| 27837 | const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod); | 27837 | const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod); |
| 27838 | if (elem_size_bytes * 8 == elem_size_bits) { | 27838 | if (elem_size_bytes * 8 == elem_size_bits) { |
| 27839 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; | 27839 | const byte_offset = ptr_ty_data.packed_offset.bit_offset / 8; |
| 27840 | const new_align: Alignment = @enumFromInt(@ctz(byte_offset | parent_align.toByteUnitsOptional().?)); | 27840 | const new_align: Alignment = @enumFromInt(@ctz(byte_offset | parent_align.toByteUnits().?)); |
| 27841 | assert(new_align != .none); | 27841 | assert(new_align != .none); |
| 27842 | ptr_ty_data.flags.alignment = new_align; | 27842 | ptr_ty_data.flags.alignment = new_align; |
| 27843 | ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 }; | 27843 | ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 }; |
| ... | @@ -29132,7 +29132,7 @@ fn coerceExtra( | ... | @@ -29132,7 +29132,7 @@ fn coerceExtra( |
| 29132 | .addr = .{ .int = if (dest_info.flags.alignment != .none) | 29132 | .addr = .{ .int = if (dest_info.flags.alignment != .none) |
| 29133 | (try mod.intValue( | 29133 | (try mod.intValue( |
| 29134 | Type.usize, | 29134 | Type.usize, |
| 29135 | dest_info.flags.alignment.toByteUnitsOptional().?, | 29135 | dest_info.flags.alignment.toByteUnits().?, |
| 29136 | )).toIntern() | 29136 | )).toIntern() |
| 29137 | else | 29137 | else |
| 29138 | try mod.intern_pool.getCoercedInts( | 29138 | try mod.intern_pool.getCoercedInts( |
| ... | @@ -29800,7 +29800,7 @@ const InMemoryCoercionResult = union(enum) { | ... | @@ -29800,7 +29800,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29800 | }, | 29800 | }, |
| 29801 | .ptr_alignment => |pair| { | 29801 | .ptr_alignment => |pair| { |
| 29802 | try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ | 29802 | try sema.errNote(block, src, msg, "pointer alignment '{d}' cannot cast into pointer alignment '{d}'", .{ |
| 29803 | pair.actual.toByteUnits(0), pair.wanted.toByteUnits(0), | 29803 | pair.actual.toByteUnits() orelse 0, pair.wanted.toByteUnits() orelse 0, |
| 29804 | }); | 29804 | }); |
| 29805 | break; | 29805 | break; |
| 29806 | }, | 29806 | }, |
src/Value.zig+8-8| ... | @@ -176,7 +176,7 @@ pub fn toBigIntAdvanced( | ... | @@ -176,7 +176,7 @@ pub fn toBigIntAdvanced( |
| 176 | if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty)); | 176 | if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty)); |
| 177 | const x = switch (int.storage) { | 177 | const x = switch (int.storage) { |
| 178 | else => unreachable, | 178 | else => unreachable, |
| 179 | .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), | 179 | .lazy_align => Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, |
| 180 | .lazy_size => Type.fromInterned(ty).abiSize(mod), | 180 | .lazy_size => Type.fromInterned(ty).abiSize(mod), |
| 181 | }; | 181 | }; |
| 182 | return BigIntMutable.init(&space.limbs, x).toConst(); | 182 | return BigIntMutable.init(&space.limbs, x).toConst(); |
| ... | @@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 | ... | @@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 |
| 237 | .u64 => |x| x, | 237 | .u64 => |x| x, |
| 238 | .i64 => |x| std.math.cast(u64, x), | 238 | .i64 => |x| std.math.cast(u64, x), |
| 239 | .lazy_align => |ty| if (opt_sema) |sema| | 239 | .lazy_align => |ty| if (opt_sema) |sema| |
| 240 | (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits(0) | 240 | (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0 |
| 241 | else | 241 | else |
| 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), | 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, |
| 243 | .lazy_size => |ty| if (opt_sema) |sema| | 243 | .lazy_size => |ty| if (opt_sema) |sema| |
| 244 | (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar | 244 | (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar |
| 245 | else | 245 | else |
| ... | @@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 { | ... | @@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 { |
| 289 | .big_int => |big_int| big_int.to(i64) catch unreachable, | 289 | .big_int => |big_int| big_int.to(i64) catch unreachable, |
| 290 | .i64 => |x| x, | 290 | .i64 => |x| x, |
| 291 | .u64 => |x| @intCast(x), | 291 | .u64 => |x| @intCast(x), |
| 292 | .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0)), | 292 | .lazy_align => |ty| @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0), |
| 293 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)), | 293 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)), |
| 294 | }, | 294 | }, |
| 295 | else => unreachable, | 295 | else => unreachable, |
| ... | @@ -497,7 +497,7 @@ pub fn writeToPackedMemory( | ... | @@ -497,7 +497,7 @@ pub fn writeToPackedMemory( |
| 497 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), | 497 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), |
| 498 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), | 498 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), |
| 499 | .lazy_align => |lazy_align| { | 499 | .lazy_align => |lazy_align| { |
| 500 | const num = Type.fromInterned(lazy_align).abiAlignment(mod).toByteUnits(0); | 500 | const num = Type.fromInterned(lazy_align).abiAlignment(mod).toByteUnits() orelse 0; |
| 501 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); | 501 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); |
| 502 | }, | 502 | }, |
| 503 | .lazy_size => |lazy_size| { | 503 | .lazy_size => |lazy_size| { |
| ... | @@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T { | ... | @@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T { |
| 890 | } | 890 | } |
| 891 | return @floatFromInt(x); | 891 | return @floatFromInt(x); |
| 892 | }, | 892 | }, |
| 893 | .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0)), | 893 | .lazy_align => |ty| @floatFromInt(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0), |
| 894 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)), | 894 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)), |
| 895 | }, | 895 | }, |
| 896 | .float => |float| switch (float.storage) { | 896 | .float => |float| switch (float.storage) { |
| ... | @@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?* | ... | @@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?* |
| 1529 | }, | 1529 | }, |
| 1530 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod), | 1530 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod), |
| 1531 | .lazy_align => |ty| if (opt_sema) |sema| { | 1531 | .lazy_align => |ty| if (opt_sema) |sema| { |
| 1532 | return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits(0), float_ty, mod); | 1532 | return floatFromIntInner((try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar.toByteUnits() orelse 0, float_ty, mod); |
| 1533 | } else { | 1533 | } else { |
| 1534 | return floatFromIntInner(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), float_ty, mod); | 1534 | return floatFromIntInner(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, float_ty, mod); |
| 1535 | }, | 1535 | }, |
| 1536 | .lazy_size => |ty| if (opt_sema) |sema| { | 1536 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 1537 | return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod); | 1537 | return floatFromIntInner((try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod); |
src/arch/wasm/CodeGen.zig+15-15| ... | @@ -1296,7 +1296,7 @@ fn genFunc(func: *CodeGen) InnerError!void { | ... | @@ -1296,7 +1296,7 @@ fn genFunc(func: *CodeGen) InnerError!void { |
| 1296 | // subtract it from the current stack pointer | 1296 | // subtract it from the current stack pointer |
| 1297 | try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } }); | 1297 | try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } }); |
| 1298 | // Get negative stack aligment | 1298 | // Get negative stack aligment |
| 1299 | try prologue.append(.{ .tag = .i32_const, .data = .{ .imm32 = @as(i32, @intCast(func.stack_alignment.toByteUnitsOptional().?)) * -1 } }); | 1299 | try prologue.append(.{ .tag = .i32_const, .data = .{ .imm32 = @as(i32, @intCast(func.stack_alignment.toByteUnits().?)) * -1 } }); |
| 1300 | // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment | 1300 | // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment |
| 1301 | try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } }); | 1301 | try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } }); |
| 1302 | // store the current stack pointer as the bottom, which will be used to calculate all stack pointer offsets | 1302 | // store the current stack pointer as the bottom, which will be used to calculate all stack pointer offsets |
| ... | @@ -2107,7 +2107,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2107,7 +2107,7 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2107 | }); | 2107 | }); |
| 2108 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ | 2108 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2109 | .offset = operand.offset(), | 2109 | .offset = operand.offset(), |
| 2110 | .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnitsOptional().?), | 2110 | .alignment = @intCast(scalar_type.abiAlignment(mod).toByteUnits().?), |
| 2111 | }); | 2111 | }); |
| 2112 | }, | 2112 | }, |
| 2113 | else => try func.emitWValue(operand), | 2113 | else => try func.emitWValue(operand), |
| ... | @@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2384 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2384 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2385 | std.wasm.simdOpcode(.v128_store), | 2385 | std.wasm.simdOpcode(.v128_store), |
| 2386 | offset + lhs.offset(), | 2386 | offset + lhs.offset(), |
| 2387 | @intCast(ty.abiAlignment(mod).toByteUnits(0)), | 2387 | @intCast(ty.abiAlignment(mod).toByteUnits() orelse 0), |
| 2388 | }); | 2388 | }); |
| 2389 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2389 | return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2390 | }, | 2390 | }, |
| ... | @@ -2440,7 +2440,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE | ... | @@ -2440,7 +2440,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2440 | Mir.Inst.Tag.fromOpcode(opcode), | 2440 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2441 | .{ | 2441 | .{ |
| 2442 | .offset = offset + lhs.offset(), | 2442 | .offset = offset + lhs.offset(), |
| 2443 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2443 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2444 | }, | 2444 | }, |
| 2445 | ); | 2445 | ); |
| 2446 | } | 2446 | } |
| ... | @@ -2500,7 +2500,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu | ... | @@ -2500,7 +2500,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2500 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 2500 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2501 | std.wasm.simdOpcode(.v128_load), | 2501 | std.wasm.simdOpcode(.v128_load), |
| 2502 | offset + operand.offset(), | 2502 | offset + operand.offset(), |
| 2503 | @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2503 | @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2504 | }); | 2504 | }); |
| 2505 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 2505 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2506 | return WValue{ .stack = {} }; | 2506 | return WValue{ .stack = {} }; |
| ... | @@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu | ... | @@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2518 | Mir.Inst.Tag.fromOpcode(opcode), | 2518 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2519 | .{ | 2519 | .{ |
| 2520 | .offset = offset + operand.offset(), | 2520 | .offset = offset + operand.offset(), |
| 2521 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 2521 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 2522 | }, | 2522 | }, |
| 2523 | ); | 2523 | ); |
| 2524 | 2524 | ||
| ... | @@ -3456,7 +3456,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 { | ... | @@ -3456,7 +3456,7 @@ fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 { |
| 3456 | .i64 => |x| @as(i32, @intCast(x)), | 3456 | .i64 => |x| @as(i32, @intCast(x)), |
| 3457 | .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))), | 3457 | .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))), |
| 3458 | .big_int => unreachable, | 3458 | .big_int => unreachable, |
| 3459 | .lazy_align => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0))))), | 3459 | .lazy_align => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0)))), |
| 3460 | .lazy_size => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiSize(mod))))), | 3460 | .lazy_size => |ty| @as(i32, @bitCast(@as(u32, @intCast(Type.fromInterned(ty).abiSize(mod))))), |
| 3461 | }; | 3461 | }; |
| 3462 | } | 3462 | } |
| ... | @@ -4204,7 +4204,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro | ... | @@ -4204,7 +4204,7 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro |
| 4204 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { | 4204 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4205 | try func.addMemArg(.i32_load16_u, .{ | 4205 | try func.addMemArg(.i32_load16_u, .{ |
| 4206 | .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))), | 4206 | .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))), |
| 4207 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnitsOptional().?), | 4207 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnits().?), |
| 4208 | }); | 4208 | }); |
| 4209 | } | 4209 | } |
| 4210 | 4210 | ||
| ... | @@ -5141,7 +5141,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5141,7 +5141,7 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5141 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ | 5141 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 5142 | opcode, | 5142 | opcode, |
| 5143 | operand.offset(), | 5143 | operand.offset(), |
| 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnitsOptional().?), | 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnits().?), |
| 5145 | }); | 5145 | }); |
| 5146 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); | 5146 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 5147 | try func.addLabel(.local_set, result.local.value); | 5147 | try func.addLabel(.local_set, result.local.value); |
| ... | @@ -6552,7 +6552,7 @@ fn lowerTry( | ... | @@ -6552,7 +6552,7 @@ fn lowerTry( |
| 6552 | const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))); | 6552 | const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 6553 | try func.addMemArg(.i32_load16_u, .{ | 6553 | try func.addMemArg(.i32_load16_u, .{ |
| 6554 | .offset = err_union.offset() + err_offset, | 6554 | .offset = err_union.offset() + err_offset, |
| 6555 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnitsOptional().?), | 6555 | .alignment = @intCast(Type.anyerror.abiAlignment(mod).toByteUnits().?), |
| 6556 | }); | 6556 | }); |
| 6557 | } | 6557 | } |
| 6558 | try func.addTag(.i32_eqz); | 6558 | try func.addTag(.i32_eqz); |
| ... | @@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7499 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), | 7499 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), |
| 7500 | }, .{ | 7500 | }, .{ |
| 7501 | .offset = ptr_operand.offset(), | 7501 | .offset = ptr_operand.offset(), |
| 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7503 | }); | 7503 | }); |
| 7504 | try func.addLabel(.local_tee, val_local.local.value); | 7504 | try func.addLabel(.local_tee, val_local.local.value); |
| 7505 | _ = try func.cmp(.stack, expected_val, ty, .eq); | 7505 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| ... | @@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7561 | try func.emitWValue(ptr); | 7561 | try func.emitWValue(ptr); |
| 7562 | try func.addAtomicMemArg(tag, .{ | 7562 | try func.addAtomicMemArg(tag, .{ |
| 7563 | .offset = ptr.offset(), | 7563 | .offset = ptr.offset(), |
| 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7565 | }); | 7565 | }); |
| 7566 | } else { | 7566 | } else { |
| 7567 | _ = try func.load(ptr, ty, 0); | 7567 | _ = try func.load(ptr, ty, 0); |
| ... | @@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7622 | }, | 7622 | }, |
| 7623 | .{ | 7623 | .{ |
| 7624 | .offset = ptr.offset(), | 7624 | .offset = ptr.offset(), |
| 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7626 | }, | 7626 | }, |
| 7627 | ); | 7627 | ); |
| 7628 | const select_res = try func.allocLocal(ty); | 7628 | const select_res = try func.allocLocal(ty); |
| ... | @@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7682 | }; | 7682 | }; |
| 7683 | try func.addAtomicMemArg(tag, .{ | 7683 | try func.addAtomicMemArg(tag, .{ |
| 7684 | .offset = ptr.offset(), | 7684 | .offset = ptr.offset(), |
| 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7686 | }); | 7686 | }); |
| 7687 | const result = try WValue.toLocal(.stack, func, ty); | 7687 | const result = try WValue.toLocal(.stack, func, ty); |
| 7688 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); | 7688 | return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand }); |
| ... | @@ -7781,7 +7781,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7781,7 +7781,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7781 | try func.lowerToStack(operand); | 7781 | try func.lowerToStack(operand); |
| 7782 | try func.addAtomicMemArg(tag, .{ | 7782 | try func.addAtomicMemArg(tag, .{ |
| 7783 | .offset = ptr.offset(), | 7783 | .offset = ptr.offset(), |
| 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), |
| 7785 | }); | 7785 | }); |
| 7786 | } else { | 7786 | } else { |
| 7787 | try func.store(ptr, operand, ty, 0); | 7787 | try func.store(ptr, operand, ty, 0); |
src/arch/x86_64/CodeGen.zig+3-3| ... | @@ -18959,7 +18959,7 @@ fn resolveCallingConventionValues( | ... | @@ -18959,7 +18959,7 @@ fn resolveCallingConventionValues( |
| 18959 | 18959 | ||
| 18960 | const param_size: u31 = @intCast(ty.abiSize(mod)); | 18960 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 18961 | const param_align: u31 = | 18961 | const param_align: u31 = |
| 18962 | @intCast(@max(ty.abiAlignment(mod).toByteUnitsOptional().?, 8)); | 18962 | @intCast(@max(ty.abiAlignment(mod).toByteUnits().?, 8)); |
| 18963 | result.stack_byte_count = | 18963 | result.stack_byte_count = |
| 18964 | mem.alignForward(u31, result.stack_byte_count, param_align); | 18964 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 18965 | arg.* = .{ .load_frame = .{ | 18965 | arg.* = .{ .load_frame = .{ |
| ... | @@ -19003,7 +19003,7 @@ fn resolveCallingConventionValues( | ... | @@ -19003,7 +19003,7 @@ fn resolveCallingConventionValues( |
| 19003 | continue; | 19003 | continue; |
| 19004 | } | 19004 | } |
| 19005 | const param_size: u31 = @intCast(ty.abiSize(mod)); | 19005 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 19006 | const param_align: u31 = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?); | 19006 | const param_align: u31 = @intCast(ty.abiAlignment(mod).toByteUnits().?); |
| 19007 | result.stack_byte_count = | 19007 | result.stack_byte_count = |
| 19008 | mem.alignForward(u31, result.stack_byte_count, param_align); | 19008 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 19009 | arg.* = .{ .load_frame = .{ | 19009 | arg.* = .{ .load_frame = .{ |
| ... | @@ -19096,7 +19096,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { | ... | @@ -19096,7 +19096,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 19096 | .integer => switch (part_i) { | 19096 | .integer => switch (part_i) { |
| 19097 | 0 => Type.u64, | 19097 | 0 => Type.u64, |
| 19098 | 1 => part: { | 19098 | 1 => part: { |
| 19099 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?; | 19099 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnits().?; |
| 19100 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); | 19100 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); |
| 19101 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { | 19101 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { |
| 19102 | 1 => elem_ty, | 19102 | 1 => elem_ty, |
src/codegen.zig+3-3| ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( | ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | const size = struct_type.size(ip).*; | 550 | const size = struct_type.size(ip).*; |
| 551 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnitsOptional().?; | 551 | const alignment = struct_type.flagsPtr(ip).alignment.toByteUnits().?; |
| 552 | 552 | ||
| 553 | const padding = math.cast( | 553 | const padding = math.cast( |
| 554 | usize, | 554 | usize, |
| ... | @@ -893,12 +893,12 @@ fn genDeclRef( | ... | @@ -893,12 +893,12 @@ fn genDeclRef( |
| 893 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? | 893 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 894 | if (ty.castPtrToFn(zcu)) |fn_ty| { | 894 | if (ty.castPtrToFn(zcu)) |fn_ty| { |
| 895 | if (zcu.typeToFunc(fn_ty).?.is_generic) { | 895 | if (zcu.typeToFunc(fn_ty).?.is_generic) { |
| 896 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? }); | 896 | return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnits().? }); |
| 897 | } | 897 | } |
| 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { | 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { |
| 899 | const elem_ty = ty.elemType2(zcu); | 899 | const elem_ty = ty.elemType2(zcu); |
| 900 | if (!elem_ty.hasRuntimeBits(zcu)) { | 900 | if (!elem_ty.hasRuntimeBits(zcu)) { |
| 901 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? }); | 901 | return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnits().? }); |
| 902 | } | 902 | } |
| 903 | } | 903 | } |
| 904 | 904 |
src/codegen/c.zig+926-983| ... | @@ -22,7 +22,7 @@ const Alignment = InternPool.Alignment; | ... | @@ -22,7 +22,7 @@ const Alignment = InternPool.Alignment; |
| 22 | const BigIntLimb = std.math.big.Limb; | 22 | const BigIntLimb = std.math.big.Limb; |
| 23 | const BigInt = std.math.big.int; | 23 | const BigInt = std.math.big.int; |
| 24 | 24 | ||
| 25 | pub const CType = @import("c/type.zig").CType; | 25 | pub const CType = @import("c/Type.zig"); |
| 26 | 26 | ||
| 27 | pub const CValue = union(enum) { | 27 | pub const CValue = union(enum) { |
| 28 | none: void, | 28 | none: void, |
| ... | @@ -62,7 +62,7 @@ pub const LazyFnKey = union(enum) { | ... | @@ -62,7 +62,7 @@ pub const LazyFnKey = union(enum) { |
| 62 | never_inline: InternPool.DeclIndex, | 62 | never_inline: InternPool.DeclIndex, |
| 63 | }; | 63 | }; |
| 64 | pub const LazyFnValue = struct { | 64 | pub const LazyFnValue = struct { |
| 65 | fn_name: []const u8, | 65 | fn_name: CType.String, |
| 66 | data: Data, | 66 | data: Data, |
| 67 | 67 | ||
| 68 | pub const Data = union { | 68 | pub const Data = union { |
| ... | @@ -74,19 +74,19 @@ pub const LazyFnValue = struct { | ... | @@ -74,19 +74,19 @@ pub const LazyFnValue = struct { |
| 74 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); | 74 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); |
| 75 | 75 | ||
| 76 | const Local = struct { | 76 | const Local = struct { |
| 77 | cty_idx: CType.Index, | 77 | ctype: CType, |
| 78 | flags: packed struct(u32) { | 78 | flags: packed struct(u32) { |
| 79 | alignas: CType.AlignAs, | 79 | alignas: CType.AlignAs, |
| 80 | _: u20 = undefined, | 80 | _: u20 = undefined, |
| 81 | }, | 81 | }, |
| 82 | 82 | ||
| 83 | pub fn getType(local: Local) LocalType { | 83 | pub fn getType(local: Local) LocalType { |
| 84 | return .{ .cty_idx = local.cty_idx, .alignas = local.flags.alignas }; | 84 | return .{ .ctype = local.ctype, .alignas = local.flags.alignas }; |
| 85 | } | 85 | } |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | const LocalIndex = u16; | 88 | const LocalIndex = u16; |
| 89 | const LocalType = struct { cty_idx: CType.Index, alignas: CType.AlignAs }; | 89 | const LocalType = struct { ctype: CType, alignas: CType.AlignAs }; |
| 90 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); | 90 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); |
| 91 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); | 91 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); |
| 92 | 92 | ||
| ... | @@ -193,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{ | ... | @@ -193,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{ |
| 193 | .{ "switch", {} }, | 193 | .{ "switch", {} }, |
| 194 | .{ "thread_local", {} }, | 194 | .{ "thread_local", {} }, |
| 195 | .{ "typedef", {} }, | 195 | .{ "typedef", {} }, |
| 196 | .{ "typeof", {} }, | ||
| 196 | .{ "uint16_t", {} }, | 197 | .{ "uint16_t", {} }, |
| 197 | .{ "uint32_t", {} }, | 198 | .{ "uint32_t", {} }, |
| 198 | .{ "uint64_t", {} }, | 199 | .{ "uint64_t", {} }, |
| ... | @@ -309,12 +310,14 @@ pub const Function = struct { | ... | @@ -309,12 +310,14 @@ pub const Function = struct { |
| 309 | 310 | ||
| 310 | const result: CValue = if (lowersToArray(ty, zcu)) result: { | 311 | const result: CValue = if (lowersToArray(ty, zcu)) result: { |
| 311 | const writer = f.object.codeHeaderWriter(); | 312 | const writer = f.object.codeHeaderWriter(); |
| 312 | const alignment: Alignment = .none; | 313 | const decl_c_value = try f.allocLocalValue(.{ |
| 313 | const decl_c_value = try f.allocLocalValue(ty, alignment); | 314 | .ctype = try f.ctypeFromType(ty, .complete), |
| 315 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)), | ||
| 316 | }); | ||
| 314 | const gpa = f.object.dg.gpa; | 317 | const gpa = f.object.dg.gpa; |
| 315 | try f.allocs.put(gpa, decl_c_value.new_local, false); | 318 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 316 | try writer.writeAll("static "); | 319 | try writer.writeAll("static "); |
| 317 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, alignment, .complete); | 320 | try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, Const, .none, .complete); |
| 318 | try writer.writeAll(" = "); | 321 | try writer.writeAll(" = "); |
| 319 | try f.object.dg.renderValue(writer, val, .StaticInitializer); | 322 | try f.object.dg.renderValue(writer, val, .StaticInitializer); |
| 320 | try writer.writeAll(";\n "); | 323 | try writer.writeAll(";\n "); |
| ... | @@ -335,42 +338,39 @@ pub const Function = struct { | ... | @@ -335,42 +338,39 @@ pub const Function = struct { |
| 335 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. | 338 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. |
| 336 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; | 339 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 337 | /// that responsibility lies with the caller. | 340 | /// that responsibility lies with the caller. |
| 338 | fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue { | 341 | fn allocLocalValue(f: *Function, local_type: LocalType) !CValue { |
| 339 | const zcu = f.object.dg.zcu; | 342 | try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1); |
| 340 | const gpa = f.object.dg.gpa; | 343 | defer f.locals.appendAssumeCapacity(.{ |
| 341 | try f.locals.append(gpa, .{ | 344 | .ctype = local_type.ctype, |
| 342 | .cty_idx = try f.typeToIndex(ty, .complete), | 345 | .flags = .{ .alignas = local_type.alignas }, |
| 343 | .flags = .{ | ||
| 344 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), | ||
| 345 | }, | ||
| 346 | }); | 346 | }); |
| 347 | return .{ .new_local = @intCast(f.locals.items.len - 1) }; | 347 | return .{ .new_local = @intCast(f.locals.items.len) }; |
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { | 350 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { |
| 351 | const result = try f.allocAlignedLocal(ty, .{}, .none); | 351 | return f.allocAlignedLocal(inst, .{ |
| 352 | if (inst) |i| { | 352 | .ctype = try f.ctypeFromType(ty, .complete), |
| 353 | log.debug("%{d}: allocating t{d}", .{ i, result.new_local }); | 353 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.zcu)), |
| 354 | } else { | 354 | }); |
| 355 | log.debug("allocating t{d}", .{result.new_local}); | ||
| 356 | } | ||
| 357 | return result; | ||
| 358 | } | 355 | } |
| 359 | 356 | ||
| 360 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should | 357 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| 361 | /// not be used for persistent locals (i.e. those in `allocs`). | 358 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 362 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue { | 359 | fn allocAlignedLocal(f: *Function, inst: ?Air.Inst.Index, local_type: LocalType) !CValue { |
| 363 | const zcu = f.object.dg.zcu; | 360 | const result: CValue = result: { |
| 364 | if (f.free_locals_map.getPtr(.{ | 361 | if (f.free_locals_map.getPtr(local_type)) |locals_list| { |
| 365 | .cty_idx = try f.typeToIndex(ty, .complete), | 362 | if (locals_list.popOrNull()) |local_entry| { |
| 366 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), | 363 | break :result .{ .new_local = local_entry.key }; |
| 367 | })) |locals_list| { | 364 | } |
| 368 | if (locals_list.popOrNull()) |local_entry| { | ||
| 369 | return .{ .new_local = local_entry.key }; | ||
| 370 | } | 365 | } |
| 366 | break :result try f.allocLocalValue(local_type); | ||
| 367 | }; | ||
| 368 | if (inst) |i| { | ||
| 369 | log.debug("%{d}: allocating t{d}", .{ i, result.new_local }); | ||
| 370 | } else { | ||
| 371 | log.debug("allocating t{d}", .{result.new_local}); | ||
| 371 | } | 372 | } |
| 372 | 373 | return result; | |
| 373 | return f.allocLocalValue(ty, alignment); | ||
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { | 376 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { |
| ... | @@ -380,15 +380,20 @@ pub const Function = struct { | ... | @@ -380,15 +380,20 @@ pub const Function = struct { |
| 380 | .local_ref => |i| { | 380 | .local_ref => |i| { |
| 381 | const local = &f.locals.items[i]; | 381 | const local = &f.locals.items[i]; |
| 382 | if (local.flags.alignas.abiOrder().compare(.lt)) { | 382 | if (local.flags.alignas.abiOrder().compare(.lt)) { |
| 383 | const zcu = f.object.dg.zcu; | 383 | const gpa = f.object.dg.gpa; |
| 384 | const pointee_ty = try zcu.intType(.unsigned, @min( | 384 | const mod = f.object.dg.mod; |
| 385 | local.flags.alignas.@"align".toByteUnitsOptional().?, | 385 | const ctype_pool = &f.object.dg.ctype_pool; |
| 386 | f.object.dg.mod.resolved_target.result.maxIntAlignment(), | ||
| 387 | ) * 8); | ||
| 388 | const ptr_ty = try zcu.singleMutPtrType(pointee_ty); | ||
| 389 | 386 | ||
| 390 | try w.writeByte('('); | 387 | try w.writeByte('('); |
| 391 | try f.renderType(w, ptr_ty); | 388 | try f.renderCType(w, try ctype_pool.getPointer(gpa, .{ |
| 389 | .elem_ctype = try ctype_pool.fromIntInfo(gpa, .{ | ||
| 390 | .signedness = .unsigned, | ||
| 391 | .bits = @min( | ||
| 392 | local.flags.alignas.toByteUnits(), | ||
| 393 | mod.resolved_target.result.maxIntAlignment(), | ||
| 394 | ) * 8, | ||
| 395 | }, mod, .forward), | ||
| 396 | })); | ||
| 392 | try w.writeByte(')'); | 397 | try w.writeByte(')'); |
| 393 | } | 398 | } |
| 394 | try w.print("&t{d}", .{i}); | 399 | try w.print("&t{d}", .{i}); |
| ... | @@ -460,28 +465,20 @@ pub const Function = struct { | ... | @@ -460,28 +465,20 @@ pub const Function = struct { |
| 460 | return f.object.dg.fail(format, args); | 465 | return f.object.dg.fail(format, args); |
| 461 | } | 466 | } |
| 462 | 467 | ||
| 463 | fn indexToCType(f: *Function, idx: CType.Index) CType { | 468 | fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType { |
| 464 | return f.object.dg.indexToCType(idx); | 469 | return f.object.dg.ctypeFromType(ty, kind); |
| 465 | } | ||
| 466 | |||
| 467 | fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index { | ||
| 468 | return f.object.dg.typeToIndex(ty, kind); | ||
| 469 | } | 470 | } |
| 470 | 471 | ||
| 471 | fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType { | 472 | fn byteSize(f: *Function, ctype: CType) u64 { |
| 472 | return f.object.dg.typeToCType(ty, kind); | 473 | return f.object.dg.byteSize(ctype); |
| 473 | } | 474 | } |
| 474 | 475 | ||
| 475 | fn byteSize(f: *Function, cty: CType) u64 { | 476 | fn renderType(f: *Function, w: anytype, ctype: Type) !void { |
| 476 | return f.object.dg.byteSize(cty); | 477 | return f.object.dg.renderType(w, ctype); |
| 477 | } | 478 | } |
| 478 | 479 | ||
| 479 | fn renderType(f: *Function, w: anytype, t: Type) !void { | 480 | fn renderCType(f: *Function, w: anytype, ctype: CType) !void { |
| 480 | return f.object.dg.renderType(w, t); | 481 | return f.object.dg.renderCType(w, ctype); |
| 481 | } | ||
| 482 | |||
| 483 | fn renderCType(f: *Function, w: anytype, t: CType.Index) !void { | ||
| 484 | return f.object.dg.renderCType(w, t); | ||
| 485 | } | 482 | } |
| 486 | 483 | ||
| 487 | fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { | 484 | fn renderIntCast(f: *Function, w: anytype, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { |
| ... | @@ -494,21 +491,19 @@ pub const Function = struct { | ... | @@ -494,21 +491,19 @@ pub const Function = struct { |
| 494 | 491 | ||
| 495 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { | 492 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| 496 | const gpa = f.object.dg.gpa; | 493 | const gpa = f.object.dg.gpa; |
| 494 | const zcu = f.object.dg.zcu; | ||
| 495 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 496 | |||
| 497 | const gop = try f.lazy_fns.getOrPut(gpa, key); | 497 | const gop = try f.lazy_fns.getOrPut(gpa, key); |
| 498 | if (!gop.found_existing) { | 498 | if (!gop.found_existing) { |
| 499 | errdefer _ = f.lazy_fns.pop(); | 499 | errdefer _ = f.lazy_fns.pop(); |
| 500 | 500 | ||
| 501 | var promoted = f.object.dg.ctypes.promote(gpa); | ||
| 502 | defer f.object.dg.ctypes.demote(promoted); | ||
| 503 | const arena = promoted.arena.allocator(); | ||
| 504 | const zcu = f.object.dg.zcu; | ||
| 505 | |||
| 506 | gop.value_ptr.* = .{ | 501 | gop.value_ptr.* = .{ |
| 507 | .fn_name = switch (key) { | 502 | .fn_name = switch (key) { |
| 508 | .tag_name, | 503 | .tag_name, |
| 509 | .never_tail, | 504 | .never_tail, |
| 510 | .never_inline, | 505 | .never_inline, |
| 511 | => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{ | 506 | => |owner_decl| try ctype_pool.fmt(gpa, "zig_{s}_{}__{d}", .{ |
| 512 | @tagName(key), | 507 | @tagName(key), |
| 513 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), | 508 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), |
| 514 | @intFromEnum(owner_decl), | 509 | @intFromEnum(owner_decl), |
| ... | @@ -521,7 +516,7 @@ pub const Function = struct { | ... | @@ -521,7 +516,7 @@ pub const Function = struct { |
| 521 | }, | 516 | }, |
| 522 | }; | 517 | }; |
| 523 | } | 518 | } |
| 524 | return gop.value_ptr.fn_name; | 519 | return gop.value_ptr.fn_name.slice(ctype_pool); |
| 525 | } | 520 | } |
| 526 | 521 | ||
| 527 | pub fn deinit(f: *Function) void { | 522 | pub fn deinit(f: *Function) void { |
| ... | @@ -532,7 +527,6 @@ pub const Function = struct { | ... | @@ -532,7 +527,6 @@ pub const Function = struct { |
| 532 | f.blocks.deinit(gpa); | 527 | f.blocks.deinit(gpa); |
| 533 | f.value_map.deinit(); | 528 | f.value_map.deinit(); |
| 534 | f.lazy_fns.deinit(gpa); | 529 | f.lazy_fns.deinit(gpa); |
| 535 | f.object.dg.ctypes.deinit(gpa); | ||
| 536 | } | 530 | } |
| 537 | 531 | ||
| 538 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { | 532 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { |
| ... | @@ -575,7 +569,8 @@ pub const DeclGen = struct { | ... | @@ -575,7 +569,8 @@ pub const DeclGen = struct { |
| 575 | /// This is a borrowed reference from `link.C`. | 569 | /// This is a borrowed reference from `link.C`. |
| 576 | fwd_decl: std.ArrayList(u8), | 570 | fwd_decl: std.ArrayList(u8), |
| 577 | error_msg: ?*Zcu.ErrorMsg, | 571 | error_msg: ?*Zcu.ErrorMsg, |
| 578 | ctypes: CType.Store, | 572 | ctype_pool: CType.Pool, |
| 573 | scratch: std.ArrayListUnmanaged(u32), | ||
| 579 | /// Keeps track of anonymous decls that need to be rendered before this | 574 | /// Keeps track of anonymous decls that need to be rendered before this |
| 580 | /// (named) Decl in the output C code. | 575 | /// (named) Decl in the output C code. |
| 581 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), | 576 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| ... | @@ -610,6 +605,7 @@ pub const DeclGen = struct { | ... | @@ -610,6 +605,7 @@ pub const DeclGen = struct { |
| 610 | ) error{ OutOfMemory, AnalysisFail }!void { | 605 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 611 | const zcu = dg.zcu; | 606 | const zcu = dg.zcu; |
| 612 | const ip = &zcu.intern_pool; | 607 | const ip = &zcu.intern_pool; |
| 608 | const ctype_pool = &dg.ctype_pool; | ||
| 613 | const decl_val = Value.fromInterned(anon_decl.val); | 609 | const decl_val = Value.fromInterned(anon_decl.val); |
| 614 | const decl_ty = decl_val.typeOf(zcu); | 610 | const decl_ty = decl_val.typeOf(zcu); |
| 615 | 611 | ||
| ... | @@ -631,10 +627,10 @@ pub const DeclGen = struct { | ... | @@ -631,10 +627,10 @@ pub const DeclGen = struct { |
| 631 | // them). The analysis until now should ensure that the C function | 627 | // them). The analysis until now should ensure that the C function |
| 632 | // pointers are compatible. If they are not, then there is a bug | 628 | // pointers are compatible. If they are not, then there is a bug |
| 633 | // somewhere and we should let the C compiler tell us about it. | 629 | // somewhere and we should let the C compiler tell us about it. |
| 634 | const child_cty = (try dg.typeToCType(ptr_ty, .complete)).cast(CType.Payload.Child).?.data; | 630 | const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype; |
| 635 | const decl_cty = try dg.typeToIndex(decl_ty, .complete); | 631 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 636 | const need_cast = child_cty != decl_cty and | 632 | const need_cast = !elem_ctype.eql(decl_ctype) and |
| 637 | (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); | 633 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); |
| 638 | if (need_cast) { | 634 | if (need_cast) { |
| 639 | try writer.writeAll("(("); | 635 | try writer.writeAll("(("); |
| 640 | try dg.renderType(writer, ptr_ty); | 636 | try dg.renderType(writer, ptr_ty); |
| ... | @@ -655,7 +651,7 @@ pub const DeclGen = struct { | ... | @@ -655,7 +651,7 @@ pub const DeclGen = struct { |
| 655 | const explicit_alignment = ptr_type.flags.alignment; | 651 | const explicit_alignment = ptr_type.flags.alignment; |
| 656 | if (explicit_alignment != .none) { | 652 | if (explicit_alignment != .none) { |
| 657 | const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu); | 653 | const abi_alignment = Type.fromInterned(ptr_type.child).abiAlignment(zcu); |
| 658 | if (explicit_alignment.compareStrict(.gt, abi_alignment)) { | 654 | if (explicit_alignment.order(abi_alignment).compare(.gt)) { |
| 659 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); | 655 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); |
| 660 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) | 656 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) |
| 661 | aligned_gop.value_ptr.maxStrict(explicit_alignment) | 657 | aligned_gop.value_ptr.maxStrict(explicit_alignment) |
| ... | @@ -673,6 +669,7 @@ pub const DeclGen = struct { | ... | @@ -673,6 +669,7 @@ pub const DeclGen = struct { |
| 673 | location: ValueRenderLocation, | 669 | location: ValueRenderLocation, |
| 674 | ) error{ OutOfMemory, AnalysisFail }!void { | 670 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 675 | const zcu = dg.zcu; | 671 | const zcu = dg.zcu; |
| 672 | const ctype_pool = &dg.ctype_pool; | ||
| 676 | const decl = zcu.declPtr(decl_index); | 673 | const decl = zcu.declPtr(decl_index); |
| 677 | assert(decl.has_tv); | 674 | assert(decl.has_tv); |
| 678 | 675 | ||
| ... | @@ -695,10 +692,10 @@ pub const DeclGen = struct { | ... | @@ -695,10 +692,10 @@ pub const DeclGen = struct { |
| 695 | // them). The analysis until now should ensure that the C function | 692 | // them). The analysis until now should ensure that the C function |
| 696 | // pointers are compatible. If they are not, then there is a bug | 693 | // pointers are compatible. If they are not, then there is a bug |
| 697 | // somewhere and we should let the C compiler tell us about it. | 694 | // somewhere and we should let the C compiler tell us about it. |
| 698 | const child_cty = (try dg.typeToCType(ty, .complete)).cast(CType.Payload.Child).?.data; | 695 | const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype; |
| 699 | const decl_cty = try dg.typeToIndex(decl_ty, .complete); | 696 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); |
| 700 | const need_cast = child_cty != decl_cty and | 697 | const need_cast = !elem_ctype.eql(decl_ctype) and |
| 701 | (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); | 698 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); |
| 702 | if (need_cast) { | 699 | if (need_cast) { |
| 703 | try writer.writeAll("(("); | 700 | try writer.writeAll("(("); |
| 704 | try dg.renderType(writer, ty); | 701 | try dg.renderType(writer, ty); |
| ... | @@ -720,31 +717,31 @@ pub const DeclGen = struct { | ... | @@ -720,31 +717,31 @@ pub const DeclGen = struct { |
| 720 | const zcu = dg.zcu; | 717 | const zcu = dg.zcu; |
| 721 | const ip = &zcu.intern_pool; | 718 | const ip = &zcu.intern_pool; |
| 722 | const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val)); | 719 | const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val)); |
| 723 | const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); | 720 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); |
| 724 | const ptr_child_cty = dg.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; | 721 | const ptr_child_ctype = ptr_ctype.info(&dg.ctype_pool).pointer.elem_ctype; |
| 725 | const ptr = ip.indexToKey(ptr_val).ptr; | 722 | const ptr = ip.indexToKey(ptr_val).ptr; |
| 726 | switch (ptr.addr) { | 723 | switch (ptr.addr) { |
| 727 | .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location), | 724 | .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location), |
| 728 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location), | 725 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location), |
| 729 | .int => |int| { | 726 | .int => |int| { |
| 730 | try writer.writeByte('('); | 727 | try writer.writeByte('('); |
| 731 | try dg.renderCType(writer, ptr_cty); | 728 | try dg.renderCType(writer, ptr_ctype); |
| 732 | try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)}); | 729 | try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)}); |
| 733 | }, | 730 | }, |
| 734 | .eu_payload, .opt_payload => |base| { | 731 | .eu_payload, .opt_payload => |base| { |
| 735 | const ptr_base_ty = Type.fromInterned(ip.typeOf(base)); | 732 | const ptr_base_ty = Type.fromInterned(ip.typeOf(base)); |
| 736 | const base_ty = ptr_base_ty.childType(zcu); | 733 | const base_ty = ptr_base_ty.childType(zcu); |
| 737 | // Ensure complete type definition is visible before accessing fields. | 734 | // Ensure complete type definition is visible before accessing fields. |
| 738 | _ = try dg.typeToIndex(base_ty, .complete); | 735 | _ = try dg.ctypeFromType(base_ty, .complete); |
| 739 | const payload_ty = switch (ptr.addr) { | 736 | const payload_ty = switch (ptr.addr) { |
| 740 | .eu_payload => base_ty.errorUnionPayload(zcu), | 737 | .eu_payload => base_ty.errorUnionPayload(zcu), |
| 741 | .opt_payload => base_ty.optionalChild(zcu), | 738 | .opt_payload => base_ty.optionalChild(zcu), |
| 742 | else => unreachable, | 739 | else => unreachable, |
| 743 | }; | 740 | }; |
| 744 | const payload_cty = try dg.typeToIndex(payload_ty, .forward); | 741 | const payload_ctype = try dg.ctypeFromType(payload_ty, .forward); |
| 745 | if (ptr_child_cty != payload_cty) { | 742 | if (!ptr_child_ctype.eql(payload_ctype)) { |
| 746 | try writer.writeByte('('); | 743 | try writer.writeByte('('); |
| 747 | try dg.renderCType(writer, ptr_cty); | 744 | try dg.renderCType(writer, ptr_ctype); |
| 748 | try writer.writeByte(')'); | 745 | try writer.writeByte(')'); |
| 749 | } | 746 | } |
| 750 | try writer.writeAll("&("); | 747 | try writer.writeAll("&("); |
| ... | @@ -754,10 +751,10 @@ pub const DeclGen = struct { | ... | @@ -754,10 +751,10 @@ pub const DeclGen = struct { |
| 754 | .elem => |elem| { | 751 | .elem => |elem| { |
| 755 | const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base)); | 752 | const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base)); |
| 756 | const elem_ty = ptr_base_ty.elemType2(zcu); | 753 | const elem_ty = ptr_base_ty.elemType2(zcu); |
| 757 | const elem_cty = try dg.typeToIndex(elem_ty, .forward); | 754 | const elem_ctype = try dg.ctypeFromType(elem_ty, .forward); |
| 758 | if (ptr_child_cty != elem_cty) { | 755 | if (!ptr_child_ctype.eql(elem_ctype)) { |
| 759 | try writer.writeByte('('); | 756 | try writer.writeByte('('); |
| 760 | try dg.renderCType(writer, ptr_cty); | 757 | try dg.renderCType(writer, ptr_ctype); |
| 761 | try writer.writeByte(')'); | 758 | try writer.writeByte(')'); |
| 762 | } | 759 | } |
| 763 | try writer.writeAll("&("); | 760 | try writer.writeAll("&("); |
| ... | @@ -769,14 +766,14 @@ pub const DeclGen = struct { | ... | @@ -769,14 +766,14 @@ pub const DeclGen = struct { |
| 769 | .field => |field| { | 766 | .field => |field| { |
| 770 | const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base)); | 767 | const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base)); |
| 771 | const base_ty = ptr_base_ty.childType(zcu); | 768 | const base_ty = ptr_base_ty.childType(zcu); |
| 772 | // Ensure complete type definition is visible before accessing fields. | 769 | // Ensure complete type definition is available before accessing fields. |
| 773 | _ = try dg.typeToIndex(base_ty, .complete); | 770 | _ = try dg.ctypeFromType(base_ty, .complete); |
| 774 | switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) { | 771 | switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) { |
| 775 | .begin => { | 772 | .begin => { |
| 776 | const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); | 773 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); |
| 777 | if (ptr_cty != ptr_base_cty) { | 774 | if (!ptr_ctype.eql(ptr_base_ctype)) { |
| 778 | try writer.writeByte('('); | 775 | try writer.writeByte('('); |
| 779 | try dg.renderCType(writer, ptr_cty); | 776 | try dg.renderCType(writer, ptr_ctype); |
| 780 | try writer.writeByte(')'); | 777 | try writer.writeByte(')'); |
| 781 | } | 778 | } |
| 782 | try dg.renderParentPtr(writer, field.base, location); | 779 | try dg.renderParentPtr(writer, field.base, location); |
| ... | @@ -797,10 +794,10 @@ pub const DeclGen = struct { | ... | @@ -797,10 +794,10 @@ pub const DeclGen = struct { |
| 797 | }, | 794 | }, |
| 798 | else => unreachable, | 795 | else => unreachable, |
| 799 | }; | 796 | }; |
| 800 | const field_cty = try dg.typeToIndex(field_ty, .forward); | 797 | const field_ctype = try dg.ctypeFromType(field_ty, .forward); |
| 801 | if (ptr_child_cty != field_cty) { | 798 | if (!ptr_child_ctype.eql(field_ctype)) { |
| 802 | try writer.writeByte('('); | 799 | try writer.writeByte('('); |
| 803 | try dg.renderCType(writer, ptr_cty); | 800 | try dg.renderCType(writer, ptr_ctype); |
| 804 | try writer.writeByte(')'); | 801 | try writer.writeByte(')'); |
| 805 | } | 802 | } |
| 806 | try writer.writeAll("&("); | 803 | try writer.writeAll("&("); |
| ... | @@ -810,15 +807,15 @@ pub const DeclGen = struct { | ... | @@ -810,15 +807,15 @@ pub const DeclGen = struct { |
| 810 | }, | 807 | }, |
| 811 | .byte_offset => |byte_offset| { | 808 | .byte_offset => |byte_offset| { |
| 812 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8); | 809 | const u8_ptr_ty = try zcu.adjustPtrTypeChild(ptr_ty, Type.u8); |
| 813 | const u8_ptr_cty = try dg.typeToIndex(u8_ptr_ty, .complete); | 810 | const u8_ptr_ctype = try dg.ctypeFromType(u8_ptr_ty, .complete); |
| 814 | 811 | ||
| 815 | if (ptr_cty != u8_ptr_cty) { | 812 | if (!ptr_ctype.eql(u8_ptr_ctype)) { |
| 816 | try writer.writeByte('('); | 813 | try writer.writeByte('('); |
| 817 | try dg.renderCType(writer, ptr_cty); | 814 | try dg.renderCType(writer, ptr_ctype); |
| 818 | try writer.writeByte(')'); | 815 | try writer.writeByte(')'); |
| 819 | } | 816 | } |
| 820 | try writer.writeAll("(("); | 817 | try writer.writeAll("(("); |
| 821 | try dg.renderCType(writer, u8_ptr_cty); | 818 | try dg.renderCType(writer, u8_ptr_ctype); |
| 822 | try writer.writeByte(')'); | 819 | try writer.writeByte(')'); |
| 823 | try dg.renderParentPtr(writer, field.base, location); | 820 | try dg.renderParentPtr(writer, field.base, location); |
| 824 | try writer.print(" + {})", .{ | 821 | try writer.print(" + {})", .{ |
| ... | @@ -826,10 +823,10 @@ pub const DeclGen = struct { | ... | @@ -826,10 +823,10 @@ pub const DeclGen = struct { |
| 826 | }); | 823 | }); |
| 827 | }, | 824 | }, |
| 828 | .end => { | 825 | .end => { |
| 829 | const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); | 826 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); |
| 830 | if (ptr_cty != ptr_base_cty) { | 827 | if (!ptr_ctype.eql(ptr_base_ctype)) { |
| 831 | try writer.writeByte('('); | 828 | try writer.writeByte('('); |
| 832 | try dg.renderCType(writer, ptr_cty); | 829 | try dg.renderCType(writer, ptr_ctype); |
| 833 | try writer.writeByte(')'); | 830 | try writer.writeByte(')'); |
| 834 | } | 831 | } |
| 835 | try writer.writeAll("(("); | 832 | try writer.writeAll("(("); |
| ... | @@ -1207,8 +1204,8 @@ pub const DeclGen = struct { | ... | @@ -1207,8 +1204,8 @@ pub const DeclGen = struct { |
| 1207 | try writer.writeByte('}'); | 1204 | try writer.writeByte('}'); |
| 1208 | }, | 1205 | }, |
| 1209 | .struct_type => { | 1206 | .struct_type => { |
| 1210 | const struct_type = ip.loadStructType(ty.toIntern()); | 1207 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| 1211 | switch (struct_type.layout) { | 1208 | switch (loaded_struct.layout) { |
| 1212 | .auto, .@"extern" => { | 1209 | .auto, .@"extern" => { |
| 1213 | if (!location.isInitializer()) { | 1210 | if (!location.isInitializer()) { |
| 1214 | try writer.writeByte('('); | 1211 | try writer.writeByte('('); |
| ... | @@ -1217,13 +1214,14 @@ pub const DeclGen = struct { | ... | @@ -1217,13 +1214,14 @@ pub const DeclGen = struct { |
| 1217 | } | 1214 | } |
| 1218 | 1215 | ||
| 1219 | try writer.writeByte('{'); | 1216 | try writer.writeByte('{'); |
| 1220 | var empty = true; | 1217 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1221 | for (0..struct_type.field_types.len) |field_index| { | 1218 | var need_comma = false; |
| 1222 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1219 | while (field_it.next()) |field_index| { |
| 1223 | if (struct_type.fieldIsComptime(ip, field_index)) continue; | 1220 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1224 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 1221 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1225 | 1222 | ||
| 1226 | if (!empty) try writer.writeByte(','); | 1223 | if (need_comma) try writer.writeByte(','); |
| 1224 | need_comma = true; | ||
| 1227 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | 1225 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1228 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ | 1226 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ |
| 1229 | .ty = field_ty.toIntern(), | 1227 | .ty = field_ty.toIntern(), |
| ... | @@ -1233,8 +1231,6 @@ pub const DeclGen = struct { | ... | @@ -1233,8 +1231,6 @@ pub const DeclGen = struct { |
| 1233 | .repeated_elem => |elem| elem, | 1231 | .repeated_elem => |elem| elem, |
| 1234 | }; | 1232 | }; |
| 1235 | try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type); | 1233 | try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type); |
| 1236 | |||
| 1237 | empty = false; | ||
| 1238 | } | 1234 | } |
| 1239 | try writer.writeByte('}'); | 1235 | try writer.writeByte('}'); |
| 1240 | }, | 1236 | }, |
| ... | @@ -1247,8 +1243,8 @@ pub const DeclGen = struct { | ... | @@ -1247,8 +1243,8 @@ pub const DeclGen = struct { |
| 1247 | var bit_offset: u64 = 0; | 1243 | var bit_offset: u64 = 0; |
| 1248 | var eff_num_fields: usize = 0; | 1244 | var eff_num_fields: usize = 0; |
| 1249 | 1245 | ||
| 1250 | for (0..struct_type.field_types.len) |field_index| { | 1246 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1251 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1247 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1252 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 1248 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1253 | eff_num_fields += 1; | 1249 | eff_num_fields += 1; |
| 1254 | } | 1250 | } |
| ... | @@ -1268,8 +1264,8 @@ pub const DeclGen = struct { | ... | @@ -1268,8 +1264,8 @@ pub const DeclGen = struct { |
| 1268 | 1264 | ||
| 1269 | var eff_index: usize = 0; | 1265 | var eff_index: usize = 0; |
| 1270 | var needs_closing_paren = false; | 1266 | var needs_closing_paren = false; |
| 1271 | for (0..struct_type.field_types.len) |field_index| { | 1267 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1272 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1268 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1273 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 1269 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1274 | 1270 | ||
| 1275 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { | 1271 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| ... | @@ -1304,8 +1300,8 @@ pub const DeclGen = struct { | ... | @@ -1304,8 +1300,8 @@ pub const DeclGen = struct { |
| 1304 | try writer.writeByte('('); | 1300 | try writer.writeByte('('); |
| 1305 | // a << a_off | b << b_off | c << c_off | 1301 | // a << a_off | b << b_off | c << c_off |
| 1306 | var empty = true; | 1302 | var empty = true; |
| 1307 | for (0..struct_type.field_types.len) |field_index| { | 1303 | for (0..loaded_struct.field_types.len) |field_index| { |
| 1308 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | 1304 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1309 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 1305 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1310 | 1306 | ||
| 1311 | if (!empty) try writer.writeAll(" | "); | 1307 | if (!empty) try writer.writeAll(" | "); |
| ... | @@ -1341,10 +1337,10 @@ pub const DeclGen = struct { | ... | @@ -1341,10 +1337,10 @@ pub const DeclGen = struct { |
| 1341 | else => unreachable, | 1337 | else => unreachable, |
| 1342 | }, | 1338 | }, |
| 1343 | .un => |un| { | 1339 | .un => |un| { |
| 1344 | const union_obj = zcu.typeToUnion(ty).?; | 1340 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1345 | if (un.tag == .none) { | 1341 | if (un.tag == .none) { |
| 1346 | const backing_ty = try ty.unionBackingType(zcu); | 1342 | const backing_ty = try ty.unionBackingType(zcu); |
| 1347 | switch (union_obj.getLayout(ip)) { | 1343 | switch (loaded_union.getLayout(ip)) { |
| 1348 | .@"packed" => { | 1344 | .@"packed" => { |
| 1349 | if (!location.isInitializer()) { | 1345 | if (!location.isInitializer()) { |
| 1350 | try writer.writeByte('('); | 1346 | try writer.writeByte('('); |
| ... | @@ -1376,10 +1372,10 @@ pub const DeclGen = struct { | ... | @@ -1376,10 +1372,10 @@ pub const DeclGen = struct { |
| 1376 | try writer.writeByte(')'); | 1372 | try writer.writeByte(')'); |
| 1377 | } | 1373 | } |
| 1378 | 1374 | ||
| 1379 | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | 1375 | const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; |
| 1380 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 1376 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); |
| 1381 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | 1377 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; |
| 1382 | if (union_obj.getLayout(ip) == .@"packed") { | 1378 | if (loaded_union.getLayout(ip) == .@"packed") { |
| 1383 | if (field_ty.hasRuntimeBits(zcu)) { | 1379 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1384 | if (field_ty.isPtrAtRuntime(zcu)) { | 1380 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 1385 | try writer.writeByte('('); | 1381 | try writer.writeByte('('); |
| ... | @@ -1399,7 +1395,7 @@ pub const DeclGen = struct { | ... | @@ -1399,7 +1395,7 @@ pub const DeclGen = struct { |
| 1399 | 1395 | ||
| 1400 | try writer.writeByte('{'); | 1396 | try writer.writeByte('{'); |
| 1401 | if (ty.unionTagTypeSafety(zcu)) |_| { | 1397 | if (ty.unionTagTypeSafety(zcu)) |_| { |
| 1402 | const layout = zcu.getUnionLayout(union_obj); | 1398 | const layout = zcu.getUnionLayout(loaded_union); |
| 1403 | if (layout.tag_size != 0) { | 1399 | if (layout.tag_size != 0) { |
| 1404 | try writer.writeAll(" .tag = "); | 1400 | try writer.writeAll(" .tag = "); |
| 1405 | try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); | 1401 | try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); |
| ... | @@ -1412,8 +1408,8 @@ pub const DeclGen = struct { | ... | @@ -1412,8 +1408,8 @@ pub const DeclGen = struct { |
| 1412 | try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); | 1408 | try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); |
| 1413 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); | 1409 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1414 | try writer.writeByte(' '); | 1410 | try writer.writeByte(' '); |
| 1415 | } else for (0..union_obj.field_types.len) |this_field_index| { | 1411 | } else for (0..loaded_union.field_types.len) |this_field_index| { |
| 1416 | const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]); | 1412 | const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]); |
| 1417 | if (!this_field_ty.hasRuntimeBits(zcu)) continue; | 1413 | if (!this_field_ty.hasRuntimeBits(zcu)) continue; |
| 1418 | try dg.renderUndefValue(writer, this_field_ty, initializer_type); | 1414 | try dg.renderUndefValue(writer, this_field_ty, initializer_type); |
| 1419 | break; | 1415 | break; |
| ... | @@ -1445,12 +1441,14 @@ pub const DeclGen = struct { | ... | @@ -1445,12 +1441,14 @@ pub const DeclGen = struct { |
| 1445 | .ReleaseFast, .ReleaseSmall => false, | 1441 | .ReleaseFast, .ReleaseSmall => false, |
| 1446 | }; | 1442 | }; |
| 1447 | 1443 | ||
| 1448 | switch (ty.zigTypeTag(zcu)) { | 1444 | switch (ty.toIntern()) { |
| 1449 | .Bool => try writer.writeAll(if (safety_on) "0xaa" else "false"), | 1445 | .c_longdouble_type, |
| 1450 | .Int, .Enum, .ErrorSet => try writer.print("{x}", .{ | 1446 | .f16_type, |
| 1451 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), | 1447 | .f32_type, |
| 1452 | }), | 1448 | .f64_type, |
| 1453 | .Float => { | 1449 | .f80_type, |
| 1450 | .f128_type, | ||
| 1451 | => { | ||
| 1454 | const bits = ty.floatBits(target.*); | 1452 | const bits = ty.floatBits(target.*); |
| 1455 | // All unsigned ints matching float types are pre-allocated. | 1453 | // All unsigned ints matching float types are pre-allocated. |
| 1456 | const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; | 1454 | const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; |
| ... | @@ -1468,49 +1466,90 @@ pub const DeclGen = struct { | ... | @@ -1468,49 +1466,90 @@ pub const DeclGen = struct { |
| 1468 | } | 1466 | } |
| 1469 | try writer.writeAll(", "); | 1467 | try writer.writeAll(", "); |
| 1470 | try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); | 1468 | try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); |
| 1471 | try writer.writeByte(')'); | 1469 | return writer.writeByte(')'); |
| 1472 | }, | 1470 | }, |
| 1473 | .Pointer => if (ty.isSlice(zcu)) { | 1471 | .bool_type => try writer.writeAll(if (safety_on) "0xaa" else "false"), |
| 1474 | if (!location.isInitializer()) { | 1472 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 1475 | try writer.writeByte('('); | 1473 | .simple_type, |
| 1474 | .int_type, | ||
| 1475 | .enum_type, | ||
| 1476 | .error_set_type, | ||
| 1477 | .inferred_error_set_type, | ||
| 1478 | => return writer.print("{x}", .{ | ||
| 1479 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), | ||
| 1480 | }), | ||
| 1481 | .ptr_type => if (ty.isSlice(zcu)) { | ||
| 1482 | if (!location.isInitializer()) { | ||
| 1483 | try writer.writeByte('('); | ||
| 1484 | try dg.renderType(writer, ty); | ||
| 1485 | try writer.writeByte(')'); | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | try writer.writeAll("{("); | ||
| 1489 | const ptr_ty = ty.slicePtrFieldType(zcu); | ||
| 1490 | try dg.renderType(writer, ptr_ty); | ||
| 1491 | return writer.print("){x}, {0x}}}", .{ | ||
| 1492 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), | ||
| 1493 | }); | ||
| 1494 | } else { | ||
| 1495 | try writer.writeAll("(("); | ||
| 1476 | try dg.renderType(writer, ty); | 1496 | try dg.renderType(writer, ty); |
| 1477 | try writer.writeByte(')'); | 1497 | return writer.print("){x})", .{ |
| 1478 | } | 1498 | try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other), |
| 1499 | }); | ||
| 1500 | }, | ||
| 1501 | .opt_type => { | ||
| 1502 | const payload_ty = ty.optionalChild(zcu); | ||
| 1479 | 1503 | ||
| 1480 | try writer.writeAll("{("); | 1504 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 1481 | const ptr_ty = ty.slicePtrFieldType(zcu); | 1505 | return dg.renderUndefValue(writer, Type.bool, location); |
| 1482 | try dg.renderType(writer, ptr_ty); | 1506 | } |
| 1483 | try writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)}); | ||
| 1484 | } else { | ||
| 1485 | try writer.writeAll("(("); | ||
| 1486 | try dg.renderType(writer, ty); | ||
| 1487 | try writer.print("){x})", .{try dg.fmtIntLiteral(try zcu.undefValue(Type.usize), .Other)}); | ||
| 1488 | }, | ||
| 1489 | .Optional => { | ||
| 1490 | const payload_ty = ty.optionalChild(zcu); | ||
| 1491 | 1507 | ||
| 1492 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 1508 | if (ty.optionalReprIsPayload(zcu)) { |
| 1493 | return dg.renderUndefValue(writer, Type.bool, location); | 1509 | return dg.renderUndefValue(writer, payload_ty, location); |
| 1494 | } | 1510 | } |
| 1495 | 1511 | ||
| 1496 | if (ty.optionalReprIsPayload(zcu)) { | 1512 | if (!location.isInitializer()) { |
| 1497 | return dg.renderUndefValue(writer, payload_ty, location); | 1513 | try writer.writeByte('('); |
| 1498 | } | 1514 | try dg.renderType(writer, ty); |
| 1515 | try writer.writeByte(')'); | ||
| 1516 | } | ||
| 1499 | 1517 | ||
| 1500 | if (!location.isInitializer()) { | 1518 | try writer.writeAll("{ .payload = "); |
| 1501 | try writer.writeByte('('); | 1519 | try dg.renderUndefValue(writer, payload_ty, initializer_type); |
| 1502 | try dg.renderType(writer, ty); | 1520 | try writer.writeAll(", .is_null = "); |
| 1503 | try writer.writeByte(')'); | 1521 | try dg.renderUndefValue(writer, Type.bool, initializer_type); |
| 1504 | } | 1522 | return writer.writeAll(" }"); |
| 1523 | }, | ||
| 1524 | .struct_type => { | ||
| 1525 | const loaded_struct = ip.loadStructType(ty.toIntern()); | ||
| 1526 | switch (loaded_struct.layout) { | ||
| 1527 | .auto, .@"extern" => { | ||
| 1528 | if (!location.isInitializer()) { | ||
| 1529 | try writer.writeByte('('); | ||
| 1530 | try dg.renderType(writer, ty); | ||
| 1531 | try writer.writeByte(')'); | ||
| 1532 | } | ||
| 1505 | 1533 | ||
| 1506 | try writer.writeAll("{ .payload = "); | 1534 | try writer.writeByte('{'); |
| 1507 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | 1535 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 1508 | try writer.writeAll(", .is_null = "); | 1536 | var need_comma = false; |
| 1509 | try dg.renderUndefValue(writer, Type.bool, initializer_type); | 1537 | while (field_it.next()) |field_index| { |
| 1510 | try writer.writeAll(" }"); | 1538 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 1511 | }, | 1539 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1512 | .Struct => switch (ty.containerLayout(zcu)) { | 1540 | |
| 1513 | .auto, .@"extern" => { | 1541 | if (need_comma) try writer.writeByte(','); |
| 1542 | need_comma = true; | ||
| 1543 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1544 | } | ||
| 1545 | return writer.writeByte('}'); | ||
| 1546 | }, | ||
| 1547 | .@"packed" => return writer.print("{x}", .{ | ||
| 1548 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | ||
| 1549 | }), | ||
| 1550 | } | ||
| 1551 | }, | ||
| 1552 | .anon_struct_type => |anon_struct_info| { | ||
| 1514 | if (!location.isInitializer()) { | 1553 | if (!location.isInitializer()) { |
| 1515 | try writer.writeByte('('); | 1554 | try writer.writeByte('('); |
| 1516 | try dg.renderType(writer, ty); | 1555 | try dg.renderType(writer, ty); |
| ... | @@ -1518,116 +1557,125 @@ pub const DeclGen = struct { | ... | @@ -1518,116 +1557,125 @@ pub const DeclGen = struct { |
| 1518 | } | 1557 | } |
| 1519 | 1558 | ||
| 1520 | try writer.writeByte('{'); | 1559 | try writer.writeByte('{'); |
| 1521 | var empty = true; | 1560 | var need_comma = false; |
| 1522 | for (0..ty.structFieldCount(zcu)) |field_index| { | 1561 | for (0..anon_struct_info.types.len) |field_index| { |
| 1523 | if (ty.structFieldIsComptime(field_index, zcu)) continue; | 1562 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; |
| 1524 | const field_ty = ty.structFieldType(field_index, zcu); | 1563 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); |
| 1525 | if (!field_ty.hasRuntimeBits(zcu)) continue; | 1564 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1526 | 1565 | ||
| 1527 | if (!empty) try writer.writeByte(','); | 1566 | if (need_comma) try writer.writeByte(','); |
| 1567 | need_comma = true; | ||
| 1528 | try dg.renderUndefValue(writer, field_ty, initializer_type); | 1568 | try dg.renderUndefValue(writer, field_ty, initializer_type); |
| 1529 | |||
| 1530 | empty = false; | ||
| 1531 | } | 1569 | } |
| 1532 | 1570 | return writer.writeByte('}'); | |
| 1533 | try writer.writeByte('}'); | ||
| 1534 | }, | 1571 | }, |
| 1535 | .@"packed" => try writer.print("{x}", .{ | 1572 | .union_type => { |
| 1536 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | 1573 | const loaded_union = ip.loadUnionType(ty.toIntern()); |
| 1537 | }), | 1574 | switch (loaded_union.getLayout(ip)) { |
| 1538 | }, | 1575 | .auto, .@"extern" => { |
| 1539 | .Union => { | 1576 | if (!location.isInitializer()) { |
| 1540 | if (!location.isInitializer()) { | 1577 | try writer.writeByte('('); |
| 1541 | try writer.writeByte('('); | 1578 | try dg.renderType(writer, ty); |
| 1542 | try dg.renderType(writer, ty); | 1579 | try writer.writeByte(')'); |
| 1543 | try writer.writeByte(')'); | 1580 | } |
| 1544 | } | ||
| 1545 | 1581 | ||
| 1546 | try writer.writeByte('{'); | 1582 | try writer.writeByte('{'); |
| 1547 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { | 1583 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { |
| 1548 | const layout = ty.unionGetLayout(zcu); | 1584 | const layout = ty.unionGetLayout(zcu); |
| 1549 | if (layout.tag_size != 0) { | 1585 | if (layout.tag_size != 0) { |
| 1550 | try writer.writeAll(" .tag = "); | 1586 | try writer.writeAll(" .tag = "); |
| 1551 | try dg.renderUndefValue(writer, tag_ty, initializer_type); | 1587 | try dg.renderUndefValue(writer, tag_ty, initializer_type); |
| 1588 | } | ||
| 1589 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); | ||
| 1590 | if (layout.tag_size != 0) try writer.writeByte(','); | ||
| 1591 | try writer.writeAll(" .payload = {"); | ||
| 1592 | } | ||
| 1593 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 1594 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); | ||
| 1595 | if (!field_ty.hasRuntimeBits(zcu)) continue; | ||
| 1596 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1597 | break; | ||
| 1598 | } | ||
| 1599 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); | ||
| 1600 | return writer.writeByte('}'); | ||
| 1601 | }, | ||
| 1602 | .@"packed" => return writer.print("{x}", .{ | ||
| 1603 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | ||
| 1604 | }), | ||
| 1552 | } | 1605 | } |
| 1553 | if (ty.unionHasAllZeroBitFieldTypes(zcu)) return try writer.writeByte('}'); | 1606 | }, |
| 1554 | if (layout.tag_size != 0) try writer.writeByte(','); | 1607 | .error_union_type => { |
| 1555 | try writer.writeAll(" .payload = {"); | 1608 | const payload_ty = ty.errorUnionPayload(zcu); |
| 1556 | } | 1609 | const error_ty = ty.errorUnionSet(zcu); |
| 1557 | const union_obj = zcu.typeToUnion(ty).?; | ||
| 1558 | for (0..union_obj.field_types.len) |field_index| { | ||
| 1559 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | ||
| 1560 | if (!field_ty.hasRuntimeBits(zcu)) continue; | ||
| 1561 | try dg.renderUndefValue(writer, field_ty, initializer_type); | ||
| 1562 | break; | ||
| 1563 | } | ||
| 1564 | if (ty.unionTagTypeSafety(zcu)) |_| try writer.writeByte('}'); | ||
| 1565 | try writer.writeByte('}'); | ||
| 1566 | }, | ||
| 1567 | .ErrorUnion => { | ||
| 1568 | const payload_ty = ty.errorUnionPayload(zcu); | ||
| 1569 | const error_ty = ty.errorUnionSet(zcu); | ||
| 1570 | |||
| 1571 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | ||
| 1572 | return dg.renderUndefValue(writer, error_ty, location); | ||
| 1573 | } | ||
| 1574 | 1610 | ||
| 1575 | if (!location.isInitializer()) { | 1611 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { |
| 1576 | try writer.writeByte('('); | 1612 | return dg.renderUndefValue(writer, error_ty, location); |
| 1577 | try dg.renderType(writer, ty); | 1613 | } |
| 1578 | try writer.writeByte(')'); | ||
| 1579 | } | ||
| 1580 | 1614 | ||
| 1581 | try writer.writeAll("{ .payload = "); | ||
| 1582 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | ||
| 1583 | try writer.writeAll(", .error = "); | ||
| 1584 | try dg.renderUndefValue(writer, error_ty, initializer_type); | ||
| 1585 | try writer.writeAll(" }"); | ||
| 1586 | }, | ||
| 1587 | .Array, .Vector => { | ||
| 1588 | const ai = ty.arrayInfo(zcu); | ||
| 1589 | if (ai.elem_type.eql(Type.u8, zcu)) { | ||
| 1590 | const c_len = ty.arrayLenIncludingSentinel(zcu); | ||
| 1591 | var literal = stringLiteral(writer, c_len); | ||
| 1592 | try literal.start(); | ||
| 1593 | var index: u64 = 0; | ||
| 1594 | while (index < c_len) : (index += 1) | ||
| 1595 | try literal.writeChar(0xaa); | ||
| 1596 | try literal.end(); | ||
| 1597 | } else { | ||
| 1598 | if (!location.isInitializer()) { | 1615 | if (!location.isInitializer()) { |
| 1599 | try writer.writeByte('('); | 1616 | try writer.writeByte('('); |
| 1600 | try dg.renderType(writer, ty); | 1617 | try dg.renderType(writer, ty); |
| 1601 | try writer.writeByte(')'); | 1618 | try writer.writeByte(')'); |
| 1602 | } | 1619 | } |
| 1603 | 1620 | ||
| 1604 | try writer.writeByte('{'); | 1621 | try writer.writeAll("{ .payload = "); |
| 1605 | const c_len = ty.arrayLenIncludingSentinel(zcu); | 1622 | try dg.renderUndefValue(writer, payload_ty, initializer_type); |
| 1606 | var index: u64 = 0; | 1623 | try writer.writeAll(", .error = "); |
| 1607 | while (index < c_len) : (index += 1) { | 1624 | try dg.renderUndefValue(writer, error_ty, initializer_type); |
| 1608 | if (index > 0) try writer.writeAll(", "); | 1625 | return writer.writeAll(" }"); |
| 1609 | try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); | 1626 | }, |
| 1627 | .array_type, .vector_type => { | ||
| 1628 | const ai = ty.arrayInfo(zcu); | ||
| 1629 | if (ai.elem_type.eql(Type.u8, zcu)) { | ||
| 1630 | const c_len = ty.arrayLenIncludingSentinel(zcu); | ||
| 1631 | var literal = stringLiteral(writer, c_len); | ||
| 1632 | try literal.start(); | ||
| 1633 | var index: u64 = 0; | ||
| 1634 | while (index < c_len) : (index += 1) | ||
| 1635 | try literal.writeChar(0xaa); | ||
| 1636 | return literal.end(); | ||
| 1637 | } else { | ||
| 1638 | if (!location.isInitializer()) { | ||
| 1639 | try writer.writeByte('('); | ||
| 1640 | try dg.renderType(writer, ty); | ||
| 1641 | try writer.writeByte(')'); | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | try writer.writeByte('{'); | ||
| 1645 | const c_len = ty.arrayLenIncludingSentinel(zcu); | ||
| 1646 | var index: u64 = 0; | ||
| 1647 | while (index < c_len) : (index += 1) { | ||
| 1648 | if (index > 0) try writer.writeAll(", "); | ||
| 1649 | try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); | ||
| 1650 | } | ||
| 1651 | return writer.writeByte('}'); | ||
| 1610 | } | 1652 | } |
| 1611 | try writer.writeByte('}'); | 1653 | }, |
| 1612 | } | 1654 | .anyframe_type, |
| 1655 | .opaque_type, | ||
| 1656 | .func_type, | ||
| 1657 | => unreachable, | ||
| 1658 | |||
| 1659 | .undef, | ||
| 1660 | .simple_value, | ||
| 1661 | .variable, | ||
| 1662 | .extern_func, | ||
| 1663 | .func, | ||
| 1664 | .int, | ||
| 1665 | .err, | ||
| 1666 | .error_union, | ||
| 1667 | .enum_literal, | ||
| 1668 | .enum_tag, | ||
| 1669 | .empty_enum_value, | ||
| 1670 | .float, | ||
| 1671 | .ptr, | ||
| 1672 | .slice, | ||
| 1673 | .opt, | ||
| 1674 | .aggregate, | ||
| 1675 | .un, | ||
| 1676 | .memoized_call, | ||
| 1677 | => unreachable, | ||
| 1613 | }, | 1678 | }, |
| 1614 | .ComptimeInt, | ||
| 1615 | .ComptimeFloat, | ||
| 1616 | .Type, | ||
| 1617 | .EnumLiteral, | ||
| 1618 | .Void, | ||
| 1619 | .NoReturn, | ||
| 1620 | .Undefined, | ||
| 1621 | .Null, | ||
| 1622 | .Opaque, | ||
| 1623 | => unreachable, | ||
| 1624 | |||
| 1625 | .Fn, | ||
| 1626 | .Frame, | ||
| 1627 | .AnyFrame, | ||
| 1628 | => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{ | ||
| 1629 | @tagName(tag), | ||
| 1630 | }), | ||
| 1631 | } | 1679 | } |
| 1632 | } | 1680 | } |
| 1633 | 1681 | ||
| ... | @@ -1641,13 +1689,12 @@ pub const DeclGen = struct { | ... | @@ -1641,13 +1689,12 @@ pub const DeclGen = struct { |
| 1641 | ident: []const u8, | 1689 | ident: []const u8, |
| 1642 | }, | 1690 | }, |
| 1643 | ) !void { | 1691 | ) !void { |
| 1644 | const store = &dg.ctypes.set; | ||
| 1645 | const zcu = dg.zcu; | 1692 | const zcu = dg.zcu; |
| 1646 | const ip = &zcu.intern_pool; | 1693 | const ip = &zcu.intern_pool; |
| 1647 | 1694 | ||
| 1648 | const fn_decl = zcu.declPtr(fn_decl_index); | 1695 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 1649 | const fn_ty = fn_decl.typeOf(zcu); | 1696 | const fn_ty = fn_decl.typeOf(zcu); |
| 1650 | const fn_cty_idx = try dg.typeToIndex(fn_ty, kind); | 1697 | const fn_ctype = try dg.ctypeFromType(fn_ty, kind); |
| 1651 | 1698 | ||
| 1652 | const fn_info = zcu.typeToFunc(fn_ty).?; | 1699 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1653 | if (fn_info.cc == .Naked) { | 1700 | if (fn_info.cc == .Naked) { |
| ... | @@ -1661,7 +1708,7 @@ pub const DeclGen = struct { | ... | @@ -1661,7 +1708,7 @@ pub const DeclGen = struct { |
| 1661 | try w.writeAll("zig_cold "); | 1708 | try w.writeAll("zig_cold "); |
| 1662 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); | 1709 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); |
| 1663 | 1710 | ||
| 1664 | var trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, fn_cty_idx, .suffix, .{}); | 1711 | var trailing = try renderTypePrefix(dg.pass, &dg.ctype_pool, zcu, w, fn_ctype, .suffix, .{}); |
| 1665 | 1712 | ||
| 1666 | if (toCallingConvention(fn_info.cc)) |call_conv| { | 1713 | if (toCallingConvention(fn_info.cc)) |call_conv| { |
| 1667 | try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); | 1714 | try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); |
| ... | @@ -1670,7 +1717,7 @@ pub const DeclGen = struct { | ... | @@ -1670,7 +1717,7 @@ pub const DeclGen = struct { |
| 1670 | 1717 | ||
| 1671 | switch (kind) { | 1718 | switch (kind) { |
| 1672 | .forward => {}, | 1719 | .forward => {}, |
| 1673 | .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| { | 1720 | .complete => if (fn_decl.alignment.toByteUnits()) |a| { |
| 1674 | try w.print("{}zig_align_fn({})", .{ trailing, a }); | 1721 | try w.print("{}zig_align_fn({})", .{ trailing, a }); |
| 1675 | trailing = .maybe_space; | 1722 | trailing = .maybe_space; |
| 1676 | }, | 1723 | }, |
| ... | @@ -1687,10 +1734,10 @@ pub const DeclGen = struct { | ... | @@ -1687,10 +1734,10 @@ pub const DeclGen = struct { |
| 1687 | 1734 | ||
| 1688 | try renderTypeSuffix( | 1735 | try renderTypeSuffix( |
| 1689 | dg.pass, | 1736 | dg.pass, |
| 1690 | store.*, | 1737 | &dg.ctype_pool, |
| 1691 | zcu, | 1738 | zcu, |
| 1692 | w, | 1739 | w, |
| 1693 | fn_cty_idx, | 1740 | fn_ctype, |
| 1694 | .suffix, | 1741 | .suffix, |
| 1695 | CQualifiers.init(.{ .@"const" = switch (kind) { | 1742 | CQualifiers.init(.{ .@"const" = switch (kind) { |
| 1696 | .forward => false, | 1743 | .forward => false, |
| ... | @@ -1701,7 +1748,7 @@ pub const DeclGen = struct { | ... | @@ -1701,7 +1748,7 @@ pub const DeclGen = struct { |
| 1701 | 1748 | ||
| 1702 | switch (kind) { | 1749 | switch (kind) { |
| 1703 | .forward => { | 1750 | .forward => { |
| 1704 | if (fn_decl.alignment.toByteUnitsOptional()) |a| { | 1751 | if (fn_decl.alignment.toByteUnits()) |a| { |
| 1705 | try w.print(" zig_align_fn({})", .{a}); | 1752 | try w.print(" zig_align_fn({})", .{a}); |
| 1706 | } | 1753 | } |
| 1707 | switch (name) { | 1754 | switch (name) { |
| ... | @@ -1748,20 +1795,13 @@ pub const DeclGen = struct { | ... | @@ -1748,20 +1795,13 @@ pub const DeclGen = struct { |
| 1748 | } | 1795 | } |
| 1749 | } | 1796 | } |
| 1750 | 1797 | ||
| 1751 | fn indexToCType(dg: *DeclGen, idx: CType.Index) CType { | 1798 | fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { |
| 1752 | return dg.ctypes.indexToCType(idx); | 1799 | defer std.debug.assert(dg.scratch.items.len == 0); |
| 1800 | return dg.ctype_pool.fromType(dg.gpa, &dg.scratch, ty, dg.zcu, dg.mod, kind); | ||
| 1753 | } | 1801 | } |
| 1754 | 1802 | ||
| 1755 | fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index { | 1803 | fn byteSize(dg: *DeclGen, ctype: CType) u64 { |
| 1756 | return dg.ctypes.typeToIndex(dg.gpa, ty, dg.zcu, dg.mod, kind); | 1804 | return ctype.byteSize(&dg.ctype_pool, dg.mod); |
| 1757 | } | ||
| 1758 | |||
| 1759 | fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { | ||
| 1760 | return dg.ctypes.typeToCType(dg.gpa, ty, dg.zcu, dg.mod, kind); | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | fn byteSize(dg: *DeclGen, cty: CType) u64 { | ||
| 1764 | return cty.byteSize(dg.ctypes.set, dg.mod); | ||
| 1765 | } | 1805 | } |
| 1766 | 1806 | ||
| 1767 | /// Renders a type as a single identifier, generating intermediate typedefs | 1807 | /// Renders a type as a single identifier, generating intermediate typedefs |
| ... | @@ -1776,14 +1816,12 @@ pub const DeclGen = struct { | ... | @@ -1776,14 +1816,12 @@ pub const DeclGen = struct { |
| 1776 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | | 1816 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1777 | /// | 1817 | /// |
| 1778 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { | 1818 | fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void { |
| 1779 | try dg.renderCType(w, try dg.typeToIndex(t, .complete)); | 1819 | try dg.renderCType(w, try dg.ctypeFromType(t, .complete)); |
| 1780 | } | 1820 | } |
| 1781 | 1821 | ||
| 1782 | fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void { | 1822 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void { |
| 1783 | const store = &dg.ctypes.set; | 1823 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1784 | const zcu = dg.zcu; | 1824 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1785 | _ = try renderTypePrefix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); | ||
| 1786 | try renderTypeSuffix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); | ||
| 1787 | } | 1825 | } |
| 1788 | 1826 | ||
| 1789 | const IntCastContext = union(enum) { | 1827 | const IntCastContext = union(enum) { |
| ... | @@ -1905,32 +1943,37 @@ pub const DeclGen = struct { | ... | @@ -1905,32 +1943,37 @@ pub const DeclGen = struct { |
| 1905 | alignment: Alignment, | 1943 | alignment: Alignment, |
| 1906 | kind: CType.Kind, | 1944 | kind: CType.Kind, |
| 1907 | ) error{ OutOfMemory, AnalysisFail }!void { | 1945 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1908 | const zcu = dg.zcu; | 1946 | try dg.renderCTypeAndName( |
| 1909 | const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)); | 1947 | w, |
| 1910 | try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); | 1948 | try dg.ctypeFromType(ty, kind), |
| 1949 | name, | ||
| 1950 | qualifiers, | ||
| 1951 | CType.AlignAs.fromAlignment(.{ | ||
| 1952 | .@"align" = alignment, | ||
| 1953 | .abi = ty.abiAlignment(dg.zcu), | ||
| 1954 | }), | ||
| 1955 | ); | ||
| 1911 | } | 1956 | } |
| 1912 | 1957 | ||
| 1913 | fn renderCTypeAndName( | 1958 | fn renderCTypeAndName( |
| 1914 | dg: *DeclGen, | 1959 | dg: *DeclGen, |
| 1915 | w: anytype, | 1960 | w: anytype, |
| 1916 | cty_idx: CType.Index, | 1961 | ctype: CType, |
| 1917 | name: CValue, | 1962 | name: CValue, |
| 1918 | qualifiers: CQualifiers, | 1963 | qualifiers: CQualifiers, |
| 1919 | alignas: CType.AlignAs, | 1964 | alignas: CType.AlignAs, |
| 1920 | ) error{ OutOfMemory, AnalysisFail }!void { | 1965 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1921 | const store = &dg.ctypes.set; | ||
| 1922 | const zcu = dg.zcu; | ||
| 1923 | |||
| 1924 | switch (alignas.abiOrder()) { | 1966 | switch (alignas.abiOrder()) { |
| 1925 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), | 1967 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), |
| 1926 | .eq => {}, | 1968 | .eq => {}, |
| 1927 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), | 1969 | .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}), |
| 1928 | } | 1970 | } |
| 1929 | 1971 | ||
| 1930 | const trailing = try renderTypePrefix(dg.pass, store.*, zcu, w, cty_idx, .suffix, qualifiers); | 1972 | try w.print("{}", .{ |
| 1931 | try w.print("{}", .{trailing}); | 1973 | try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, qualifiers), |
| 1974 | }); | ||
| 1932 | try dg.writeName(w, name); | 1975 | try dg.writeName(w, name); |
| 1933 | try renderTypeSuffix(dg.pass, store.*, zcu, w, cty_idx, .suffix, .{}); | 1976 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); |
| 1934 | } | 1977 | } |
| 1935 | 1978 | ||
| 1936 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { | 1979 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { |
| ... | @@ -2094,33 +2137,31 @@ pub const DeclGen = struct { | ... | @@ -2094,33 +2137,31 @@ pub const DeclGen = struct { |
| 2094 | } | 2137 | } |
| 2095 | 2138 | ||
| 2096 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { | 2139 | fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { |
| 2097 | try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete)); | 2140 | try dg.renderCTypeForBuiltinFnName(writer, try dg.ctypeFromType(ty, .complete)); |
| 2098 | } | 2141 | } |
| 2099 | 2142 | ||
| 2100 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, cty: CType) !void { | 2143 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void { |
| 2101 | switch (cty.tag()) { | 2144 | switch (ctype.info(&dg.ctype_pool)) { |
| 2102 | else => try writer.print("{c}{d}", .{ | 2145 | else => |ctype_info| try writer.print("{c}{d}", .{ |
| 2103 | if (cty.isBool()) | 2146 | if (ctype.isBool()) |
| 2104 | signAbbrev(.unsigned) | 2147 | signAbbrev(.unsigned) |
| 2105 | else if (cty.isInteger()) | 2148 | else if (ctype.isInteger()) |
| 2106 | signAbbrev(cty.signedness(dg.mod)) | 2149 | signAbbrev(ctype.signedness(dg.mod)) |
| 2107 | else if (cty.isFloat()) | 2150 | else if (ctype.isFloat()) |
| 2108 | @as(u8, 'f') | 2151 | @as(u8, 'f') |
| 2109 | else if (cty.isPointer()) | 2152 | else if (ctype_info == .pointer) |
| 2110 | @as(u8, 'p') | 2153 | @as(u8, 'p') |
| 2111 | else | 2154 | else |
| 2112 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ | 2155 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), |
| 2113 | cty.tag(), | 2156 | if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8, |
| 2114 | }), | ||
| 2115 | if (cty.isFloat()) cty.floatActiveBits(dg.mod) else dg.byteSize(cty) * 8, | ||
| 2116 | }), | 2157 | }), |
| 2117 | .array => try writer.writeAll("big"), | 2158 | .array => try writer.writeAll("big"), |
| 2118 | } | 2159 | } |
| 2119 | } | 2160 | } |
| 2120 | 2161 | ||
| 2121 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { | 2162 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { |
| 2122 | const cty = try dg.typeToCType(ty, .complete); | 2163 | const ctype = try dg.ctypeFromType(ty, .complete); |
| 2123 | const is_big = cty.tag() == .array; | 2164 | const is_big = ctype.info(&dg.ctype_pool) == .array; |
| 2124 | switch (info) { | 2165 | switch (info) { |
| 2125 | .none => if (!is_big) return, | 2166 | .none => if (!is_big) return, |
| 2126 | .bits => {}, | 2167 | .bits => {}, |
| ... | @@ -2155,7 +2196,7 @@ pub const DeclGen = struct { | ... | @@ -2155,7 +2196,7 @@ pub const DeclGen = struct { |
| 2155 | .dg = dg, | 2196 | .dg = dg, |
| 2156 | .int_info = ty.intInfo(zcu), | 2197 | .int_info = ty.intInfo(zcu), |
| 2157 | .kind = kind, | 2198 | .kind = kind, |
| 2158 | .cty = try dg.typeToCType(ty, kind), | 2199 | .ctype = try dg.ctypeFromType(ty, kind), |
| 2159 | .val = val, | 2200 | .val = val, |
| 2160 | } }; | 2201 | } }; |
| 2161 | } | 2202 | } |
| ... | @@ -2184,122 +2225,74 @@ const RenderCTypeTrailing = enum { | ... | @@ -2184,122 +2225,74 @@ const RenderCTypeTrailing = enum { |
| 2184 | } | 2225 | } |
| 2185 | } | 2226 | } |
| 2186 | }; | 2227 | }; |
| 2187 | fn renderTypeName( | 2228 | fn renderAlignedTypeName(w: anytype, ctype: CType) !void { |
| 2229 | try w.print("anon__aligned_{d}", .{@intFromEnum(ctype.index)}); | ||
| 2230 | } | ||
| 2231 | fn renderFwdDeclTypeName( | ||
| 2188 | zcu: *Zcu, | 2232 | zcu: *Zcu, |
| 2189 | w: anytype, | 2233 | w: anytype, |
| 2190 | idx: CType.Index, | 2234 | ctype: CType, |
| 2191 | cty: CType, | 2235 | fwd_decl: CType.Info.FwdDecl, |
| 2192 | attributes: []const u8, | 2236 | attributes: []const u8, |
| 2193 | ) !void { | 2237 | ) !void { |
| 2194 | switch (cty.tag()) { | 2238 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); |
| 2195 | else => unreachable, | 2239 | switch (fwd_decl.name) { |
| 2196 | 2240 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), | |
| 2197 | .fwd_anon_struct, | 2241 | .owner_decl => |owner_decl| try w.print("{}__{d}", .{ |
| 2198 | .fwd_anon_union, | 2242 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), |
| 2199 | => |tag| try w.print("{s} {s}anon__lazy_{d}", .{ | 2243 | @intFromEnum(owner_decl), |
| 2200 | @tagName(tag)["fwd_anon_".len..], | ||
| 2201 | attributes, | ||
| 2202 | idx, | ||
| 2203 | }), | 2244 | }), |
| 2204 | |||
| 2205 | .fwd_struct, | ||
| 2206 | .fwd_union, | ||
| 2207 | => |tag| { | ||
| 2208 | const owner_decl = cty.cast(CType.Payload.FwdDecl).?.data; | ||
| 2209 | try w.print("{s} {s}{}__{d}", .{ | ||
| 2210 | @tagName(tag)["fwd_".len..], | ||
| 2211 | attributes, | ||
| 2212 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), | ||
| 2213 | @intFromEnum(owner_decl), | ||
| 2214 | }); | ||
| 2215 | }, | ||
| 2216 | } | 2245 | } |
| 2217 | } | 2246 | } |
| 2218 | fn renderTypePrefix( | 2247 | fn renderTypePrefix( |
| 2219 | pass: DeclGen.Pass, | 2248 | pass: DeclGen.Pass, |
| 2220 | store: CType.Store.Set, | 2249 | ctype_pool: *const CType.Pool, |
| 2221 | zcu: *Zcu, | 2250 | zcu: *Zcu, |
| 2222 | w: anytype, | 2251 | w: anytype, |
| 2223 | idx: CType.Index, | 2252 | ctype: CType, |
| 2224 | parent_fix: CTypeFix, | 2253 | parent_fix: CTypeFix, |
| 2225 | qualifiers: CQualifiers, | 2254 | qualifiers: CQualifiers, |
| 2226 | ) @TypeOf(w).Error!RenderCTypeTrailing { | 2255 | ) @TypeOf(w).Error!RenderCTypeTrailing { |
| 2227 | var trailing = RenderCTypeTrailing.maybe_space; | 2256 | var trailing = RenderCTypeTrailing.maybe_space; |
| 2257 | switch (ctype.info(ctype_pool)) { | ||
| 2258 | .basic => |basic_info| try w.writeAll(@tagName(basic_info)), | ||
| 2228 | 2259 | ||
| 2229 | const cty = store.indexToCType(idx); | 2260 | .pointer => |pointer_info| { |
| 2230 | switch (cty.tag()) { | 2261 | try w.print("{}*", .{try renderTypePrefix( |
| 2231 | .void, | ||
| 2232 | .char, | ||
| 2233 | .@"signed char", | ||
| 2234 | .short, | ||
| 2235 | .int, | ||
| 2236 | .long, | ||
| 2237 | .@"long long", | ||
| 2238 | ._Bool, | ||
| 2239 | .@"unsigned char", | ||
| 2240 | .@"unsigned short", | ||
| 2241 | .@"unsigned int", | ||
| 2242 | .@"unsigned long", | ||
| 2243 | .@"unsigned long long", | ||
| 2244 | .float, | ||
| 2245 | .double, | ||
| 2246 | .@"long double", | ||
| 2247 | .bool, | ||
| 2248 | .size_t, | ||
| 2249 | .ptrdiff_t, | ||
| 2250 | .uint8_t, | ||
| 2251 | .int8_t, | ||
| 2252 | .uint16_t, | ||
| 2253 | .int16_t, | ||
| 2254 | .uint32_t, | ||
| 2255 | .int32_t, | ||
| 2256 | .uint64_t, | ||
| 2257 | .int64_t, | ||
| 2258 | .uintptr_t, | ||
| 2259 | .intptr_t, | ||
| 2260 | .zig_u128, | ||
| 2261 | .zig_i128, | ||
| 2262 | .zig_f16, | ||
| 2263 | .zig_f32, | ||
| 2264 | .zig_f64, | ||
| 2265 | .zig_f80, | ||
| 2266 | .zig_f128, | ||
| 2267 | .zig_c_longdouble, | ||
| 2268 | => |tag| try w.writeAll(@tagName(tag)), | ||
| 2269 | |||
| 2270 | .pointer, | ||
| 2271 | .pointer_const, | ||
| 2272 | .pointer_volatile, | ||
| 2273 | .pointer_const_volatile, | ||
| 2274 | => |tag| { | ||
| 2275 | const child_idx = cty.cast(CType.Payload.Child).?.data; | ||
| 2276 | const child_trailing = try renderTypePrefix( | ||
| 2277 | pass, | 2262 | pass, |
| 2278 | store, | 2263 | ctype_pool, |
| 2279 | zcu, | 2264 | zcu, |
| 2280 | w, | 2265 | w, |
| 2281 | child_idx, | 2266 | pointer_info.elem_ctype, |
| 2282 | .prefix, | 2267 | .prefix, |
| 2283 | CQualifiers.init(.{ .@"const" = switch (tag) { | 2268 | CQualifiers.init(.{ |
| 2284 | .pointer, .pointer_volatile => false, | 2269 | .@"const" = pointer_info.@"const", |
| 2285 | .pointer_const, .pointer_const_volatile => true, | 2270 | .@"volatile" = pointer_info.@"volatile", |
| 2286 | else => unreachable, | 2271 | }), |
| 2287 | }, .@"volatile" = switch (tag) { | 2272 | )}); |
| 2288 | .pointer, .pointer_const => false, | ||
| 2289 | .pointer_volatile, .pointer_const_volatile => true, | ||
| 2290 | else => unreachable, | ||
| 2291 | } }), | ||
| 2292 | ); | ||
| 2293 | try w.print("{}*", .{child_trailing}); | ||
| 2294 | trailing = .no_space; | 2273 | trailing = .no_space; |
| 2295 | }, | 2274 | }, |
| 2296 | 2275 | ||
| 2297 | .array, | 2276 | .aligned => switch (pass) { |
| 2298 | .vector, | 2277 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ |
| 2299 | => { | 2278 | @intFromEnum(decl_index), @intFromEnum(ctype.index), |
| 2300 | const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type; | 2279 | }), |
| 2301 | const child_trailing = | 2280 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ |
| 2302 | try renderTypePrefix(pass, store, zcu, w, child_idx, .suffix, qualifiers); | 2281 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), |
| 2282 | }), | ||
| 2283 | .flush => try renderAlignedTypeName(w, ctype), | ||
| 2284 | }, | ||
| 2285 | |||
| 2286 | .array, .vector => |sequence_info| { | ||
| 2287 | const child_trailing = try renderTypePrefix( | ||
| 2288 | pass, | ||
| 2289 | ctype_pool, | ||
| 2290 | zcu, | ||
| 2291 | w, | ||
| 2292 | sequence_info.elem_ctype, | ||
| 2293 | .suffix, | ||
| 2294 | qualifiers, | ||
| 2295 | ); | ||
| 2303 | switch (parent_fix) { | 2296 | switch (parent_fix) { |
| 2304 | .prefix => { | 2297 | .prefix => { |
| 2305 | try w.print("{}(", .{child_trailing}); | 2298 | try w.print("{}(", .{child_trailing}); |
| ... | @@ -2309,56 +2302,46 @@ fn renderTypePrefix( | ... | @@ -2309,56 +2302,46 @@ fn renderTypePrefix( |
| 2309 | } | 2302 | } |
| 2310 | }, | 2303 | }, |
| 2311 | 2304 | ||
| 2312 | .fwd_anon_struct, | 2305 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { |
| 2313 | .fwd_anon_union, | 2306 | .anon => switch (pass) { |
| 2314 | => switch (pass) { | 2307 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ |
| 2315 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }), | 2308 | @intFromEnum(decl_index), @intFromEnum(ctype.index), |
| 2316 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }), | 2309 | }), |
| 2317 | .flush => try renderTypeName(zcu, w, idx, cty, ""), | 2310 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ |
| 2311 | @intFromEnum(anon_decl), @intFromEnum(ctype.index), | ||
| 2312 | }), | ||
| 2313 | .flush => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | ||
| 2314 | }, | ||
| 2315 | .owner_decl => try renderFwdDeclTypeName(zcu, w, ctype, fwd_decl_info, ""), | ||
| 2318 | }, | 2316 | }, |
| 2319 | 2317 | ||
| 2320 | .fwd_struct, | 2318 | .aggregate => |aggregate_info| switch (aggregate_info.name) { |
| 2321 | .fwd_union, | 2319 | .anon => { |
| 2322 | => try renderTypeName(zcu, w, idx, cty, ""), | 2320 | try w.print("{s} {s}", .{ |
| 2323 | 2321 | @tagName(aggregate_info.tag), | |
| 2324 | .unnamed_struct, | 2322 | if (aggregate_info.@"packed") "zig_packed(" else "", |
| 2325 | .unnamed_union, | 2323 | }); |
| 2326 | .packed_unnamed_struct, | 2324 | try renderFields(zcu, w, ctype_pool, aggregate_info, 1); |
| 2327 | .packed_unnamed_union, | 2325 | if (aggregate_info.@"packed") try w.writeByte(')'); |
| 2328 | => |tag| { | 2326 | }, |
| 2329 | try w.print("{s} {s}", .{ | 2327 | .fwd_decl => |fwd_decl| return renderTypePrefix( |
| 2330 | @tagName(tag)["unnamed_".len..], | 2328 | pass, |
| 2331 | if (cty.isPacked()) "zig_packed(" else "", | 2329 | ctype_pool, |
| 2332 | }); | 2330 | zcu, |
| 2333 | try renderAggregateFields(zcu, w, store, cty, 1); | 2331 | w, |
| 2334 | if (cty.isPacked()) try w.writeByte(')'); | 2332 | fwd_decl, |
| 2333 | parent_fix, | ||
| 2334 | qualifiers, | ||
| 2335 | ), | ||
| 2335 | }, | 2336 | }, |
| 2336 | 2337 | ||
| 2337 | .anon_struct, | 2338 | .function => |function_info| { |
| 2338 | .anon_union, | ||
| 2339 | .@"struct", | ||
| 2340 | .@"union", | ||
| 2341 | .packed_struct, | ||
| 2342 | .packed_union, | ||
| 2343 | => return renderTypePrefix( | ||
| 2344 | pass, | ||
| 2345 | store, | ||
| 2346 | zcu, | ||
| 2347 | w, | ||
| 2348 | cty.cast(CType.Payload.Aggregate).?.data.fwd_decl, | ||
| 2349 | parent_fix, | ||
| 2350 | qualifiers, | ||
| 2351 | ), | ||
| 2352 | |||
| 2353 | .function, | ||
| 2354 | .varargs_function, | ||
| 2355 | => { | ||
| 2356 | const child_trailing = try renderTypePrefix( | 2339 | const child_trailing = try renderTypePrefix( |
| 2357 | pass, | 2340 | pass, |
| 2358 | store, | 2341 | ctype_pool, |
| 2359 | zcu, | 2342 | zcu, |
| 2360 | w, | 2343 | w, |
| 2361 | cty.cast(CType.Payload.Function).?.data.return_type, | 2344 | function_info.return_ctype, |
| 2362 | .suffix, | 2345 | .suffix, |
| 2363 | .{}, | 2346 | .{}, |
| 2364 | ); | 2347 | ); |
| ... | @@ -2371,170 +2354,107 @@ fn renderTypePrefix( | ... | @@ -2371,170 +2354,107 @@ fn renderTypePrefix( |
| 2371 | } | 2354 | } |
| 2372 | }, | 2355 | }, |
| 2373 | } | 2356 | } |
| 2374 | |||
| 2375 | var qualifier_it = qualifiers.iterator(); | 2357 | var qualifier_it = qualifiers.iterator(); |
| 2376 | while (qualifier_it.next()) |qualifier| { | 2358 | while (qualifier_it.next()) |qualifier| { |
| 2377 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); | 2359 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); |
| 2378 | trailing = .maybe_space; | 2360 | trailing = .maybe_space; |
| 2379 | } | 2361 | } |
| 2380 | |||
| 2381 | return trailing; | 2362 | return trailing; |
| 2382 | } | 2363 | } |
| 2383 | fn renderTypeSuffix( | 2364 | fn renderTypeSuffix( |
| 2384 | pass: DeclGen.Pass, | 2365 | pass: DeclGen.Pass, |
| 2385 | store: CType.Store.Set, | 2366 | ctype_pool: *const CType.Pool, |
| 2386 | zcu: *Zcu, | 2367 | zcu: *Zcu, |
| 2387 | w: anytype, | 2368 | w: anytype, |
| 2388 | idx: CType.Index, | 2369 | ctype: CType, |
| 2389 | parent_fix: CTypeFix, | 2370 | parent_fix: CTypeFix, |
| 2390 | qualifiers: CQualifiers, | 2371 | qualifiers: CQualifiers, |
| 2391 | ) @TypeOf(w).Error!void { | 2372 | ) @TypeOf(w).Error!void { |
| 2392 | const cty = store.indexToCType(idx); | 2373 | switch (ctype.info(ctype_pool)) { |
| 2393 | switch (cty.tag()) { | 2374 | .basic, .aligned, .fwd_decl, .aggregate => {}, |
| 2394 | .void, | 2375 | .pointer => |pointer_info| try renderTypeSuffix( |
| 2395 | .char, | ||
| 2396 | .@"signed char", | ||
| 2397 | .short, | ||
| 2398 | .int, | ||
| 2399 | .long, | ||
| 2400 | .@"long long", | ||
| 2401 | ._Bool, | ||
| 2402 | .@"unsigned char", | ||
| 2403 | .@"unsigned short", | ||
| 2404 | .@"unsigned int", | ||
| 2405 | .@"unsigned long", | ||
| 2406 | .@"unsigned long long", | ||
| 2407 | .float, | ||
| 2408 | .double, | ||
| 2409 | .@"long double", | ||
| 2410 | .bool, | ||
| 2411 | .size_t, | ||
| 2412 | .ptrdiff_t, | ||
| 2413 | .uint8_t, | ||
| 2414 | .int8_t, | ||
| 2415 | .uint16_t, | ||
| 2416 | .int16_t, | ||
| 2417 | .uint32_t, | ||
| 2418 | .int32_t, | ||
| 2419 | .uint64_t, | ||
| 2420 | .int64_t, | ||
| 2421 | .uintptr_t, | ||
| 2422 | .intptr_t, | ||
| 2423 | .zig_u128, | ||
| 2424 | .zig_i128, | ||
| 2425 | .zig_f16, | ||
| 2426 | .zig_f32, | ||
| 2427 | .zig_f64, | ||
| 2428 | .zig_f80, | ||
| 2429 | .zig_f128, | ||
| 2430 | .zig_c_longdouble, | ||
| 2431 | => {}, | ||
| 2432 | |||
| 2433 | .pointer, | ||
| 2434 | .pointer_const, | ||
| 2435 | .pointer_volatile, | ||
| 2436 | .pointer_const_volatile, | ||
| 2437 | => try renderTypeSuffix( | ||
| 2438 | pass, | 2376 | pass, |
| 2439 | store, | 2377 | ctype_pool, |
| 2440 | zcu, | 2378 | zcu, |
| 2441 | w, | 2379 | w, |
| 2442 | cty.cast(CType.Payload.Child).?.data, | 2380 | pointer_info.elem_ctype, |
| 2443 | .prefix, | 2381 | .prefix, |
| 2444 | .{}, | 2382 | .{}, |
| 2445 | ), | 2383 | ), |
| 2446 | 2384 | .array, .vector => |sequence_info| { | |
| 2447 | .array, | ||
| 2448 | .vector, | ||
| 2449 | => { | ||
| 2450 | switch (parent_fix) { | 2385 | switch (parent_fix) { |
| 2451 | .prefix => try w.writeByte(')'), | 2386 | .prefix => try w.writeByte(')'), |
| 2452 | .suffix => {}, | 2387 | .suffix => {}, |
| 2453 | } | 2388 | } |
| 2454 | 2389 | ||
| 2455 | try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len}); | 2390 | try w.print("[{}]", .{sequence_info.len}); |
| 2456 | try renderTypeSuffix( | 2391 | try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{}); |
| 2457 | pass, | ||
| 2458 | store, | ||
| 2459 | zcu, | ||
| 2460 | w, | ||
| 2461 | cty.cast(CType.Payload.Sequence).?.data.elem_type, | ||
| 2462 | .suffix, | ||
| 2463 | .{}, | ||
| 2464 | ); | ||
| 2465 | }, | 2392 | }, |
| 2466 | 2393 | .function => |function_info| { | |
| 2467 | .fwd_anon_struct, | ||
| 2468 | .fwd_anon_union, | ||
| 2469 | .fwd_struct, | ||
| 2470 | .fwd_union, | ||
| 2471 | .unnamed_struct, | ||
| 2472 | .unnamed_union, | ||
| 2473 | .packed_unnamed_struct, | ||
| 2474 | .packed_unnamed_union, | ||
| 2475 | .anon_struct, | ||
| 2476 | .anon_union, | ||
| 2477 | .@"struct", | ||
| 2478 | .@"union", | ||
| 2479 | .packed_struct, | ||
| 2480 | .packed_union, | ||
| 2481 | => {}, | ||
| 2482 | |||
| 2483 | .function, | ||
| 2484 | .varargs_function, | ||
| 2485 | => |tag| { | ||
| 2486 | switch (parent_fix) { | 2394 | switch (parent_fix) { |
| 2487 | .prefix => try w.writeByte(')'), | 2395 | .prefix => try w.writeByte(')'), |
| 2488 | .suffix => {}, | 2396 | .suffix => {}, |
| 2489 | } | 2397 | } |
| 2490 | 2398 | ||
| 2491 | const data = cty.cast(CType.Payload.Function).?.data; | ||
| 2492 | |||
| 2493 | try w.writeByte('('); | 2399 | try w.writeByte('('); |
| 2494 | var need_comma = false; | 2400 | var need_comma = false; |
| 2495 | for (data.param_types, 0..) |param_type, param_i| { | 2401 | for (0..function_info.param_ctypes.len) |param_index| { |
| 2402 | const param_type = function_info.param_ctypes.at(param_index, ctype_pool); | ||
| 2496 | if (need_comma) try w.writeAll(", "); | 2403 | if (need_comma) try w.writeAll(", "); |
| 2497 | need_comma = true; | 2404 | need_comma = true; |
| 2498 | const trailing = | 2405 | const trailing = |
| 2499 | try renderTypePrefix(pass, store, zcu, w, param_type, .suffix, qualifiers); | 2406 | try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers); |
| 2500 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i }); | 2407 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index }); |
| 2501 | try renderTypeSuffix(pass, store, zcu, w, param_type, .suffix, .{}); | 2408 | try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); |
| 2502 | } | 2409 | } |
| 2503 | switch (tag) { | 2410 | if (function_info.varargs) { |
| 2504 | .function => {}, | 2411 | if (need_comma) try w.writeAll(", "); |
| 2505 | .varargs_function => { | 2412 | need_comma = true; |
| 2506 | if (need_comma) try w.writeAll(", "); | 2413 | try w.writeAll("..."); |
| 2507 | need_comma = true; | ||
| 2508 | try w.writeAll("..."); | ||
| 2509 | }, | ||
| 2510 | else => unreachable, | ||
| 2511 | } | 2414 | } |
| 2512 | if (!need_comma) try w.writeAll("void"); | 2415 | if (!need_comma) try w.writeAll("void"); |
| 2513 | try w.writeByte(')'); | 2416 | try w.writeByte(')'); |
| 2514 | 2417 | ||
| 2515 | try renderTypeSuffix(pass, store, zcu, w, data.return_type, .suffix, .{}); | 2418 | try renderTypeSuffix(pass, ctype_pool, zcu, w, function_info.return_ctype, .suffix, .{}); |
| 2516 | }, | 2419 | }, |
| 2517 | } | 2420 | } |
| 2518 | } | 2421 | } |
| 2519 | fn renderAggregateFields( | 2422 | fn renderFields( |
| 2520 | zcu: *Zcu, | 2423 | zcu: *Zcu, |
| 2521 | writer: anytype, | 2424 | writer: anytype, |
| 2522 | store: CType.Store.Set, | 2425 | ctype_pool: *const CType.Pool, |
| 2523 | cty: CType, | 2426 | aggregate_info: CType.Info.Aggregate, |
| 2524 | indent: usize, | 2427 | indent: usize, |
| 2525 | ) !void { | 2428 | ) !void { |
| 2526 | try writer.writeAll("{\n"); | 2429 | try writer.writeAll("{\n"); |
| 2527 | const fields = cty.fields(); | 2430 | for (0..aggregate_info.fields.len) |field_index| { |
| 2528 | for (fields) |field| { | 2431 | const field_info = aggregate_info.fields.at(field_index, ctype_pool); |
| 2529 | try writer.writeByteNTimes(' ', indent + 1); | 2432 | try writer.writeByteNTimes(' ', indent + 1); |
| 2530 | switch (field.alignas.abiOrder()) { | 2433 | switch (field_info.alignas.abiOrder()) { |
| 2531 | .lt => try writer.print("zig_under_align({}) ", .{field.alignas.toByteUnits()}), | 2434 | .lt => { |
| 2532 | .eq => {}, | 2435 | std.debug.assert(aggregate_info.@"packed"); |
| 2533 | .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}), | 2436 | if (field_info.alignas.@"align" != .@"1") try writer.print("zig_under_align({}) ", .{ |
| 2437 | field_info.alignas.toByteUnits(), | ||
| 2438 | }); | ||
| 2439 | }, | ||
| 2440 | .eq => if (aggregate_info.@"packed" and field_info.alignas.@"align" != .@"1") | ||
| 2441 | try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}), | ||
| 2442 | .gt => { | ||
| 2443 | std.debug.assert(field_info.alignas.@"align" != .@"1"); | ||
| 2444 | try writer.print("zig_align({}) ", .{field_info.alignas.toByteUnits()}); | ||
| 2445 | }, | ||
| 2534 | } | 2446 | } |
| 2535 | const trailing = try renderTypePrefix(.flush, store, zcu, writer, field.type, .suffix, .{}); | 2447 | const trailing = try renderTypePrefix( |
| 2536 | try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) }); | 2448 | .flush, |
| 2537 | try renderTypeSuffix(.flush, store, zcu, writer, field.type, .suffix, .{}); | 2449 | ctype_pool, |
| 2450 | zcu, | ||
| 2451 | writer, | ||
| 2452 | field_info.ctype, | ||
| 2453 | .suffix, | ||
| 2454 | .{}, | ||
| 2455 | ); | ||
| 2456 | try writer.print("{}{ }", .{ trailing, fmtIdent(field_info.name.slice(ctype_pool)) }); | ||
| 2457 | try renderTypeSuffix(.flush, ctype_pool, zcu, writer, field_info.ctype, .suffix, .{}); | ||
| 2538 | try writer.writeAll(";\n"); | 2458 | try writer.writeAll(";\n"); |
| 2539 | } | 2459 | } |
| 2540 | try writer.writeByteNTimes(' ', indent); | 2460 | try writer.writeByteNTimes(' ', indent); |
| ... | @@ -2544,77 +2464,77 @@ fn renderAggregateFields( | ... | @@ -2544,77 +2464,77 @@ fn renderAggregateFields( |
| 2544 | pub fn genTypeDecl( | 2464 | pub fn genTypeDecl( |
| 2545 | zcu: *Zcu, | 2465 | zcu: *Zcu, |
| 2546 | writer: anytype, | 2466 | writer: anytype, |
| 2547 | global_store: CType.Store.Set, | 2467 | global_ctype_pool: *const CType.Pool, |
| 2548 | global_idx: CType.Index, | 2468 | global_ctype: CType, |
| 2549 | pass: DeclGen.Pass, | 2469 | pass: DeclGen.Pass, |
| 2550 | decl_store: CType.Store.Set, | 2470 | decl_ctype_pool: *const CType.Pool, |
| 2551 | decl_idx: CType.Index, | 2471 | decl_ctype: CType, |
| 2552 | found_existing: bool, | 2472 | found_existing: bool, |
| 2553 | ) !void { | 2473 | ) !void { |
| 2554 | const global_cty = global_store.indexToCType(global_idx); | 2474 | switch (global_ctype.info(global_ctype_pool)) { |
| 2555 | switch (global_cty.tag()) { | 2475 | .basic, .pointer, .array, .vector, .function => {}, |
| 2556 | .fwd_anon_struct => if (pass != .flush) { | 2476 | .aligned => |aligned_info| { |
| 2557 | try writer.writeAll("typedef "); | 2477 | if (!found_existing) { |
| 2558 | _ = try renderTypePrefix(.flush, global_store, zcu, writer, global_idx, .suffix, .{}); | 2478 | try writer.writeAll("typedef "); |
| 2559 | try writer.writeByte(' '); | 2479 | try writer.print("{}", .{ |
| 2560 | _ = try renderTypePrefix(pass, decl_store, zcu, writer, decl_idx, .suffix, .{}); | 2480 | try renderTypePrefix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}), |
| 2561 | try writer.writeAll(";\n"); | 2481 | }); |
| 2562 | }, | 2482 | try renderAlignedTypeName(writer, global_ctype); |
| 2563 | 2483 | try renderTypeSuffix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}); | |
| 2564 | .fwd_struct, | 2484 | std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); |
| 2565 | .fwd_union, | 2485 | try writer.print(" zig_under_align({d});\n", .{aligned_info.alignas.toByteUnits()}); |
| 2566 | .anon_struct, | 2486 | } |
| 2567 | .anon_union, | 2487 | switch (pass) { |
| 2568 | .@"struct", | 2488 | .decl, .anon => { |
| 2569 | .@"union", | 2489 | try writer.writeAll("typedef "); |
| 2570 | .packed_struct, | 2490 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); |
| 2571 | .packed_union, | ||
| 2572 | => |tag| if (!found_existing) { | ||
| 2573 | switch (tag) { | ||
| 2574 | .fwd_struct, | ||
| 2575 | .fwd_union, | ||
| 2576 | => { | ||
| 2577 | const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data; | ||
| 2578 | _ = try renderTypePrefix( | ||
| 2579 | .flush, | ||
| 2580 | global_store, | ||
| 2581 | zcu, | ||
| 2582 | writer, | ||
| 2583 | global_idx, | ||
| 2584 | .suffix, | ||
| 2585 | .{}, | ||
| 2586 | ); | ||
| 2587 | try writer.writeAll("; /* "); | ||
| 2588 | try zcu.declPtr(owner_decl).renderFullyQualifiedName(zcu, writer); | ||
| 2589 | try writer.writeAll(" */\n"); | ||
| 2590 | }, | ||
| 2591 | |||
| 2592 | .anon_struct, | ||
| 2593 | .anon_union, | ||
| 2594 | .@"struct", | ||
| 2595 | .@"union", | ||
| 2596 | .packed_struct, | ||
| 2597 | .packed_union, | ||
| 2598 | => { | ||
| 2599 | const fwd_idx = global_cty.cast(CType.Payload.Aggregate).?.data.fwd_decl; | ||
| 2600 | try renderTypeName( | ||
| 2601 | zcu, | ||
| 2602 | writer, | ||
| 2603 | fwd_idx, | ||
| 2604 | global_store.indexToCType(fwd_idx), | ||
| 2605 | if (global_cty.isPacked()) "zig_packed(" else "", | ||
| 2606 | ); | ||
| 2607 | try writer.writeByte(' '); | 2491 | try writer.writeByte(' '); |
| 2608 | try renderAggregateFields(zcu, writer, global_store, global_cty, 0); | 2492 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); |
| 2609 | if (global_cty.isPacked()) try writer.writeByte(')'); | ||
| 2610 | try writer.writeAll(";\n"); | 2493 | try writer.writeAll(";\n"); |
| 2611 | }, | 2494 | }, |
| 2612 | 2495 | .flush => {}, | |
| 2613 | else => unreachable, | ||
| 2614 | } | 2496 | } |
| 2615 | }, | 2497 | }, |
| 2616 | 2498 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2617 | else => {}, | 2499 | .anon => switch (pass) { |
| 2500 | .decl, .anon => { | ||
| 2501 | try writer.writeAll("typedef "); | ||
| 2502 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | ||
| 2503 | try writer.writeByte(' '); | ||
| 2504 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); | ||
| 2505 | try writer.writeAll(";\n"); | ||
| 2506 | }, | ||
| 2507 | .flush => {}, | ||
| 2508 | }, | ||
| 2509 | .owner_decl => |owner_decl_index| if (!found_existing) { | ||
| 2510 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | ||
| 2511 | try writer.writeByte(';'); | ||
| 2512 | const owner_decl = zcu.declPtr(owner_decl_index); | ||
| 2513 | const owner_mod = zcu.namespacePtr(owner_decl.src_namespace).file_scope.mod; | ||
| 2514 | if (!owner_mod.strip) { | ||
| 2515 | try writer.writeAll(" /* "); | ||
| 2516 | try owner_decl.renderFullyQualifiedName(zcu, writer); | ||
| 2517 | try writer.writeAll(" */"); | ||
| 2518 | } | ||
| 2519 | try writer.writeByte('\n'); | ||
| 2520 | }, | ||
| 2521 | }, | ||
| 2522 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | ||
| 2523 | .anon => {}, | ||
| 2524 | .fwd_decl => |fwd_decl| if (!found_existing) { | ||
| 2525 | try renderFwdDeclTypeName( | ||
| 2526 | zcu, | ||
| 2527 | writer, | ||
| 2528 | fwd_decl, | ||
| 2529 | fwd_decl.info(global_ctype_pool).fwd_decl, | ||
| 2530 | if (aggregate_info.@"packed") "zig_packed(" else "", | ||
| 2531 | ); | ||
| 2532 | try writer.writeByte(' '); | ||
| 2533 | try renderFields(zcu, writer, global_ctype_pool, aggregate_info, 0); | ||
| 2534 | if (aggregate_info.@"packed") try writer.writeByte(')'); | ||
| 2535 | try writer.writeAll(";\n"); | ||
| 2536 | }, | ||
| 2537 | }, | ||
| 2618 | } | 2538 | } |
| 2619 | } | 2539 | } |
| 2620 | 2540 | ||
| ... | @@ -2771,13 +2691,13 @@ fn genExports(o: *Object) !void { | ... | @@ -2771,13 +2691,13 @@ fn genExports(o: *Object) !void { |
| 2771 | } | 2691 | } |
| 2772 | } | 2692 | } |
| 2773 | 2693 | ||
| 2774 | pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | 2694 | pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFnMap.Entry) !void { |
| 2775 | const zcu = o.dg.zcu; | 2695 | const zcu = o.dg.zcu; |
| 2776 | const ip = &zcu.intern_pool; | 2696 | const ip = &zcu.intern_pool; |
| 2697 | const ctype_pool = &o.dg.ctype_pool; | ||
| 2777 | const w = o.writer(); | 2698 | const w = o.writer(); |
| 2778 | const key = lazy_fn.key_ptr.*; | 2699 | const key = lazy_fn.key_ptr.*; |
| 2779 | const val = lazy_fn.value_ptr; | 2700 | const val = lazy_fn.value_ptr; |
| 2780 | const fn_name = val.fn_name; | ||
| 2781 | switch (key) { | 2701 | switch (key) { |
| 2782 | .tag_name => { | 2702 | .tag_name => { |
| 2783 | const enum_ty = val.data.tag_name; | 2703 | const enum_ty = val.data.tag_name; |
| ... | @@ -2787,7 +2707,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2787,7 +2707,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2787 | try w.writeAll("static "); | 2707 | try w.writeAll("static "); |
| 2788 | try o.dg.renderType(w, name_slice_ty); | 2708 | try o.dg.renderType(w, name_slice_ty); |
| 2789 | try w.writeByte(' '); | 2709 | try w.writeByte(' '); |
| 2790 | try w.writeAll(fn_name); | 2710 | try w.writeAll(val.fn_name.slice(lazy_ctype_pool)); |
| 2791 | try w.writeByte('('); | 2711 | try w.writeByte('('); |
| 2792 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); | 2712 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); |
| 2793 | try w.writeAll(") {\n switch (tag) {\n"); | 2713 | try w.writeAll(") {\n switch (tag) {\n"); |
| ... | @@ -2829,8 +2749,9 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2829,8 +2749,9 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2829 | }, | 2749 | }, |
| 2830 | .never_tail, .never_inline => |fn_decl_index| { | 2750 | .never_tail, .never_inline => |fn_decl_index| { |
| 2831 | const fn_decl = zcu.declPtr(fn_decl_index); | 2751 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 2832 | const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(zcu), .complete); | 2752 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); |
| 2833 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; | 2753 | const fn_info = fn_ctype.info(ctype_pool).function; |
| 2754 | const fn_name = val.fn_name.slice(lazy_ctype_pool); | ||
| 2834 | 2755 | ||
| 2835 | const fwd_decl_writer = o.dg.fwdDeclWriter(); | 2756 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2836 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); | 2757 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| ... | @@ -2843,11 +2764,13 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2843,11 +2764,13 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2843 | try fwd_decl_writer.writeAll(";\n"); | 2764 | try fwd_decl_writer.writeAll(";\n"); |
| 2844 | 2765 | ||
| 2845 | try w.print("static zig_{s} ", .{@tagName(key)}); | 2766 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| 2846 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ .ident = fn_name }); | 2767 | try o.dg.renderFunctionSignature(w, fn_decl_index, .complete, .{ |
| 2768 | .ident = fn_name, | ||
| 2769 | }); | ||
| 2847 | try w.writeAll(" {\n return "); | 2770 | try w.writeAll(" {\n return "); |
| 2848 | try o.dg.renderDeclName(w, fn_decl_index, 0); | 2771 | try o.dg.renderDeclName(w, fn_decl_index, 0); |
| 2849 | try w.writeByte('('); | 2772 | try w.writeByte('('); |
| 2850 | for (0..fn_info.param_types.len) |arg| { | 2773 | for (0..fn_info.param_ctypes.len) |arg| { |
| 2851 | if (arg > 0) try w.writeAll(", "); | 2774 | if (arg > 0) try w.writeAll(", "); |
| 2852 | try o.dg.writeCValue(w, .{ .arg = arg }); | 2775 | try o.dg.writeCValue(w, .{ .arg = arg }); |
| 2853 | } | 2776 | } |
| ... | @@ -2931,7 +2854,7 @@ pub fn genFunc(f: *Function) !void { | ... | @@ -2931,7 +2854,7 @@ pub fn genFunc(f: *Function) !void { |
| 2931 | for (free_locals.values()) |list| { | 2854 | for (free_locals.values()) |list| { |
| 2932 | for (list.keys()) |local_index| { | 2855 | for (list.keys()) |local_index| { |
| 2933 | const local = f.locals.items[local_index]; | 2856 | const local = f.locals.items[local_index]; |
| 2934 | try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.flags.alignas); | 2857 | try o.dg.renderCTypeAndName(w, local.ctype, .{ .local = local_index }, .{}, local.flags.alignas); |
| 2935 | try w.writeAll(";\n "); | 2858 | try w.writeAll(";\n "); |
| 2936 | } | 2859 | } |
| 2937 | } | 2860 | } |
| ... | @@ -3451,11 +3374,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3451,11 +3374,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3451 | 3374 | ||
| 3452 | const inst_ty = f.typeOfIndex(inst); | 3375 | const inst_ty = f.typeOfIndex(inst); |
| 3453 | const ptr_ty = f.typeOf(bin_op.lhs); | 3376 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 3454 | const ptr_align = ptr_ty.ptrAlignment(zcu); | 3377 | const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu); |
| 3455 | const elem_ty = ptr_ty.elemType2(zcu); | ||
| 3456 | const elem_align = elem_ty.abiAlignment(zcu); | ||
| 3457 | const is_under_aligned = ptr_align.compareStrict(.lt, elem_align); | ||
| 3458 | const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); | ||
| 3459 | 3378 | ||
| 3460 | const ptr = try f.resolveInst(bin_op.lhs); | 3379 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3461 | const index = try f.resolveInst(bin_op.rhs); | 3380 | const index = try f.resolveInst(bin_op.rhs); |
| ... | @@ -3470,22 +3389,13 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3470,22 +3389,13 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3470 | try f.renderType(writer, inst_ty); | 3389 | try f.renderType(writer, inst_ty); |
| 3471 | try writer.writeByte(')'); | 3390 | try writer.writeByte(')'); |
| 3472 | if (elem_has_bits) try writer.writeByte('&'); | 3391 | if (elem_has_bits) try writer.writeByte('&'); |
| 3473 | if (elem_has_bits and ptr_ty.ptrSize(zcu) == .One and !is_under_aligned) { | 3392 | if (elem_has_bits and ptr_ty.ptrSize(zcu) == .One) { |
| 3474 | // It's a pointer to an array, so we need to de-reference. | 3393 | // It's a pointer to an array, so we need to de-reference. |
| 3475 | try f.writeCValueDeref(writer, ptr); | 3394 | try f.writeCValueDeref(writer, ptr); |
| 3476 | } else try f.writeCValue(writer, ptr, .Other); | 3395 | } else try f.writeCValue(writer, ptr, .Other); |
| 3477 | if (elem_has_bits) { | 3396 | if (elem_has_bits) { |
| 3478 | try writer.writeByte('['); | 3397 | try writer.writeByte('['); |
| 3479 | try f.writeCValue(writer, index, .Other); | 3398 | try f.writeCValue(writer, index, .Other); |
| 3480 | if (is_under_aligned) { | ||
| 3481 | const factor = @divExact(elem_align.toByteUnitsOptional().?, @min( | ||
| 3482 | ptr_align.toByteUnitsOptional().?, | ||
| 3483 | f.object.dg.mod.resolved_target.result.maxIntAlignment(), | ||
| 3484 | )); | ||
| 3485 | try writer.print(" * {}", .{ | ||
| 3486 | try f.fmtIntLiteral(try zcu.intValue(Type.usize, factor)), | ||
| 3487 | }); | ||
| 3488 | } | ||
| 3489 | try writer.writeByte(']'); | 3399 | try writer.writeByte(']'); |
| 3490 | } | 3400 | } |
| 3491 | try a.end(f, writer); | 3401 | try a.end(f, writer); |
| ... | @@ -3577,13 +3487,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3577,13 +3487,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3577 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { | 3487 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3578 | const zcu = f.object.dg.zcu; | 3488 | const zcu = f.object.dg.zcu; |
| 3579 | const inst_ty = f.typeOfIndex(inst); | 3489 | const inst_ty = f.typeOfIndex(inst); |
| 3580 | const elem_type = inst_ty.childType(zcu); | 3490 | const elem_ty = inst_ty.childType(zcu); |
| 3581 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | 3491 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; |
| 3582 | 3492 | ||
| 3583 | const local = try f.allocLocalValue( | 3493 | const local = try f.allocLocalValue(.{ |
| 3584 | elem_type, | 3494 | .ctype = try f.ctypeFromType(elem_ty, .complete), |
| 3585 | inst_ty.ptrAlignment(zcu), | 3495 | .alignas = CType.AlignAs.fromAlignment(.{ |
| 3586 | ); | 3496 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, |
| 3497 | .abi = elem_ty.abiAlignment(zcu), | ||
| 3498 | }), | ||
| 3499 | }); | ||
| 3587 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3500 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3588 | const gpa = f.object.dg.zcu.gpa; | 3501 | const gpa = f.object.dg.zcu.gpa; |
| 3589 | try f.allocs.put(gpa, local.new_local, true); | 3502 | try f.allocs.put(gpa, local.new_local, true); |
| ... | @@ -3596,10 +3509,13 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3596,10 +3509,13 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3596 | const elem_ty = inst_ty.childType(zcu); | 3509 | const elem_ty = inst_ty.childType(zcu); |
| 3597 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | 3510 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; |
| 3598 | 3511 | ||
| 3599 | const local = try f.allocLocalValue( | 3512 | const local = try f.allocLocalValue(.{ |
| 3600 | elem_ty, | 3513 | .ctype = try f.ctypeFromType(elem_ty, .complete), |
| 3601 | inst_ty.ptrAlignment(zcu), | 3514 | .alignas = CType.AlignAs.fromAlignment(.{ |
| 3602 | ); | 3515 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, |
| 3516 | .abi = elem_ty.abiAlignment(zcu), | ||
| 3517 | }), | ||
| 3518 | }); | ||
| 3603 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); | 3519 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3604 | const gpa = f.object.dg.zcu.gpa; | 3520 | const gpa = f.object.dg.zcu.gpa; |
| 3605 | try f.allocs.put(gpa, local.new_local, true); | 3521 | try f.allocs.put(gpa, local.new_local, true); |
| ... | @@ -3608,14 +3524,14 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3608,14 +3524,14 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3608 | 3524 | ||
| 3609 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { | 3525 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3610 | const inst_ty = f.typeOfIndex(inst); | 3526 | const inst_ty = f.typeOfIndex(inst); |
| 3611 | const inst_cty = try f.typeToIndex(inst_ty, .parameter); | 3527 | const inst_ctype = try f.ctypeFromType(inst_ty, .parameter); |
| 3612 | 3528 | ||
| 3613 | const i = f.next_arg_index; | 3529 | const i = f.next_arg_index; |
| 3614 | f.next_arg_index += 1; | 3530 | f.next_arg_index += 1; |
| 3615 | const result: CValue = if (inst_cty != try f.typeToIndex(inst_ty, .complete)) | 3531 | const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete))) |
| 3616 | .{ .arg_array = i } | 3532 | .{ .arg = i } |
| 3617 | else | 3533 | else |
| 3618 | .{ .arg = i }; | 3534 | .{ .arg_array = i }; |
| 3619 | 3535 | ||
| 3620 | if (f.liveness.isUnused(inst)) { | 3536 | if (f.liveness.isUnused(inst)) { |
| 3621 | const writer = f.object.writer(); | 3537 | const writer = f.object.writer(); |
| ... | @@ -3649,7 +3565,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3649,7 +3565,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3649 | try reap(f, inst, &.{ty_op.operand}); | 3565 | try reap(f, inst, &.{ty_op.operand}); |
| 3650 | 3566 | ||
| 3651 | const is_aligned = if (ptr_info.flags.alignment != .none) | 3567 | const is_aligned = if (ptr_info.flags.alignment != .none) |
| 3652 | ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu)) | 3568 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 3653 | else | 3569 | else |
| 3654 | true; | 3570 | true; |
| 3655 | const is_array = lowersToArray(src_ty, zcu); | 3571 | const is_array = lowersToArray(src_ty, zcu); |
| ... | @@ -3724,18 +3640,21 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { | ... | @@ -3724,18 +3640,21 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue { |
| 3724 | const op_inst = un_op.toIndex(); | 3640 | const op_inst = un_op.toIndex(); |
| 3725 | const op_ty = f.typeOf(un_op); | 3641 | const op_ty = f.typeOf(un_op); |
| 3726 | const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; | 3642 | const ret_ty = if (is_ptr) op_ty.childType(zcu) else op_ty; |
| 3727 | const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu); | 3643 | const ret_ctype = try f.ctypeFromType(ret_ty, .parameter); |
| 3728 | 3644 | ||
| 3729 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { | 3645 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { |
| 3730 | try reap(f, inst, &.{un_op}); | 3646 | try reap(f, inst, &.{un_op}); |
| 3731 | _ = try airCall(f, op_inst.?, .always_tail); | 3647 | _ = try airCall(f, op_inst.?, .always_tail); |
| 3732 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 3648 | } else if (ret_ctype.index != .void) { |
| 3733 | const operand = try f.resolveInst(un_op); | 3649 | const operand = try f.resolveInst(un_op); |
| 3734 | try reap(f, inst, &.{un_op}); | 3650 | try reap(f, inst, &.{un_op}); |
| 3735 | var deref = is_ptr; | 3651 | var deref = is_ptr; |
| 3736 | const is_array = lowersToArray(ret_ty, zcu); | 3652 | const is_array = lowersToArray(ret_ty, zcu); |
| 3737 | const ret_val = if (is_array) ret_val: { | 3653 | const ret_val = if (is_array) ret_val: { |
| 3738 | const array_local = try f.allocLocal(inst, lowered_ret_ty); | 3654 | const array_local = try f.allocAlignedLocal(inst, .{ |
| 3655 | .ctype = ret_ctype, | ||
| 3656 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(f.object.dg.zcu)), | ||
| 3657 | }); | ||
| 3739 | try writer.writeAll("memcpy("); | 3658 | try writer.writeAll("memcpy("); |
| 3740 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | 3659 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 3741 | try writer.writeAll(", "); | 3660 | try writer.writeAll(", "); |
| ... | @@ -3921,7 +3840,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { | ... | @@ -3921,7 +3840,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3921 | } | 3840 | } |
| 3922 | 3841 | ||
| 3923 | const is_aligned = if (ptr_info.flags.alignment != .none) | 3842 | const is_aligned = if (ptr_info.flags.alignment != .none) |
| 3924 | ptr_info.flags.alignment.compare(.gte, src_ty.abiAlignment(zcu)) | 3843 | ptr_info.flags.alignment.order(src_ty.abiAlignment(zcu)).compare(.gte) |
| 3925 | else | 3844 | else |
| 3926 | true; | 3845 | true; |
| 3927 | const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu); | 3846 | const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu); |
| ... | @@ -4397,22 +4316,23 @@ fn airCall( | ... | @@ -4397,22 +4316,23 @@ fn airCall( |
| 4397 | defer gpa.free(resolved_args); | 4316 | defer gpa.free(resolved_args); |
| 4398 | for (resolved_args, args) |*resolved_arg, arg| { | 4317 | for (resolved_args, args) |*resolved_arg, arg| { |
| 4399 | const arg_ty = f.typeOf(arg); | 4318 | const arg_ty = f.typeOf(arg); |
| 4400 | const arg_cty = try f.typeToIndex(arg_ty, .parameter); | 4319 | const arg_ctype = try f.ctypeFromType(arg_ty, .parameter); |
| 4401 | if (f.indexToCType(arg_cty).tag() == .void) { | 4320 | if (arg_ctype.index == .void) { |
| 4402 | resolved_arg.* = .none; | 4321 | resolved_arg.* = .none; |
| 4403 | continue; | 4322 | continue; |
| 4404 | } | 4323 | } |
| 4405 | resolved_arg.* = try f.resolveInst(arg); | 4324 | resolved_arg.* = try f.resolveInst(arg); |
| 4406 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { | 4325 | if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) { |
| 4407 | const lowered_arg_ty = try lowerFnRetTy(arg_ty, zcu); | 4326 | const array_local = try f.allocAlignedLocal(inst, .{ |
| 4408 | 4327 | .ctype = arg_ctype, | |
| 4409 | const array_local = try f.allocLocal(inst, lowered_arg_ty); | 4328 | .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), |
| 4329 | }); | ||
| 4410 | try writer.writeAll("memcpy("); | 4330 | try writer.writeAll("memcpy("); |
| 4411 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); | 4331 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 4412 | try writer.writeAll(", "); | 4332 | try writer.writeAll(", "); |
| 4413 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); | 4333 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); |
| 4414 | try writer.writeAll(", sizeof("); | 4334 | try writer.writeAll(", sizeof("); |
| 4415 | try f.renderType(writer, lowered_arg_ty); | 4335 | try f.renderCType(writer, arg_ctype); |
| 4416 | try writer.writeAll("));\n"); | 4336 | try writer.writeAll("));\n"); |
| 4417 | resolved_arg.* = array_local; | 4337 | resolved_arg.* = array_local; |
| 4418 | } | 4338 | } |
| ... | @@ -4433,21 +4353,27 @@ fn airCall( | ... | @@ -4433,21 +4353,27 @@ fn airCall( |
| 4433 | else => unreachable, | 4353 | else => unreachable, |
| 4434 | }).?; | 4354 | }).?; |
| 4435 | const ret_ty = Type.fromInterned(fn_info.return_type); | 4355 | const ret_ty = Type.fromInterned(fn_info.return_type); |
| 4436 | const lowered_ret_ty = try lowerFnRetTy(ret_ty, zcu); | 4356 | const ret_ctype: CType = if (ret_ty.isNoReturn(zcu)) |
| 4357 | .{ .index = .void } | ||
| 4358 | else | ||
| 4359 | try f.ctypeFromType(ret_ty, .parameter); | ||
| 4437 | 4360 | ||
| 4438 | const result_local = result: { | 4361 | const result_local = result: { |
| 4439 | if (modifier == .always_tail) { | 4362 | if (modifier == .always_tail) { |
| 4440 | try writer.writeAll("zig_always_tail return "); | 4363 | try writer.writeAll("zig_always_tail return "); |
| 4441 | break :result .none; | 4364 | break :result .none; |
| 4442 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | 4365 | } else if (ret_ctype.index == .void) { |
| 4443 | break :result .none; | 4366 | break :result .none; |
| 4444 | } else if (f.liveness.isUnused(inst)) { | 4367 | } else if (f.liveness.isUnused(inst)) { |
| 4445 | try writer.writeByte('('); | 4368 | try writer.writeByte('('); |
| 4446 | try f.renderType(writer, Type.void); | 4369 | try f.renderCType(writer, .{ .index = .void }); |
| 4447 | try writer.writeByte(')'); | 4370 | try writer.writeByte(')'); |
| 4448 | break :result .none; | 4371 | break :result .none; |
| 4449 | } else { | 4372 | } else { |
| 4450 | const local = try f.allocLocal(inst, lowered_ret_ty); | 4373 | const local = try f.allocAlignedLocal(inst, .{ |
| 4374 | .ctype = ret_ctype, | ||
| 4375 | .alignas = CType.AlignAs.fromAbiAlignment(ret_ty.abiAlignment(zcu)), | ||
| 4376 | }); | ||
| 4451 | try f.writeCValue(writer, local, .Other); | 4377 | try f.writeCValue(writer, local, .Other); |
| 4452 | try writer.writeAll(" = "); | 4378 | try writer.writeAll(" = "); |
| 4453 | break :result local; | 4379 | break :result local; |
| ... | @@ -4767,6 +4693,7 @@ const LocalResult = struct { | ... | @@ -4767,6 +4693,7 @@ const LocalResult = struct { |
| 4767 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { | 4693 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { |
| 4768 | const zcu = f.object.dg.zcu; | 4694 | const zcu = f.object.dg.zcu; |
| 4769 | const target = &f.object.dg.mod.resolved_target.result; | 4695 | const target = &f.object.dg.mod.resolved_target.result; |
| 4696 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 4770 | const writer = f.object.writer(); | 4697 | const writer = f.object.writer(); |
| 4771 | 4698 | ||
| 4772 | if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { | 4699 | if (operand_ty.isAbiInt(zcu) and dest_ty.isAbiInt(zcu)) { |
| ... | @@ -4825,49 +4752,54 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca | ... | @@ -4825,49 +4752,54 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca |
| 4825 | 4752 | ||
| 4826 | // Ensure padding bits have the expected value. | 4753 | // Ensure padding bits have the expected value. |
| 4827 | if (dest_ty.isAbiInt(zcu)) { | 4754 | if (dest_ty.isAbiInt(zcu)) { |
| 4828 | const dest_cty = try f.typeToCType(dest_ty, .complete); | 4755 | const dest_ctype = try f.ctypeFromType(dest_ty, .complete); |
| 4829 | const dest_info = dest_ty.intInfo(zcu); | 4756 | const dest_info = dest_ty.intInfo(zcu); |
| 4830 | var bits: u16 = dest_info.bits; | 4757 | var bits: u16 = dest_info.bits; |
| 4831 | var wrap_cty: ?CType = null; | 4758 | var wrap_ctype: ?CType = null; |
| 4832 | var need_bitcasts = false; | 4759 | var need_bitcasts = false; |
| 4833 | 4760 | ||
| 4834 | try f.writeCValue(writer, local, .Other); | 4761 | try f.writeCValue(writer, local, .Other); |
| 4835 | if (dest_cty.castTag(.array)) |pl| { | 4762 | switch (dest_ctype.info(ctype_pool)) { |
| 4836 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | 4763 | else => {}, |
| 4837 | .little => pl.data.len - 1, | 4764 | .array => |array_info| { |
| 4838 | .big => 0, | 4765 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { |
| 4839 | }}); | 4766 | .little => array_info.len - 1, |
| 4840 | const elem_cty = f.indexToCType(pl.data.elem_type); | 4767 | .big => 0, |
| 4841 | wrap_cty = elem_cty.toSignedness(dest_info.signedness); | 4768 | }}); |
| 4842 | need_bitcasts = wrap_cty.?.tag() == .zig_i128; | 4769 | wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness); |
| 4843 | bits -= 1; | 4770 | need_bitcasts = wrap_ctype.?.index == .zig_i128; |
| 4844 | bits %= @as(u16, @intCast(f.byteSize(elem_cty) * 8)); | 4771 | bits -= 1; |
| 4845 | bits += 1; | 4772 | bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8)); |
| 4773 | bits += 1; | ||
| 4774 | }, | ||
| 4846 | } | 4775 | } |
| 4847 | try writer.writeAll(" = "); | 4776 | try writer.writeAll(" = "); |
| 4848 | if (need_bitcasts) { | 4777 | if (need_bitcasts) { |
| 4849 | try writer.writeAll("zig_bitCast_"); | 4778 | try writer.writeAll("zig_bitCast_"); |
| 4850 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?.toUnsigned()); | 4779 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?.toUnsigned()); |
| 4851 | try writer.writeByte('('); | 4780 | try writer.writeByte('('); |
| 4852 | } | 4781 | } |
| 4853 | try writer.writeAll("zig_wrap_"); | 4782 | try writer.writeAll("zig_wrap_"); |
| 4854 | const info_ty = try zcu.intType(dest_info.signedness, bits); | 4783 | const info_ty = try zcu.intType(dest_info.signedness, bits); |
| 4855 | if (wrap_cty) |cty| | 4784 | if (wrap_ctype) |ctype| |
| 4856 | try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) | 4785 | try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype) |
| 4857 | else | 4786 | else |
| 4858 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); | 4787 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); |
| 4859 | try writer.writeByte('('); | 4788 | try writer.writeByte('('); |
| 4860 | if (need_bitcasts) { | 4789 | if (need_bitcasts) { |
| 4861 | try writer.writeAll("zig_bitCast_"); | 4790 | try writer.writeAll("zig_bitCast_"); |
| 4862 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_cty.?); | 4791 | try f.object.dg.renderCTypeForBuiltinFnName(writer, wrap_ctype.?); |
| 4863 | try writer.writeByte('('); | 4792 | try writer.writeByte('('); |
| 4864 | } | 4793 | } |
| 4865 | try f.writeCValue(writer, local, .Other); | 4794 | try f.writeCValue(writer, local, .Other); |
| 4866 | if (dest_cty.castTag(.array)) |pl| { | 4795 | switch (dest_ctype.info(ctype_pool)) { |
| 4867 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | 4796 | else => {}, |
| 4868 | .little => pl.data.len - 1, | 4797 | .array => |array_info| try writer.print("[{d}]", .{ |
| 4869 | .big => 0, | 4798 | switch (target.cpu.arch.endian()) { |
| 4870 | }}); | 4799 | .little => array_info.len - 1, |
| 4800 | .big => 0, | ||
| 4801 | }, | ||
| 4802 | }), | ||
| 4871 | } | 4803 | } |
| 4872 | if (need_bitcasts) try writer.writeByte(')'); | 4804 | if (need_bitcasts) try writer.writeByte(')'); |
| 4873 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); | 4805 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); |
| ... | @@ -5131,10 +5063,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5131,10 +5063,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5131 | if (is_reg) { | 5063 | if (is_reg) { |
| 5132 | const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu); | 5064 | const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu); |
| 5133 | try writer.writeAll("register "); | 5065 | try writer.writeAll("register "); |
| 5134 | const alignment: Alignment = .none; | 5066 | const local_value = try f.allocLocal(inst, output_ty); |
| 5135 | const local_value = try f.allocLocalValue(output_ty, alignment); | ||
| 5136 | try f.allocs.put(gpa, local_value.new_local, false); | 5067 | try f.allocs.put(gpa, local_value.new_local, false); |
| 5137 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, alignment, .complete); | 5068 | try f.object.dg.renderTypeAndName(writer, output_ty, local_value, .{}, .none, .complete); |
| 5138 | try writer.writeAll(" __asm(\""); | 5069 | try writer.writeAll(" __asm(\""); |
| 5139 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); | 5070 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| 5140 | try writer.writeAll("\")"); | 5071 | try writer.writeAll("\")"); |
| ... | @@ -5164,10 +5095,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5164,10 +5095,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5164 | if (asmInputNeedsLocal(f, constraint, input_val)) { | 5095 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 5165 | const input_ty = f.typeOf(input); | 5096 | const input_ty = f.typeOf(input); |
| 5166 | if (is_reg) try writer.writeAll("register "); | 5097 | if (is_reg) try writer.writeAll("register "); |
| 5167 | const alignment: Alignment = .none; | 5098 | const local_value = try f.allocLocal(inst, input_ty); |
| 5168 | const local_value = try f.allocLocalValue(input_ty, alignment); | ||
| 5169 | try f.allocs.put(gpa, local_value.new_local, false); | 5099 | try f.allocs.put(gpa, local_value.new_local, false); |
| 5170 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, alignment, .complete); | 5100 | try f.object.dg.renderTypeAndName(writer, input_ty, local_value, Const, .none, .complete); |
| 5171 | if (is_reg) { | 5101 | if (is_reg) { |
| 5172 | try writer.writeAll(" __asm(\""); | 5102 | try writer.writeAll(" __asm(\""); |
| 5173 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); | 5103 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | @@ -5512,59 +5442,74 @@ fn fieldLocation( | ... | @@ -5512,59 +5442,74 @@ fn fieldLocation( |
| 5512 | end: void, | 5442 | end: void, |
| 5513 | } { | 5443 | } { |
| 5514 | const ip = &zcu.intern_pool; | 5444 | const ip = &zcu.intern_pool; |
| 5515 | const container_ty = container_ptr_ty.childType(zcu); | 5445 | const container_ty = Type.fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child); |
| 5516 | return switch (container_ty.zigTypeTag(zcu)) { | 5446 | switch (ip.indexToKey(container_ty.toIntern())) { |
| 5517 | .Struct => blk: { | 5447 | .struct_type => { |
| 5518 | if (zcu.typeToPackedStruct(container_ty)) |struct_type| { | 5448 | const loaded_struct = ip.loadStructType(container_ty.toIntern()); |
| 5519 | if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) | 5449 | switch (loaded_struct.layout) { |
| 5520 | break :blk .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } | 5450 | .auto, .@"extern" => { |
| 5451 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | ||
| 5452 | var before = true; | ||
| 5453 | while (field_it.next()) |next_field_index| { | ||
| 5454 | if (next_field_index == field_index) before = false; | ||
| 5455 | if (before) continue; | ||
| 5456 | const field_type = Type.fromInterned(loaded_struct.field_types.get(ip)[next_field_index]); | ||
| 5457 | if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 5458 | return .{ .field = if (loaded_struct.fieldName(ip, next_field_index).unwrap()) |field_name| | ||
| 5459 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 5460 | else | ||
| 5461 | .{ .field = next_field_index } }; | ||
| 5462 | } | ||
| 5463 | return if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; | ||
| 5464 | }, | ||
| 5465 | .@"packed" => return if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) | ||
| 5466 | .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) + | ||
| 5467 | container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } | ||
| 5521 | else | 5468 | else |
| 5522 | break :blk .begin; | 5469 | .begin, |
| 5523 | } | 5470 | } |
| 5524 | 5471 | }, | |
| 5525 | for (field_index..container_ty.structFieldCount(zcu)) |next_field_index_usize| { | 5472 | .anon_struct_type => |anon_struct_info| { |
| 5526 | const next_field_index: u32 = @intCast(next_field_index_usize); | 5473 | for (field_index..anon_struct_info.types.len) |next_field_index| { |
| 5527 | if (container_ty.structFieldIsComptime(next_field_index, zcu)) continue; | 5474 | if (anon_struct_info.values.get(ip)[next_field_index] != .none) continue; |
| 5528 | const field_ty = container_ty.structFieldType(next_field_index, zcu); | 5475 | const field_type = Type.fromInterned(anon_struct_info.types.get(ip)[next_field_index]); |
| 5529 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 5476 | if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 5530 | 5477 | return .{ .field = if (anon_struct_info.fieldName(ip, next_field_index).unwrap()) |field_name| | |
| 5531 | break :blk .{ .field = if (container_ty.isSimpleTuple(zcu)) | 5478 | .{ .identifier = ip.stringToSlice(field_name) } |
| 5532 | .{ .field = next_field_index } | ||
| 5533 | else | 5479 | else |
| 5534 | .{ .identifier = ip.stringToSlice(container_ty.legacyStructFieldName(next_field_index, zcu)) } }; | 5480 | .{ .field = next_field_index } }; |
| 5535 | } | 5481 | } |
| 5536 | break :blk if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; | 5482 | return if (container_ty.hasRuntimeBitsIgnoreComptime(zcu)) .end else .begin; |
| 5537 | }, | 5483 | }, |
| 5538 | .Union => { | 5484 | .union_type => { |
| 5539 | const union_obj = zcu.typeToUnion(container_ty).?; | 5485 | const loaded_union = ip.loadUnionType(container_ty.toIntern()); |
| 5540 | return switch (union_obj.getLayout(ip)) { | 5486 | switch (loaded_union.getLayout(ip)) { |
| 5541 | .auto, .@"extern" => { | 5487 | .auto, .@"extern" => { |
| 5542 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | 5488 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); |
| 5543 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) | 5489 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 5544 | return if (container_ty.unionTagTypeSafety(zcu) != null and | 5490 | return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) |
| 5545 | !container_ty.unionHasAllZeroBitFieldTypes(zcu)) | ||
| 5546 | .{ .field = .{ .identifier = "payload" } } | 5491 | .{ .field = .{ .identifier = "payload" } } |
| 5547 | else | 5492 | else |
| 5548 | .begin; | 5493 | .begin; |
| 5549 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | 5494 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; |
| 5550 | return .{ .field = if (container_ty.unionTagTypeSafety(zcu)) |_| | 5495 | return .{ .field = if (loaded_union.hasTag(ip)) |
| 5551 | .{ .payload_identifier = ip.stringToSlice(field_name) } | 5496 | .{ .payload_identifier = ip.stringToSlice(field_name) } |
| 5552 | else | 5497 | else |
| 5553 | .{ .identifier = ip.stringToSlice(field_name) } }; | 5498 | .{ .identifier = ip.stringToSlice(field_name) } }; |
| 5554 | }, | 5499 | }, |
| 5555 | .@"packed" => .begin, | 5500 | .@"packed" => return .begin, |
| 5556 | }; | 5501 | } |
| 5557 | }, | 5502 | }, |
| 5558 | .Pointer => switch (container_ty.ptrSize(zcu)) { | 5503 | .ptr_type => |ptr_info| switch (ptr_info.flags.size) { |
| 5504 | .One, .Many, .C => unreachable, | ||
| 5559 | .Slice => switch (field_index) { | 5505 | .Slice => switch (field_index) { |
| 5560 | 0 => .{ .field = .{ .identifier = "ptr" } }, | 5506 | 0 => return .{ .field = .{ .identifier = "ptr" } }, |
| 5561 | 1 => .{ .field = .{ .identifier = "len" } }, | 5507 | 1 => return .{ .field = .{ .identifier = "len" } }, |
| 5562 | else => unreachable, | 5508 | else => unreachable, |
| 5563 | }, | 5509 | }, |
| 5564 | .One, .Many, .C => unreachable, | ||
| 5565 | }, | 5510 | }, |
| 5566 | else => unreachable, | 5511 | else => unreachable, |
| 5567 | }; | 5512 | } |
| 5568 | } | 5513 | } |
| 5569 | 5514 | ||
| 5570 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { | 5515 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | @@ -5653,7 +5598,7 @@ fn fieldPtr( | ... | @@ -5653,7 +5598,7 @@ fn fieldPtr( |
| 5653 | const field_ptr_ty = f.typeOfIndex(inst); | 5598 | const field_ptr_ty = f.typeOfIndex(inst); |
| 5654 | 5599 | ||
| 5655 | // Ensure complete type definition is visible before accessing fields. | 5600 | // Ensure complete type definition is visible before accessing fields. |
| 5656 | _ = try f.typeToIndex(container_ty, .complete); | 5601 | _ = try f.ctypeFromType(container_ty, .complete); |
| 5657 | 5602 | ||
| 5658 | const writer = f.object.writer(); | 5603 | const writer = f.object.writer(); |
| 5659 | const local = try f.allocLocal(inst, field_ptr_ty); | 5604 | const local = try f.allocLocal(inst, field_ptr_ty); |
| ... | @@ -5708,109 +5653,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -5708,109 +5653,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5708 | const writer = f.object.writer(); | 5653 | const writer = f.object.writer(); |
| 5709 | 5654 | ||
| 5710 | // Ensure complete type definition is visible before accessing fields. | 5655 | // Ensure complete type definition is visible before accessing fields. |
| 5711 | _ = try f.typeToIndex(struct_ty, .complete); | 5656 | _ = try f.ctypeFromType(struct_ty, .complete); |
| 5657 | |||
| 5658 | const field_name: CValue = switch (ip.indexToKey(struct_ty.toIntern())) { | ||
| 5659 | .struct_type => field_name: { | ||
| 5660 | const loaded_struct = ip.loadStructType(struct_ty.toIntern()); | ||
| 5661 | switch (loaded_struct.layout) { | ||
| 5662 | .auto, .@"extern" => break :field_name if (loaded_struct.fieldName(ip, extra.field_index).unwrap()) |field_name| | ||
| 5663 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 5664 | else | ||
| 5665 | .{ .field = extra.field_index }, | ||
| 5666 | .@"packed" => { | ||
| 5667 | const int_info = struct_ty.intInfo(zcu); | ||
| 5712 | 5668 | ||
| 5713 | const field_name: CValue = switch (zcu.intern_pool.indexToKey(struct_ty.toIntern())) { | 5669 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 5714 | .struct_type => switch (struct_ty.containerLayout(zcu)) { | ||
| 5715 | .auto, .@"extern" => if (struct_ty.isSimpleTuple(zcu)) | ||
| 5716 | .{ .field = extra.field_index } | ||
| 5717 | else | ||
| 5718 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) }, | ||
| 5719 | .@"packed" => { | ||
| 5720 | const struct_type = zcu.typeToStruct(struct_ty).?; | ||
| 5721 | const int_info = struct_ty.intInfo(zcu); | ||
| 5722 | 5670 | ||
| 5723 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | 5671 | const bit_offset = zcu.structPackedFieldBitOffset(loaded_struct, extra.field_index); |
| 5724 | 5672 | ||
| 5725 | const bit_offset = zcu.structPackedFieldBitOffset(struct_type, extra.field_index); | 5673 | const field_int_signedness = if (inst_ty.isAbiInt(zcu)) |
| 5674 | inst_ty.intInfo(zcu).signedness | ||
| 5675 | else | ||
| 5676 | .unsigned; | ||
| 5677 | const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); | ||
| 5726 | 5678 | ||
| 5727 | const field_int_signedness = if (inst_ty.isAbiInt(zcu)) | 5679 | const temp_local = try f.allocLocal(inst, field_int_ty); |
| 5728 | inst_ty.intInfo(zcu).signedness | 5680 | try f.writeCValue(writer, temp_local, .Other); |
| 5729 | else | 5681 | try writer.writeAll(" = zig_wrap_"); |
| 5730 | .unsigned; | 5682 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); |
| 5731 | const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); | 5683 | try writer.writeAll("(("); |
| 5732 | 5684 | try f.renderType(writer, field_int_ty); | |
| 5733 | const temp_local = try f.allocLocal(inst, field_int_ty); | ||
| 5734 | try f.writeCValue(writer, temp_local, .Other); | ||
| 5735 | try writer.writeAll(" = zig_wrap_"); | ||
| 5736 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | ||
| 5737 | try writer.writeAll("(("); | ||
| 5738 | try f.renderType(writer, field_int_ty); | ||
| 5739 | try writer.writeByte(')'); | ||
| 5740 | const cant_cast = int_info.bits > 64; | ||
| 5741 | if (cant_cast) { | ||
| 5742 | if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | ||
| 5743 | try writer.writeAll("zig_lo_"); | ||
| 5744 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5745 | try writer.writeByte('('); | ||
| 5746 | } | ||
| 5747 | if (bit_offset > 0) { | ||
| 5748 | try writer.writeAll("zig_shr_"); | ||
| 5749 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5750 | try writer.writeByte('('); | ||
| 5751 | } | ||
| 5752 | try f.writeCValue(writer, struct_byval, .Other); | ||
| 5753 | if (bit_offset > 0) { | ||
| 5754 | try writer.writeAll(", "); | ||
| 5755 | try f.object.dg.renderValue(writer, try zcu.intValue(bit_offset_ty, bit_offset), .FunctionArgument); | ||
| 5756 | try writer.writeByte(')'); | 5685 | try writer.writeByte(')'); |
| 5757 | } | 5686 | const cant_cast = int_info.bits > 64; |
| 5758 | if (cant_cast) try writer.writeByte(')'); | 5687 | if (cant_cast) { |
| 5759 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | 5688 | if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); |
| 5760 | try writer.writeAll(");\n"); | 5689 | try writer.writeAll("zig_lo_"); |
| 5761 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; | 5690 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); |
| 5691 | try writer.writeByte('('); | ||
| 5692 | } | ||
| 5693 | if (bit_offset > 0) { | ||
| 5694 | try writer.writeAll("zig_shr_"); | ||
| 5695 | try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty); | ||
| 5696 | try writer.writeByte('('); | ||
| 5697 | } | ||
| 5698 | try f.writeCValue(writer, struct_byval, .Other); | ||
| 5699 | if (bit_offset > 0) try writer.print(", {})", .{ | ||
| 5700 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), | ||
| 5701 | }); | ||
| 5702 | if (cant_cast) try writer.writeByte(')'); | ||
| 5703 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | ||
| 5704 | try writer.writeAll(");\n"); | ||
| 5705 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; | ||
| 5762 | 5706 | ||
| 5763 | const local = try f.allocLocal(inst, inst_ty); | 5707 | const local = try f.allocLocal(inst, inst_ty); |
| 5764 | try writer.writeAll("memcpy("); | 5708 | try writer.writeAll("memcpy("); |
| 5765 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | 5709 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); |
| 5766 | try writer.writeAll(", "); | 5710 | try writer.writeAll(", "); |
| 5767 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | 5711 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); |
| 5768 | try writer.writeAll(", sizeof("); | 5712 | try writer.writeAll(", sizeof("); |
| 5769 | try f.renderType(writer, inst_ty); | 5713 | try f.renderType(writer, inst_ty); |
| 5770 | try writer.writeAll("));\n"); | 5714 | try writer.writeAll("));\n"); |
| 5771 | try freeLocal(f, inst, temp_local.new_local, null); | 5715 | try freeLocal(f, inst, temp_local.new_local, null); |
| 5772 | return local; | 5716 | return local; |
| 5773 | }, | 5717 | }, |
| 5718 | } | ||
| 5774 | }, | 5719 | }, |
| 5775 | 5720 | .anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name| | |
| 5776 | .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) | 5721 | .{ .identifier = ip.stringToSlice(field_name) } |
| 5777 | .{ .field = extra.field_index } | ||
| 5778 | else | 5722 | else |
| 5779 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) }, | 5723 | .{ .field = extra.field_index }, |
| 5780 | |||
| 5781 | .union_type => field_name: { | 5724 | .union_type => field_name: { |
| 5782 | const union_obj = ip.loadUnionType(struct_ty.toIntern()); | 5725 | const loaded_union = ip.loadUnionType(struct_ty.toIntern()); |
| 5783 | if (union_obj.flagsPtr(ip).layout == .@"packed") { | 5726 | switch (loaded_union.getLayout(ip)) { |
| 5784 | const operand_lval = if (struct_byval == .constant) blk: { | 5727 | .auto, .@"extern" => { |
| 5785 | const operand_local = try f.allocLocal(inst, struct_ty); | 5728 | const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 5786 | try f.writeCValue(writer, operand_local, .Other); | 5729 | break :field_name if (loaded_union.hasTag(ip)) |
| 5787 | try writer.writeAll(" = "); | 5730 | .{ .payload_identifier = ip.stringToSlice(name) } |
| 5788 | try f.writeCValue(writer, struct_byval, .Initializer); | 5731 | else |
| 5789 | try writer.writeAll(";\n"); | 5732 | .{ .identifier = ip.stringToSlice(name) }; |
| 5790 | break :blk operand_local; | 5733 | }, |
| 5791 | } else struct_byval; | 5734 | .@"packed" => { |
| 5792 | 5735 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5793 | const local = try f.allocLocal(inst, inst_ty); | 5736 | const operand_local = try f.allocLocal(inst, struct_ty); |
| 5794 | try writer.writeAll("memcpy(&"); | 5737 | try f.writeCValue(writer, operand_local, .Other); |
| 5795 | try f.writeCValue(writer, local, .Other); | 5738 | try writer.writeAll(" = "); |
| 5796 | try writer.writeAll(", &"); | 5739 | try f.writeCValue(writer, struct_byval, .Initializer); |
| 5797 | try f.writeCValue(writer, operand_lval, .Other); | 5740 | try writer.writeAll(";\n"); |
| 5798 | try writer.writeAll(", sizeof("); | 5741 | break :blk operand_local; |
| 5799 | try f.renderType(writer, inst_ty); | 5742 | } else struct_byval; |
| 5800 | try writer.writeAll("));\n"); | 5743 | |
| 5801 | 5744 | const local = try f.allocLocal(inst, inst_ty); | |
| 5802 | if (struct_byval == .constant) { | 5745 | try writer.writeAll("memcpy(&"); |
| 5803 | try freeLocal(f, inst, operand_lval.new_local, null); | 5746 | try f.writeCValue(writer, local, .Other); |
| 5804 | } | 5747 | try writer.writeAll(", &"); |
| 5748 | try f.writeCValue(writer, operand_lval, .Other); | ||
| 5749 | try writer.writeAll(", sizeof("); | ||
| 5750 | try f.renderType(writer, inst_ty); | ||
| 5751 | try writer.writeAll("));\n"); | ||
| 5752 | |||
| 5753 | if (struct_byval == .constant) { | ||
| 5754 | try freeLocal(f, inst, operand_lval.new_local, null); | ||
| 5755 | } | ||
| 5805 | 5756 | ||
| 5806 | return local; | 5757 | return local; |
| 5807 | } else { | 5758 | }, |
| 5808 | const name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | ||
| 5809 | break :field_name if (union_obj.hasTag(ip)) .{ | ||
| 5810 | .payload_identifier = ip.stringToSlice(name), | ||
| 5811 | } else .{ | ||
| 5812 | .identifier = ip.stringToSlice(name), | ||
| 5813 | }; | ||
| 5814 | } | 5759 | } |
| 5815 | }, | 5760 | }, |
| 5816 | else => unreachable, | 5761 | else => unreachable, |
| ... | @@ -6089,6 +6034,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const | ... | @@ -6089,6 +6034,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 6089 | 6034 | ||
| 6090 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | 6035 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6091 | const zcu = f.object.dg.zcu; | 6036 | const zcu = f.object.dg.zcu; |
| 6037 | const ctype_pool = &f.object.dg.ctype_pool; | ||
| 6092 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; | 6038 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6093 | 6039 | ||
| 6094 | const operand = try f.resolveInst(ty_op.operand); | 6040 | const operand = try f.resolveInst(ty_op.operand); |
| ... | @@ -6107,18 +6053,18 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -6107,18 +6053,18 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6107 | if (operand == .undef) { | 6053 | if (operand == .undef) { |
| 6108 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer); | 6054 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer); |
| 6109 | } else { | 6055 | } else { |
| 6110 | const ptr_cty = try f.typeToIndex(ptr_ty, .complete); | 6056 | const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); |
| 6111 | const ptr_child_cty = f.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; | 6057 | const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; |
| 6112 | const elem_ty = array_ty.childType(zcu); | 6058 | const elem_ty = array_ty.childType(zcu); |
| 6113 | const elem_cty = try f.typeToIndex(elem_ty, .complete); | 6059 | const elem_ctype = try f.ctypeFromType(elem_ty, .complete); |
| 6114 | if (ptr_child_cty != elem_cty) { | 6060 | if (!ptr_child_ctype.eql(elem_ctype)) { |
| 6115 | try writer.writeByte('('); | 6061 | try writer.writeByte('('); |
| 6116 | try f.renderCType(writer, ptr_cty); | 6062 | try f.renderCType(writer, ptr_ctype); |
| 6117 | try writer.writeByte(')'); | 6063 | try writer.writeByte(')'); |
| 6118 | } | 6064 | } |
| 6119 | const operand_cty = try f.typeToCType(operand_ty, .complete); | 6065 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); |
| 6120 | const operand_child_cty = operand_cty.cast(CType.Payload.Child).?.data; | 6066 | const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; |
| 6121 | if (f.indexToCType(operand_child_cty).tag() == .array) { | 6067 | if (operand_child_ctype.info(ctype_pool) == .array) { |
| 6122 | try writer.writeByte('&'); | 6068 | try writer.writeByte('&'); |
| 6123 | try f.writeCValueDeref(writer, operand); | 6069 | try f.writeCValueDeref(writer, operand); |
| 6124 | try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); | 6070 | try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); |
| ... | @@ -6229,8 +6175,8 @@ fn airUnBuiltinCall( | ... | @@ -6229,8 +6175,8 @@ fn airUnBuiltinCall( |
| 6229 | const operand_ty = f.typeOf(ty_op.operand); | 6175 | const operand_ty = f.typeOf(ty_op.operand); |
| 6230 | const scalar_ty = operand_ty.scalarType(zcu); | 6176 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6231 | 6177 | ||
| 6232 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6178 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6233 | const ref_ret = inst_scalar_cty.tag() == .array; | 6179 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6234 | 6180 | ||
| 6235 | const writer = f.object.writer(); | 6181 | const writer = f.object.writer(); |
| 6236 | const local = try f.allocLocal(inst, inst_ty); | 6182 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6267,8 +6213,8 @@ fn airBinBuiltinCall( | ... | @@ -6267,8 +6213,8 @@ fn airBinBuiltinCall( |
| 6267 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 6213 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6268 | 6214 | ||
| 6269 | const operand_ty = f.typeOf(bin_op.lhs); | 6215 | const operand_ty = f.typeOf(bin_op.lhs); |
| 6270 | const operand_cty = try f.typeToCType(operand_ty, .complete); | 6216 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); |
| 6271 | const is_big = operand_cty.tag() == .array; | 6217 | const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6272 | 6218 | ||
| 6273 | const lhs = try f.resolveInst(bin_op.lhs); | 6219 | const lhs = try f.resolveInst(bin_op.lhs); |
| 6274 | const rhs = try f.resolveInst(bin_op.rhs); | 6220 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | @@ -6278,8 +6224,8 @@ fn airBinBuiltinCall( | ... | @@ -6278,8 +6224,8 @@ fn airBinBuiltinCall( |
| 6278 | const inst_scalar_ty = inst_ty.scalarType(zcu); | 6224 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6279 | const scalar_ty = operand_ty.scalarType(zcu); | 6225 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6280 | 6226 | ||
| 6281 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6227 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6282 | const ref_ret = inst_scalar_cty.tag() == .array; | 6228 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6283 | 6229 | ||
| 6284 | const writer = f.object.writer(); | 6230 | const writer = f.object.writer(); |
| 6285 | const local = try f.allocLocal(inst, inst_ty); | 6231 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -6328,8 +6274,8 @@ fn airCmpBuiltinCall( | ... | @@ -6328,8 +6274,8 @@ fn airCmpBuiltinCall( |
| 6328 | const operand_ty = f.typeOf(data.lhs); | 6274 | const operand_ty = f.typeOf(data.lhs); |
| 6329 | const scalar_ty = operand_ty.scalarType(zcu); | 6275 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6330 | 6276 | ||
| 6331 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | 6277 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); |
| 6332 | const ref_ret = inst_scalar_cty.tag() == .array; | 6278 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; |
| 6333 | 6279 | ||
| 6334 | const writer = f.object.writer(); | 6280 | const writer = f.object.writer(); |
| 6335 | const local = try f.allocLocal(inst, inst_ty); | 6281 | const local = try f.allocLocal(inst, inst_ty); |
| ... | @@ -7112,9 +7058,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7112,9 +7058,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7112 | 7058 | ||
| 7113 | const writer = f.object.writer(); | 7059 | const writer = f.object.writer(); |
| 7114 | const local = try f.allocLocal(inst, inst_ty); | 7060 | const local = try f.allocLocal(inst, inst_ty); |
| 7115 | switch (inst_ty.zigTypeTag(zcu)) { | 7061 | switch (ip.indexToKey(inst_ty.toIntern())) { |
| 7116 | .Array, .Vector => { | 7062 | inline .array_type, .vector_type => |info, tag| { |
| 7117 | const a = try Assignment.init(f, inst_ty.childType(zcu)); | 7063 | const a = try Assignment.init(f, Type.fromInterned(info.child)); |
| 7118 | for (resolved_elements, 0..) |element, i| { | 7064 | for (resolved_elements, 0..) |element, i| { |
| 7119 | try a.restart(f, writer); | 7065 | try a.restart(f, writer); |
| 7120 | try f.writeCValue(writer, local, .Other); | 7066 | try f.writeCValue(writer, local, .Other); |
| ... | @@ -7123,94 +7069,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7123,94 +7069,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7123 | try f.writeCValue(writer, element, .Other); | 7069 | try f.writeCValue(writer, element, .Other); |
| 7124 | try a.end(f, writer); | 7070 | try a.end(f, writer); |
| 7125 | } | 7071 | } |
| 7126 | if (inst_ty.sentinel(zcu)) |sentinel| { | 7072 | if (tag == .array_type and info.sentinel != .none) { |
| 7127 | try a.restart(f, writer); | 7073 | try a.restart(f, writer); |
| 7128 | try f.writeCValue(writer, local, .Other); | 7074 | try f.writeCValue(writer, local, .Other); |
| 7129 | try writer.print("[{d}]", .{resolved_elements.len}); | 7075 | try writer.print("[{d}]", .{info.len}); |
| 7130 | try a.assign(f, writer); | 7076 | try a.assign(f, writer); |
| 7131 | try f.object.dg.renderValue(writer, sentinel, .Other); | 7077 | try f.object.dg.renderValue(writer, Value.fromInterned(info.sentinel), .Other); |
| 7132 | try a.end(f, writer); | 7078 | try a.end(f, writer); |
| 7133 | } | 7079 | } |
| 7134 | }, | 7080 | }, |
| 7135 | .Struct => switch (inst_ty.containerLayout(zcu)) { | 7081 | .struct_type => { |
| 7136 | .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| { | 7082 | const loaded_struct = ip.loadStructType(inst_ty.toIntern()); |
| 7137 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | 7083 | switch (loaded_struct.layout) { |
| 7138 | const field_ty = inst_ty.structFieldType(field_index, zcu); | 7084 | .auto, .@"extern" => { |
| 7139 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | 7085 | var field_it = loaded_struct.iterateRuntimeOrder(ip); |
| 7140 | 7086 | while (field_it.next()) |field_index| { | |
| 7141 | const a = try Assignment.start(f, writer, field_ty); | 7087 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 7142 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(zcu)) | 7088 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7143 | .{ .field = field_index } | ||
| 7144 | else | ||
| 7145 | .{ .identifier = ip.stringToSlice(inst_ty.legacyStructFieldName(@intCast(field_index), zcu)) }); | ||
| 7146 | try a.assign(f, writer); | ||
| 7147 | try f.writeCValue(writer, element, .Other); | ||
| 7148 | try a.end(f, writer); | ||
| 7149 | }, | ||
| 7150 | .@"packed" => { | ||
| 7151 | try f.writeCValue(writer, local, .Other); | ||
| 7152 | try writer.writeAll(" = "); | ||
| 7153 | const int_info = inst_ty.intInfo(zcu); | ||
| 7154 | 7089 | ||
| 7155 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | 7090 | const a = try Assignment.start(f, writer, field_ty); |
| 7091 | try f.writeCValueMember(writer, local, if (loaded_struct.fieldName(ip, field_index).unwrap()) |field_name| | ||
| 7092 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 7093 | else | ||
| 7094 | .{ .field = field_index }); | ||
| 7095 | try a.assign(f, writer); | ||
| 7096 | try f.writeCValue(writer, resolved_elements[field_index], .Other); | ||
| 7097 | try a.end(f, writer); | ||
| 7098 | } | ||
| 7099 | }, | ||
| 7100 | .@"packed" => { | ||
| 7101 | try f.writeCValue(writer, local, .Other); | ||
| 7102 | try writer.writeAll(" = "); | ||
| 7103 | const int_info = inst_ty.intInfo(zcu); | ||
| 7156 | 7104 | ||
| 7157 | var bit_offset: u64 = 0; | 7105 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); |
| 7158 | 7106 | ||
| 7159 | var empty = true; | 7107 | var bit_offset: u64 = 0; |
| 7160 | for (0..elements.len) |field_index| { | ||
| 7161 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | ||
| 7162 | const field_ty = inst_ty.structFieldType(field_index, zcu); | ||
| 7163 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7164 | 7108 | ||
| 7165 | if (!empty) { | 7109 | var empty = true; |
| 7166 | try writer.writeAll("zig_or_"); | 7110 | for (0..elements.len) |field_index| { |
| 7167 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | 7111 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; |
| 7168 | try writer.writeByte('('); | 7112 | const field_ty = inst_ty.structFieldType(field_index, zcu); |
| 7113 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7114 | |||
| 7115 | if (!empty) { | ||
| 7116 | try writer.writeAll("zig_or_"); | ||
| 7117 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | ||
| 7118 | try writer.writeByte('('); | ||
| 7119 | } | ||
| 7120 | empty = false; | ||
| 7169 | } | 7121 | } |
| 7170 | empty = false; | 7122 | empty = true; |
| 7171 | } | 7123 | for (resolved_elements, 0..) |element, field_index| { |
| 7172 | empty = true; | 7124 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; |
| 7173 | for (resolved_elements, 0..) |element, field_index| { | 7125 | const field_ty = inst_ty.structFieldType(field_index, zcu); |
| 7174 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | 7126 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 7175 | const field_ty = inst_ty.structFieldType(field_index, zcu); | ||
| 7176 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7177 | |||
| 7178 | if (!empty) try writer.writeAll(", "); | ||
| 7179 | // TODO: Skip this entire shift if val is 0? | ||
| 7180 | try writer.writeAll("zig_shlw_"); | ||
| 7181 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | ||
| 7182 | try writer.writeByte('('); | ||
| 7183 | 7127 | ||
| 7184 | if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { | 7128 | if (!empty) try writer.writeAll(", "); |
| 7185 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); | 7129 | // TODO: Skip this entire shift if val is 0? |
| 7186 | } else { | 7130 | try writer.writeAll("zig_shlw_"); |
| 7131 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | ||
| 7187 | try writer.writeByte('('); | 7132 | try writer.writeByte('('); |
| 7188 | try f.renderType(writer, inst_ty); | 7133 | |
| 7189 | try writer.writeByte(')'); | 7134 | if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { |
| 7190 | if (field_ty.isPtrAtRuntime(zcu)) { | 7135 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); |
| 7136 | } else { | ||
| 7191 | try writer.writeByte('('); | 7137 | try writer.writeByte('('); |
| 7192 | try f.renderType(writer, switch (int_info.signedness) { | 7138 | try f.renderType(writer, inst_ty); |
| 7193 | .unsigned => Type.usize, | ||
| 7194 | .signed => Type.isize, | ||
| 7195 | }); | ||
| 7196 | try writer.writeByte(')'); | 7139 | try writer.writeByte(')'); |
| 7140 | if (field_ty.isPtrAtRuntime(zcu)) { | ||
| 7141 | try writer.writeByte('('); | ||
| 7142 | try f.renderType(writer, switch (int_info.signedness) { | ||
| 7143 | .unsigned => Type.usize, | ||
| 7144 | .signed => Type.isize, | ||
| 7145 | }); | ||
| 7146 | try writer.writeByte(')'); | ||
| 7147 | } | ||
| 7148 | try f.writeCValue(writer, element, .Other); | ||
| 7197 | } | 7149 | } |
| 7198 | try f.writeCValue(writer, element, .Other); | ||
| 7199 | } | ||
| 7200 | |||
| 7201 | try writer.print(", {}", .{ | ||
| 7202 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), | ||
| 7203 | }); | ||
| 7204 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | ||
| 7205 | try writer.writeByte(')'); | ||
| 7206 | if (!empty) try writer.writeByte(')'); | ||
| 7207 | 7150 | ||
| 7208 | bit_offset += field_ty.bitSize(zcu); | 7151 | try writer.print(", {}", .{ |
| 7209 | empty = false; | 7152 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), |
| 7210 | } | 7153 | }); |
| 7154 | try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits); | ||
| 7155 | try writer.writeByte(')'); | ||
| 7156 | if (!empty) try writer.writeByte(')'); | ||
| 7211 | 7157 | ||
| 7212 | try writer.writeAll(";\n"); | 7158 | bit_offset += field_ty.bitSize(zcu); |
| 7213 | }, | 7159 | empty = false; |
| 7160 | } | ||
| 7161 | try writer.writeAll(";\n"); | ||
| 7162 | }, | ||
| 7163 | } | ||
| 7164 | }, | ||
| 7165 | .anon_struct_type => |anon_struct_info| for (0..anon_struct_info.types.len) |field_index| { | ||
| 7166 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | ||
| 7167 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); | ||
| 7168 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 7169 | |||
| 7170 | const a = try Assignment.start(f, writer, field_ty); | ||
| 7171 | try f.writeCValueMember(writer, local, if (anon_struct_info.fieldName(ip, field_index).unwrap()) |field_name| | ||
| 7172 | .{ .identifier = ip.stringToSlice(field_name) } | ||
| 7173 | else | ||
| 7174 | .{ .field = field_index }); | ||
| 7175 | try a.assign(f, writer); | ||
| 7176 | try f.writeCValue(writer, resolved_elements[field_index], .Other); | ||
| 7177 | try a.end(f, writer); | ||
| 7214 | }, | 7178 | }, |
| 7215 | else => unreachable, | 7179 | else => unreachable, |
| 7216 | } | 7180 | } |
| ... | @@ -7225,15 +7189,15 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7225,15 +7189,15 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7225 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; | 7189 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 7226 | 7190 | ||
| 7227 | const union_ty = f.typeOfIndex(inst); | 7191 | const union_ty = f.typeOfIndex(inst); |
| 7228 | const union_obj = zcu.typeToUnion(union_ty).?; | 7192 | const loaded_union = ip.loadUnionType(union_ty.toIntern()); |
| 7229 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | 7193 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; |
| 7230 | const payload_ty = f.typeOf(extra.init); | 7194 | const payload_ty = f.typeOf(extra.init); |
| 7231 | const payload = try f.resolveInst(extra.init); | 7195 | const payload = try f.resolveInst(extra.init); |
| 7232 | try reap(f, inst, &.{extra.init}); | 7196 | try reap(f, inst, &.{extra.init}); |
| 7233 | 7197 | ||
| 7234 | const writer = f.object.writer(); | 7198 | const writer = f.object.writer(); |
| 7235 | const local = try f.allocLocal(inst, union_ty); | 7199 | const local = try f.allocLocal(inst, union_ty); |
| 7236 | if (union_obj.getLayout(ip) == .@"packed") { | 7200 | if (loaded_union.getLayout(ip) == .@"packed") { |
| 7237 | try f.writeCValue(writer, local, .Other); | 7201 | try f.writeCValue(writer, local, .Other); |
| 7238 | try writer.writeAll(" = "); | 7202 | try writer.writeAll(" = "); |
| 7239 | try f.writeCValue(writer, payload, .Initializer); | 7203 | try f.writeCValue(writer, payload, .Initializer); |
| ... | @@ -7465,16 +7429,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -7465,16 +7429,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7465 | const inst_ty = f.typeOfIndex(inst); | 7429 | const inst_ty = f.typeOfIndex(inst); |
| 7466 | const decl_index = f.object.dg.pass.decl; | 7430 | const decl_index = f.object.dg.pass.decl; |
| 7467 | const decl = zcu.declPtr(decl_index); | 7431 | const decl = zcu.declPtr(decl_index); |
| 7468 | const fn_cty = try f.typeToCType(decl.typeOf(zcu), .complete); | 7432 | const function_ctype = try f.ctypeFromType(decl.typeOf(zcu), .complete); |
| 7469 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; | 7433 | const params_len = function_ctype.info(&f.object.dg.ctype_pool).function.param_ctypes.len; |
| 7470 | 7434 | ||
| 7471 | const writer = f.object.writer(); | 7435 | const writer = f.object.writer(); |
| 7472 | const local = try f.allocLocal(inst, inst_ty); | 7436 | const local = try f.allocLocal(inst, inst_ty); |
| 7473 | try writer.writeAll("va_start(*(va_list *)&"); | 7437 | try writer.writeAll("va_start(*(va_list *)&"); |
| 7474 | try f.writeCValue(writer, local, .Other); | 7438 | try f.writeCValue(writer, local, .Other); |
| 7475 | if (param_len > 0) { | 7439 | if (params_len > 0) { |
| 7476 | try writer.writeAll(", "); | 7440 | try writer.writeAll(", "); |
| 7477 | try f.writeCValue(writer, .{ .arg = param_len - 1 }, .FunctionArgument); | 7441 | try f.writeCValue(writer, .{ .arg = params_len - 1 }, .FunctionArgument); |
| 7478 | } | 7442 | } |
| 7479 | try writer.writeAll(");\n"); | 7443 | try writer.writeAll(");\n"); |
| 7480 | return local; | 7444 | return local; |
| ... | @@ -7823,7 +7787,7 @@ const FormatIntLiteralContext = struct { | ... | @@ -7823,7 +7787,7 @@ const FormatIntLiteralContext = struct { |
| 7823 | dg: *DeclGen, | 7787 | dg: *DeclGen, |
| 7824 | int_info: InternPool.Key.IntType, | 7788 | int_info: InternPool.Key.IntType, |
| 7825 | kind: CType.Kind, | 7789 | kind: CType.Kind, |
| 7826 | cty: CType, | 7790 | ctype: CType, |
| 7827 | val: Value, | 7791 | val: Value, |
| 7828 | }; | 7792 | }; |
| 7829 | fn formatIntLiteral( | 7793 | fn formatIntLiteral( |
| ... | @@ -7834,6 +7798,7 @@ fn formatIntLiteral( | ... | @@ -7834,6 +7798,7 @@ fn formatIntLiteral( |
| 7834 | ) @TypeOf(writer).Error!void { | 7798 | ) @TypeOf(writer).Error!void { |
| 7835 | const zcu = data.dg.zcu; | 7799 | const zcu = data.dg.zcu; |
| 7836 | const target = &data.dg.mod.resolved_target.result; | 7800 | const target = &data.dg.mod.resolved_target.result; |
| 7801 | const ctype_pool = &data.dg.ctype_pool; | ||
| 7837 | 7802 | ||
| 7838 | const ExpectedContents = struct { | 7803 | const ExpectedContents = struct { |
| 7839 | const base = 10; | 7804 | const base = 10; |
| ... | @@ -7867,7 +7832,7 @@ fn formatIntLiteral( | ... | @@ -7867,7 +7832,7 @@ fn formatIntLiteral( |
| 7867 | } else data.val.toBigInt(&int_buf, zcu); | 7832 | } else data.val.toBigInt(&int_buf, zcu); |
| 7868 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); | 7833 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); |
| 7869 | 7834 | ||
| 7870 | const c_bits: usize = @intCast(data.cty.byteSize(data.dg.ctypes.set, data.dg.mod) * 8); | 7835 | const c_bits: usize = @intCast(data.ctype.byteSize(ctype_pool, data.dg.mod) * 8); |
| 7871 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; | 7836 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 7872 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | 7837 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 7873 | 7838 | ||
| ... | @@ -7879,45 +7844,45 @@ fn formatIntLiteral( | ... | @@ -7879,45 +7844,45 @@ fn formatIntLiteral( |
| 7879 | defer allocator.free(wrap.limbs); | 7844 | defer allocator.free(wrap.limbs); |
| 7880 | 7845 | ||
| 7881 | const c_limb_info: struct { | 7846 | const c_limb_info: struct { |
| 7882 | cty: CType, | 7847 | ctype: CType, |
| 7883 | count: usize, | 7848 | count: usize, |
| 7884 | endian: std.builtin.Endian, | 7849 | endian: std.builtin.Endian, |
| 7885 | homogeneous: bool, | 7850 | homogeneous: bool, |
| 7886 | } = switch (data.cty.tag()) { | 7851 | } = switch (data.ctype.info(ctype_pool)) { |
| 7887 | else => .{ | 7852 | .basic => |basic_info| switch (basic_info) { |
| 7888 | .cty = CType.initTag(.void), | 7853 | else => .{ |
| 7889 | .count = 1, | 7854 | .ctype = .{ .index = .void }, |
| 7890 | .endian = .little, | 7855 | .count = 1, |
| 7891 | .homogeneous = true, | 7856 | .endian = .little, |
| 7892 | }, | ||
| 7893 | .zig_u128, .zig_i128 => .{ | ||
| 7894 | .cty = CType.initTag(.uint64_t), | ||
| 7895 | .count = 2, | ||
| 7896 | .endian = .big, | ||
| 7897 | .homogeneous = false, | ||
| 7898 | }, | ||
| 7899 | .array => info: { | ||
| 7900 | const array_data = data.cty.castTag(.array).?.data; | ||
| 7901 | break :info .{ | ||
| 7902 | .cty = data.dg.indexToCType(array_data.elem_type), | ||
| 7903 | .count = @as(usize, @intCast(array_data.len)), | ||
| 7904 | .endian = target.cpu.arch.endian(), | ||
| 7905 | .homogeneous = true, | 7857 | .homogeneous = true, |
| 7906 | }; | 7858 | }, |
| 7859 | .zig_u128, .zig_i128 => .{ | ||
| 7860 | .ctype = .{ .index = .uint64_t }, | ||
| 7861 | .count = 2, | ||
| 7862 | .endian = .big, | ||
| 7863 | .homogeneous = false, | ||
| 7864 | }, | ||
| 7865 | }, | ||
| 7866 | .array => |array_info| .{ | ||
| 7867 | .ctype = array_info.elem_ctype, | ||
| 7868 | .count = @intCast(array_info.len), | ||
| 7869 | .endian = target.cpu.arch.endian(), | ||
| 7870 | .homogeneous = true, | ||
| 7907 | }, | 7871 | }, |
| 7872 | else => unreachable, | ||
| 7908 | }; | 7873 | }; |
| 7909 | if (c_limb_info.count == 1) { | 7874 | if (c_limb_info.count == 1) { |
| 7910 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or | 7875 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 7911 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) | 7876 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 7912 | return writer.print("{s}_{s}", .{ | 7877 | return writer.print("{s}_{s}", .{ |
| 7913 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ | 7878 | data.ctype.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ |
| 7914 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, | 7879 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 7915 | }), | 7880 | }), |
| 7916 | if (int.positive) "MAX" else "MIN", | 7881 | if (int.positive) "MAX" else "MIN", |
| 7917 | }); | 7882 | }); |
| 7918 | 7883 | ||
| 7919 | if (!int.positive) try writer.writeByte('-'); | 7884 | if (!int.positive) try writer.writeByte('-'); |
| 7920 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7885 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); |
| 7921 | 7886 | ||
| 7922 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { | 7887 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { |
| 7923 | 0 => .{ .base = 10 }, | 7888 | 0 => .{ .base = 10 }, |
| ... | @@ -7948,7 +7913,7 @@ fn formatIntLiteral( | ... | @@ -7948,7 +7913,7 @@ fn formatIntLiteral( |
| 7948 | defer allocator.free(string); | 7913 | defer allocator.free(string); |
| 7949 | try writer.writeAll(string); | 7914 | try writer.writeAll(string); |
| 7950 | } else { | 7915 | } else { |
| 7951 | try data.cty.renderLiteralPrefix(writer, data.kind); | 7916 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); |
| 7952 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); | 7917 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); |
| 7953 | @memset(wrap.limbs[wrap.len..], 0); | 7918 | @memset(wrap.limbs[wrap.len..], 0); |
| 7954 | wrap.len = wrap.limbs.len; | 7919 | wrap.len = wrap.limbs.len; |
| ... | @@ -7958,7 +7923,7 @@ fn formatIntLiteral( | ... | @@ -7958,7 +7923,7 @@ fn formatIntLiteral( |
| 7958 | .signedness = undefined, | 7923 | .signedness = undefined, |
| 7959 | .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))), | 7924 | .bits = @as(u16, @intCast(@divExact(c_bits, c_limb_info.count))), |
| 7960 | }; | 7925 | }; |
| 7961 | var c_limb_cty: CType = undefined; | 7926 | var c_limb_ctype: CType = undefined; |
| 7962 | 7927 | ||
| 7963 | var limb_offset: usize = 0; | 7928 | var limb_offset: usize = 0; |
| 7964 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; | 7929 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; |
| ... | @@ -7979,7 +7944,7 @@ fn formatIntLiteral( | ... | @@ -7979,7 +7944,7 @@ fn formatIntLiteral( |
| 7979 | { | 7944 | { |
| 7980 | // most significant limb is actually signed | 7945 | // most significant limb is actually signed |
| 7981 | c_limb_int_info.signedness = .signed; | 7946 | c_limb_int_info.signedness = .signed; |
| 7982 | c_limb_cty = c_limb_info.cty.toSigned(); | 7947 | c_limb_ctype = c_limb_info.ctype.toSigned(); |
| 7983 | 7948 | ||
| 7984 | c_limb_mut.positive = wrap.positive; | 7949 | c_limb_mut.positive = wrap.positive; |
| 7985 | c_limb_mut.truncate( | 7950 | c_limb_mut.truncate( |
| ... | @@ -7989,7 +7954,7 @@ fn formatIntLiteral( | ... | @@ -7989,7 +7954,7 @@ fn formatIntLiteral( |
| 7989 | ); | 7954 | ); |
| 7990 | } else { | 7955 | } else { |
| 7991 | c_limb_int_info.signedness = .unsigned; | 7956 | c_limb_int_info.signedness = .unsigned; |
| 7992 | c_limb_cty = c_limb_info.cty; | 7957 | c_limb_ctype = c_limb_info.ctype; |
| 7993 | } | 7958 | } |
| 7994 | 7959 | ||
| 7995 | if (limb_offset > 0) try writer.writeAll(", "); | 7960 | if (limb_offset > 0) try writer.writeAll(", "); |
| ... | @@ -7997,12 +7962,12 @@ fn formatIntLiteral( | ... | @@ -7997,12 +7962,12 @@ fn formatIntLiteral( |
| 7997 | .dg = data.dg, | 7962 | .dg = data.dg, |
| 7998 | .int_info = c_limb_int_info, | 7963 | .int_info = c_limb_int_info, |
| 7999 | .kind = data.kind, | 7964 | .kind = data.kind, |
| 8000 | .cty = c_limb_cty, | 7965 | .ctype = c_limb_ctype, |
| 8001 | .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()), | 7966 | .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()), |
| 8002 | }, fmt, options, writer); | 7967 | }, fmt, options, writer); |
| 8003 | } | 7968 | } |
| 8004 | } | 7969 | } |
| 8005 | try data.cty.renderLiteralSuffix(writer); | 7970 | try data.ctype.renderLiteralSuffix(writer, ctype_pool); |
| 8006 | } | 7971 | } |
| 8007 | 7972 | ||
| 8008 | const Materialize = struct { | 7973 | const Materialize = struct { |
| ... | @@ -8045,10 +8010,10 @@ const Materialize = struct { | ... | @@ -8045,10 +8010,10 @@ const Materialize = struct { |
| 8045 | }; | 8010 | }; |
| 8046 | 8011 | ||
| 8047 | const Assignment = struct { | 8012 | const Assignment = struct { |
| 8048 | cty: CType.Index, | 8013 | ctype: CType, |
| 8049 | 8014 | ||
| 8050 | pub fn init(f: *Function, ty: Type) !Assignment { | 8015 | pub fn init(f: *Function, ty: Type) !Assignment { |
| 8051 | return .{ .cty = try f.typeToIndex(ty, .complete) }; | 8016 | return .{ .ctype = try f.ctypeFromType(ty, .complete) }; |
| 8052 | } | 8017 | } |
| 8053 | 8018 | ||
| 8054 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { | 8019 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { |
| ... | @@ -8076,7 +8041,7 @@ const Assignment = struct { | ... | @@ -8076,7 +8041,7 @@ const Assignment = struct { |
| 8076 | .assign => {}, | 8041 | .assign => {}, |
| 8077 | .memcpy => { | 8042 | .memcpy => { |
| 8078 | try writer.writeAll(", sizeof("); | 8043 | try writer.writeAll(", sizeof("); |
| 8079 | try f.renderCType(writer, self.cty); | 8044 | try f.renderCType(writer, self.ctype); |
| 8080 | try writer.writeAll("))"); | 8045 | try writer.writeAll("))"); |
| 8081 | }, | 8046 | }, |
| 8082 | } | 8047 | } |
| ... | @@ -8084,7 +8049,7 @@ const Assignment = struct { | ... | @@ -8084,7 +8049,7 @@ const Assignment = struct { |
| 8084 | } | 8049 | } |
| 8085 | 8050 | ||
| 8086 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { | 8051 | fn strategy(self: Assignment, f: *Function) enum { assign, memcpy } { |
| 8087 | return switch (f.indexToCType(self.cty).tag()) { | 8052 | return switch (self.ctype.info(&f.object.dg.ctype_pool)) { |
| 8088 | else => .assign, | 8053 | else => .assign, |
| 8089 | .array, .vector => .memcpy, | 8054 | .array, .vector => .memcpy, |
| 8090 | }; | 8055 | }; |
| ... | @@ -8129,28 +8094,6 @@ const Vectorize = struct { | ... | @@ -8129,28 +8094,6 @@ const Vectorize = struct { |
| 8129 | } | 8094 | } |
| 8130 | }; | 8095 | }; |
| 8131 | 8096 | ||
| 8132 | fn lowerFnRetTy(ret_ty: Type, zcu: *Zcu) !Type { | ||
| 8133 | if (ret_ty.toIntern() == .noreturn_type) return Type.noreturn; | ||
| 8134 | |||
| 8135 | if (lowersToArray(ret_ty, zcu)) { | ||
| 8136 | const gpa = zcu.gpa; | ||
| 8137 | const ip = &zcu.intern_pool; | ||
| 8138 | const names = [1]InternPool.NullTerminatedString{ | ||
| 8139 | try ip.getOrPutString(gpa, "array"), | ||
| 8140 | }; | ||
| 8141 | const types = [1]InternPool.Index{ret_ty.toIntern()}; | ||
| 8142 | const values = [1]InternPool.Index{.none}; | ||
| 8143 | const interned = try ip.getAnonStructType(gpa, .{ | ||
| 8144 | .names = &names, | ||
| 8145 | .types = &types, | ||
| 8146 | .values = &values, | ||
| 8147 | }); | ||
| 8148 | return Type.fromInterned(interned); | ||
| 8149 | } | ||
| 8150 | |||
| 8151 | return if (ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) ret_ty else Type.void; | ||
| 8152 | } | ||
| 8153 | |||
| 8154 | fn lowersToArray(ty: Type, zcu: *Zcu) bool { | 8097 | fn lowersToArray(ty: Type, zcu: *Zcu) bool { |
| 8155 | return switch (ty.zigTypeTag(zcu)) { | 8098 | return switch (ty.zigTypeTag(zcu)) { |
| 8156 | .Array, .Vector => return true, | 8099 | .Array, .Vector => return true, |
src/codegen/c/Type.zig created+2472| ... | @@ -0,0 +1,2472 @@ | ||
| 1 | index: CType.Index, | ||
| 2 | |||
| 3 | pub fn fromPoolIndex(pool_index: usize) CType { | ||
| 4 | return .{ .index = @enumFromInt(CType.Index.first_pool_index + pool_index) }; | ||
| 5 | } | ||
| 6 | |||
| 7 | pub fn toPoolIndex(ctype: CType) ?u32 { | ||
| 8 | const pool_index, const is_basic = | ||
| 9 | @subWithOverflow(@intFromEnum(ctype.index), CType.Index.first_pool_index); | ||
| 10 | return switch (is_basic) { | ||
| 11 | 0 => pool_index, | ||
| 12 | 1 => null, | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | |||
| 16 | pub fn eql(lhs: CType, rhs: CType) bool { | ||
| 17 | return lhs.index == rhs.index; | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn isBool(ctype: CType) bool { | ||
| 21 | return switch (ctype.index) { | ||
| 22 | ._Bool, .bool => true, | ||
| 23 | else => false, | ||
| 24 | }; | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn isInteger(ctype: CType) bool { | ||
| 28 | return switch (ctype.index) { | ||
| 29 | .char, | ||
| 30 | .@"signed char", | ||
| 31 | .short, | ||
| 32 | .int, | ||
| 33 | .long, | ||
| 34 | .@"long long", | ||
| 35 | .@"unsigned char", | ||
| 36 | .@"unsigned short", | ||
| 37 | .@"unsigned int", | ||
| 38 | .@"unsigned long", | ||
| 39 | .@"unsigned long long", | ||
| 40 | .size_t, | ||
| 41 | .ptrdiff_t, | ||
| 42 | .uint8_t, | ||
| 43 | .int8_t, | ||
| 44 | .uint16_t, | ||
| 45 | .int16_t, | ||
| 46 | .uint32_t, | ||
| 47 | .int32_t, | ||
| 48 | .uint64_t, | ||
| 49 | .int64_t, | ||
| 50 | .uintptr_t, | ||
| 51 | .intptr_t, | ||
| 52 | .zig_u128, | ||
| 53 | .zig_i128, | ||
| 54 | => true, | ||
| 55 | else => false, | ||
| 56 | }; | ||
| 57 | } | ||
| 58 | |||
| 59 | pub fn signedness(ctype: CType, mod: *Module) std.builtin.Signedness { | ||
| 60 | return switch (ctype.index) { | ||
| 61 | .char => mod.resolved_target.result.charSignedness(), | ||
| 62 | .@"signed char", | ||
| 63 | .short, | ||
| 64 | .int, | ||
| 65 | .long, | ||
| 66 | .@"long long", | ||
| 67 | .ptrdiff_t, | ||
| 68 | .int8_t, | ||
| 69 | .int16_t, | ||
| 70 | .int32_t, | ||
| 71 | .int64_t, | ||
| 72 | .intptr_t, | ||
| 73 | .zig_i128, | ||
| 74 | => .signed, | ||
| 75 | .@"unsigned char", | ||
| 76 | .@"unsigned short", | ||
| 77 | .@"unsigned int", | ||
| 78 | .@"unsigned long", | ||
| 79 | .@"unsigned long long", | ||
| 80 | .size_t, | ||
| 81 | .uint8_t, | ||
| 82 | .uint16_t, | ||
| 83 | .uint32_t, | ||
| 84 | .uint64_t, | ||
| 85 | .uintptr_t, | ||
| 86 | .zig_u128, | ||
| 87 | => .unsigned, | ||
| 88 | else => unreachable, | ||
| 89 | }; | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn isFloat(ctype: CType) bool { | ||
| 93 | return switch (ctype.index) { | ||
| 94 | .float, | ||
| 95 | .double, | ||
| 96 | .@"long double", | ||
| 97 | .zig_f16, | ||
| 98 | .zig_f32, | ||
| 99 | .zig_f64, | ||
| 100 | .zig_f80, | ||
| 101 | .zig_f128, | ||
| 102 | .zig_c_longdouble, | ||
| 103 | => true, | ||
| 104 | else => false, | ||
| 105 | }; | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn toSigned(ctype: CType) CType { | ||
| 109 | return switch (ctype.index) { | ||
| 110 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"signed char" }, | ||
| 111 | .short, .@"unsigned short" => .{ .index = .short }, | ||
| 112 | .int, .@"unsigned int" => .{ .index = .int }, | ||
| 113 | .long, .@"unsigned long" => .{ .index = .long }, | ||
| 114 | .@"long long", .@"unsigned long long" => .{ .index = .@"long long" }, | ||
| 115 | .size_t, .ptrdiff_t => .{ .index = .ptrdiff_t }, | ||
| 116 | .uint8_t, .int8_t => .{ .index = .int8_t }, | ||
| 117 | .uint16_t, .int16_t => .{ .index = .int16_t }, | ||
| 118 | .uint32_t, .int32_t => .{ .index = .int32_t }, | ||
| 119 | .uint64_t, .int64_t => .{ .index = .int64_t }, | ||
| 120 | .uintptr_t, .intptr_t => .{ .index = .intptr_t }, | ||
| 121 | .zig_u128, .zig_i128 => .{ .index = .zig_i128 }, | ||
| 122 | .float, | ||
| 123 | .double, | ||
| 124 | .@"long double", | ||
| 125 | .zig_f16, | ||
| 126 | .zig_f32, | ||
| 127 | .zig_f80, | ||
| 128 | .zig_f128, | ||
| 129 | .zig_c_longdouble, | ||
| 130 | => ctype, | ||
| 131 | else => unreachable, | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | pub fn toUnsigned(ctype: CType) CType { | ||
| 136 | return switch (ctype.index) { | ||
| 137 | .char, .@"signed char", .@"unsigned char" => .{ .index = .@"unsigned char" }, | ||
| 138 | .short, .@"unsigned short" => .{ .index = .@"unsigned short" }, | ||
| 139 | .int, .@"unsigned int" => .{ .index = .@"unsigned int" }, | ||
| 140 | .long, .@"unsigned long" => .{ .index = .@"unsigned long" }, | ||
| 141 | .@"long long", .@"unsigned long long" => .{ .index = .@"unsigned long long" }, | ||
| 142 | .size_t, .ptrdiff_t => .{ .index = .size_t }, | ||
| 143 | .uint8_t, .int8_t => .{ .index = .uint8_t }, | ||
| 144 | .uint16_t, .int16_t => .{ .index = .uint16_t }, | ||
| 145 | .uint32_t, .int32_t => .{ .index = .uint32_t }, | ||
| 146 | .uint64_t, .int64_t => .{ .index = .uint64_t }, | ||
| 147 | .uintptr_t, .intptr_t => .{ .index = .uintptr_t }, | ||
| 148 | .zig_u128, .zig_i128 => .{ .index = .zig_u128 }, | ||
| 149 | else => unreachable, | ||
| 150 | }; | ||
| 151 | } | ||
| 152 | |||
| 153 | pub fn toSignedness(ctype: CType, s: std.builtin.Signedness) CType { | ||
| 154 | return switch (s) { | ||
| 155 | .unsigned => ctype.toUnsigned(), | ||
| 156 | .signed => ctype.toSigned(), | ||
| 157 | }; | ||
| 158 | } | ||
| 159 | |||
| 160 | pub fn getStandardDefineAbbrev(ctype: CType) ?[]const u8 { | ||
| 161 | return switch (ctype.index) { | ||
| 162 | .char => "CHAR", | ||
| 163 | .@"signed char" => "SCHAR", | ||
| 164 | .short => "SHRT", | ||
| 165 | .int => "INT", | ||
| 166 | .long => "LONG", | ||
| 167 | .@"long long" => "LLONG", | ||
| 168 | .@"unsigned char" => "UCHAR", | ||
| 169 | .@"unsigned short" => "USHRT", | ||
| 170 | .@"unsigned int" => "UINT", | ||
| 171 | .@"unsigned long" => "ULONG", | ||
| 172 | .@"unsigned long long" => "ULLONG", | ||
| 173 | .float => "FLT", | ||
| 174 | .double => "DBL", | ||
| 175 | .@"long double" => "LDBL", | ||
| 176 | .size_t => "SIZE", | ||
| 177 | .ptrdiff_t => "PTRDIFF", | ||
| 178 | .uint8_t => "UINT8", | ||
| 179 | .int8_t => "INT8", | ||
| 180 | .uint16_t => "UINT16", | ||
| 181 | .int16_t => "INT16", | ||
| 182 | .uint32_t => "UINT32", | ||
| 183 | .int32_t => "INT32", | ||
| 184 | .uint64_t => "UINT64", | ||
| 185 | .int64_t => "INT64", | ||
| 186 | .uintptr_t => "UINTPTR", | ||
| 187 | .intptr_t => "INTPTR", | ||
| 188 | else => null, | ||
| 189 | }; | ||
| 190 | } | ||
| 191 | |||
| 192 | pub fn renderLiteralPrefix(ctype: CType, writer: anytype, kind: Kind, pool: *const Pool) @TypeOf(writer).Error!void { | ||
| 193 | switch (ctype.info(pool)) { | ||
| 194 | .basic => |basic_info| switch (basic_info) { | ||
| 195 | .void => unreachable, | ||
| 196 | ._Bool, | ||
| 197 | .char, | ||
| 198 | .@"signed char", | ||
| 199 | .short, | ||
| 200 | .@"unsigned short", | ||
| 201 | .bool, | ||
| 202 | .size_t, | ||
| 203 | .ptrdiff_t, | ||
| 204 | .uintptr_t, | ||
| 205 | .intptr_t, | ||
| 206 | => switch (kind) { | ||
| 207 | else => try writer.print("({s})", .{@tagName(basic_info)}), | ||
| 208 | .global => {}, | ||
| 209 | }, | ||
| 210 | .int, | ||
| 211 | .long, | ||
| 212 | .@"long long", | ||
| 213 | .@"unsigned char", | ||
| 214 | .@"unsigned int", | ||
| 215 | .@"unsigned long", | ||
| 216 | .@"unsigned long long", | ||
| 217 | .float, | ||
| 218 | .double, | ||
| 219 | .@"long double", | ||
| 220 | => {}, | ||
| 221 | .uint8_t, | ||
| 222 | .int8_t, | ||
| 223 | .uint16_t, | ||
| 224 | .int16_t, | ||
| 225 | .uint32_t, | ||
| 226 | .int32_t, | ||
| 227 | .uint64_t, | ||
| 228 | .int64_t, | ||
| 229 | => try writer.print("{s}_C(", .{ctype.getStandardDefineAbbrev().?}), | ||
| 230 | .zig_u128, | ||
| 231 | .zig_i128, | ||
| 232 | .zig_f16, | ||
| 233 | .zig_f32, | ||
| 234 | .zig_f64, | ||
| 235 | .zig_f80, | ||
| 236 | .zig_f128, | ||
| 237 | .zig_c_longdouble, | ||
| 238 | => try writer.print("zig_{s}_{s}(", .{ | ||
| 239 | switch (kind) { | ||
| 240 | else => "make", | ||
| 241 | .global => "init", | ||
| 242 | }, | ||
| 243 | @tagName(basic_info)["zig_".len..], | ||
| 244 | }), | ||
| 245 | .va_list => unreachable, | ||
| 246 | _ => unreachable, | ||
| 247 | }, | ||
| 248 | .array, .vector => try writer.writeByte('{'), | ||
| 249 | else => unreachable, | ||
| 250 | } | ||
| 251 | } | ||
| 252 | |||
| 253 | pub fn renderLiteralSuffix(ctype: CType, writer: anytype, pool: *const Pool) @TypeOf(writer).Error!void { | ||
| 254 | switch (ctype.info(pool)) { | ||
| 255 | .basic => |basic_info| switch (basic_info) { | ||
| 256 | .void => unreachable, | ||
| 257 | ._Bool => {}, | ||
| 258 | .char, | ||
| 259 | .@"signed char", | ||
| 260 | .short, | ||
| 261 | .int, | ||
| 262 | => {}, | ||
| 263 | .long => try writer.writeByte('l'), | ||
| 264 | .@"long long" => try writer.writeAll("ll"), | ||
| 265 | .@"unsigned char", | ||
| 266 | .@"unsigned short", | ||
| 267 | .@"unsigned int", | ||
| 268 | => try writer.writeByte('u'), | ||
| 269 | .@"unsigned long", | ||
| 270 | .size_t, | ||
| 271 | .uintptr_t, | ||
| 272 | => try writer.writeAll("ul"), | ||
| 273 | .@"unsigned long long" => try writer.writeAll("ull"), | ||
| 274 | .float => try writer.writeByte('f'), | ||
| 275 | .double => {}, | ||
| 276 | .@"long double" => try writer.writeByte('l'), | ||
| 277 | .bool, | ||
| 278 | .ptrdiff_t, | ||
| 279 | .intptr_t, | ||
| 280 | => {}, | ||
| 281 | .uint8_t, | ||
| 282 | .int8_t, | ||
| 283 | .uint16_t, | ||
| 284 | .int16_t, | ||
| 285 | .uint32_t, | ||
| 286 | .int32_t, | ||
| 287 | .uint64_t, | ||
| 288 | .int64_t, | ||
| 289 | .zig_u128, | ||
| 290 | .zig_i128, | ||
| 291 | .zig_f16, | ||
| 292 | .zig_f32, | ||
| 293 | .zig_f64, | ||
| 294 | .zig_f80, | ||
| 295 | .zig_f128, | ||
| 296 | .zig_c_longdouble, | ||
| 297 | => try writer.writeByte(')'), | ||
| 298 | .va_list => unreachable, | ||
| 299 | _ => unreachable, | ||
| 300 | }, | ||
| 301 | .array, .vector => try writer.writeByte('}'), | ||
| 302 | else => unreachable, | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 306 | pub fn floatActiveBits(ctype: CType, mod: *Module) u16 { | ||
| 307 | const target = &mod.resolved_target.result; | ||
| 308 | return switch (ctype.index) { | ||
| 309 | .float => target.c_type_bit_size(.float), | ||
| 310 | .double => target.c_type_bit_size(.double), | ||
| 311 | .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble), | ||
| 312 | .zig_f16 => 16, | ||
| 313 | .zig_f32 => 32, | ||
| 314 | .zig_f64 => 64, | ||
| 315 | .zig_f80 => 80, | ||
| 316 | .zig_f128 => 128, | ||
| 317 | else => unreachable, | ||
| 318 | }; | ||
| 319 | } | ||
| 320 | |||
| 321 | pub fn byteSize(ctype: CType, pool: *const Pool, mod: *Module) u64 { | ||
| 322 | const target = &mod.resolved_target.result; | ||
| 323 | return switch (ctype.info(pool)) { | ||
| 324 | .basic => |basic_info| switch (basic_info) { | ||
| 325 | .void => 0, | ||
| 326 | .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, | ||
| 327 | .short => target.c_type_byte_size(.short), | ||
| 328 | .int => target.c_type_byte_size(.int), | ||
| 329 | .long => target.c_type_byte_size(.long), | ||
| 330 | .@"long long" => target.c_type_byte_size(.longlong), | ||
| 331 | .@"unsigned short" => target.c_type_byte_size(.ushort), | ||
| 332 | .@"unsigned int" => target.c_type_byte_size(.uint), | ||
| 333 | .@"unsigned long" => target.c_type_byte_size(.ulong), | ||
| 334 | .@"unsigned long long" => target.c_type_byte_size(.ulonglong), | ||
| 335 | .float => target.c_type_byte_size(.float), | ||
| 336 | .double => target.c_type_byte_size(.double), | ||
| 337 | .@"long double" => target.c_type_byte_size(.longdouble), | ||
| 338 | .size_t, | ||
| 339 | .ptrdiff_t, | ||
| 340 | .uintptr_t, | ||
| 341 | .intptr_t, | ||
| 342 | => @divExact(target.ptrBitWidth(), 8), | ||
| 343 | .uint16_t, .int16_t, .zig_f16 => 2, | ||
| 344 | .uint32_t, .int32_t, .zig_f32 => 4, | ||
| 345 | .uint64_t, .int64_t, .zig_f64 => 8, | ||
| 346 | .zig_u128, .zig_i128, .zig_f128 => 16, | ||
| 347 | .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80) | ||
| 348 | target.c_type_byte_size(.longdouble) | ||
| 349 | else | ||
| 350 | 16, | ||
| 351 | .zig_c_longdouble => target.c_type_byte_size(.longdouble), | ||
| 352 | .va_list => unreachable, | ||
| 353 | _ => unreachable, | ||
| 354 | }, | ||
| 355 | .pointer => @divExact(target.ptrBitWidth(), 8), | ||
| 356 | .array, .vector => |sequence_info| sequence_info.elem_ctype.byteSize(pool, mod) * sequence_info.len, | ||
| 357 | else => unreachable, | ||
| 358 | }; | ||
| 359 | } | ||
| 360 | |||
| 361 | pub fn info(ctype: CType, pool: *const Pool) Info { | ||
| 362 | const pool_index = ctype.toPoolIndex() orelse return .{ .basic = ctype.index }; | ||
| 363 | const item = pool.items.get(pool_index); | ||
| 364 | switch (item.tag) { | ||
| 365 | .basic => unreachable, | ||
| 366 | .pointer => return .{ .pointer = .{ | ||
| 367 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 368 | } }, | ||
| 369 | .pointer_const => return .{ .pointer = .{ | ||
| 370 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 371 | .@"const" = true, | ||
| 372 | } }, | ||
| 373 | .pointer_volatile => return .{ .pointer = .{ | ||
| 374 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 375 | .@"volatile" = true, | ||
| 376 | } }, | ||
| 377 | .pointer_const_volatile => return .{ .pointer = .{ | ||
| 378 | .elem_ctype = .{ .index = @enumFromInt(item.data) }, | ||
| 379 | .@"const" = true, | ||
| 380 | .@"volatile" = true, | ||
| 381 | } }, | ||
| 382 | .aligned => { | ||
| 383 | const extra = pool.getExtra(Pool.Aligned, item.data); | ||
| 384 | return .{ .aligned = .{ | ||
| 385 | .ctype = .{ .index = extra.ctype }, | ||
| 386 | .alignas = extra.flags.alignas, | ||
| 387 | } }; | ||
| 388 | }, | ||
| 389 | .array_small => { | ||
| 390 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | ||
| 391 | return .{ .array = .{ | ||
| 392 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 393 | .len = extra.len, | ||
| 394 | } }; | ||
| 395 | }, | ||
| 396 | .array_large => { | ||
| 397 | const extra = pool.getExtra(Pool.SequenceLarge, item.data); | ||
| 398 | return .{ .array = .{ | ||
| 399 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 400 | .len = extra.len(), | ||
| 401 | } }; | ||
| 402 | }, | ||
| 403 | .vector => { | ||
| 404 | const extra = pool.getExtra(Pool.SequenceSmall, item.data); | ||
| 405 | return .{ .vector = .{ | ||
| 406 | .elem_ctype = .{ .index = extra.elem_ctype }, | ||
| 407 | .len = extra.len, | ||
| 408 | } }; | ||
| 409 | }, | ||
| 410 | .fwd_decl_struct_anon => { | ||
| 411 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | ||
| 412 | return .{ .fwd_decl = .{ | ||
| 413 | .tag = .@"struct", | ||
| 414 | .name = .{ .anon = .{ | ||
| 415 | .extra_index = extra_trail.trail.extra_index, | ||
| 416 | .len = extra_trail.extra.fields_len, | ||
| 417 | } }, | ||
| 418 | } }; | ||
| 419 | }, | ||
| 420 | .fwd_decl_union_anon => { | ||
| 421 | const extra_trail = pool.getExtraTrail(Pool.FwdDeclAnon, item.data); | ||
| 422 | return .{ .fwd_decl = .{ | ||
| 423 | .tag = .@"union", | ||
| 424 | .name = .{ .anon = .{ | ||
| 425 | .extra_index = extra_trail.trail.extra_index, | ||
| 426 | .len = extra_trail.extra.fields_len, | ||
| 427 | } }, | ||
| 428 | } }; | ||
| 429 | }, | ||
| 430 | .fwd_decl_struct => return .{ .fwd_decl = .{ | ||
| 431 | .tag = .@"struct", | ||
| 432 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | ||
| 433 | } }, | ||
| 434 | .fwd_decl_union => return .{ .fwd_decl = .{ | ||
| 435 | .tag = .@"union", | ||
| 436 | .name = .{ .owner_decl = @enumFromInt(item.data) }, | ||
| 437 | } }, | ||
| 438 | .aggregate_struct_anon => { | ||
| 439 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 440 | return .{ .aggregate = .{ | ||
| 441 | .tag = .@"struct", | ||
| 442 | .name = .{ .anon = .{ | ||
| 443 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 444 | .id = extra_trail.extra.id, | ||
| 445 | } }, | ||
| 446 | .fields = .{ | ||
| 447 | .extra_index = extra_trail.trail.extra_index, | ||
| 448 | .len = extra_trail.extra.fields_len, | ||
| 449 | }, | ||
| 450 | } }; | ||
| 451 | }, | ||
| 452 | .aggregate_union_anon => { | ||
| 453 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 454 | return .{ .aggregate = .{ | ||
| 455 | .tag = .@"union", | ||
| 456 | .name = .{ .anon = .{ | ||
| 457 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 458 | .id = extra_trail.extra.id, | ||
| 459 | } }, | ||
| 460 | .fields = .{ | ||
| 461 | .extra_index = extra_trail.trail.extra_index, | ||
| 462 | .len = extra_trail.extra.fields_len, | ||
| 463 | }, | ||
| 464 | } }; | ||
| 465 | }, | ||
| 466 | .aggregate_struct_packed_anon => { | ||
| 467 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 468 | return .{ .aggregate = .{ | ||
| 469 | .tag = .@"struct", | ||
| 470 | .@"packed" = true, | ||
| 471 | .name = .{ .anon = .{ | ||
| 472 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 473 | .id = extra_trail.extra.id, | ||
| 474 | } }, | ||
| 475 | .fields = .{ | ||
| 476 | .extra_index = extra_trail.trail.extra_index, | ||
| 477 | .len = extra_trail.extra.fields_len, | ||
| 478 | }, | ||
| 479 | } }; | ||
| 480 | }, | ||
| 481 | .aggregate_union_packed_anon => { | ||
| 482 | const extra_trail = pool.getExtraTrail(Pool.AggregateAnon, item.data); | ||
| 483 | return .{ .aggregate = .{ | ||
| 484 | .tag = .@"union", | ||
| 485 | .@"packed" = true, | ||
| 486 | .name = .{ .anon = .{ | ||
| 487 | .owner_decl = extra_trail.extra.owner_decl, | ||
| 488 | .id = extra_trail.extra.id, | ||
| 489 | } }, | ||
| 490 | .fields = .{ | ||
| 491 | .extra_index = extra_trail.trail.extra_index, | ||
| 492 | .len = extra_trail.extra.fields_len, | ||
| 493 | }, | ||
| 494 | } }; | ||
| 495 | }, | ||
| 496 | .aggregate_struct => { | ||
| 497 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 498 | return .{ .aggregate = .{ | ||
| 499 | .tag = .@"struct", | ||
| 500 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 501 | .fields = .{ | ||
| 502 | .extra_index = extra_trail.trail.extra_index, | ||
| 503 | .len = extra_trail.extra.fields_len, | ||
| 504 | }, | ||
| 505 | } }; | ||
| 506 | }, | ||
| 507 | .aggregate_union => { | ||
| 508 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 509 | return .{ .aggregate = .{ | ||
| 510 | .tag = .@"union", | ||
| 511 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 512 | .fields = .{ | ||
| 513 | .extra_index = extra_trail.trail.extra_index, | ||
| 514 | .len = extra_trail.extra.fields_len, | ||
| 515 | }, | ||
| 516 | } }; | ||
| 517 | }, | ||
| 518 | .aggregate_struct_packed => { | ||
| 519 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 520 | return .{ .aggregate = .{ | ||
| 521 | .tag = .@"struct", | ||
| 522 | .@"packed" = true, | ||
| 523 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 524 | .fields = .{ | ||
| 525 | .extra_index = extra_trail.trail.extra_index, | ||
| 526 | .len = extra_trail.extra.fields_len, | ||
| 527 | }, | ||
| 528 | } }; | ||
| 529 | }, | ||
| 530 | .aggregate_union_packed => { | ||
| 531 | const extra_trail = pool.getExtraTrail(Pool.Aggregate, item.data); | ||
| 532 | return .{ .aggregate = .{ | ||
| 533 | .tag = .@"union", | ||
| 534 | .@"packed" = true, | ||
| 535 | .name = .{ .fwd_decl = .{ .index = extra_trail.extra.fwd_decl } }, | ||
| 536 | .fields = .{ | ||
| 537 | .extra_index = extra_trail.trail.extra_index, | ||
| 538 | .len = extra_trail.extra.fields_len, | ||
| 539 | }, | ||
| 540 | } }; | ||
| 541 | }, | ||
| 542 | .function => { | ||
| 543 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | ||
| 544 | return .{ .function = .{ | ||
| 545 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | ||
| 546 | .param_ctypes = .{ | ||
| 547 | .extra_index = extra_trail.trail.extra_index, | ||
| 548 | .len = extra_trail.extra.param_ctypes_len, | ||
| 549 | }, | ||
| 550 | .varargs = false, | ||
| 551 | } }; | ||
| 552 | }, | ||
| 553 | .function_varargs => { | ||
| 554 | const extra_trail = pool.getExtraTrail(Pool.Function, item.data); | ||
| 555 | return .{ .function = .{ | ||
| 556 | .return_ctype = .{ .index = extra_trail.extra.return_ctype }, | ||
| 557 | .param_ctypes = .{ | ||
| 558 | .extra_index = extra_trail.trail.extra_index, | ||
| 559 | .len = extra_trail.extra.param_ctypes_len, | ||
| 560 | }, | ||
| 561 | .varargs = true, | ||
| 562 | } }; | ||
| 563 | }, | ||
| 564 | } | ||
| 565 | } | ||
| 566 | |||
| 567 | pub fn hash(ctype: CType, pool: *const Pool) Pool.Map.Hash { | ||
| 568 | return if (ctype.toPoolIndex()) |pool_index| | ||
| 569 | pool.map.entries.items(.hash)[pool_index] | ||
| 570 | else | ||
| 571 | CType.Index.basic_hashes[@intFromEnum(ctype.index)]; | ||
| 572 | } | ||
| 573 | |||
| 574 | fn toForward(ctype: CType, pool: *Pool, allocator: std.mem.Allocator) !CType { | ||
| 575 | return switch (ctype.info(pool)) { | ||
| 576 | .basic, .pointer, .fwd_decl => ctype, | ||
| 577 | .aligned => |aligned_info| pool.getAligned(allocator, .{ | ||
| 578 | .ctype = try aligned_info.ctype.toForward(pool, allocator), | ||
| 579 | .alignas = aligned_info.alignas, | ||
| 580 | }), | ||
| 581 | .array => |array_info| pool.getArray(allocator, .{ | ||
| 582 | .elem_ctype = try array_info.elem_ctype.toForward(pool, allocator), | ||
| 583 | .len = array_info.len, | ||
| 584 | }), | ||
| 585 | .vector => |vector_info| pool.getVector(allocator, .{ | ||
| 586 | .elem_ctype = try vector_info.elem_ctype.toForward(pool, allocator), | ||
| 587 | .len = vector_info.len, | ||
| 588 | }), | ||
| 589 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | ||
| 590 | .anon => ctype, | ||
| 591 | .fwd_decl => |fwd_decl| fwd_decl, | ||
| 592 | }, | ||
| 593 | .function => unreachable, | ||
| 594 | }; | ||
| 595 | } | ||
| 596 | |||
| 597 | const Index = enum(u32) { | ||
| 598 | void, | ||
| 599 | |||
| 600 | // C basic types | ||
| 601 | char, | ||
| 602 | |||
| 603 | @"signed char", | ||
| 604 | short, | ||
| 605 | int, | ||
| 606 | long, | ||
| 607 | @"long long", | ||
| 608 | |||
| 609 | _Bool, | ||
| 610 | @"unsigned char", | ||
| 611 | @"unsigned short", | ||
| 612 | @"unsigned int", | ||
| 613 | @"unsigned long", | ||
| 614 | @"unsigned long long", | ||
| 615 | |||
| 616 | float, | ||
| 617 | double, | ||
| 618 | @"long double", | ||
| 619 | |||
| 620 | // C header types | ||
| 621 | // - stdbool.h | ||
| 622 | bool, | ||
| 623 | // - stddef.h | ||
| 624 | size_t, | ||
| 625 | ptrdiff_t, | ||
| 626 | // - stdint.h | ||
| 627 | uint8_t, | ||
| 628 | int8_t, | ||
| 629 | uint16_t, | ||
| 630 | int16_t, | ||
| 631 | uint32_t, | ||
| 632 | int32_t, | ||
| 633 | uint64_t, | ||
| 634 | int64_t, | ||
| 635 | uintptr_t, | ||
| 636 | intptr_t, | ||
| 637 | // - stdarg.h | ||
| 638 | va_list, | ||
| 639 | |||
| 640 | // zig.h types | ||
| 641 | zig_u128, | ||
| 642 | zig_i128, | ||
| 643 | zig_f16, | ||
| 644 | zig_f32, | ||
| 645 | zig_f64, | ||
| 646 | zig_f80, | ||
| 647 | zig_f128, | ||
| 648 | zig_c_longdouble, | ||
| 649 | |||
| 650 | _, | ||
| 651 | |||
| 652 | const first_pool_index: u32 = @typeInfo(CType.Index).Enum.fields.len; | ||
| 653 | const basic_hashes = init: { | ||
| 654 | @setEvalBranchQuota(1_600); | ||
| 655 | var basic_hashes_init: [first_pool_index]Pool.Map.Hash = undefined; | ||
| 656 | for (&basic_hashes_init, 0..) |*basic_hash, index| { | ||
| 657 | const ctype_index: CType.Index = @enumFromInt(index); | ||
| 658 | var hasher = Pool.Hasher.init; | ||
| 659 | hasher.update(@intFromEnum(ctype_index)); | ||
| 660 | basic_hash.* = hasher.final(.basic); | ||
| 661 | } | ||
| 662 | break :init basic_hashes_init; | ||
| 663 | }; | ||
| 664 | }; | ||
| 665 | |||
| 666 | const Slice = struct { | ||
| 667 | extra_index: Pool.ExtraIndex, | ||
| 668 | len: u32, | ||
| 669 | |||
| 670 | pub fn at(slice: CType.Slice, index: usize, pool: *const Pool) CType { | ||
| 671 | var extra: Pool.ExtraTrail = .{ .extra_index = slice.extra_index }; | ||
| 672 | return .{ .index = extra.next(slice.len, CType.Index, pool)[index] }; | ||
| 673 | } | ||
| 674 | }; | ||
| 675 | |||
| 676 | pub const Kind = enum { | ||
| 677 | forward, | ||
| 678 | forward_parameter, | ||
| 679 | complete, | ||
| 680 | global, | ||
| 681 | parameter, | ||
| 682 | |||
| 683 | pub fn isForward(kind: Kind) bool { | ||
| 684 | return switch (kind) { | ||
| 685 | .forward, .forward_parameter => true, | ||
| 686 | .complete, .global, .parameter => false, | ||
| 687 | }; | ||
| 688 | } | ||
| 689 | |||
| 690 | pub fn isParameter(kind: Kind) bool { | ||
| 691 | return switch (kind) { | ||
| 692 | .forward_parameter, .parameter => true, | ||
| 693 | .forward, .complete, .global => false, | ||
| 694 | }; | ||
| 695 | } | ||
| 696 | |||
| 697 | pub fn asParameter(kind: Kind) Kind { | ||
| 698 | return switch (kind) { | ||
| 699 | .forward, .forward_parameter => .forward_parameter, | ||
| 700 | .complete, .parameter, .global => .parameter, | ||
| 701 | }; | ||
| 702 | } | ||
| 703 | |||
| 704 | pub fn noParameter(kind: Kind) Kind { | ||
| 705 | return switch (kind) { | ||
| 706 | .forward, .forward_parameter => .forward, | ||
| 707 | .complete, .parameter => .complete, | ||
| 708 | .global => .global, | ||
| 709 | }; | ||
| 710 | } | ||
| 711 | }; | ||
| 712 | |||
| 713 | pub const String = struct { | ||
| 714 | index: String.Index, | ||
| 715 | |||
| 716 | const Index = enum(u32) { | ||
| 717 | _, | ||
| 718 | }; | ||
| 719 | |||
| 720 | pub fn slice(string: String, pool: *const Pool) []const u8 { | ||
| 721 | const start = pool.string_indices.items[@intFromEnum(string.index)]; | ||
| 722 | const end = pool.string_indices.items[@intFromEnum(string.index) + 1]; | ||
| 723 | return pool.string_bytes.items[start..end]; | ||
| 724 | } | ||
| 725 | }; | ||
| 726 | |||
| 727 | pub const Info = union(enum) { | ||
| 728 | basic: CType.Index, | ||
| 729 | pointer: Pointer, | ||
| 730 | aligned: Aligned, | ||
| 731 | array: Sequence, | ||
| 732 | vector: Sequence, | ||
| 733 | fwd_decl: FwdDecl, | ||
| 734 | aggregate: Aggregate, | ||
| 735 | function: Function, | ||
| 736 | |||
| 737 | pub const Pointer = struct { | ||
| 738 | elem_ctype: CType, | ||
| 739 | @"const": bool = false, | ||
| 740 | @"volatile": bool = false, | ||
| 741 | |||
| 742 | fn tag(pointer_info: Pointer) Pool.Tag { | ||
| 743 | return @enumFromInt(@intFromEnum(Pool.Tag.pointer) + | ||
| 744 | @as(u2, @bitCast(packed struct(u2) { | ||
| 745 | @"const": bool, | ||
| 746 | @"volatile": bool, | ||
| 747 | }{ | ||
| 748 | .@"const" = pointer_info.@"const", | ||
| 749 | .@"volatile" = pointer_info.@"volatile", | ||
| 750 | }))); | ||
| 751 | } | ||
| 752 | }; | ||
| 753 | |||
| 754 | pub const Aligned = struct { | ||
| 755 | ctype: CType, | ||
| 756 | alignas: AlignAs, | ||
| 757 | }; | ||
| 758 | |||
| 759 | pub const Sequence = struct { | ||
| 760 | elem_ctype: CType, | ||
| 761 | len: u64, | ||
| 762 | }; | ||
| 763 | |||
| 764 | pub const Tag = enum { @"enum", @"struct", @"union" }; | ||
| 765 | |||
| 766 | pub const Field = struct { | ||
| 767 | name: String, | ||
| 768 | ctype: CType, | ||
| 769 | alignas: AlignAs, | ||
| 770 | |||
| 771 | pub const Slice = struct { | ||
| 772 | extra_index: Pool.ExtraIndex, | ||
| 773 | len: u32, | ||
| 774 | |||
| 775 | pub fn at(slice: Field.Slice, index: usize, pool: *const Pool) Field { | ||
| 776 | assert(index < slice.len); | ||
| 777 | const extra = pool.getExtra(Pool.Field, @intCast(slice.extra_index + | ||
| 778 | index * @typeInfo(Pool.Field).Struct.fields.len)); | ||
| 779 | return .{ | ||
| 780 | .name = .{ .index = extra.name }, | ||
| 781 | .ctype = .{ .index = extra.ctype }, | ||
| 782 | .alignas = extra.flags.alignas, | ||
| 783 | }; | ||
| 784 | } | ||
| 785 | |||
| 786 | fn eqlAdapted( | ||
| 787 | lhs_slice: Field.Slice, | ||
| 788 | lhs_pool: *const Pool, | ||
| 789 | rhs_slice: Field.Slice, | ||
| 790 | rhs_pool: *const Pool, | ||
| 791 | pool_adapter: anytype, | ||
| 792 | ) bool { | ||
| 793 | if (lhs_slice.len != rhs_slice.len) return false; | ||
| 794 | for (0..lhs_slice.len) |index| { | ||
| 795 | if (!lhs_slice.at(index, lhs_pool).eqlAdapted( | ||
| 796 | lhs_pool, | ||
| 797 | rhs_slice.at(index, rhs_pool), | ||
| 798 | rhs_pool, | ||
| 799 | pool_adapter, | ||
| 800 | )) return false; | ||
| 801 | } | ||
| 802 | return true; | ||
| 803 | } | ||
| 804 | }; | ||
| 805 | |||
| 806 | fn eqlAdapted( | ||
| 807 | lhs_field: Field, | ||
| 808 | lhs_pool: *const Pool, | ||
| 809 | rhs_field: Field, | ||
| 810 | rhs_pool: *const Pool, | ||
| 811 | pool_adapter: anytype, | ||
| 812 | ) bool { | ||
| 813 | return std.meta.eql(lhs_field.alignas, rhs_field.alignas) and | ||
| 814 | pool_adapter.eql(lhs_field.ctype, rhs_field.ctype) and std.mem.eql( | ||
| 815 | u8, | ||
| 816 | lhs_field.name.slice(lhs_pool), | ||
| 817 | rhs_field.name.slice(rhs_pool), | ||
| 818 | ); | ||
| 819 | } | ||
| 820 | }; | ||
| 821 | |||
| 822 | pub const FwdDecl = struct { | ||
| 823 | tag: Tag, | ||
| 824 | name: union(enum) { | ||
| 825 | anon: Field.Slice, | ||
| 826 | owner_decl: DeclIndex, | ||
| 827 | }, | ||
| 828 | }; | ||
| 829 | |||
| 830 | pub const Aggregate = struct { | ||
| 831 | tag: Tag, | ||
| 832 | @"packed": bool = false, | ||
| 833 | name: union(enum) { | ||
| 834 | anon: struct { | ||
| 835 | owner_decl: DeclIndex, | ||
| 836 | id: u32, | ||
| 837 | }, | ||
| 838 | fwd_decl: CType, | ||
| 839 | }, | ||
| 840 | fields: Field.Slice, | ||
| 841 | }; | ||
| 842 | |||
| 843 | pub const Function = struct { | ||
| 844 | return_ctype: CType, | ||
| 845 | param_ctypes: CType.Slice, | ||
| 846 | varargs: bool = false, | ||
| 847 | }; | ||
| 848 | |||
| 849 | pub fn eqlAdapted( | ||
| 850 | lhs_info: Info, | ||
| 851 | lhs_pool: *const Pool, | ||
| 852 | rhs_ctype: CType, | ||
| 853 | rhs_pool: *const Pool, | ||
| 854 | pool_adapter: anytype, | ||
| 855 | ) bool { | ||
| 856 | const InfoTag = @typeInfo(Info).Union.tag_type.?; | ||
| 857 | const rhs_info = rhs_ctype.info(rhs_pool); | ||
| 858 | if (@as(InfoTag, lhs_info) != @as(InfoTag, rhs_info)) return false; | ||
| 859 | return switch (lhs_info) { | ||
| 860 | .basic => |lhs_basic_info| lhs_basic_info == rhs_info.basic, | ||
| 861 | .pointer => |lhs_pointer_info| lhs_pointer_info.@"const" == rhs_info.pointer.@"const" and | ||
| 862 | lhs_pointer_info.@"volatile" == rhs_info.pointer.@"volatile" and | ||
| 863 | pool_adapter.eql(lhs_pointer_info.elem_ctype, rhs_info.pointer.elem_ctype), | ||
| 864 | .aligned => |lhs_aligned_info| std.meta.eql(lhs_aligned_info.alignas, rhs_info.aligned.alignas) and | ||
| 865 | pool_adapter.eql(lhs_aligned_info.ctype, rhs_info.aligned.ctype), | ||
| 866 | .array => |lhs_array_info| lhs_array_info.len == rhs_info.array.len and | ||
| 867 | pool_adapter.eql(lhs_array_info.elem_ctype, rhs_info.array.elem_ctype), | ||
| 868 | .vector => |lhs_vector_info| lhs_vector_info.len == rhs_info.vector.len and | ||
| 869 | pool_adapter.eql(lhs_vector_info.elem_ctype, rhs_info.vector.elem_ctype), | ||
| 870 | .fwd_decl => |lhs_fwd_decl_info| lhs_fwd_decl_info.tag == rhs_info.fwd_decl.tag and | ||
| 871 | switch (lhs_fwd_decl_info.name) { | ||
| 872 | .anon => |lhs_anon| rhs_info.fwd_decl.name == .anon and lhs_anon.eqlAdapted( | ||
| 873 | lhs_pool, | ||
| 874 | rhs_info.fwd_decl.name.anon, | ||
| 875 | rhs_pool, | ||
| 876 | pool_adapter, | ||
| 877 | ), | ||
| 878 | .owner_decl => |lhs_owner_decl| rhs_info.fwd_decl.name == .owner_decl and | ||
| 879 | lhs_owner_decl == rhs_info.fwd_decl.name.owner_decl, | ||
| 880 | }, | ||
| 881 | .aggregate => |lhs_aggregate_info| lhs_aggregate_info.tag == rhs_info.aggregate.tag and | ||
| 882 | lhs_aggregate_info.@"packed" == rhs_info.aggregate.@"packed" and | ||
| 883 | switch (lhs_aggregate_info.name) { | ||
| 884 | .anon => |lhs_anon| rhs_info.aggregate.name == .anon and | ||
| 885 | lhs_anon.owner_decl == rhs_info.aggregate.name.anon.owner_decl and | ||
| 886 | lhs_anon.id == rhs_info.aggregate.name.anon.id, | ||
| 887 | .fwd_decl => |lhs_fwd_decl| rhs_info.aggregate.name == .fwd_decl and | ||
| 888 | pool_adapter.eql(lhs_fwd_decl, rhs_info.aggregate.name.fwd_decl), | ||
| 889 | } and lhs_aggregate_info.fields.eqlAdapted( | ||
| 890 | lhs_pool, | ||
| 891 | rhs_info.aggregate.fields, | ||
| 892 | rhs_pool, | ||
| 893 | pool_adapter, | ||
| 894 | ), | ||
| 895 | .function => |lhs_function_info| lhs_function_info.param_ctypes.len == | ||
| 896 | rhs_info.function.param_ctypes.len and | ||
| 897 | pool_adapter.eql(lhs_function_info.return_ctype, rhs_info.function.return_ctype) and | ||
| 898 | for (0..lhs_function_info.param_ctypes.len) |param_index| | ||
| 899 | { | ||
| 900 | if (!pool_adapter.eql( | ||
| 901 | lhs_function_info.param_ctypes.at(param_index, lhs_pool), | ||
| 902 | rhs_info.function.param_ctypes.at(param_index, rhs_pool), | ||
| 903 | )) break false; | ||
| 904 | } else true, | ||
| 905 | }; | ||
| 906 | } | ||
| 907 | }; | ||
| 908 | |||
| 909 | pub const Pool = struct { | ||
| 910 | map: Map, | ||
| 911 | items: std.MultiArrayList(Item), | ||
| 912 | extra: std.ArrayListUnmanaged(u32), | ||
| 913 | |||
| 914 | string_map: Map, | ||
| 915 | string_indices: std.ArrayListUnmanaged(u32), | ||
| 916 | string_bytes: std.ArrayListUnmanaged(u8), | ||
| 917 | |||
| 918 | const Map = std.AutoArrayHashMapUnmanaged(void, void); | ||
| 919 | |||
| 920 | pub const empty: Pool = .{ | ||
| 921 | .map = .{}, | ||
| 922 | .items = .{}, | ||
| 923 | .extra = .{}, | ||
| 924 | |||
| 925 | .string_map = .{}, | ||
| 926 | .string_indices = .{}, | ||
| 927 | .string_bytes = .{}, | ||
| 928 | }; | ||
| 929 | |||
| 930 | pub fn init(pool: *Pool, allocator: std.mem.Allocator) !void { | ||
| 931 | if (pool.string_indices.items.len == 0) | ||
| 932 | try pool.string_indices.append(allocator, 0); | ||
| 933 | } | ||
| 934 | |||
| 935 | pub fn deinit(pool: *Pool, allocator: std.mem.Allocator) void { | ||
| 936 | pool.map.deinit(allocator); | ||
| 937 | pool.items.deinit(allocator); | ||
| 938 | pool.extra.deinit(allocator); | ||
| 939 | |||
| 940 | pool.string_map.deinit(allocator); | ||
| 941 | pool.string_indices.deinit(allocator); | ||
| 942 | pool.string_bytes.deinit(allocator); | ||
| 943 | |||
| 944 | pool.* = undefined; | ||
| 945 | } | ||
| 946 | |||
| 947 | pub fn move(pool: *Pool) Pool { | ||
| 948 | defer pool.* = empty; | ||
| 949 | return pool.*; | ||
| 950 | } | ||
| 951 | |||
| 952 | pub fn clearRetainingCapacity(pool: *Pool) void { | ||
| 953 | pool.map.clearRetainingCapacity(); | ||
| 954 | pool.items.shrinkRetainingCapacity(0); | ||
| 955 | pool.extra.clearRetainingCapacity(); | ||
| 956 | |||
| 957 | pool.string_map.clearRetainingCapacity(); | ||
| 958 | pool.string_indices.shrinkRetainingCapacity(1); | ||
| 959 | pool.string_bytes.clearRetainingCapacity(); | ||
| 960 | } | ||
| 961 | |||
| 962 | pub fn freeUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator) void { | ||
| 963 | pool.map.shrinkAndFree(allocator, pool.map.count()); | ||
| 964 | pool.items.shrinkAndFree(allocator, pool.items.len); | ||
| 965 | pool.extra.shrinkAndFree(allocator, pool.extra.items.len); | ||
| 966 | |||
| 967 | pool.string_map.shrinkAndFree(allocator, pool.string_map.count()); | ||
| 968 | pool.string_indices.shrinkAndFree(allocator, pool.string_indices.items.len); | ||
| 969 | pool.string_bytes.shrinkAndFree(allocator, pool.string_bytes.items.len); | ||
| 970 | } | ||
| 971 | |||
| 972 | pub fn getPointer(pool: *Pool, allocator: std.mem.Allocator, pointer_info: Info.Pointer) !CType { | ||
| 973 | var hasher = Hasher.init; | ||
| 974 | hasher.update(pointer_info.elem_ctype.hash(pool)); | ||
| 975 | return pool.tagData( | ||
| 976 | allocator, | ||
| 977 | hasher, | ||
| 978 | pointer_info.tag(), | ||
| 979 | @intFromEnum(pointer_info.elem_ctype.index), | ||
| 980 | ); | ||
| 981 | } | ||
| 982 | |||
| 983 | pub fn getAligned(pool: *Pool, allocator: std.mem.Allocator, aligned_info: Info.Aligned) !CType { | ||
| 984 | return pool.tagExtra(allocator, .aligned, Aligned, .{ | ||
| 985 | .ctype = aligned_info.ctype.index, | ||
| 986 | .flags = .{ .alignas = aligned_info.alignas }, | ||
| 987 | }); | ||
| 988 | } | ||
| 989 | |||
| 990 | pub fn getArray(pool: *Pool, allocator: std.mem.Allocator, array_info: Info.Sequence) !CType { | ||
| 991 | return if (std.math.cast(u32, array_info.len)) |small_len| | ||
| 992 | pool.tagExtra(allocator, .array_small, SequenceSmall, .{ | ||
| 993 | .elem_ctype = array_info.elem_ctype.index, | ||
| 994 | .len = small_len, | ||
| 995 | }) | ||
| 996 | else | ||
| 997 | pool.tagExtra(allocator, .array_large, SequenceLarge, .{ | ||
| 998 | .elem_ctype = array_info.elem_ctype.index, | ||
| 999 | .len_lo = @truncate(array_info.len >> 0), | ||
| 1000 | .len_hi = @truncate(array_info.len >> 32), | ||
| 1001 | }); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | pub fn getVector(pool: *Pool, allocator: std.mem.Allocator, vector_info: Info.Sequence) !CType { | ||
| 1005 | return pool.tagExtra(allocator, .vector, SequenceSmall, .{ | ||
| 1006 | .elem_ctype = vector_info.elem_ctype.index, | ||
| 1007 | .len = @intCast(vector_info.len), | ||
| 1008 | }); | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | pub fn getFwdDecl( | ||
| 1012 | pool: *Pool, | ||
| 1013 | allocator: std.mem.Allocator, | ||
| 1014 | fwd_decl_info: struct { | ||
| 1015 | tag: Info.Tag, | ||
| 1016 | name: union(enum) { | ||
| 1017 | anon: []const Info.Field, | ||
| 1018 | owner_decl: DeclIndex, | ||
| 1019 | }, | ||
| 1020 | }, | ||
| 1021 | ) !CType { | ||
| 1022 | var hasher = Hasher.init; | ||
| 1023 | switch (fwd_decl_info.name) { | ||
| 1024 | .anon => |fields| { | ||
| 1025 | const ExpectedContents = [32]CType; | ||
| 1026 | var stack align(@max( | ||
| 1027 | @alignOf(std.heap.StackFallbackAllocator(0)), | ||
| 1028 | @alignOf(ExpectedContents), | ||
| 1029 | )) = std.heap.stackFallback(@sizeOf(ExpectedContents), allocator); | ||
| 1030 | const stack_allocator = stack.get(); | ||
| 1031 | const field_ctypes = try stack_allocator.alloc(CType, fields.len); | ||
| 1032 | defer stack_allocator.free(field_ctypes); | ||
| 1033 | for (field_ctypes, fields) |*field_ctype, field| | ||
| 1034 | field_ctype.* = try field.ctype.toForward(pool, allocator); | ||
| 1035 | const extra: FwdDeclAnon = .{ .fields_len = @intCast(fields.len) }; | ||
| 1036 | const extra_index = try pool.addExtra( | ||
| 1037 | allocator, | ||
| 1038 | FwdDeclAnon, | ||
| 1039 | extra, | ||
| 1040 | fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1041 | ); | ||
| 1042 | for (fields, field_ctypes) |field, field_ctype| pool.addHashedExtraAssumeCapacity( | ||
| 1043 | &hasher, | ||
| 1044 | Field, | ||
| 1045 | .{ | ||
| 1046 | .name = field.name.index, | ||
| 1047 | .ctype = field_ctype.index, | ||
| 1048 | .flags = .{ .alignas = field.alignas }, | ||
| 1049 | }, | ||
| 1050 | ); | ||
| 1051 | hasher.updateExtra(FwdDeclAnon, extra, pool); | ||
| 1052 | return pool.tagTrailingExtra(allocator, hasher, switch (fwd_decl_info.tag) { | ||
| 1053 | .@"struct" => .fwd_decl_struct_anon, | ||
| 1054 | .@"union" => .fwd_decl_union_anon, | ||
| 1055 | .@"enum" => unreachable, | ||
| 1056 | }, extra_index); | ||
| 1057 | }, | ||
| 1058 | .owner_decl => |owner_decl| { | ||
| 1059 | hasher.update(owner_decl); | ||
| 1060 | return pool.tagData(allocator, hasher, switch (fwd_decl_info.tag) { | ||
| 1061 | .@"struct" => .fwd_decl_struct, | ||
| 1062 | .@"union" => .fwd_decl_union, | ||
| 1063 | .@"enum" => unreachable, | ||
| 1064 | }, @intFromEnum(owner_decl)); | ||
| 1065 | }, | ||
| 1066 | } | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | pub fn getAggregate( | ||
| 1070 | pool: *Pool, | ||
| 1071 | allocator: std.mem.Allocator, | ||
| 1072 | aggregate_info: struct { | ||
| 1073 | tag: Info.Tag, | ||
| 1074 | @"packed": bool = false, | ||
| 1075 | name: union(enum) { | ||
| 1076 | anon: struct { | ||
| 1077 | owner_decl: DeclIndex, | ||
| 1078 | id: u32, | ||
| 1079 | }, | ||
| 1080 | fwd_decl: CType, | ||
| 1081 | }, | ||
| 1082 | fields: []const Info.Field, | ||
| 1083 | }, | ||
| 1084 | ) !CType { | ||
| 1085 | var hasher = Hasher.init; | ||
| 1086 | switch (aggregate_info.name) { | ||
| 1087 | .anon => |anon| { | ||
| 1088 | const extra: AggregateAnon = .{ | ||
| 1089 | .owner_decl = anon.owner_decl, | ||
| 1090 | .id = anon.id, | ||
| 1091 | .fields_len = @intCast(aggregate_info.fields.len), | ||
| 1092 | }; | ||
| 1093 | const extra_index = try pool.addExtra( | ||
| 1094 | allocator, | ||
| 1095 | AggregateAnon, | ||
| 1096 | extra, | ||
| 1097 | aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1098 | ); | ||
| 1099 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | ||
| 1100 | .name = field.name.index, | ||
| 1101 | .ctype = field.ctype.index, | ||
| 1102 | .flags = .{ .alignas = field.alignas }, | ||
| 1103 | }); | ||
| 1104 | hasher.updateExtra(AggregateAnon, extra, pool); | ||
| 1105 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | ||
| 1106 | .@"struct" => switch (aggregate_info.@"packed") { | ||
| 1107 | false => .aggregate_struct_anon, | ||
| 1108 | true => .aggregate_struct_packed_anon, | ||
| 1109 | }, | ||
| 1110 | .@"union" => switch (aggregate_info.@"packed") { | ||
| 1111 | false => .aggregate_union_anon, | ||
| 1112 | true => .aggregate_union_packed_anon, | ||
| 1113 | }, | ||
| 1114 | .@"enum" => unreachable, | ||
| 1115 | }, extra_index); | ||
| 1116 | }, | ||
| 1117 | .fwd_decl => |fwd_decl| { | ||
| 1118 | const extra: Aggregate = .{ | ||
| 1119 | .fwd_decl = fwd_decl.index, | ||
| 1120 | .fields_len = @intCast(aggregate_info.fields.len), | ||
| 1121 | }; | ||
| 1122 | const extra_index = try pool.addExtra( | ||
| 1123 | allocator, | ||
| 1124 | Aggregate, | ||
| 1125 | extra, | ||
| 1126 | aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len, | ||
| 1127 | ); | ||
| 1128 | for (aggregate_info.fields) |field| pool.addHashedExtraAssumeCapacity(&hasher, Field, .{ | ||
| 1129 | .name = field.name.index, | ||
| 1130 | .ctype = field.ctype.index, | ||
| 1131 | .flags = .{ .alignas = field.alignas }, | ||
| 1132 | }); | ||
| 1133 | hasher.updateExtra(Aggregate, extra, pool); | ||
| 1134 | return pool.tagTrailingExtra(allocator, hasher, switch (aggregate_info.tag) { | ||
| 1135 | .@"struct" => switch (aggregate_info.@"packed") { | ||
| 1136 | false => .aggregate_struct, | ||
| 1137 | true => .aggregate_struct_packed, | ||
| 1138 | }, | ||
| 1139 | .@"union" => switch (aggregate_info.@"packed") { | ||
| 1140 | false => .aggregate_union, | ||
| 1141 | true => .aggregate_union_packed, | ||
| 1142 | }, | ||
| 1143 | .@"enum" => unreachable, | ||
| 1144 | }, extra_index); | ||
| 1145 | }, | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | pub fn getFunction( | ||
| 1150 | pool: *Pool, | ||
| 1151 | allocator: std.mem.Allocator, | ||
| 1152 | function_info: struct { | ||
| 1153 | return_ctype: CType, | ||
| 1154 | param_ctypes: []const CType, | ||
| 1155 | varargs: bool = false, | ||
| 1156 | }, | ||
| 1157 | ) !CType { | ||
| 1158 | var hasher = Hasher.init; | ||
| 1159 | const extra: Function = .{ | ||
| 1160 | .return_ctype = function_info.return_ctype.index, | ||
| 1161 | .param_ctypes_len = @intCast(function_info.param_ctypes.len), | ||
| 1162 | }; | ||
| 1163 | const extra_index = try pool.addExtra(allocator, Function, extra, function_info.param_ctypes.len); | ||
| 1164 | for (function_info.param_ctypes) |param_ctype| { | ||
| 1165 | hasher.update(param_ctype.hash(pool)); | ||
| 1166 | pool.extra.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | ||
| 1167 | } | ||
| 1168 | hasher.updateExtra(Function, extra, pool); | ||
| 1169 | return pool.tagTrailingExtra(allocator, hasher, switch (function_info.varargs) { | ||
| 1170 | false => .function, | ||
| 1171 | true => .function_varargs, | ||
| 1172 | }, extra_index); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | pub fn fromFields( | ||
| 1176 | pool: *Pool, | ||
| 1177 | allocator: std.mem.Allocator, | ||
| 1178 | tag: Info.Tag, | ||
| 1179 | fields: []Info.Field, | ||
| 1180 | kind: Kind, | ||
| 1181 | ) !CType { | ||
| 1182 | sortFields(fields); | ||
| 1183 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1184 | .tag = tag, | ||
| 1185 | .name = .{ .anon = fields }, | ||
| 1186 | }); | ||
| 1187 | return if (kind.isForward()) fwd_decl else pool.getAggregate(allocator, .{ | ||
| 1188 | .tag = tag, | ||
| 1189 | .name = .{ .fwd_decl = fwd_decl }, | ||
| 1190 | .fields = fields, | ||
| 1191 | }); | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | pub fn fromIntInfo( | ||
| 1195 | pool: *Pool, | ||
| 1196 | allocator: std.mem.Allocator, | ||
| 1197 | int_info: std.builtin.Type.Int, | ||
| 1198 | mod: *Module, | ||
| 1199 | kind: Kind, | ||
| 1200 | ) !CType { | ||
| 1201 | switch (int_info.bits) { | ||
| 1202 | 0 => return .{ .index = .void }, | ||
| 1203 | 1...8 => switch (int_info.signedness) { | ||
| 1204 | .unsigned => return .{ .index = .uint8_t }, | ||
| 1205 | .signed => return .{ .index = .int8_t }, | ||
| 1206 | }, | ||
| 1207 | 9...16 => switch (int_info.signedness) { | ||
| 1208 | .unsigned => return .{ .index = .uint16_t }, | ||
| 1209 | .signed => return .{ .index = .int16_t }, | ||
| 1210 | }, | ||
| 1211 | 17...32 => switch (int_info.signedness) { | ||
| 1212 | .unsigned => return .{ .index = .uint32_t }, | ||
| 1213 | .signed => return .{ .index = .int32_t }, | ||
| 1214 | }, | ||
| 1215 | 33...64 => switch (int_info.signedness) { | ||
| 1216 | .unsigned => return .{ .index = .uint64_t }, | ||
| 1217 | .signed => return .{ .index = .int64_t }, | ||
| 1218 | }, | ||
| 1219 | 65...128 => switch (int_info.signedness) { | ||
| 1220 | .unsigned => return .{ .index = .zig_u128 }, | ||
| 1221 | .signed => return .{ .index = .zig_i128 }, | ||
| 1222 | }, | ||
| 1223 | else => { | ||
| 1224 | const target = &mod.resolved_target.result; | ||
| 1225 | const abi_align = Type.intAbiAlignment(int_info.bits, target.*); | ||
| 1226 | const abi_align_bytes = abi_align.toByteUnits().?; | ||
| 1227 | const array_ctype = try pool.getArray(allocator, .{ | ||
| 1228 | .len = @divExact(Type.intAbiSize(int_info.bits, target.*), abi_align_bytes), | ||
| 1229 | .elem_ctype = try pool.fromIntInfo(allocator, .{ | ||
| 1230 | .signedness = .unsigned, | ||
| 1231 | .bits = @intCast(abi_align_bytes * 8), | ||
| 1232 | }, mod, kind.noParameter()), | ||
| 1233 | }); | ||
| 1234 | if (!kind.isParameter()) return array_ctype; | ||
| 1235 | var fields = [_]Info.Field{ | ||
| 1236 | .{ | ||
| 1237 | .name = try pool.string(allocator, "array"), | ||
| 1238 | .ctype = array_ctype, | ||
| 1239 | .alignas = AlignAs.fromAbiAlignment(abi_align), | ||
| 1240 | }, | ||
| 1241 | }; | ||
| 1242 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1243 | }, | ||
| 1244 | } | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | pub fn fromType( | ||
| 1248 | pool: *Pool, | ||
| 1249 | allocator: std.mem.Allocator, | ||
| 1250 | scratch: *std.ArrayListUnmanaged(u32), | ||
| 1251 | ty: Type, | ||
| 1252 | zcu: *Zcu, | ||
| 1253 | mod: *Module, | ||
| 1254 | kind: Kind, | ||
| 1255 | ) !CType { | ||
| 1256 | const ip = &zcu.intern_pool; | ||
| 1257 | switch (ty.toIntern()) { | ||
| 1258 | .u0_type, | ||
| 1259 | .i0_type, | ||
| 1260 | .anyopaque_type, | ||
| 1261 | .void_type, | ||
| 1262 | .empty_struct_type, | ||
| 1263 | .type_type, | ||
| 1264 | .comptime_int_type, | ||
| 1265 | .comptime_float_type, | ||
| 1266 | .null_type, | ||
| 1267 | .undefined_type, | ||
| 1268 | .enum_literal_type, | ||
| 1269 | => return .{ .index = .void }, | ||
| 1270 | .u1_type, .u8_type => return .{ .index = .uint8_t }, | ||
| 1271 | .i8_type => return .{ .index = .int8_t }, | ||
| 1272 | .u16_type => return .{ .index = .uint16_t }, | ||
| 1273 | .i16_type => return .{ .index = .int16_t }, | ||
| 1274 | .u29_type, .u32_type => return .{ .index = .uint32_t }, | ||
| 1275 | .i32_type => return .{ .index = .int32_t }, | ||
| 1276 | .u64_type => return .{ .index = .uint64_t }, | ||
| 1277 | .i64_type => return .{ .index = .int64_t }, | ||
| 1278 | .u80_type, .u128_type => return .{ .index = .zig_u128 }, | ||
| 1279 | .i128_type => return .{ .index = .zig_i128 }, | ||
| 1280 | .usize_type => return .{ .index = .uintptr_t }, | ||
| 1281 | .isize_type => return .{ .index = .intptr_t }, | ||
| 1282 | .c_char_type => return .{ .index = .char }, | ||
| 1283 | .c_short_type => return .{ .index = .short }, | ||
| 1284 | .c_ushort_type => return .{ .index = .@"unsigned short" }, | ||
| 1285 | .c_int_type => return .{ .index = .int }, | ||
| 1286 | .c_uint_type => return .{ .index = .@"unsigned int" }, | ||
| 1287 | .c_long_type => return .{ .index = .long }, | ||
| 1288 | .c_ulong_type => return .{ .index = .@"unsigned long" }, | ||
| 1289 | .c_longlong_type => return .{ .index = .@"long long" }, | ||
| 1290 | .c_ulonglong_type => return .{ .index = .@"unsigned long long" }, | ||
| 1291 | .c_longdouble_type => return .{ .index = .@"long double" }, | ||
| 1292 | .f16_type => return .{ .index = .zig_f16 }, | ||
| 1293 | .f32_type => return .{ .index = .zig_f32 }, | ||
| 1294 | .f64_type => return .{ .index = .zig_f64 }, | ||
| 1295 | .f80_type => return .{ .index = .zig_f80 }, | ||
| 1296 | .f128_type => return .{ .index = .zig_f128 }, | ||
| 1297 | .bool_type, .optional_noreturn_type => return .{ .index = .bool }, | ||
| 1298 | .noreturn_type, | ||
| 1299 | .anyframe_type, | ||
| 1300 | .generic_poison_type, | ||
| 1301 | => unreachable, | ||
| 1302 | .atomic_order_type, | ||
| 1303 | .atomic_rmw_op_type, | ||
| 1304 | .calling_convention_type, | ||
| 1305 | .address_space_type, | ||
| 1306 | .float_mode_type, | ||
| 1307 | .reduce_op_type, | ||
| 1308 | .call_modifier_type, | ||
| 1309 | => |ip_index| return pool.fromType( | ||
| 1310 | allocator, | ||
| 1311 | scratch, | ||
| 1312 | Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), | ||
| 1313 | zcu, | ||
| 1314 | mod, | ||
| 1315 | kind, | ||
| 1316 | ), | ||
| 1317 | .anyerror_type, | ||
| 1318 | .anyerror_void_error_union_type, | ||
| 1319 | .adhoc_inferred_error_set_type, | ||
| 1320 | => return pool.fromIntInfo(allocator, .{ | ||
| 1321 | .signedness = .unsigned, | ||
| 1322 | .bits = zcu.errorSetBits(), | ||
| 1323 | }, mod, kind), | ||
| 1324 | .manyptr_u8_type, | ||
| 1325 | => return pool.getPointer(allocator, .{ | ||
| 1326 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1327 | }), | ||
| 1328 | .manyptr_const_u8_type, | ||
| 1329 | .manyptr_const_u8_sentinel_0_type, | ||
| 1330 | => return pool.getPointer(allocator, .{ | ||
| 1331 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1332 | .@"const" = true, | ||
| 1333 | }), | ||
| 1334 | .single_const_pointer_to_comptime_int_type, | ||
| 1335 | => return pool.getPointer(allocator, .{ | ||
| 1336 | .elem_ctype = .{ .index = .void }, | ||
| 1337 | .@"const" = true, | ||
| 1338 | }), | ||
| 1339 | .slice_const_u8_type, | ||
| 1340 | .slice_const_u8_sentinel_0_type, | ||
| 1341 | => { | ||
| 1342 | const target = &mod.resolved_target.result; | ||
| 1343 | var fields = [_]Info.Field{ | ||
| 1344 | .{ | ||
| 1345 | .name = try pool.string(allocator, "ptr"), | ||
| 1346 | .ctype = try pool.getPointer(allocator, .{ | ||
| 1347 | .elem_ctype = .{ .index = .uint8_t }, | ||
| 1348 | .@"const" = true, | ||
| 1349 | }), | ||
| 1350 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)), | ||
| 1351 | }, | ||
| 1352 | .{ | ||
| 1353 | .name = try pool.string(allocator, "len"), | ||
| 1354 | .ctype = .{ .index = .uintptr_t }, | ||
| 1355 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1356 | Type.intAbiAlignment(target.ptrBitWidth(), target.*), | ||
| 1357 | ), | ||
| 1358 | }, | ||
| 1359 | }; | ||
| 1360 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1361 | }, | ||
| 1362 | |||
| 1363 | .undef, | ||
| 1364 | .zero, | ||
| 1365 | .zero_usize, | ||
| 1366 | .zero_u8, | ||
| 1367 | .one, | ||
| 1368 | .one_usize, | ||
| 1369 | .one_u8, | ||
| 1370 | .four_u8, | ||
| 1371 | .negative_one, | ||
| 1372 | .calling_convention_c, | ||
| 1373 | .calling_convention_inline, | ||
| 1374 | .void_value, | ||
| 1375 | .unreachable_value, | ||
| 1376 | .null_value, | ||
| 1377 | .bool_true, | ||
| 1378 | .bool_false, | ||
| 1379 | .empty_struct, | ||
| 1380 | .generic_poison, | ||
| 1381 | .var_args_param_type, | ||
| 1382 | .none, | ||
| 1383 | => unreachable, | ||
| 1384 | |||
| 1385 | //.prefetch_options_type, | ||
| 1386 | //.export_options_type, | ||
| 1387 | //.extern_options_type, | ||
| 1388 | //.type_info_type, | ||
| 1389 | //_, | ||
| 1390 | else => |ip_index| switch (ip.indexToKey(ip_index)) { | ||
| 1391 | .int_type => |int_info| return pool.fromIntInfo(allocator, int_info, mod, kind), | ||
| 1392 | .ptr_type => |ptr_info| switch (ptr_info.flags.size) { | ||
| 1393 | .One, .Many, .C => return pool.getPointer(allocator, .{ | ||
| 1394 | .elem_ctype = elem_ctype: { | ||
| 1395 | if (ptr_info.packed_offset.host_size > 0 and | ||
| 1396 | ptr_info.flags.vector_index == .none) | ||
| 1397 | break :elem_ctype try pool.fromIntInfo(allocator, .{ | ||
| 1398 | .signedness = .unsigned, | ||
| 1399 | .bits = ptr_info.packed_offset.host_size * 8, | ||
| 1400 | }, mod, .forward); | ||
| 1401 | const elem: Info.Aligned = .{ | ||
| 1402 | .ctype = try pool.fromType( | ||
| 1403 | allocator, | ||
| 1404 | scratch, | ||
| 1405 | Type.fromInterned(ptr_info.child), | ||
| 1406 | zcu, | ||
| 1407 | mod, | ||
| 1408 | .forward, | ||
| 1409 | ), | ||
| 1410 | .alignas = AlignAs.fromAlignment(.{ | ||
| 1411 | .@"align" = ptr_info.flags.alignment, | ||
| 1412 | .abi = Type.fromInterned(ptr_info.child).abiAlignment(zcu), | ||
| 1413 | }), | ||
| 1414 | }; | ||
| 1415 | if (elem.alignas.abiOrder().compare(.gte)) | ||
| 1416 | break :elem_ctype elem.ctype; | ||
| 1417 | break :elem_ctype try pool.getAligned(allocator, elem); | ||
| 1418 | }, | ||
| 1419 | .@"const" = ptr_info.flags.is_const, | ||
| 1420 | .@"volatile" = ptr_info.flags.is_volatile, | ||
| 1421 | }), | ||
| 1422 | .Slice => { | ||
| 1423 | const target = &mod.resolved_target.result; | ||
| 1424 | var fields = [_]Info.Field{ | ||
| 1425 | .{ | ||
| 1426 | .name = try pool.string(allocator, "ptr"), | ||
| 1427 | .ctype = try pool.fromType( | ||
| 1428 | allocator, | ||
| 1429 | scratch, | ||
| 1430 | Type.fromInterned(ip.slicePtrType(ip_index)), | ||
| 1431 | zcu, | ||
| 1432 | mod, | ||
| 1433 | kind, | ||
| 1434 | ), | ||
| 1435 | .alignas = AlignAs.fromAbiAlignment(Type.ptrAbiAlignment(target.*)), | ||
| 1436 | }, | ||
| 1437 | .{ | ||
| 1438 | .name = try pool.string(allocator, "len"), | ||
| 1439 | .ctype = .{ .index = .uintptr_t }, | ||
| 1440 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1441 | Type.intAbiAlignment(target.ptrBitWidth(), target.*), | ||
| 1442 | ), | ||
| 1443 | }, | ||
| 1444 | }; | ||
| 1445 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1446 | }, | ||
| 1447 | }, | ||
| 1448 | .array_type => |array_info| { | ||
| 1449 | const len = array_info.len + @intFromBool(array_info.sentinel != .none); | ||
| 1450 | if (len == 0) return .{ .index = .void }; | ||
| 1451 | const elem_type = Type.fromInterned(array_info.child); | ||
| 1452 | const elem_ctype = try pool.fromType( | ||
| 1453 | allocator, | ||
| 1454 | scratch, | ||
| 1455 | elem_type, | ||
| 1456 | zcu, | ||
| 1457 | mod, | ||
| 1458 | kind.noParameter(), | ||
| 1459 | ); | ||
| 1460 | if (elem_ctype.index == .void) return .{ .index = .void }; | ||
| 1461 | const array_ctype = try pool.getArray(allocator, .{ | ||
| 1462 | .elem_ctype = elem_ctype, | ||
| 1463 | .len = array_info.len + @intFromBool(array_info.sentinel != .none), | ||
| 1464 | }); | ||
| 1465 | if (!kind.isParameter()) return array_ctype; | ||
| 1466 | var fields = [_]Info.Field{ | ||
| 1467 | .{ | ||
| 1468 | .name = try pool.string(allocator, "array"), | ||
| 1469 | .ctype = array_ctype, | ||
| 1470 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | ||
| 1471 | }, | ||
| 1472 | }; | ||
| 1473 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1474 | }, | ||
| 1475 | .vector_type => |vector_info| { | ||
| 1476 | if (vector_info.len == 0) return .{ .index = .void }; | ||
| 1477 | const elem_type = Type.fromInterned(vector_info.child); | ||
| 1478 | const elem_ctype = try pool.fromType( | ||
| 1479 | allocator, | ||
| 1480 | scratch, | ||
| 1481 | elem_type, | ||
| 1482 | zcu, | ||
| 1483 | mod, | ||
| 1484 | kind.noParameter(), | ||
| 1485 | ); | ||
| 1486 | if (elem_ctype.index == .void) return .{ .index = .void }; | ||
| 1487 | const vector_ctype = try pool.getVector(allocator, .{ | ||
| 1488 | .elem_ctype = elem_ctype, | ||
| 1489 | .len = vector_info.len, | ||
| 1490 | }); | ||
| 1491 | if (!kind.isParameter()) return vector_ctype; | ||
| 1492 | var fields = [_]Info.Field{ | ||
| 1493 | .{ | ||
| 1494 | .name = try pool.string(allocator, "array"), | ||
| 1495 | .ctype = vector_ctype, | ||
| 1496 | .alignas = AlignAs.fromAbiAlignment(elem_type.abiAlignment(zcu)), | ||
| 1497 | }, | ||
| 1498 | }; | ||
| 1499 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1500 | }, | ||
| 1501 | .opt_type => |payload_type| { | ||
| 1502 | if (ip.isNoReturn(payload_type)) return .{ .index = .void }; | ||
| 1503 | const payload_ctype = try pool.fromType( | ||
| 1504 | allocator, | ||
| 1505 | scratch, | ||
| 1506 | Type.fromInterned(payload_type), | ||
| 1507 | zcu, | ||
| 1508 | mod, | ||
| 1509 | kind.noParameter(), | ||
| 1510 | ); | ||
| 1511 | if (payload_ctype.index == .void) return .{ .index = .bool }; | ||
| 1512 | switch (payload_type) { | ||
| 1513 | .anyerror_type => return payload_ctype, | ||
| 1514 | else => switch (ip.indexToKey(payload_type)) { | ||
| 1515 | .ptr_type => |payload_ptr_info| if (payload_ptr_info.flags.size != .C and | ||
| 1516 | !payload_ptr_info.flags.is_allowzero) return payload_ctype, | ||
| 1517 | .error_set_type, .inferred_error_set_type => return payload_ctype, | ||
| 1518 | else => {}, | ||
| 1519 | }, | ||
| 1520 | } | ||
| 1521 | var fields = [_]Info.Field{ | ||
| 1522 | .{ | ||
| 1523 | .name = try pool.string(allocator, "is_null"), | ||
| 1524 | .ctype = .{ .index = .bool }, | ||
| 1525 | .alignas = AlignAs.fromAbiAlignment(.@"1"), | ||
| 1526 | }, | ||
| 1527 | .{ | ||
| 1528 | .name = try pool.string(allocator, "payload"), | ||
| 1529 | .ctype = payload_ctype, | ||
| 1530 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1531 | Type.fromInterned(payload_type).abiAlignment(zcu), | ||
| 1532 | ), | ||
| 1533 | }, | ||
| 1534 | }; | ||
| 1535 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1536 | }, | ||
| 1537 | .anyframe_type => unreachable, | ||
| 1538 | .error_union_type => |error_union_info| { | ||
| 1539 | const error_set_bits = zcu.errorSetBits(); | ||
| 1540 | const error_set_ctype = try pool.fromIntInfo(allocator, .{ | ||
| 1541 | .signedness = .unsigned, | ||
| 1542 | .bits = error_set_bits, | ||
| 1543 | }, mod, kind); | ||
| 1544 | if (ip.isNoReturn(error_union_info.payload_type)) return error_set_ctype; | ||
| 1545 | const payload_type = Type.fromInterned(error_union_info.payload_type); | ||
| 1546 | const payload_ctype = try pool.fromType( | ||
| 1547 | allocator, | ||
| 1548 | scratch, | ||
| 1549 | payload_type, | ||
| 1550 | zcu, | ||
| 1551 | mod, | ||
| 1552 | kind.noParameter(), | ||
| 1553 | ); | ||
| 1554 | if (payload_ctype.index == .void) return error_set_ctype; | ||
| 1555 | const target = &mod.resolved_target.result; | ||
| 1556 | var fields = [_]Info.Field{ | ||
| 1557 | .{ | ||
| 1558 | .name = try pool.string(allocator, "error"), | ||
| 1559 | .ctype = error_set_ctype, | ||
| 1560 | .alignas = AlignAs.fromAbiAlignment( | ||
| 1561 | Type.intAbiAlignment(error_set_bits, target.*), | ||
| 1562 | ), | ||
| 1563 | }, | ||
| 1564 | .{ | ||
| 1565 | .name = try pool.string(allocator, "payload"), | ||
| 1566 | .ctype = payload_ctype, | ||
| 1567 | .alignas = AlignAs.fromAbiAlignment(payload_type.abiAlignment(zcu)), | ||
| 1568 | }, | ||
| 1569 | }; | ||
| 1570 | return pool.fromFields(allocator, .@"struct", &fields, kind); | ||
| 1571 | }, | ||
| 1572 | .simple_type => unreachable, | ||
| 1573 | .struct_type => { | ||
| 1574 | const loaded_struct = ip.loadStructType(ip_index); | ||
| 1575 | switch (loaded_struct.layout) { | ||
| 1576 | .auto, .@"extern" => { | ||
| 1577 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1578 | .tag = .@"struct", | ||
| 1579 | .name = .{ .owner_decl = loaded_struct.decl.unwrap().? }, | ||
| 1580 | }); | ||
| 1581 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | ||
| 1582 | fwd_decl | ||
| 1583 | else | ||
| 1584 | .{ .index = .void }; | ||
| 1585 | const scratch_top = scratch.items.len; | ||
| 1586 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1587 | try scratch.ensureUnusedCapacity( | ||
| 1588 | allocator, | ||
| 1589 | loaded_struct.field_types.len * @typeInfo(Field).Struct.fields.len, | ||
| 1590 | ); | ||
| 1591 | var hasher = Hasher.init; | ||
| 1592 | var tag: Tag = .aggregate_struct; | ||
| 1593 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | ||
| 1594 | while (field_it.next()) |field_index| { | ||
| 1595 | const field_type = Type.fromInterned( | ||
| 1596 | loaded_struct.field_types.get(ip)[field_index], | ||
| 1597 | ); | ||
| 1598 | const field_ctype = try pool.fromType( | ||
| 1599 | allocator, | ||
| 1600 | scratch, | ||
| 1601 | field_type, | ||
| 1602 | zcu, | ||
| 1603 | mod, | ||
| 1604 | kind.noParameter(), | ||
| 1605 | ); | ||
| 1606 | if (field_ctype.index == .void) continue; | ||
| 1607 | const field_name = if (loaded_struct.fieldName(ip, field_index) | ||
| 1608 | .unwrap()) |field_name| | ||
| 1609 | try pool.string(allocator, ip.stringToSlice(field_name)) | ||
| 1610 | else | ||
| 1611 | try pool.fmt(allocator, "f{d}", .{field_index}); | ||
| 1612 | const field_alignas = AlignAs.fromAlignment(.{ | ||
| 1613 | .@"align" = loaded_struct.fieldAlign(ip, field_index), | ||
| 1614 | .abi = field_type.abiAlignment(zcu), | ||
| 1615 | }); | ||
| 1616 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1617 | .name = field_name.index, | ||
| 1618 | .ctype = field_ctype.index, | ||
| 1619 | .flags = .{ .alignas = field_alignas }, | ||
| 1620 | }); | ||
| 1621 | if (field_alignas.abiOrder().compare(.lt)) | ||
| 1622 | tag = .aggregate_struct_packed; | ||
| 1623 | } | ||
| 1624 | const fields_len: u32 = @intCast(@divExact( | ||
| 1625 | scratch.items.len - scratch_top, | ||
| 1626 | @typeInfo(Field).Struct.fields.len, | ||
| 1627 | )); | ||
| 1628 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1629 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1630 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | ||
| 1631 | .fwd_decl = fwd_decl.index, | ||
| 1632 | .fields_len = fields_len, | ||
| 1633 | }, fields_len * @typeInfo(Field).Struct.fields.len); | ||
| 1634 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1635 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 1636 | }, | ||
| 1637 | .@"packed" => return pool.fromType( | ||
| 1638 | allocator, | ||
| 1639 | scratch, | ||
| 1640 | Type.fromInterned(loaded_struct.backingIntType(ip).*), | ||
| 1641 | zcu, | ||
| 1642 | mod, | ||
| 1643 | kind, | ||
| 1644 | ), | ||
| 1645 | } | ||
| 1646 | }, | ||
| 1647 | .anon_struct_type => |anon_struct_info| { | ||
| 1648 | const scratch_top = scratch.items.len; | ||
| 1649 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1650 | try scratch.ensureUnusedCapacity(allocator, anon_struct_info.types.len * | ||
| 1651 | @typeInfo(Field).Struct.fields.len); | ||
| 1652 | var hasher = Hasher.init; | ||
| 1653 | for (0..anon_struct_info.types.len) |field_index| { | ||
| 1654 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | ||
| 1655 | const field_type = Type.fromInterned( | ||
| 1656 | anon_struct_info.types.get(ip)[field_index], | ||
| 1657 | ); | ||
| 1658 | const field_ctype = try pool.fromType( | ||
| 1659 | allocator, | ||
| 1660 | scratch, | ||
| 1661 | field_type, | ||
| 1662 | zcu, | ||
| 1663 | mod, | ||
| 1664 | kind.noParameter(), | ||
| 1665 | ); | ||
| 1666 | if (field_ctype.index == .void) continue; | ||
| 1667 | const field_name = if (anon_struct_info.fieldName(ip, @intCast(field_index)) | ||
| 1668 | .unwrap()) |field_name| | ||
| 1669 | try pool.string(allocator, ip.stringToSlice(field_name)) | ||
| 1670 | else | ||
| 1671 | try pool.fmt(allocator, "f{d}", .{field_index}); | ||
| 1672 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1673 | .name = field_name.index, | ||
| 1674 | .ctype = field_ctype.index, | ||
| 1675 | .flags = .{ .alignas = AlignAs.fromAbiAlignment( | ||
| 1676 | field_type.abiAlignment(zcu), | ||
| 1677 | ) }, | ||
| 1678 | }); | ||
| 1679 | } | ||
| 1680 | const fields_len: u32 = @intCast(@divExact( | ||
| 1681 | scratch.items.len - scratch_top, | ||
| 1682 | @typeInfo(Field).Struct.fields.len, | ||
| 1683 | )); | ||
| 1684 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1685 | if (kind.isForward()) { | ||
| 1686 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1687 | const extra_index = try pool.addHashedExtra( | ||
| 1688 | allocator, | ||
| 1689 | &hasher, | ||
| 1690 | FwdDeclAnon, | ||
| 1691 | .{ .fields_len = fields_len }, | ||
| 1692 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1693 | ); | ||
| 1694 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1695 | return pool.tagTrailingExtra( | ||
| 1696 | allocator, | ||
| 1697 | hasher, | ||
| 1698 | .fwd_decl_struct_anon, | ||
| 1699 | extra_index, | ||
| 1700 | ); | ||
| 1701 | } | ||
| 1702 | const fwd_decl = try pool.fromType(allocator, scratch, ty, zcu, mod, .forward); | ||
| 1703 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1704 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Aggregate, .{ | ||
| 1705 | .fwd_decl = fwd_decl.index, | ||
| 1706 | .fields_len = fields_len, | ||
| 1707 | }, fields_len * @typeInfo(Field).Struct.fields.len); | ||
| 1708 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1709 | return pool.tagTrailingExtraAssumeCapacity(hasher, .aggregate_struct, extra_index); | ||
| 1710 | }, | ||
| 1711 | .union_type => { | ||
| 1712 | const loaded_union = ip.loadUnionType(ip_index); | ||
| 1713 | switch (loaded_union.getLayout(ip)) { | ||
| 1714 | .auto, .@"extern" => { | ||
| 1715 | const has_tag = loaded_union.hasTag(ip); | ||
| 1716 | const fwd_decl = try pool.getFwdDecl(allocator, .{ | ||
| 1717 | .tag = if (has_tag) .@"struct" else .@"union", | ||
| 1718 | .name = .{ .owner_decl = loaded_union.decl }, | ||
| 1719 | }); | ||
| 1720 | if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) | ||
| 1721 | fwd_decl | ||
| 1722 | else | ||
| 1723 | .{ .index = .void }; | ||
| 1724 | const loaded_tag = loaded_union.loadTagType(ip); | ||
| 1725 | const scratch_top = scratch.items.len; | ||
| 1726 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1727 | try scratch.ensureUnusedCapacity( | ||
| 1728 | allocator, | ||
| 1729 | loaded_union.field_types.len * @typeInfo(Field).Struct.fields.len, | ||
| 1730 | ); | ||
| 1731 | var hasher = Hasher.init; | ||
| 1732 | var tag: Tag = .aggregate_union; | ||
| 1733 | var payload_align: Alignment = .@"1"; | ||
| 1734 | for (0..loaded_union.field_types.len) |field_index| { | ||
| 1735 | const field_type = Type.fromInterned( | ||
| 1736 | loaded_union.field_types.get(ip)[field_index], | ||
| 1737 | ); | ||
| 1738 | if (ip.isNoReturn(field_type.toIntern())) continue; | ||
| 1739 | const field_ctype = try pool.fromType( | ||
| 1740 | allocator, | ||
| 1741 | scratch, | ||
| 1742 | field_type, | ||
| 1743 | zcu, | ||
| 1744 | mod, | ||
| 1745 | kind.noParameter(), | ||
| 1746 | ); | ||
| 1747 | if (field_ctype.index == .void) continue; | ||
| 1748 | const field_name = try pool.string( | ||
| 1749 | allocator, | ||
| 1750 | ip.stringToSlice(loaded_tag.names.get(ip)[field_index]), | ||
| 1751 | ); | ||
| 1752 | const field_alignas = AlignAs.fromAlignment(.{ | ||
| 1753 | .@"align" = loaded_union.fieldAlign(ip, @intCast(field_index)), | ||
| 1754 | .abi = field_type.abiAlignment(zcu), | ||
| 1755 | }); | ||
| 1756 | pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ | ||
| 1757 | .name = field_name.index, | ||
| 1758 | .ctype = field_ctype.index, | ||
| 1759 | .flags = .{ .alignas = field_alignas }, | ||
| 1760 | }); | ||
| 1761 | if (field_alignas.abiOrder().compare(.lt)) | ||
| 1762 | tag = .aggregate_union_packed; | ||
| 1763 | payload_align = payload_align.maxStrict(field_alignas.@"align"); | ||
| 1764 | } | ||
| 1765 | const fields_len: u32 = @intCast(@divExact( | ||
| 1766 | scratch.items.len - scratch_top, | ||
| 1767 | @typeInfo(Field).Struct.fields.len, | ||
| 1768 | )); | ||
| 1769 | if (!has_tag) { | ||
| 1770 | if (fields_len == 0) return .{ .index = .void }; | ||
| 1771 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1772 | const extra_index = try pool.addHashedExtra( | ||
| 1773 | allocator, | ||
| 1774 | &hasher, | ||
| 1775 | Aggregate, | ||
| 1776 | .{ .fwd_decl = fwd_decl.index, .fields_len = fields_len }, | ||
| 1777 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1778 | ); | ||
| 1779 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1780 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 1781 | } | ||
| 1782 | try pool.ensureUnusedCapacity(allocator, 2); | ||
| 1783 | var struct_fields: [2]Info.Field = undefined; | ||
| 1784 | var struct_fields_len: usize = 0; | ||
| 1785 | if (loaded_tag.tag_ty != .comptime_int_type) { | ||
| 1786 | const tag_type = Type.fromInterned(loaded_tag.tag_ty); | ||
| 1787 | const tag_ctype: CType = try pool.fromType( | ||
| 1788 | allocator, | ||
| 1789 | scratch, | ||
| 1790 | tag_type, | ||
| 1791 | zcu, | ||
| 1792 | mod, | ||
| 1793 | kind.noParameter(), | ||
| 1794 | ); | ||
| 1795 | if (tag_ctype.index != .void) { | ||
| 1796 | struct_fields[struct_fields_len] = .{ | ||
| 1797 | .name = try pool.string(allocator, "tag"), | ||
| 1798 | .ctype = tag_ctype, | ||
| 1799 | .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), | ||
| 1800 | }; | ||
| 1801 | struct_fields_len += 1; | ||
| 1802 | } | ||
| 1803 | } | ||
| 1804 | if (fields_len > 0) { | ||
| 1805 | const payload_ctype = payload_ctype: { | ||
| 1806 | const extra_index = try pool.addHashedExtra( | ||
| 1807 | allocator, | ||
| 1808 | &hasher, | ||
| 1809 | AggregateAnon, | ||
| 1810 | .{ | ||
| 1811 | .owner_decl = loaded_union.decl, | ||
| 1812 | .id = 0, | ||
| 1813 | .fields_len = fields_len, | ||
| 1814 | }, | ||
| 1815 | fields_len * @typeInfo(Field).Struct.fields.len, | ||
| 1816 | ); | ||
| 1817 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1818 | break :payload_ctype pool.tagTrailingExtraAssumeCapacity( | ||
| 1819 | hasher, | ||
| 1820 | switch (tag) { | ||
| 1821 | .aggregate_union => .aggregate_union_anon, | ||
| 1822 | .aggregate_union_packed => .aggregate_union_packed_anon, | ||
| 1823 | else => unreachable, | ||
| 1824 | }, | ||
| 1825 | extra_index, | ||
| 1826 | ); | ||
| 1827 | }; | ||
| 1828 | if (payload_ctype.index != .void) { | ||
| 1829 | struct_fields[struct_fields_len] = .{ | ||
| 1830 | .name = try pool.string(allocator, "payload"), | ||
| 1831 | .ctype = payload_ctype, | ||
| 1832 | .alignas = AlignAs.fromAbiAlignment(payload_align), | ||
| 1833 | }; | ||
| 1834 | struct_fields_len += 1; | ||
| 1835 | } | ||
| 1836 | } | ||
| 1837 | if (struct_fields_len == 0) return .{ .index = .void }; | ||
| 1838 | sortFields(struct_fields[0..struct_fields_len]); | ||
| 1839 | return pool.getAggregate(allocator, .{ | ||
| 1840 | .tag = .@"struct", | ||
| 1841 | .name = .{ .fwd_decl = fwd_decl }, | ||
| 1842 | .fields = struct_fields[0..struct_fields_len], | ||
| 1843 | }); | ||
| 1844 | }, | ||
| 1845 | .@"packed" => return pool.fromIntInfo(allocator, .{ | ||
| 1846 | .signedness = .unsigned, | ||
| 1847 | .bits = @intCast(ty.bitSize(zcu)), | ||
| 1848 | }, mod, kind), | ||
| 1849 | } | ||
| 1850 | }, | ||
| 1851 | .opaque_type => return .{ .index = .void }, | ||
| 1852 | .enum_type => return pool.fromType( | ||
| 1853 | allocator, | ||
| 1854 | scratch, | ||
| 1855 | Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), | ||
| 1856 | zcu, | ||
| 1857 | mod, | ||
| 1858 | kind, | ||
| 1859 | ), | ||
| 1860 | .func_type => |func_info| if (func_info.is_generic) return .{ .index = .void } else { | ||
| 1861 | const scratch_top = scratch.items.len; | ||
| 1862 | defer scratch.shrinkRetainingCapacity(scratch_top); | ||
| 1863 | try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); | ||
| 1864 | var hasher = Hasher.init; | ||
| 1865 | const return_type = Type.fromInterned(func_info.return_type); | ||
| 1866 | const return_ctype: CType = | ||
| 1867 | if (!ip.isNoReturn(func_info.return_type)) try pool.fromType( | ||
| 1868 | allocator, | ||
| 1869 | scratch, | ||
| 1870 | return_type, | ||
| 1871 | zcu, | ||
| 1872 | mod, | ||
| 1873 | kind.asParameter(), | ||
| 1874 | ) else .{ .index = .void }; | ||
| 1875 | for (0..func_info.param_types.len) |param_index| { | ||
| 1876 | const param_type = Type.fromInterned( | ||
| 1877 | func_info.param_types.get(ip)[param_index], | ||
| 1878 | ); | ||
| 1879 | const param_ctype = try pool.fromType( | ||
| 1880 | allocator, | ||
| 1881 | scratch, | ||
| 1882 | param_type, | ||
| 1883 | zcu, | ||
| 1884 | mod, | ||
| 1885 | kind.asParameter(), | ||
| 1886 | ); | ||
| 1887 | if (param_ctype.index == .void) continue; | ||
| 1888 | hasher.update(param_ctype.hash(pool)); | ||
| 1889 | scratch.appendAssumeCapacity(@intFromEnum(param_ctype.index)); | ||
| 1890 | } | ||
| 1891 | const param_ctypes_len: u32 = @intCast(scratch.items.len - scratch_top); | ||
| 1892 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1893 | const extra_index = try pool.addHashedExtra(allocator, &hasher, Function, .{ | ||
| 1894 | .return_ctype = return_ctype.index, | ||
| 1895 | .param_ctypes_len = param_ctypes_len, | ||
| 1896 | }, param_ctypes_len); | ||
| 1897 | pool.extra.appendSliceAssumeCapacity(scratch.items[scratch_top..]); | ||
| 1898 | return pool.tagTrailingExtraAssumeCapacity(hasher, switch (func_info.is_var_args) { | ||
| 1899 | false => .function, | ||
| 1900 | true => .function_varargs, | ||
| 1901 | }, extra_index); | ||
| 1902 | }, | ||
| 1903 | .error_set_type, | ||
| 1904 | .inferred_error_set_type, | ||
| 1905 | => return pool.fromIntInfo(allocator, .{ | ||
| 1906 | .signedness = .unsigned, | ||
| 1907 | .bits = zcu.errorSetBits(), | ||
| 1908 | }, mod, kind), | ||
| 1909 | |||
| 1910 | .undef, | ||
| 1911 | .simple_value, | ||
| 1912 | .variable, | ||
| 1913 | .extern_func, | ||
| 1914 | .func, | ||
| 1915 | .int, | ||
| 1916 | .err, | ||
| 1917 | .error_union, | ||
| 1918 | .enum_literal, | ||
| 1919 | .enum_tag, | ||
| 1920 | .empty_enum_value, | ||
| 1921 | .float, | ||
| 1922 | .ptr, | ||
| 1923 | .slice, | ||
| 1924 | .opt, | ||
| 1925 | .aggregate, | ||
| 1926 | .un, | ||
| 1927 | .memoized_call, | ||
| 1928 | => unreachable, | ||
| 1929 | }, | ||
| 1930 | } | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | pub fn getOrPutAdapted( | ||
| 1934 | pool: *Pool, | ||
| 1935 | allocator: std.mem.Allocator, | ||
| 1936 | source_pool: *const Pool, | ||
| 1937 | source_ctype: CType, | ||
| 1938 | pool_adapter: anytype, | ||
| 1939 | ) !struct { CType, bool } { | ||
| 1940 | const tag = source_pool.items.items(.tag)[ | ||
| 1941 | source_ctype.toPoolIndex() orelse return .{ source_ctype, true } | ||
| 1942 | ]; | ||
| 1943 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 1944 | const CTypeAdapter = struct { | ||
| 1945 | pool: *const Pool, | ||
| 1946 | source_pool: *const Pool, | ||
| 1947 | source_info: Info, | ||
| 1948 | pool_adapter: @TypeOf(pool_adapter), | ||
| 1949 | pub fn hash(map_adapter: @This(), key_ctype: CType) Map.Hash { | ||
| 1950 | return key_ctype.hash(map_adapter.source_pool); | ||
| 1951 | } | ||
| 1952 | pub fn eql(map_adapter: @This(), _: CType, _: void, pool_index: usize) bool { | ||
| 1953 | return map_adapter.source_info.eqlAdapted( | ||
| 1954 | map_adapter.source_pool, | ||
| 1955 | CType.fromPoolIndex(pool_index), | ||
| 1956 | map_adapter.pool, | ||
| 1957 | map_adapter.pool_adapter, | ||
| 1958 | ); | ||
| 1959 | } | ||
| 1960 | }; | ||
| 1961 | const source_info = source_ctype.info(source_pool); | ||
| 1962 | const gop = pool.map.getOrPutAssumeCapacityAdapted(source_ctype, CTypeAdapter{ | ||
| 1963 | .pool = pool, | ||
| 1964 | .source_pool = source_pool, | ||
| 1965 | .source_info = source_info, | ||
| 1966 | .pool_adapter = pool_adapter, | ||
| 1967 | }); | ||
| 1968 | errdefer _ = pool.map.pop(); | ||
| 1969 | const ctype = CType.fromPoolIndex(gop.index); | ||
| 1970 | if (!gop.found_existing) switch (source_info) { | ||
| 1971 | .basic => unreachable, | ||
| 1972 | .pointer => |pointer_info| pool.items.appendAssumeCapacity(.{ | ||
| 1973 | .tag = tag, | ||
| 1974 | .data = @intFromEnum(pool_adapter.copy(pointer_info.elem_ctype).index), | ||
| 1975 | }), | ||
| 1976 | .aligned => |aligned_info| pool.items.appendAssumeCapacity(.{ | ||
| 1977 | .tag = tag, | ||
| 1978 | .data = try pool.addExtra(allocator, Aligned, .{ | ||
| 1979 | .ctype = pool_adapter.copy(aligned_info.ctype).index, | ||
| 1980 | .flags = .{ .alignas = aligned_info.alignas }, | ||
| 1981 | }, 0), | ||
| 1982 | }), | ||
| 1983 | .array, .vector => |sequence_info| pool.items.appendAssumeCapacity(.{ | ||
| 1984 | .tag = tag, | ||
| 1985 | .data = switch (tag) { | ||
| 1986 | .array_small, .vector => try pool.addExtra(allocator, SequenceSmall, .{ | ||
| 1987 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | ||
| 1988 | .len = @intCast(sequence_info.len), | ||
| 1989 | }, 0), | ||
| 1990 | .array_large => try pool.addExtra(allocator, SequenceLarge, .{ | ||
| 1991 | .elem_ctype = pool_adapter.copy(sequence_info.elem_ctype).index, | ||
| 1992 | .len_lo = @truncate(sequence_info.len >> 0), | ||
| 1993 | .len_hi = @truncate(sequence_info.len >> 32), | ||
| 1994 | }, 0), | ||
| 1995 | else => unreachable, | ||
| 1996 | }, | ||
| 1997 | }), | ||
| 1998 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | ||
| 1999 | .anon => |fields| { | ||
| 2000 | pool.items.appendAssumeCapacity(.{ | ||
| 2001 | .tag = tag, | ||
| 2002 | .data = try pool.addExtra(allocator, FwdDeclAnon, .{ | ||
| 2003 | .fields_len = fields.len, | ||
| 2004 | }, fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2005 | }); | ||
| 2006 | for (0..fields.len) |field_index| { | ||
| 2007 | const field = fields.at(field_index, source_pool); | ||
| 2008 | const field_name = try pool.string(allocator, field.name.slice(source_pool)); | ||
| 2009 | pool.addExtraAssumeCapacity(Field, .{ | ||
| 2010 | .name = field_name.index, | ||
| 2011 | .ctype = pool_adapter.copy(field.ctype).index, | ||
| 2012 | .flags = .{ .alignas = field.alignas }, | ||
| 2013 | }); | ||
| 2014 | } | ||
| 2015 | }, | ||
| 2016 | .owner_decl => |owner_decl| pool.items.appendAssumeCapacity(.{ | ||
| 2017 | .tag = tag, | ||
| 2018 | .data = @intFromEnum(owner_decl), | ||
| 2019 | }), | ||
| 2020 | }, | ||
| 2021 | .aggregate => |aggregate_info| { | ||
| 2022 | pool.items.appendAssumeCapacity(.{ | ||
| 2023 | .tag = tag, | ||
| 2024 | .data = switch (aggregate_info.name) { | ||
| 2025 | .anon => |anon| try pool.addExtra(allocator, AggregateAnon, .{ | ||
| 2026 | .owner_decl = anon.owner_decl, | ||
| 2027 | .id = anon.id, | ||
| 2028 | .fields_len = aggregate_info.fields.len, | ||
| 2029 | }, aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2030 | .fwd_decl => |fwd_decl| try pool.addExtra(allocator, Aggregate, .{ | ||
| 2031 | .fwd_decl = pool_adapter.copy(fwd_decl).index, | ||
| 2032 | .fields_len = aggregate_info.fields.len, | ||
| 2033 | }, aggregate_info.fields.len * @typeInfo(Field).Struct.fields.len), | ||
| 2034 | }, | ||
| 2035 | }); | ||
| 2036 | for (0..aggregate_info.fields.len) |field_index| { | ||
| 2037 | const field = aggregate_info.fields.at(field_index, source_pool); | ||
| 2038 | const field_name = try pool.string(allocator, field.name.slice(source_pool)); | ||
| 2039 | pool.addExtraAssumeCapacity(Field, .{ | ||
| 2040 | .name = field_name.index, | ||
| 2041 | .ctype = pool_adapter.copy(field.ctype).index, | ||
| 2042 | .flags = .{ .alignas = field.alignas }, | ||
| 2043 | }); | ||
| 2044 | } | ||
| 2045 | }, | ||
| 2046 | .function => |function_info| { | ||
| 2047 | pool.items.appendAssumeCapacity(.{ | ||
| 2048 | .tag = tag, | ||
| 2049 | .data = try pool.addExtra(allocator, Function, .{ | ||
| 2050 | .return_ctype = pool_adapter.copy(function_info.return_ctype).index, | ||
| 2051 | .param_ctypes_len = function_info.param_ctypes.len, | ||
| 2052 | }, function_info.param_ctypes.len), | ||
| 2053 | }); | ||
| 2054 | for (0..function_info.param_ctypes.len) |param_index| pool.extra.appendAssumeCapacity( | ||
| 2055 | @intFromEnum(pool_adapter.copy( | ||
| 2056 | function_info.param_ctypes.at(param_index, source_pool), | ||
| 2057 | ).index), | ||
| 2058 | ); | ||
| 2059 | }, | ||
| 2060 | }; | ||
| 2061 | assert(source_info.eqlAdapted(source_pool, ctype, pool, pool_adapter)); | ||
| 2062 | assert(source_ctype.hash(source_pool) == ctype.hash(pool)); | ||
| 2063 | return .{ ctype, gop.found_existing }; | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | pub fn string(pool: *Pool, allocator: std.mem.Allocator, str: []const u8) !String { | ||
| 2067 | try pool.string_bytes.appendSlice(allocator, str); | ||
| 2068 | return pool.trailingString(allocator); | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | pub fn fmt( | ||
| 2072 | pool: *Pool, | ||
| 2073 | allocator: std.mem.Allocator, | ||
| 2074 | comptime fmt_str: []const u8, | ||
| 2075 | fmt_args: anytype, | ||
| 2076 | ) !String { | ||
| 2077 | try pool.string_bytes.writer(allocator).print(fmt_str, fmt_args); | ||
| 2078 | return pool.trailingString(allocator); | ||
| 2079 | } | ||
| 2080 | |||
| 2081 | fn ensureUnusedCapacity(pool: *Pool, allocator: std.mem.Allocator, len: u32) !void { | ||
| 2082 | try pool.map.ensureUnusedCapacity(allocator, len); | ||
| 2083 | try pool.items.ensureUnusedCapacity(allocator, len); | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | const Hasher = struct { | ||
| 2087 | const Impl = std.hash.Wyhash; | ||
| 2088 | impl: Impl, | ||
| 2089 | |||
| 2090 | const init: Hasher = .{ .impl = Impl.init(0) }; | ||
| 2091 | |||
| 2092 | fn updateExtra(hasher: *Hasher, comptime Extra: type, extra: Extra, pool: *const Pool) void { | ||
| 2093 | inline for (@typeInfo(Extra).Struct.fields) |field| { | ||
| 2094 | const value = @field(extra, field.name); | ||
| 2095 | hasher.update(switch (field.type) { | ||
| 2096 | Tag, String, CType => unreachable, | ||
| 2097 | CType.Index => (CType{ .index = value }).hash(pool), | ||
| 2098 | String.Index => (String{ .index = value }).slice(pool), | ||
| 2099 | else => value, | ||
| 2100 | }); | ||
| 2101 | } | ||
| 2102 | } | ||
| 2103 | fn update(hasher: *Hasher, data: anytype) void { | ||
| 2104 | switch (@TypeOf(data)) { | ||
| 2105 | Tag => @compileError("pass tag to final"), | ||
| 2106 | CType, CType.Index => @compileError("hash ctype.hash(pool) instead"), | ||
| 2107 | String, String.Index => @compileError("hash string.slice(pool) instead"), | ||
| 2108 | u32, DeclIndex, Aligned.Flags => hasher.impl.update(std.mem.asBytes(&data)), | ||
| 2109 | []const u8 => hasher.impl.update(data), | ||
| 2110 | else => @compileError("unhandled type: " ++ @typeName(@TypeOf(data))), | ||
| 2111 | } | ||
| 2112 | } | ||
| 2113 | |||
| 2114 | fn final(hasher: Hasher, tag: Tag) Map.Hash { | ||
| 2115 | var impl = hasher.impl; | ||
| 2116 | impl.update(std.mem.asBytes(&tag)); | ||
| 2117 | return @truncate(impl.final()); | ||
| 2118 | } | ||
| 2119 | }; | ||
| 2120 | |||
| 2121 | fn tagData( | ||
| 2122 | pool: *Pool, | ||
| 2123 | allocator: std.mem.Allocator, | ||
| 2124 | hasher: Hasher, | ||
| 2125 | tag: Tag, | ||
| 2126 | data: u32, | ||
| 2127 | ) !CType { | ||
| 2128 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 2129 | const Key = struct { hash: Map.Hash, tag: Tag, data: u32 }; | ||
| 2130 | const CTypeAdapter = struct { | ||
| 2131 | pool: *const Pool, | ||
| 2132 | pub fn hash(_: @This(), key: Key) Map.Hash { | ||
| 2133 | return key.hash; | ||
| 2134 | } | ||
| 2135 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | ||
| 2136 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | ||
| 2137 | return lhs_key.tag == rhs_item.tag and lhs_key.data == rhs_item.data; | ||
| 2138 | } | ||
| 2139 | }; | ||
| 2140 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | ||
| 2141 | Key{ .hash = hasher.final(tag), .tag = tag, .data = data }, | ||
| 2142 | CTypeAdapter{ .pool = pool }, | ||
| 2143 | ); | ||
| 2144 | if (!gop.found_existing) pool.items.appendAssumeCapacity(.{ .tag = tag, .data = data }); | ||
| 2145 | return CType.fromPoolIndex(gop.index); | ||
| 2146 | } | ||
| 2147 | |||
| 2148 | fn tagExtra( | ||
| 2149 | pool: *Pool, | ||
| 2150 | allocator: std.mem.Allocator, | ||
| 2151 | tag: Tag, | ||
| 2152 | comptime Extra: type, | ||
| 2153 | extra: Extra, | ||
| 2154 | ) !CType { | ||
| 2155 | var hasher = Hasher.init; | ||
| 2156 | hasher.updateExtra(Extra, extra, pool); | ||
| 2157 | return pool.tagTrailingExtra( | ||
| 2158 | allocator, | ||
| 2159 | hasher, | ||
| 2160 | tag, | ||
| 2161 | try pool.addExtra(allocator, Extra, extra, 0), | ||
| 2162 | ); | ||
| 2163 | } | ||
| 2164 | |||
| 2165 | fn tagTrailingExtra( | ||
| 2166 | pool: *Pool, | ||
| 2167 | allocator: std.mem.Allocator, | ||
| 2168 | hasher: Hasher, | ||
| 2169 | tag: Tag, | ||
| 2170 | extra_index: ExtraIndex, | ||
| 2171 | ) !CType { | ||
| 2172 | try pool.ensureUnusedCapacity(allocator, 1); | ||
| 2173 | return pool.tagTrailingExtraAssumeCapacity(hasher, tag, extra_index); | ||
| 2174 | } | ||
| 2175 | |||
| 2176 | fn tagTrailingExtraAssumeCapacity( | ||
| 2177 | pool: *Pool, | ||
| 2178 | hasher: Hasher, | ||
| 2179 | tag: Tag, | ||
| 2180 | extra_index: ExtraIndex, | ||
| 2181 | ) CType { | ||
| 2182 | const Key = struct { hash: Map.Hash, tag: Tag, extra: []const u32 }; | ||
| 2183 | const CTypeAdapter = struct { | ||
| 2184 | pool: *const Pool, | ||
| 2185 | pub fn hash(_: @This(), key: Key) Map.Hash { | ||
| 2186 | return key.hash; | ||
| 2187 | } | ||
| 2188 | pub fn eql(ctype_adapter: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { | ||
| 2189 | const rhs_item = ctype_adapter.pool.items.get(rhs_index); | ||
| 2190 | if (lhs_key.tag != rhs_item.tag) return false; | ||
| 2191 | const rhs_extra = ctype_adapter.pool.extra.items[rhs_item.data..]; | ||
| 2192 | return std.mem.startsWith(u32, rhs_extra, lhs_key.extra); | ||
| 2193 | } | ||
| 2194 | }; | ||
| 2195 | const gop = pool.map.getOrPutAssumeCapacityAdapted( | ||
| 2196 | Key{ .hash = hasher.final(tag), .tag = tag, .extra = pool.extra.items[extra_index..] }, | ||
| 2197 | CTypeAdapter{ .pool = pool }, | ||
| 2198 | ); | ||
| 2199 | if (gop.found_existing) | ||
| 2200 | pool.extra.shrinkRetainingCapacity(extra_index) | ||
| 2201 | else | ||
| 2202 | pool.items.appendAssumeCapacity(.{ .tag = tag, .data = extra_index }); | ||
| 2203 | return CType.fromPoolIndex(gop.index); | ||
| 2204 | } | ||
| 2205 | |||
| 2206 | fn sortFields(fields: []Info.Field) void { | ||
| 2207 | std.mem.sort(Info.Field, fields, {}, struct { | ||
| 2208 | fn before(_: void, lhs_field: Info.Field, rhs_field: Info.Field) bool { | ||
| 2209 | return lhs_field.alignas.order(rhs_field.alignas).compare(.gt); | ||
| 2210 | } | ||
| 2211 | }.before); | ||
| 2212 | } | ||
| 2213 | |||
| 2214 | fn trailingString(pool: *Pool, allocator: std.mem.Allocator) !String { | ||
| 2215 | const StringAdapter = struct { | ||
| 2216 | pool: *const Pool, | ||
| 2217 | pub fn hash(_: @This(), slice: []const u8) Map.Hash { | ||
| 2218 | return @truncate(Hasher.Impl.hash(1, slice)); | ||
| 2219 | } | ||
| 2220 | pub fn eql(string_adapter: @This(), lhs_slice: []const u8, _: void, rhs_index: usize) bool { | ||
| 2221 | const rhs_string: String = .{ .index = @enumFromInt(rhs_index) }; | ||
| 2222 | const rhs_slice = rhs_string.slice(string_adapter.pool); | ||
| 2223 | return std.mem.eql(u8, lhs_slice, rhs_slice); | ||
| 2224 | } | ||
| 2225 | }; | ||
| 2226 | try pool.string_map.ensureUnusedCapacity(allocator, 1); | ||
| 2227 | try pool.string_indices.ensureUnusedCapacity(allocator, 1); | ||
| 2228 | |||
| 2229 | const start = pool.string_indices.getLast(); | ||
| 2230 | const gop = pool.string_map.getOrPutAssumeCapacityAdapted( | ||
| 2231 | @as([]const u8, pool.string_bytes.items[start..]), | ||
| 2232 | StringAdapter{ .pool = pool }, | ||
| 2233 | ); | ||
| 2234 | if (gop.found_existing) | ||
| 2235 | pool.string_bytes.shrinkRetainingCapacity(start) | ||
| 2236 | else | ||
| 2237 | pool.string_indices.appendAssumeCapacity(@intCast(pool.string_bytes.items.len)); | ||
| 2238 | return .{ .index = @enumFromInt(gop.index) }; | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | const Item = struct { | ||
| 2242 | tag: Tag, | ||
| 2243 | data: u32, | ||
| 2244 | }; | ||
| 2245 | |||
| 2246 | const ExtraIndex = u32; | ||
| 2247 | |||
| 2248 | const Tag = enum(u8) { | ||
| 2249 | basic, | ||
| 2250 | pointer, | ||
| 2251 | pointer_const, | ||
| 2252 | pointer_volatile, | ||
| 2253 | pointer_const_volatile, | ||
| 2254 | aligned, | ||
| 2255 | array_small, | ||
| 2256 | array_large, | ||
| 2257 | vector, | ||
| 2258 | fwd_decl_struct_anon, | ||
| 2259 | fwd_decl_union_anon, | ||
| 2260 | fwd_decl_struct, | ||
| 2261 | fwd_decl_union, | ||
| 2262 | aggregate_struct_anon, | ||
| 2263 | aggregate_struct_packed_anon, | ||
| 2264 | aggregate_union_anon, | ||
| 2265 | aggregate_union_packed_anon, | ||
| 2266 | aggregate_struct, | ||
| 2267 | aggregate_struct_packed, | ||
| 2268 | aggregate_union, | ||
| 2269 | aggregate_union_packed, | ||
| 2270 | function, | ||
| 2271 | function_varargs, | ||
| 2272 | }; | ||
| 2273 | |||
| 2274 | const Aligned = struct { | ||
| 2275 | ctype: CType.Index, | ||
| 2276 | flags: Flags, | ||
| 2277 | |||
| 2278 | const Flags = packed struct(u32) { | ||
| 2279 | alignas: AlignAs, | ||
| 2280 | _: u20 = 0, | ||
| 2281 | }; | ||
| 2282 | }; | ||
| 2283 | |||
| 2284 | const SequenceSmall = struct { | ||
| 2285 | elem_ctype: CType.Index, | ||
| 2286 | len: u32, | ||
| 2287 | }; | ||
| 2288 | |||
| 2289 | const SequenceLarge = struct { | ||
| 2290 | elem_ctype: CType.Index, | ||
| 2291 | len_lo: u32, | ||
| 2292 | len_hi: u32, | ||
| 2293 | |||
| 2294 | fn len(extra: SequenceLarge) u64 { | ||
| 2295 | return @as(u64, extra.len_lo) << 0 | | ||
| 2296 | @as(u64, extra.len_hi) << 32; | ||
| 2297 | } | ||
| 2298 | }; | ||
| 2299 | |||
| 2300 | const Field = struct { | ||
| 2301 | name: String.Index, | ||
| 2302 | ctype: CType.Index, | ||
| 2303 | flags: Flags, | ||
| 2304 | |||
| 2305 | const Flags = Aligned.Flags; | ||
| 2306 | }; | ||
| 2307 | |||
| 2308 | const FwdDeclAnon = struct { | ||
| 2309 | fields_len: u32, | ||
| 2310 | }; | ||
| 2311 | |||
| 2312 | const AggregateAnon = struct { | ||
| 2313 | owner_decl: DeclIndex, | ||
| 2314 | id: u32, | ||
| 2315 | fields_len: u32, | ||
| 2316 | }; | ||
| 2317 | |||
| 2318 | const Aggregate = struct { | ||
| 2319 | fwd_decl: CType.Index, | ||
| 2320 | fields_len: u32, | ||
| 2321 | }; | ||
| 2322 | |||
| 2323 | const Function = struct { | ||
| 2324 | return_ctype: CType.Index, | ||
| 2325 | param_ctypes_len: u32, | ||
| 2326 | }; | ||
| 2327 | |||
| 2328 | fn addExtra( | ||
| 2329 | pool: *Pool, | ||
| 2330 | allocator: std.mem.Allocator, | ||
| 2331 | comptime Extra: type, | ||
| 2332 | extra: Extra, | ||
| 2333 | trailing_len: usize, | ||
| 2334 | ) !ExtraIndex { | ||
| 2335 | try pool.extra.ensureUnusedCapacity( | ||
| 2336 | allocator, | ||
| 2337 | @typeInfo(Extra).Struct.fields.len + trailing_len, | ||
| 2338 | ); | ||
| 2339 | defer pool.addExtraAssumeCapacity(Extra, extra); | ||
| 2340 | return @intCast(pool.extra.items.len); | ||
| 2341 | } | ||
| 2342 | fn addExtraAssumeCapacity(pool: *Pool, comptime Extra: type, extra: Extra) void { | ||
| 2343 | addExtraAssumeCapacityTo(&pool.extra, Extra, extra); | ||
| 2344 | } | ||
| 2345 | fn addExtraAssumeCapacityTo( | ||
| 2346 | array: *std.ArrayListUnmanaged(u32), | ||
| 2347 | comptime Extra: type, | ||
| 2348 | extra: Extra, | ||
| 2349 | ) void { | ||
| 2350 | inline for (@typeInfo(Extra).Struct.fields) |field| { | ||
| 2351 | const value = @field(extra, field.name); | ||
| 2352 | array.appendAssumeCapacity(switch (field.type) { | ||
| 2353 | u32 => value, | ||
| 2354 | CType.Index, String.Index, DeclIndex => @intFromEnum(value), | ||
| 2355 | Aligned.Flags => @bitCast(value), | ||
| 2356 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ | ||
| 2357 | @typeName(field.type)), | ||
| 2358 | }); | ||
| 2359 | } | ||
| 2360 | } | ||
| 2361 | |||
| 2362 | fn addHashedExtra( | ||
| 2363 | pool: *Pool, | ||
| 2364 | allocator: std.mem.Allocator, | ||
| 2365 | hasher: *Hasher, | ||
| 2366 | comptime Extra: type, | ||
| 2367 | extra: Extra, | ||
| 2368 | trailing_len: usize, | ||
| 2369 | ) !ExtraIndex { | ||
| 2370 | hasher.updateExtra(Extra, extra, pool); | ||
| 2371 | return pool.addExtra(allocator, Extra, extra, trailing_len); | ||
| 2372 | } | ||
| 2373 | fn addHashedExtraAssumeCapacity( | ||
| 2374 | pool: *Pool, | ||
| 2375 | hasher: *Hasher, | ||
| 2376 | comptime Extra: type, | ||
| 2377 | extra: Extra, | ||
| 2378 | ) void { | ||
| 2379 | hasher.updateExtra(Extra, extra, pool); | ||
| 2380 | pool.addExtraAssumeCapacity(Extra, extra); | ||
| 2381 | } | ||
| 2382 | fn addHashedExtraAssumeCapacityTo( | ||
| 2383 | pool: *Pool, | ||
| 2384 | array: *std.ArrayListUnmanaged(u32), | ||
| 2385 | hasher: *Hasher, | ||
| 2386 | comptime Extra: type, | ||
| 2387 | extra: Extra, | ||
| 2388 | ) void { | ||
| 2389 | hasher.updateExtra(Extra, extra, pool); | ||
| 2390 | addExtraAssumeCapacityTo(array, Extra, extra); | ||
| 2391 | } | ||
| 2392 | |||
| 2393 | const ExtraTrail = struct { | ||
| 2394 | extra_index: ExtraIndex, | ||
| 2395 | |||
| 2396 | fn next( | ||
| 2397 | extra_trail: *ExtraTrail, | ||
| 2398 | len: u32, | ||
| 2399 | comptime Extra: type, | ||
| 2400 | pool: *const Pool, | ||
| 2401 | ) []const Extra { | ||
| 2402 | defer extra_trail.extra_index += @intCast(len); | ||
| 2403 | return @ptrCast(pool.extra.items[extra_trail.extra_index..][0..len]); | ||
| 2404 | } | ||
| 2405 | }; | ||
| 2406 | |||
| 2407 | fn getExtraTrail( | ||
| 2408 | pool: *const Pool, | ||
| 2409 | comptime Extra: type, | ||
| 2410 | extra_index: ExtraIndex, | ||
| 2411 | ) struct { extra: Extra, trail: ExtraTrail } { | ||
| 2412 | var extra: Extra = undefined; | ||
| 2413 | const fields = @typeInfo(Extra).Struct.fields; | ||
| 2414 | inline for (fields, pool.extra.items[extra_index..][0..fields.len]) |field, value| | ||
| 2415 | @field(extra, field.name) = switch (field.type) { | ||
| 2416 | u32 => value, | ||
| 2417 | CType.Index, String.Index, DeclIndex => @enumFromInt(value), | ||
| 2418 | Aligned.Flags => @bitCast(value), | ||
| 2419 | else => @compileError("bad field type: " ++ field.name ++ ": " ++ @typeName(field.type)), | ||
| 2420 | }; | ||
| 2421 | return .{ | ||
| 2422 | .extra = extra, | ||
| 2423 | .trail = .{ .extra_index = extra_index + @as(ExtraIndex, @intCast(fields.len)) }, | ||
| 2424 | }; | ||
| 2425 | } | ||
| 2426 | |||
| 2427 | fn getExtra(pool: *const Pool, comptime Extra: type, extra_index: ExtraIndex) Extra { | ||
| 2428 | return pool.getExtraTrail(Extra, extra_index).extra; | ||
| 2429 | } | ||
| 2430 | }; | ||
| 2431 | |||
| 2432 | pub const AlignAs = packed struct { | ||
| 2433 | @"align": Alignment, | ||
| 2434 | abi: Alignment, | ||
| 2435 | |||
| 2436 | pub fn fromAlignment(alignas: AlignAs) AlignAs { | ||
| 2437 | assert(alignas.abi != .none); | ||
| 2438 | return .{ | ||
| 2439 | .@"align" = if (alignas.@"align" != .none) alignas.@"align" else alignas.abi, | ||
| 2440 | .abi = alignas.abi, | ||
| 2441 | }; | ||
| 2442 | } | ||
| 2443 | pub fn fromAbiAlignment(abi: Alignment) AlignAs { | ||
| 2444 | assert(abi != .none); | ||
| 2445 | return .{ .@"align" = abi, .abi = abi }; | ||
| 2446 | } | ||
| 2447 | pub fn fromByteUnits(@"align": u64, abi: u64) AlignAs { | ||
| 2448 | return fromAlignment(.{ | ||
| 2449 | .@"align" = Alignment.fromByteUnits(@"align"), | ||
| 2450 | .abi = Alignment.fromNonzeroByteUnits(abi), | ||
| 2451 | }); | ||
| 2452 | } | ||
| 2453 | |||
| 2454 | pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { | ||
| 2455 | return lhs.@"align".order(rhs.@"align"); | ||
| 2456 | } | ||
| 2457 | pub fn abiOrder(alignas: AlignAs) std.math.Order { | ||
| 2458 | return alignas.@"align".order(alignas.abi); | ||
| 2459 | } | ||
| 2460 | pub fn toByteUnits(alignas: AlignAs) u64 { | ||
| 2461 | return alignas.@"align".toByteUnits().?; | ||
| 2462 | } | ||
| 2463 | }; | ||
| 2464 | |||
| 2465 | const Alignment = @import("../../InternPool.zig").Alignment; | ||
| 2466 | const assert = std.debug.assert; | ||
| 2467 | const CType = @This(); | ||
| 2468 | const DeclIndex = std.zig.DeclIndex; | ||
| 2469 | const Module = @import("../../Package/Module.zig"); | ||
| 2470 | const std = @import("std"); | ||
| 2471 | const Type = @import("../../type.zig").Type; | ||
| 2472 | const Zcu = @import("../../Module.zig"); | ||
src/codegen/c/type.zig deleted-2332| ... | @@ -1,2332 +0,0 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const Allocator = mem.Allocator; | ||
| 4 | const assert = std.debug.assert; | ||
| 5 | const autoHash = std.hash.autoHash; | ||
| 6 | |||
| 7 | const Alignment = @import("../../InternPool.zig").Alignment; | ||
| 8 | const Zcu = @import("../../Module.zig"); | ||
| 9 | const Module = @import("../../Package/Module.zig"); | ||
| 10 | const InternPool = @import("../../InternPool.zig"); | ||
| 11 | const Type = @import("../../type.zig").Type; | ||
| 12 | |||
| 13 | pub const CType = extern union { | ||
| 14 | /// If the tag value is less than Tag.no_payload_count, then no pointer | ||
| 15 | /// dereference is needed. | ||
| 16 | tag_if_small_enough: Tag, | ||
| 17 | ptr_otherwise: *const Payload, | ||
| 18 | |||
| 19 | pub fn initTag(small_tag: Tag) CType { | ||
| 20 | assert(!small_tag.hasPayload()); | ||
| 21 | return .{ .tag_if_small_enough = small_tag }; | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn initPayload(pl: anytype) CType { | ||
| 25 | const T = @typeInfo(@TypeOf(pl)).Pointer.child; | ||
| 26 | return switch (pl.base.tag) { | ||
| 27 | inline else => |t| if (comptime t.hasPayload() and t.Type() == T) .{ | ||
| 28 | .ptr_otherwise = &pl.base, | ||
| 29 | } else unreachable, | ||
| 30 | }; | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn hasPayload(self: CType) bool { | ||
| 34 | return self.tag_if_small_enough.hasPayload(); | ||
| 35 | } | ||
| 36 | |||
| 37 | pub fn tag(self: CType) Tag { | ||
| 38 | return if (self.hasPayload()) self.ptr_otherwise.tag else self.tag_if_small_enough; | ||
| 39 | } | ||
| 40 | |||
| 41 | pub fn cast(self: CType, comptime T: type) ?*const T { | ||
| 42 | if (!self.hasPayload()) return null; | ||
| 43 | const pl = self.ptr_otherwise; | ||
| 44 | return switch (pl.tag) { | ||
| 45 | inline else => |t| if (comptime t.hasPayload() and t.Type() == T) | ||
| 46 | @fieldParentPtr(T, "base", pl) | ||
| 47 | else | ||
| 48 | null, | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn castTag(self: CType, comptime t: Tag) ?*const t.Type() { | ||
| 53 | return if (self.tag() == t) @fieldParentPtr(t.Type(), "base", self.ptr_otherwise) else null; | ||
| 54 | } | ||
| 55 | |||
| 56 | pub const Tag = enum(usize) { | ||
| 57 | // The first section of this enum are tags that require no payload. | ||
| 58 | void, | ||
| 59 | |||
| 60 | // C basic types | ||
| 61 | char, | ||
| 62 | |||
| 63 | @"signed char", | ||
| 64 | short, | ||
| 65 | int, | ||
| 66 | long, | ||
| 67 | @"long long", | ||
| 68 | |||
| 69 | _Bool, | ||
| 70 | @"unsigned char", | ||
| 71 | @"unsigned short", | ||
| 72 | @"unsigned int", | ||
| 73 | @"unsigned long", | ||
| 74 | @"unsigned long long", | ||
| 75 | |||
| 76 | float, | ||
| 77 | double, | ||
| 78 | @"long double", | ||
| 79 | |||
| 80 | // C header types | ||
| 81 | // - stdbool.h | ||
| 82 | bool, | ||
| 83 | // - stddef.h | ||
| 84 | size_t, | ||
| 85 | ptrdiff_t, | ||
| 86 | // - stdint.h | ||
| 87 | uint8_t, | ||
| 88 | int8_t, | ||
| 89 | uint16_t, | ||
| 90 | int16_t, | ||
| 91 | uint32_t, | ||
| 92 | int32_t, | ||
| 93 | uint64_t, | ||
| 94 | int64_t, | ||
| 95 | uintptr_t, | ||
| 96 | intptr_t, | ||
| 97 | |||
| 98 | // zig.h types | ||
| 99 | zig_u128, | ||
| 100 | zig_i128, | ||
| 101 | zig_f16, | ||
| 102 | zig_f32, | ||
| 103 | zig_f64, | ||
| 104 | zig_f80, | ||
| 105 | zig_f128, | ||
| 106 | zig_c_longdouble, // Keep last_no_payload_tag updated! | ||
| 107 | |||
| 108 | // After this, the tag requires a payload. | ||
| 109 | pointer, | ||
| 110 | pointer_const, | ||
| 111 | pointer_volatile, | ||
| 112 | pointer_const_volatile, | ||
| 113 | array, | ||
| 114 | vector, | ||
| 115 | fwd_anon_struct, | ||
| 116 | fwd_anon_union, | ||
| 117 | fwd_struct, | ||
| 118 | fwd_union, | ||
| 119 | unnamed_struct, | ||
| 120 | unnamed_union, | ||
| 121 | packed_unnamed_struct, | ||
| 122 | packed_unnamed_union, | ||
| 123 | anon_struct, | ||
| 124 | anon_union, | ||
| 125 | @"struct", | ||
| 126 | @"union", | ||
| 127 | packed_struct, | ||
| 128 | packed_union, | ||
| 129 | function, | ||
| 130 | varargs_function, | ||
| 131 | |||
| 132 | pub const last_no_payload_tag = Tag.zig_c_longdouble; | ||
| 133 | pub const no_payload_count = @intFromEnum(last_no_payload_tag) + 1; | ||
| 134 | |||
| 135 | pub fn hasPayload(self: Tag) bool { | ||
| 136 | return @intFromEnum(self) >= no_payload_count; | ||
| 137 | } | ||
| 138 | |||
| 139 | pub fn toIndex(self: Tag) Index { | ||
| 140 | assert(!self.hasPayload()); | ||
| 141 | return @as(Index, @intCast(@intFromEnum(self))); | ||
| 142 | } | ||
| 143 | |||
| 144 | pub fn Type(comptime self: Tag) type { | ||
| 145 | return switch (self) { | ||
| 146 | .void, | ||
| 147 | .char, | ||
| 148 | .@"signed char", | ||
| 149 | .short, | ||
| 150 | .int, | ||
| 151 | .long, | ||
| 152 | .@"long long", | ||
| 153 | ._Bool, | ||
| 154 | .@"unsigned char", | ||
| 155 | .@"unsigned short", | ||
| 156 | .@"unsigned int", | ||
| 157 | .@"unsigned long", | ||
| 158 | .@"unsigned long long", | ||
| 159 | .float, | ||
| 160 | .double, | ||
| 161 | .@"long double", | ||
| 162 | .bool, | ||
| 163 | .size_t, | ||
| 164 | .ptrdiff_t, | ||
| 165 | .uint8_t, | ||
| 166 | .int8_t, | ||
| 167 | .uint16_t, | ||
| 168 | .int16_t, | ||
| 169 | .uint32_t, | ||
| 170 | .int32_t, | ||
| 171 | .uint64_t, | ||
| 172 | .int64_t, | ||
| 173 | .uintptr_t, | ||
| 174 | .intptr_t, | ||
| 175 | .zig_u128, | ||
| 176 | .zig_i128, | ||
| 177 | .zig_f16, | ||
| 178 | .zig_f32, | ||
| 179 | .zig_f64, | ||
| 180 | .zig_f80, | ||
| 181 | .zig_f128, | ||
| 182 | .zig_c_longdouble, | ||
| 183 | => @compileError("Type Tag " ++ @tagName(self) ++ " has no payload"), | ||
| 184 | |||
| 185 | .pointer, | ||
| 186 | .pointer_const, | ||
| 187 | .pointer_volatile, | ||
| 188 | .pointer_const_volatile, | ||
| 189 | => Payload.Child, | ||
| 190 | |||
| 191 | .array, | ||
| 192 | .vector, | ||
| 193 | => Payload.Sequence, | ||
| 194 | |||
| 195 | .fwd_anon_struct, | ||
| 196 | .fwd_anon_union, | ||
| 197 | => Payload.Fields, | ||
| 198 | |||
| 199 | .fwd_struct, | ||
| 200 | .fwd_union, | ||
| 201 | => Payload.FwdDecl, | ||
| 202 | |||
| 203 | .unnamed_struct, | ||
| 204 | .unnamed_union, | ||
| 205 | .packed_unnamed_struct, | ||
| 206 | .packed_unnamed_union, | ||
| 207 | => Payload.Unnamed, | ||
| 208 | |||
| 209 | .anon_struct, | ||
| 210 | .anon_union, | ||
| 211 | .@"struct", | ||
| 212 | .@"union", | ||
| 213 | .packed_struct, | ||
| 214 | .packed_union, | ||
| 215 | => Payload.Aggregate, | ||
| 216 | |||
| 217 | .function, | ||
| 218 | .varargs_function, | ||
| 219 | => Payload.Function, | ||
| 220 | }; | ||
| 221 | } | ||
| 222 | }; | ||
| 223 | |||
| 224 | pub const Payload = struct { | ||
| 225 | tag: Tag, | ||
| 226 | |||
| 227 | pub const Child = struct { | ||
| 228 | base: Payload, | ||
| 229 | data: Index, | ||
| 230 | }; | ||
| 231 | |||
| 232 | pub const Sequence = struct { | ||
| 233 | base: Payload, | ||
| 234 | data: struct { | ||
| 235 | len: u64, | ||
| 236 | elem_type: Index, | ||
| 237 | }, | ||
| 238 | }; | ||
| 239 | |||
| 240 | pub const FwdDecl = struct { | ||
| 241 | base: Payload, | ||
| 242 | data: InternPool.DeclIndex, | ||
| 243 | }; | ||
| 244 | |||
| 245 | pub const Fields = struct { | ||
| 246 | base: Payload, | ||
| 247 | data: Data, | ||
| 248 | |||
| 249 | pub const Data = []const Field; | ||
| 250 | pub const Field = struct { | ||
| 251 | name: [*:0]const u8, | ||
| 252 | type: Index, | ||
| 253 | alignas: AlignAs, | ||
| 254 | }; | ||
| 255 | }; | ||
| 256 | |||
| 257 | pub const Unnamed = struct { | ||
| 258 | base: Payload, | ||
| 259 | data: struct { | ||
| 260 | fields: Fields.Data, | ||
| 261 | owner_decl: InternPool.DeclIndex, | ||
| 262 | id: u32, | ||
| 263 | }, | ||
| 264 | }; | ||
| 265 | |||
| 266 | pub const Aggregate = struct { | ||
| 267 | base: Payload, | ||
| 268 | data: struct { | ||
| 269 | fields: Fields.Data, | ||
| 270 | fwd_decl: Index, | ||
| 271 | }, | ||
| 272 | }; | ||
| 273 | |||
| 274 | pub const Function = struct { | ||
| 275 | base: Payload, | ||
| 276 | data: struct { | ||
| 277 | return_type: Index, | ||
| 278 | param_types: []const Index, | ||
| 279 | }, | ||
| 280 | }; | ||
| 281 | }; | ||
| 282 | |||
| 283 | pub const AlignAs = packed struct { | ||
| 284 | @"align": Alignment, | ||
| 285 | abi: Alignment, | ||
| 286 | |||
| 287 | pub fn init(@"align": Alignment, abi_align: Alignment) AlignAs { | ||
| 288 | assert(abi_align != .none); | ||
| 289 | return .{ | ||
| 290 | .@"align" = if (@"align" != .none) @"align" else abi_align, | ||
| 291 | .abi = abi_align, | ||
| 292 | }; | ||
| 293 | } | ||
| 294 | |||
| 295 | pub fn initByteUnits(alignment: u64, abi_alignment: u32) AlignAs { | ||
| 296 | return init( | ||
| 297 | Alignment.fromByteUnits(alignment), | ||
| 298 | Alignment.fromNonzeroByteUnits(abi_alignment), | ||
| 299 | ); | ||
| 300 | } | ||
| 301 | pub fn abiAlign(ty: Type, zcu: *Zcu) AlignAs { | ||
| 302 | const abi_align = ty.abiAlignment(zcu); | ||
| 303 | return init(abi_align, abi_align); | ||
| 304 | } | ||
| 305 | pub fn fieldAlign(struct_ty: Type, field_i: usize, zcu: *Zcu) AlignAs { | ||
| 306 | return init( | ||
| 307 | struct_ty.structFieldAlign(field_i, zcu), | ||
| 308 | struct_ty.structFieldType(field_i, zcu).abiAlignment(zcu), | ||
| 309 | ); | ||
| 310 | } | ||
| 311 | pub fn unionPayloadAlign(union_ty: Type, zcu: *Zcu) AlignAs { | ||
| 312 | const union_obj = zcu.typeToUnion(union_ty).?; | ||
| 313 | const union_payload_align = zcu.unionAbiAlignment(union_obj); | ||
| 314 | return init(union_payload_align, union_payload_align); | ||
| 315 | } | ||
| 316 | |||
| 317 | pub fn order(lhs: AlignAs, rhs: AlignAs) std.math.Order { | ||
| 318 | return lhs.@"align".order(rhs.@"align"); | ||
| 319 | } | ||
| 320 | pub fn abiOrder(self: AlignAs) std.math.Order { | ||
| 321 | return self.@"align".order(self.abi); | ||
| 322 | } | ||
| 323 | pub fn toByteUnits(self: AlignAs) u64 { | ||
| 324 | return self.@"align".toByteUnitsOptional().?; | ||
| 325 | } | ||
| 326 | }; | ||
| 327 | |||
| 328 | pub const Index = u32; | ||
| 329 | pub const Store = struct { | ||
| 330 | arena: std.heap.ArenaAllocator.State = .{}, | ||
| 331 | set: Set = .{}, | ||
| 332 | |||
| 333 | pub const Set = struct { | ||
| 334 | pub const Map = std.ArrayHashMapUnmanaged(CType, void, HashContext, true); | ||
| 335 | const HashContext = struct { | ||
| 336 | store: *const Set, | ||
| 337 | |||
| 338 | pub fn hash(self: @This(), cty: CType) Map.Hash { | ||
| 339 | return @as(Map.Hash, @truncate(cty.hash(self.store.*))); | ||
| 340 | } | ||
| 341 | pub fn eql(_: @This(), lhs: CType, rhs: CType, _: usize) bool { | ||
| 342 | return lhs.eql(rhs); | ||
| 343 | } | ||
| 344 | }; | ||
| 345 | |||
| 346 | map: Map = .{}, | ||
| 347 | |||
| 348 | pub fn indexToCType(self: Set, index: Index) CType { | ||
| 349 | if (index < Tag.no_payload_count) return initTag(@as(Tag, @enumFromInt(index))); | ||
| 350 | return self.map.keys()[index - Tag.no_payload_count]; | ||
| 351 | } | ||
| 352 | |||
| 353 | pub fn indexToHash(self: Set, index: Index) Map.Hash { | ||
| 354 | if (index < Tag.no_payload_count) | ||
| 355 | return (HashContext{ .store = &self }).hash(self.indexToCType(index)); | ||
| 356 | return self.map.entries.items(.hash)[index - Tag.no_payload_count]; | ||
| 357 | } | ||
| 358 | |||
| 359 | pub fn typeToIndex(self: Set, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) ?Index { | ||
| 360 | const lookup = Convert.Lookup{ .imm = .{ .set = &self, .zcu = zcu, .mod = mod } }; | ||
| 361 | |||
| 362 | var convert: Convert = undefined; | ||
| 363 | convert.initType(ty, kind, lookup) catch unreachable; | ||
| 364 | |||
| 365 | const t = convert.tag(); | ||
| 366 | if (!t.hasPayload()) return t.toIndex(); | ||
| 367 | |||
| 368 | return if (self.map.getIndexAdapted( | ||
| 369 | ty, | ||
| 370 | TypeAdapter32{ .kind = kind, .lookup = lookup, .convert = &convert }, | ||
| 371 | )) |idx| @as(Index, @intCast(Tag.no_payload_count + idx)) else null; | ||
| 372 | } | ||
| 373 | }; | ||
| 374 | |||
| 375 | pub const Promoted = struct { | ||
| 376 | arena: std.heap.ArenaAllocator, | ||
| 377 | set: Set, | ||
| 378 | |||
| 379 | pub fn gpa(self: *Promoted) Allocator { | ||
| 380 | return self.arena.child_allocator; | ||
| 381 | } | ||
| 382 | |||
| 383 | pub fn cTypeToIndex(self: *Promoted, cty: CType) Allocator.Error!Index { | ||
| 384 | const t = cty.tag(); | ||
| 385 | if (@intFromEnum(t) < Tag.no_payload_count) return @as(Index, @intCast(@intFromEnum(t))); | ||
| 386 | |||
| 387 | const gop = try self.set.map.getOrPutContext(self.gpa(), cty, .{ .store = &self.set }); | ||
| 388 | if (!gop.found_existing) gop.key_ptr.* = cty; | ||
| 389 | if (std.debug.runtime_safety) { | ||
| 390 | const key = &self.set.map.entries.items(.key)[gop.index]; | ||
| 391 | assert(key == gop.key_ptr); | ||
| 392 | assert(cty.eql(key.*)); | ||
| 393 | assert(cty.hash(self.set) == key.hash(self.set)); | ||
| 394 | } | ||
| 395 | return @as(Index, @intCast(Tag.no_payload_count + gop.index)); | ||
| 396 | } | ||
| 397 | |||
| 398 | pub fn typeToIndex( | ||
| 399 | self: *Promoted, | ||
| 400 | ty: Type, | ||
| 401 | zcu: *Zcu, | ||
| 402 | mod: *Module, | ||
| 403 | kind: Kind, | ||
| 404 | ) Allocator.Error!Index { | ||
| 405 | const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .zcu = zcu, .mod = mod } }; | ||
| 406 | |||
| 407 | var convert: Convert = undefined; | ||
| 408 | try convert.initType(ty, kind, lookup); | ||
| 409 | |||
| 410 | const t = convert.tag(); | ||
| 411 | if (!t.hasPayload()) return t.toIndex(); | ||
| 412 | |||
| 413 | const gop = try self.set.map.getOrPutContextAdapted( | ||
| 414 | self.gpa(), | ||
| 415 | ty, | ||
| 416 | TypeAdapter32{ .kind = kind, .lookup = lookup.freeze(), .convert = &convert }, | ||
| 417 | .{ .store = &self.set }, | ||
| 418 | ); | ||
| 419 | if (!gop.found_existing) { | ||
| 420 | errdefer _ = self.set.map.pop(); | ||
| 421 | gop.key_ptr.* = try createFromConvert(self, ty, zcu, mod, kind, convert); | ||
| 422 | } | ||
| 423 | if (std.debug.runtime_safety) { | ||
| 424 | const adapter = TypeAdapter64{ | ||
| 425 | .kind = kind, | ||
| 426 | .lookup = lookup.freeze(), | ||
| 427 | .convert = &convert, | ||
| 428 | }; | ||
| 429 | const cty = &self.set.map.entries.items(.key)[gop.index]; | ||
| 430 | assert(cty == gop.key_ptr); | ||
| 431 | assert(adapter.eql(ty, cty.*)); | ||
| 432 | assert(adapter.hash(ty) == cty.hash(self.set)); | ||
| 433 | } | ||
| 434 | return @as(Index, @intCast(Tag.no_payload_count + gop.index)); | ||
| 435 | } | ||
| 436 | }; | ||
| 437 | |||
| 438 | pub fn promote(self: Store, gpa: Allocator) Promoted { | ||
| 439 | return .{ .arena = self.arena.promote(gpa), .set = self.set }; | ||
| 440 | } | ||
| 441 | |||
| 442 | pub fn demote(self: *Store, promoted: Promoted) void { | ||
| 443 | self.arena = promoted.arena.state; | ||
| 444 | self.set = promoted.set; | ||
| 445 | } | ||
| 446 | |||
| 447 | pub fn indexToCType(self: Store, index: Index) CType { | ||
| 448 | return self.set.indexToCType(index); | ||
| 449 | } | ||
| 450 | |||
| 451 | pub fn indexToHash(self: Store, index: Index) Set.Map.Hash { | ||
| 452 | return self.set.indexToHash(index); | ||
| 453 | } | ||
| 454 | |||
| 455 | pub fn cTypeToIndex(self: *Store, gpa: Allocator, cty: CType) !Index { | ||
| 456 | var promoted = self.promote(gpa); | ||
| 457 | defer self.demote(promoted); | ||
| 458 | return promoted.cTypeToIndex(cty); | ||
| 459 | } | ||
| 460 | |||
| 461 | pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType { | ||
| 462 | const idx = try self.typeToIndex(gpa, ty, zcu, mod, kind); | ||
| 463 | return self.indexToCType(idx); | ||
| 464 | } | ||
| 465 | |||
| 466 | pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !Index { | ||
| 467 | var promoted = self.promote(gpa); | ||
| 468 | defer self.demote(promoted); | ||
| 469 | return promoted.typeToIndex(ty, zcu, mod, kind); | ||
| 470 | } | ||
| 471 | |||
| 472 | pub fn clearRetainingCapacity(self: *Store, gpa: Allocator) void { | ||
| 473 | var promoted = self.promote(gpa); | ||
| 474 | defer self.demote(promoted); | ||
| 475 | promoted.set.map.clearRetainingCapacity(); | ||
| 476 | _ = promoted.arena.reset(.retain_capacity); | ||
| 477 | } | ||
| 478 | |||
| 479 | pub fn clearAndFree(self: *Store, gpa: Allocator) void { | ||
| 480 | var promoted = self.promote(gpa); | ||
| 481 | defer self.demote(promoted); | ||
| 482 | promoted.set.map.clearAndFree(gpa); | ||
| 483 | _ = promoted.arena.reset(.free_all); | ||
| 484 | } | ||
| 485 | |||
| 486 | pub fn shrinkRetainingCapacity(self: *Store, gpa: Allocator, new_len: usize) void { | ||
| 487 | self.set.map.shrinkRetainingCapacity(gpa, new_len); | ||
| 488 | } | ||
| 489 | |||
| 490 | pub fn shrinkAndFree(self: *Store, gpa: Allocator, new_len: usize) void { | ||
| 491 | self.set.map.shrinkAndFree(gpa, new_len); | ||
| 492 | } | ||
| 493 | |||
| 494 | pub fn count(self: Store) usize { | ||
| 495 | return self.set.map.count(); | ||
| 496 | } | ||
| 497 | |||
| 498 | pub fn move(self: *Store) Store { | ||
| 499 | const moved = self.*; | ||
| 500 | self.* = .{}; | ||
| 501 | return moved; | ||
| 502 | } | ||
| 503 | |||
| 504 | pub fn deinit(self: *Store, gpa: Allocator) void { | ||
| 505 | var promoted = self.promote(gpa); | ||
| 506 | promoted.set.map.deinit(gpa); | ||
| 507 | _ = promoted.arena.deinit(); | ||
| 508 | self.* = undefined; | ||
| 509 | } | ||
| 510 | }; | ||
| 511 | |||
| 512 | pub fn isBool(self: CType) bool { | ||
| 513 | return switch (self.tag()) { | ||
| 514 | ._Bool, | ||
| 515 | .bool, | ||
| 516 | => true, | ||
| 517 | else => false, | ||
| 518 | }; | ||
| 519 | } | ||
| 520 | |||
| 521 | pub fn isInteger(self: CType) bool { | ||
| 522 | return switch (self.tag()) { | ||
| 523 | .char, | ||
| 524 | .@"signed char", | ||
| 525 | .short, | ||
| 526 | .int, | ||
| 527 | .long, | ||
| 528 | .@"long long", | ||
| 529 | .@"unsigned char", | ||
| 530 | .@"unsigned short", | ||
| 531 | .@"unsigned int", | ||
| 532 | .@"unsigned long", | ||
| 533 | .@"unsigned long long", | ||
| 534 | .size_t, | ||
| 535 | .ptrdiff_t, | ||
| 536 | .uint8_t, | ||
| 537 | .int8_t, | ||
| 538 | .uint16_t, | ||
| 539 | .int16_t, | ||
| 540 | .uint32_t, | ||
| 541 | .int32_t, | ||
| 542 | .uint64_t, | ||
| 543 | .int64_t, | ||
| 544 | .uintptr_t, | ||
| 545 | .intptr_t, | ||
| 546 | .zig_u128, | ||
| 547 | .zig_i128, | ||
| 548 | => true, | ||
| 549 | else => false, | ||
| 550 | }; | ||
| 551 | } | ||
| 552 | |||
| 553 | pub fn signedness(self: CType, mod: *Module) std.builtin.Signedness { | ||
| 554 | return switch (self.tag()) { | ||
| 555 | .char => mod.resolved_target.result.charSignedness(), | ||
| 556 | .@"signed char", | ||
| 557 | .short, | ||
| 558 | .int, | ||
| 559 | .long, | ||
| 560 | .@"long long", | ||
| 561 | .ptrdiff_t, | ||
| 562 | .int8_t, | ||
| 563 | .int16_t, | ||
| 564 | .int32_t, | ||
| 565 | .int64_t, | ||
| 566 | .intptr_t, | ||
| 567 | .zig_i128, | ||
| 568 | => .signed, | ||
| 569 | .@"unsigned char", | ||
| 570 | .@"unsigned short", | ||
| 571 | .@"unsigned int", | ||
| 572 | .@"unsigned long", | ||
| 573 | .@"unsigned long long", | ||
| 574 | .size_t, | ||
| 575 | .uint8_t, | ||
| 576 | .uint16_t, | ||
| 577 | .uint32_t, | ||
| 578 | .uint64_t, | ||
| 579 | .uintptr_t, | ||
| 580 | .zig_u128, | ||
| 581 | => .unsigned, | ||
| 582 | else => unreachable, | ||
| 583 | }; | ||
| 584 | } | ||
| 585 | |||
| 586 | pub fn isFloat(self: CType) bool { | ||
| 587 | return switch (self.tag()) { | ||
| 588 | .float, | ||
| 589 | .double, | ||
| 590 | .@"long double", | ||
| 591 | .zig_f16, | ||
| 592 | .zig_f32, | ||
| 593 | .zig_f64, | ||
| 594 | .zig_f80, | ||
| 595 | .zig_f128, | ||
| 596 | .zig_c_longdouble, | ||
| 597 | => true, | ||
| 598 | else => false, | ||
| 599 | }; | ||
| 600 | } | ||
| 601 | |||
| 602 | pub fn isPointer(self: CType) bool { | ||
| 603 | return switch (self.tag()) { | ||
| 604 | .pointer, | ||
| 605 | .pointer_const, | ||
| 606 | .pointer_volatile, | ||
| 607 | .pointer_const_volatile, | ||
| 608 | => true, | ||
| 609 | else => false, | ||
| 610 | }; | ||
| 611 | } | ||
| 612 | |||
| 613 | pub fn isFunction(self: CType) bool { | ||
| 614 | return switch (self.tag()) { | ||
| 615 | .function, | ||
| 616 | .varargs_function, | ||
| 617 | => true, | ||
| 618 | else => false, | ||
| 619 | }; | ||
| 620 | } | ||
| 621 | |||
| 622 | pub fn toSigned(self: CType) CType { | ||
| 623 | return CType.initTag(switch (self.tag()) { | ||
| 624 | .char, .@"signed char", .@"unsigned char" => .@"signed char", | ||
| 625 | .short, .@"unsigned short" => .short, | ||
| 626 | .int, .@"unsigned int" => .int, | ||
| 627 | .long, .@"unsigned long" => .long, | ||
| 628 | .@"long long", .@"unsigned long long" => .@"long long", | ||
| 629 | .size_t, .ptrdiff_t => .ptrdiff_t, | ||
| 630 | .uint8_t, .int8_t => .int8_t, | ||
| 631 | .uint16_t, .int16_t => .int16_t, | ||
| 632 | .uint32_t, .int32_t => .int32_t, | ||
| 633 | .uint64_t, .int64_t => .int64_t, | ||
| 634 | .uintptr_t, .intptr_t => .intptr_t, | ||
| 635 | .zig_u128, .zig_i128 => .zig_i128, | ||
| 636 | .float, | ||
| 637 | .double, | ||
| 638 | .@"long double", | ||
| 639 | .zig_f16, | ||
| 640 | .zig_f32, | ||
| 641 | .zig_f80, | ||
| 642 | .zig_f128, | ||
| 643 | .zig_c_longdouble, | ||
| 644 | => |t| t, | ||
| 645 | else => unreachable, | ||
| 646 | }); | ||
| 647 | } | ||
| 648 | |||
| 649 | pub fn toUnsigned(self: CType) CType { | ||
| 650 | return CType.initTag(switch (self.tag()) { | ||
| 651 | .char, .@"signed char", .@"unsigned char" => .@"unsigned char", | ||
| 652 | .short, .@"unsigned short" => .@"unsigned short", | ||
| 653 | .int, .@"unsigned int" => .@"unsigned int", | ||
| 654 | .long, .@"unsigned long" => .@"unsigned long", | ||
| 655 | .@"long long", .@"unsigned long long" => .@"unsigned long long", | ||
| 656 | .size_t, .ptrdiff_t => .size_t, | ||
| 657 | .uint8_t, .int8_t => .uint8_t, | ||
| 658 | .uint16_t, .int16_t => .uint16_t, | ||
| 659 | .uint32_t, .int32_t => .uint32_t, | ||
| 660 | .uint64_t, .int64_t => .uint64_t, | ||
| 661 | .uintptr_t, .intptr_t => .uintptr_t, | ||
| 662 | .zig_u128, .zig_i128 => .zig_u128, | ||
| 663 | else => unreachable, | ||
| 664 | }); | ||
| 665 | } | ||
| 666 | |||
| 667 | pub fn toSignedness(self: CType, s: std.builtin.Signedness) CType { | ||
| 668 | return switch (s) { | ||
| 669 | .unsigned => self.toUnsigned(), | ||
| 670 | .signed => self.toSigned(), | ||
| 671 | }; | ||
| 672 | } | ||
| 673 | |||
| 674 | pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 { | ||
| 675 | return switch (self.tag()) { | ||
| 676 | .char => "CHAR", | ||
| 677 | .@"signed char" => "SCHAR", | ||
| 678 | .short => "SHRT", | ||
| 679 | .int => "INT", | ||
| 680 | .long => "LONG", | ||
| 681 | .@"long long" => "LLONG", | ||
| 682 | .@"unsigned char" => "UCHAR", | ||
| 683 | .@"unsigned short" => "USHRT", | ||
| 684 | .@"unsigned int" => "UINT", | ||
| 685 | .@"unsigned long" => "ULONG", | ||
| 686 | .@"unsigned long long" => "ULLONG", | ||
| 687 | .float => "FLT", | ||
| 688 | .double => "DBL", | ||
| 689 | .@"long double" => "LDBL", | ||
| 690 | .size_t => "SIZE", | ||
| 691 | .ptrdiff_t => "PTRDIFF", | ||
| 692 | .uint8_t => "UINT8", | ||
| 693 | .int8_t => "INT8", | ||
| 694 | .uint16_t => "UINT16", | ||
| 695 | .int16_t => "INT16", | ||
| 696 | .uint32_t => "UINT32", | ||
| 697 | .int32_t => "INT32", | ||
| 698 | .uint64_t => "UINT64", | ||
| 699 | .int64_t => "INT64", | ||
| 700 | .uintptr_t => "UINTPTR", | ||
| 701 | .intptr_t => "INTPTR", | ||
| 702 | else => null, | ||
| 703 | }; | ||
| 704 | } | ||
| 705 | |||
| 706 | pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void { | ||
| 707 | switch (self.tag()) { | ||
| 708 | .void => unreachable, | ||
| 709 | ._Bool, | ||
| 710 | .char, | ||
| 711 | .@"signed char", | ||
| 712 | .short, | ||
| 713 | .@"unsigned short", | ||
| 714 | .bool, | ||
| 715 | .size_t, | ||
| 716 | .ptrdiff_t, | ||
| 717 | .uintptr_t, | ||
| 718 | .intptr_t, | ||
| 719 | => |t| switch (kind) { | ||
| 720 | else => try writer.print("({s})", .{@tagName(t)}), | ||
| 721 | .global => {}, | ||
| 722 | }, | ||
| 723 | .int, | ||
| 724 | .long, | ||
| 725 | .@"long long", | ||
| 726 | .@"unsigned char", | ||
| 727 | .@"unsigned int", | ||
| 728 | .@"unsigned long", | ||
| 729 | .@"unsigned long long", | ||
| 730 | .float, | ||
| 731 | .double, | ||
| 732 | .@"long double", | ||
| 733 | => {}, | ||
| 734 | .uint8_t, | ||
| 735 | .int8_t, | ||
| 736 | .uint16_t, | ||
| 737 | .int16_t, | ||
| 738 | .uint32_t, | ||
| 739 | .int32_t, | ||
| 740 | .uint64_t, | ||
| 741 | .int64_t, | ||
| 742 | => try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}), | ||
| 743 | .zig_u128, | ||
| 744 | .zig_i128, | ||
| 745 | .zig_f16, | ||
| 746 | .zig_f32, | ||
| 747 | .zig_f64, | ||
| 748 | .zig_f80, | ||
| 749 | .zig_f128, | ||
| 750 | .zig_c_longdouble, | ||
| 751 | => |t| try writer.print("zig_{s}_{s}(", .{ | ||
| 752 | switch (kind) { | ||
| 753 | else => "make", | ||
| 754 | .global => "init", | ||
| 755 | }, | ||
| 756 | @tagName(t)["zig_".len..], | ||
| 757 | }), | ||
| 758 | .pointer, | ||
| 759 | .pointer_const, | ||
| 760 | .pointer_volatile, | ||
| 761 | .pointer_const_volatile, | ||
| 762 | => unreachable, | ||
| 763 | .array, | ||
| 764 | .vector, | ||
| 765 | => try writer.writeByte('{'), | ||
| 766 | .fwd_anon_struct, | ||
| 767 | .fwd_anon_union, | ||
| 768 | .fwd_struct, | ||
| 769 | .fwd_union, | ||
| 770 | .unnamed_struct, | ||
| 771 | .unnamed_union, | ||
| 772 | .packed_unnamed_struct, | ||
| 773 | .packed_unnamed_union, | ||
| 774 | .anon_struct, | ||
| 775 | .anon_union, | ||
| 776 | .@"struct", | ||
| 777 | .@"union", | ||
| 778 | .packed_struct, | ||
| 779 | .packed_union, | ||
| 780 | .function, | ||
| 781 | .varargs_function, | ||
| 782 | => unreachable, | ||
| 783 | } | ||
| 784 | } | ||
| 785 | |||
| 786 | pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void { | ||
| 787 | switch (self.tag()) { | ||
| 788 | .void => unreachable, | ||
| 789 | ._Bool => {}, | ||
| 790 | .char, | ||
| 791 | .@"signed char", | ||
| 792 | .short, | ||
| 793 | .int, | ||
| 794 | => {}, | ||
| 795 | .long => try writer.writeByte('l'), | ||
| 796 | .@"long long" => try writer.writeAll("ll"), | ||
| 797 | .@"unsigned char", | ||
| 798 | .@"unsigned short", | ||
| 799 | .@"unsigned int", | ||
| 800 | => try writer.writeByte('u'), | ||
| 801 | .@"unsigned long", | ||
| 802 | .size_t, | ||
| 803 | .uintptr_t, | ||
| 804 | => try writer.writeAll("ul"), | ||
| 805 | .@"unsigned long long" => try writer.writeAll("ull"), | ||
| 806 | .float => try writer.writeByte('f'), | ||
| 807 | .double => {}, | ||
| 808 | .@"long double" => try writer.writeByte('l'), | ||
| 809 | .bool, | ||
| 810 | .ptrdiff_t, | ||
| 811 | .intptr_t, | ||
| 812 | => {}, | ||
| 813 | .uint8_t, | ||
| 814 | .int8_t, | ||
| 815 | .uint16_t, | ||
| 816 | .int16_t, | ||
| 817 | .uint32_t, | ||
| 818 | .int32_t, | ||
| 819 | .uint64_t, | ||
| 820 | .int64_t, | ||
| 821 | .zig_u128, | ||
| 822 | .zig_i128, | ||
| 823 | .zig_f16, | ||
| 824 | .zig_f32, | ||
| 825 | .zig_f64, | ||
| 826 | .zig_f80, | ||
| 827 | .zig_f128, | ||
| 828 | .zig_c_longdouble, | ||
| 829 | => try writer.writeByte(')'), | ||
| 830 | .pointer, | ||
| 831 | .pointer_const, | ||
| 832 | .pointer_volatile, | ||
| 833 | .pointer_const_volatile, | ||
| 834 | => unreachable, | ||
| 835 | .array, | ||
| 836 | .vector, | ||
| 837 | => try writer.writeByte('}'), | ||
| 838 | .fwd_anon_struct, | ||
| 839 | .fwd_anon_union, | ||
| 840 | .fwd_struct, | ||
| 841 | .fwd_union, | ||
| 842 | .unnamed_struct, | ||
| 843 | .unnamed_union, | ||
| 844 | .packed_unnamed_struct, | ||
| 845 | .packed_unnamed_union, | ||
| 846 | .anon_struct, | ||
| 847 | .anon_union, | ||
| 848 | .@"struct", | ||
| 849 | .@"union", | ||
| 850 | .packed_struct, | ||
| 851 | .packed_union, | ||
| 852 | .function, | ||
| 853 | .varargs_function, | ||
| 854 | => unreachable, | ||
| 855 | } | ||
| 856 | } | ||
| 857 | |||
| 858 | pub fn floatActiveBits(self: CType, mod: *Module) u16 { | ||
| 859 | const target = &mod.resolved_target.result; | ||
| 860 | return switch (self.tag()) { | ||
| 861 | .float => target.c_type_bit_size(.float), | ||
| 862 | .double => target.c_type_bit_size(.double), | ||
| 863 | .@"long double", .zig_c_longdouble => target.c_type_bit_size(.longdouble), | ||
| 864 | .zig_f16 => 16, | ||
| 865 | .zig_f32 => 32, | ||
| 866 | .zig_f64 => 64, | ||
| 867 | .zig_f80 => 80, | ||
| 868 | .zig_f128 => 128, | ||
| 869 | else => unreachable, | ||
| 870 | }; | ||
| 871 | } | ||
| 872 | |||
| 873 | pub fn byteSize(self: CType, store: Store.Set, mod: *Module) u64 { | ||
| 874 | const target = &mod.resolved_target.result; | ||
| 875 | return switch (self.tag()) { | ||
| 876 | .void => 0, | ||
| 877 | .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1, | ||
| 878 | .short => target.c_type_byte_size(.short), | ||
| 879 | .int => target.c_type_byte_size(.int), | ||
| 880 | .long => target.c_type_byte_size(.long), | ||
| 881 | .@"long long" => target.c_type_byte_size(.longlong), | ||
| 882 | .@"unsigned short" => target.c_type_byte_size(.ushort), | ||
| 883 | .@"unsigned int" => target.c_type_byte_size(.uint), | ||
| 884 | .@"unsigned long" => target.c_type_byte_size(.ulong), | ||
| 885 | .@"unsigned long long" => target.c_type_byte_size(.ulonglong), | ||
| 886 | .float => target.c_type_byte_size(.float), | ||
| 887 | .double => target.c_type_byte_size(.double), | ||
| 888 | .@"long double" => target.c_type_byte_size(.longdouble), | ||
| 889 | .size_t, | ||
| 890 | .ptrdiff_t, | ||
| 891 | .uintptr_t, | ||
| 892 | .intptr_t, | ||
| 893 | .pointer, | ||
| 894 | .pointer_const, | ||
| 895 | .pointer_volatile, | ||
| 896 | .pointer_const_volatile, | ||
| 897 | => @divExact(target.ptrBitWidth(), 8), | ||
| 898 | .uint16_t, .int16_t, .zig_f16 => 2, | ||
| 899 | .uint32_t, .int32_t, .zig_f32 => 4, | ||
| 900 | .uint64_t, .int64_t, .zig_f64 => 8, | ||
| 901 | .zig_u128, .zig_i128, .zig_f128 => 16, | ||
| 902 | .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80) | ||
| 903 | target.c_type_byte_size(.longdouble) | ||
| 904 | else | ||
| 905 | 16, | ||
| 906 | .zig_c_longdouble => target.c_type_byte_size(.longdouble), | ||
| 907 | |||
| 908 | .array, | ||
| 909 | .vector, | ||
| 910 | => { | ||
| 911 | const data = self.cast(Payload.Sequence).?.data; | ||
| 912 | return data.len * store.indexToCType(data.elem_type).byteSize(store, mod); | ||
| 913 | }, | ||
| 914 | |||
| 915 | .fwd_anon_struct, | ||
| 916 | .fwd_anon_union, | ||
| 917 | .fwd_struct, | ||
| 918 | .fwd_union, | ||
| 919 | .unnamed_struct, | ||
| 920 | .unnamed_union, | ||
| 921 | .packed_unnamed_struct, | ||
| 922 | .packed_unnamed_union, | ||
| 923 | .anon_struct, | ||
| 924 | .anon_union, | ||
| 925 | .@"struct", | ||
| 926 | .@"union", | ||
| 927 | .packed_struct, | ||
| 928 | .packed_union, | ||
| 929 | .function, | ||
| 930 | .varargs_function, | ||
| 931 | => unreachable, | ||
| 932 | }; | ||
| 933 | } | ||
| 934 | |||
| 935 | pub fn isPacked(self: CType) bool { | ||
| 936 | return switch (self.tag()) { | ||
| 937 | else => false, | ||
| 938 | .packed_unnamed_struct, | ||
| 939 | .packed_unnamed_union, | ||
| 940 | .packed_struct, | ||
| 941 | .packed_union, | ||
| 942 | => true, | ||
| 943 | }; | ||
| 944 | } | ||
| 945 | |||
| 946 | pub fn fields(self: CType) Payload.Fields.Data { | ||
| 947 | return if (self.cast(Payload.Aggregate)) |pl| | ||
| 948 | pl.data.fields | ||
| 949 | else if (self.cast(Payload.Unnamed)) |pl| | ||
| 950 | pl.data.fields | ||
| 951 | else if (self.cast(Payload.Fields)) |pl| | ||
| 952 | pl.data | ||
| 953 | else | ||
| 954 | unreachable; | ||
| 955 | } | ||
| 956 | |||
| 957 | pub fn eql(lhs: CType, rhs: CType) bool { | ||
| 958 | return lhs.eqlContext(rhs, struct { | ||
| 959 | pub fn eqlIndex(_: @This(), lhs_idx: Index, rhs_idx: Index) bool { | ||
| 960 | return lhs_idx == rhs_idx; | ||
| 961 | } | ||
| 962 | }{}); | ||
| 963 | } | ||
| 964 | |||
| 965 | pub fn eqlContext(lhs: CType, rhs: CType, ctx: anytype) bool { | ||
| 966 | // As a shortcut, if the small tags / addresses match, we're done. | ||
| 967 | if (lhs.tag_if_small_enough == rhs.tag_if_small_enough) return true; | ||
| 968 | |||
| 969 | const lhs_tag = lhs.tag(); | ||
| 970 | const rhs_tag = rhs.tag(); | ||
| 971 | if (lhs_tag != rhs_tag) return false; | ||
| 972 | |||
| 973 | return switch (lhs_tag) { | ||
| 974 | .void, | ||
| 975 | .char, | ||
| 976 | .@"signed char", | ||
| 977 | .short, | ||
| 978 | .int, | ||
| 979 | .long, | ||
| 980 | .@"long long", | ||
| 981 | ._Bool, | ||
| 982 | .@"unsigned char", | ||
| 983 | .@"unsigned short", | ||
| 984 | .@"unsigned int", | ||
| 985 | .@"unsigned long", | ||
| 986 | .@"unsigned long long", | ||
| 987 | .float, | ||
| 988 | .double, | ||
| 989 | .@"long double", | ||
| 990 | .bool, | ||
| 991 | .size_t, | ||
| 992 | .ptrdiff_t, | ||
| 993 | .uint8_t, | ||
| 994 | .int8_t, | ||
| 995 | .uint16_t, | ||
| 996 | .int16_t, | ||
| 997 | .uint32_t, | ||
| 998 | .int32_t, | ||
| 999 | .uint64_t, | ||
| 1000 | .int64_t, | ||
| 1001 | .uintptr_t, | ||
| 1002 | .intptr_t, | ||
| 1003 | .zig_u128, | ||
| 1004 | .zig_i128, | ||
| 1005 | .zig_f16, | ||
| 1006 | .zig_f32, | ||
| 1007 | .zig_f64, | ||
| 1008 | .zig_f80, | ||
| 1009 | .zig_f128, | ||
| 1010 | .zig_c_longdouble, | ||
| 1011 | => false, | ||
| 1012 | |||
| 1013 | .pointer, | ||
| 1014 | .pointer_const, | ||
| 1015 | .pointer_volatile, | ||
| 1016 | .pointer_const_volatile, | ||
| 1017 | => ctx.eqlIndex(lhs.cast(Payload.Child).?.data, rhs.cast(Payload.Child).?.data), | ||
| 1018 | |||
| 1019 | .array, | ||
| 1020 | .vector, | ||
| 1021 | => { | ||
| 1022 | const lhs_data = lhs.cast(Payload.Sequence).?.data; | ||
| 1023 | const rhs_data = rhs.cast(Payload.Sequence).?.data; | ||
| 1024 | return lhs_data.len == rhs_data.len and | ||
| 1025 | ctx.eqlIndex(lhs_data.elem_type, rhs_data.elem_type); | ||
| 1026 | }, | ||
| 1027 | |||
| 1028 | .fwd_anon_struct, | ||
| 1029 | .fwd_anon_union, | ||
| 1030 | => { | ||
| 1031 | const lhs_data = lhs.cast(Payload.Fields).?.data; | ||
| 1032 | const rhs_data = rhs.cast(Payload.Fields).?.data; | ||
| 1033 | if (lhs_data.len != rhs_data.len) return false; | ||
| 1034 | for (lhs_data, rhs_data) |lhs_field, rhs_field| { | ||
| 1035 | if (!ctx.eqlIndex(lhs_field.type, rhs_field.type)) return false; | ||
| 1036 | if (lhs_field.alignas.@"align" != rhs_field.alignas.@"align") return false; | ||
| 1037 | if (std.mem.orderZ(u8, lhs_field.name, rhs_field.name) != .eq) return false; | ||
| 1038 | } | ||
| 1039 | return true; | ||
| 1040 | }, | ||
| 1041 | |||
| 1042 | .fwd_struct, | ||
| 1043 | .fwd_union, | ||
| 1044 | => lhs.cast(Payload.FwdDecl).?.data == rhs.cast(Payload.FwdDecl).?.data, | ||
| 1045 | |||
| 1046 | .unnamed_struct, | ||
| 1047 | .unnamed_union, | ||
| 1048 | .packed_unnamed_struct, | ||
| 1049 | .packed_unnamed_union, | ||
| 1050 | => { | ||
| 1051 | const lhs_data = lhs.cast(Payload.Unnamed).?.data; | ||
| 1052 | const rhs_data = rhs.cast(Payload.Unnamed).?.data; | ||
| 1053 | return lhs_data.owner_decl == rhs_data.owner_decl and lhs_data.id == rhs_data.id; | ||
| 1054 | }, | ||
| 1055 | |||
| 1056 | .anon_struct, | ||
| 1057 | .anon_union, | ||
| 1058 | .@"struct", | ||
| 1059 | .@"union", | ||
| 1060 | .packed_struct, | ||
| 1061 | .packed_union, | ||
| 1062 | => ctx.eqlIndex( | ||
| 1063 | lhs.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 1064 | rhs.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 1065 | ), | ||
| 1066 | |||
| 1067 | .function, | ||
| 1068 | .varargs_function, | ||
| 1069 | => { | ||
| 1070 | const lhs_data = lhs.cast(Payload.Function).?.data; | ||
| 1071 | const rhs_data = rhs.cast(Payload.Function).?.data; | ||
| 1072 | if (lhs_data.param_types.len != rhs_data.param_types.len) return false; | ||
| 1073 | if (!ctx.eqlIndex(lhs_data.return_type, rhs_data.return_type)) return false; | ||
| 1074 | for (lhs_data.param_types, rhs_data.param_types) |lhs_param_idx, rhs_param_idx| { | ||
| 1075 | if (!ctx.eqlIndex(lhs_param_idx, rhs_param_idx)) return false; | ||
| 1076 | } | ||
| 1077 | return true; | ||
| 1078 | }, | ||
| 1079 | }; | ||
| 1080 | } | ||
| 1081 | |||
| 1082 | pub fn hash(self: CType, store: Store.Set) u64 { | ||
| 1083 | var hasher = std.hash.Wyhash.init(0); | ||
| 1084 | self.updateHasher(&hasher, store); | ||
| 1085 | return hasher.final(); | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | pub fn updateHasher(self: CType, hasher: anytype, store: Store.Set) void { | ||
| 1089 | const t = self.tag(); | ||
| 1090 | autoHash(hasher, t); | ||
| 1091 | switch (t) { | ||
| 1092 | .void, | ||
| 1093 | .char, | ||
| 1094 | .@"signed char", | ||
| 1095 | .short, | ||
| 1096 | .int, | ||
| 1097 | .long, | ||
| 1098 | .@"long long", | ||
| 1099 | ._Bool, | ||
| 1100 | .@"unsigned char", | ||
| 1101 | .@"unsigned short", | ||
| 1102 | .@"unsigned int", | ||
| 1103 | .@"unsigned long", | ||
| 1104 | .@"unsigned long long", | ||
| 1105 | .float, | ||
| 1106 | .double, | ||
| 1107 | .@"long double", | ||
| 1108 | .bool, | ||
| 1109 | .size_t, | ||
| 1110 | .ptrdiff_t, | ||
| 1111 | .uint8_t, | ||
| 1112 | .int8_t, | ||
| 1113 | .uint16_t, | ||
| 1114 | .int16_t, | ||
| 1115 | .uint32_t, | ||
| 1116 | .int32_t, | ||
| 1117 | .uint64_t, | ||
| 1118 | .int64_t, | ||
| 1119 | .uintptr_t, | ||
| 1120 | .intptr_t, | ||
| 1121 | .zig_u128, | ||
| 1122 | .zig_i128, | ||
| 1123 | .zig_f16, | ||
| 1124 | .zig_f32, | ||
| 1125 | .zig_f64, | ||
| 1126 | .zig_f80, | ||
| 1127 | .zig_f128, | ||
| 1128 | .zig_c_longdouble, | ||
| 1129 | => {}, | ||
| 1130 | |||
| 1131 | .pointer, | ||
| 1132 | .pointer_const, | ||
| 1133 | .pointer_volatile, | ||
| 1134 | .pointer_const_volatile, | ||
| 1135 | => store.indexToCType(self.cast(Payload.Child).?.data).updateHasher(hasher, store), | ||
| 1136 | |||
| 1137 | .array, | ||
| 1138 | .vector, | ||
| 1139 | => { | ||
| 1140 | const data = self.cast(Payload.Sequence).?.data; | ||
| 1141 | autoHash(hasher, data.len); | ||
| 1142 | store.indexToCType(data.elem_type).updateHasher(hasher, store); | ||
| 1143 | }, | ||
| 1144 | |||
| 1145 | .fwd_anon_struct, | ||
| 1146 | .fwd_anon_union, | ||
| 1147 | => for (self.cast(Payload.Fields).?.data) |field| { | ||
| 1148 | store.indexToCType(field.type).updateHasher(hasher, store); | ||
| 1149 | hasher.update(mem.span(field.name)); | ||
| 1150 | autoHash(hasher, field.alignas.@"align"); | ||
| 1151 | }, | ||
| 1152 | |||
| 1153 | .fwd_struct, | ||
| 1154 | .fwd_union, | ||
| 1155 | => autoHash(hasher, self.cast(Payload.FwdDecl).?.data), | ||
| 1156 | |||
| 1157 | .unnamed_struct, | ||
| 1158 | .unnamed_union, | ||
| 1159 | .packed_unnamed_struct, | ||
| 1160 | .packed_unnamed_union, | ||
| 1161 | => { | ||
| 1162 | const data = self.cast(Payload.Unnamed).?.data; | ||
| 1163 | autoHash(hasher, data.owner_decl); | ||
| 1164 | autoHash(hasher, data.id); | ||
| 1165 | }, | ||
| 1166 | |||
| 1167 | .anon_struct, | ||
| 1168 | .anon_union, | ||
| 1169 | .@"struct", | ||
| 1170 | .@"union", | ||
| 1171 | .packed_struct, | ||
| 1172 | .packed_union, | ||
| 1173 | => store.indexToCType(self.cast(Payload.Aggregate).?.data.fwd_decl) | ||
| 1174 | .updateHasher(hasher, store), | ||
| 1175 | |||
| 1176 | .function, | ||
| 1177 | .varargs_function, | ||
| 1178 | => { | ||
| 1179 | const data = self.cast(Payload.Function).?.data; | ||
| 1180 | store.indexToCType(data.return_type).updateHasher(hasher, store); | ||
| 1181 | for (data.param_types) |param_ty| { | ||
| 1182 | store.indexToCType(param_ty).updateHasher(hasher, store); | ||
| 1183 | } | ||
| 1184 | }, | ||
| 1185 | } | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | pub const Kind = enum { forward, forward_parameter, complete, global, parameter, payload }; | ||
| 1189 | |||
| 1190 | const Convert = struct { | ||
| 1191 | storage: union { | ||
| 1192 | none: void, | ||
| 1193 | child: Payload.Child, | ||
| 1194 | seq: Payload.Sequence, | ||
| 1195 | fwd: Payload.FwdDecl, | ||
| 1196 | anon: struct { | ||
| 1197 | fields: [2]Payload.Fields.Field, | ||
| 1198 | pl: union { | ||
| 1199 | forward: Payload.Fields, | ||
| 1200 | complete: Payload.Aggregate, | ||
| 1201 | }, | ||
| 1202 | }, | ||
| 1203 | }, | ||
| 1204 | value: union(enum) { | ||
| 1205 | tag: Tag, | ||
| 1206 | cty: CType, | ||
| 1207 | }, | ||
| 1208 | |||
| 1209 | pub fn init(self: *@This(), t: Tag) void { | ||
| 1210 | self.* = if (t.hasPayload()) .{ | ||
| 1211 | .storage = .{ .none = {} }, | ||
| 1212 | .value = .{ .tag = t }, | ||
| 1213 | } else .{ | ||
| 1214 | .storage = .{ .none = {} }, | ||
| 1215 | .value = .{ .cty = initTag(t) }, | ||
| 1216 | }; | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | pub fn tag(self: @This()) Tag { | ||
| 1220 | return switch (self.value) { | ||
| 1221 | .tag => |t| t, | ||
| 1222 | .cty => |c| c.tag(), | ||
| 1223 | }; | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag { | ||
| 1227 | return switch (int_info.bits) { | ||
| 1228 | 0 => .void, | ||
| 1229 | 1...8 => switch (int_info.signedness) { | ||
| 1230 | .unsigned => .uint8_t, | ||
| 1231 | .signed => .int8_t, | ||
| 1232 | }, | ||
| 1233 | 9...16 => switch (int_info.signedness) { | ||
| 1234 | .unsigned => .uint16_t, | ||
| 1235 | .signed => .int16_t, | ||
| 1236 | }, | ||
| 1237 | 17...32 => switch (int_info.signedness) { | ||
| 1238 | .unsigned => .uint32_t, | ||
| 1239 | .signed => .int32_t, | ||
| 1240 | }, | ||
| 1241 | 33...64 => switch (int_info.signedness) { | ||
| 1242 | .unsigned => .uint64_t, | ||
| 1243 | .signed => .int64_t, | ||
| 1244 | }, | ||
| 1245 | 65...128 => switch (int_info.signedness) { | ||
| 1246 | .unsigned => .zig_u128, | ||
| 1247 | .signed => .zig_i128, | ||
| 1248 | }, | ||
| 1249 | else => .array, | ||
| 1250 | }; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | pub const Lookup = union(enum) { | ||
| 1254 | fail: struct { | ||
| 1255 | zcu: *Zcu, | ||
| 1256 | mod: *Module, | ||
| 1257 | }, | ||
| 1258 | imm: struct { | ||
| 1259 | set: *const Store.Set, | ||
| 1260 | zcu: *Zcu, | ||
| 1261 | mod: *Module, | ||
| 1262 | }, | ||
| 1263 | mut: struct { | ||
| 1264 | promoted: *Store.Promoted, | ||
| 1265 | zcu: *Zcu, | ||
| 1266 | mod: *Module, | ||
| 1267 | }, | ||
| 1268 | |||
| 1269 | pub fn isMutable(self: @This()) bool { | ||
| 1270 | return switch (self) { | ||
| 1271 | .fail, .imm => false, | ||
| 1272 | .mut => true, | ||
| 1273 | }; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | pub fn getZcu(self: @This()) *Zcu { | ||
| 1277 | return switch (self) { | ||
| 1278 | inline else => |pl| pl.zcu, | ||
| 1279 | }; | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | pub fn getModule(self: @This()) *Module { | ||
| 1283 | return switch (self) { | ||
| 1284 | inline else => |pl| pl.mod, | ||
| 1285 | }; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | pub fn getSet(self: @This()) ?*const Store.Set { | ||
| 1289 | return switch (self) { | ||
| 1290 | .fail => null, | ||
| 1291 | .imm => |imm| imm.set, | ||
| 1292 | .mut => |mut| &mut.promoted.set, | ||
| 1293 | }; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index { | ||
| 1297 | return switch (self) { | ||
| 1298 | .fail => null, | ||
| 1299 | .imm => |imm| imm.set.typeToIndex(ty, imm.zcu, imm.mod, kind), | ||
| 1300 | .mut => |mut| try mut.promoted.typeToIndex(ty, mut.zcu, mut.mod, kind), | ||
| 1301 | }; | ||
| 1302 | } | ||
| 1303 | |||
| 1304 | pub fn indexToCType(self: @This(), index: Index) ?CType { | ||
| 1305 | return if (self.getSet()) |set| set.indexToCType(index) else null; | ||
| 1306 | } | ||
| 1307 | |||
| 1308 | pub fn freeze(self: @This()) @This() { | ||
| 1309 | return switch (self) { | ||
| 1310 | .fail, .imm => self, | ||
| 1311 | .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .zcu = mut.zcu, .mod = mut.mod } }, | ||
| 1312 | }; | ||
| 1313 | } | ||
| 1314 | }; | ||
| 1315 | |||
| 1316 | fn sortFields(self: *@This(), fields_len: usize) []Payload.Fields.Field { | ||
| 1317 | const Field = Payload.Fields.Field; | ||
| 1318 | const slice = self.storage.anon.fields[0..fields_len]; | ||
| 1319 | mem.sort(Field, slice, {}, struct { | ||
| 1320 | fn before(_: void, lhs: Field, rhs: Field) bool { | ||
| 1321 | return lhs.alignas.order(rhs.alignas).compare(.gt); | ||
| 1322 | } | ||
| 1323 | }.before); | ||
| 1324 | return slice; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | fn initAnon(self: *@This(), kind: Kind, fwd_idx: Index, fields_len: usize) void { | ||
| 1328 | switch (kind) { | ||
| 1329 | .forward, .forward_parameter => { | ||
| 1330 | self.storage.anon.pl = .{ .forward = .{ | ||
| 1331 | .base = .{ .tag = .fwd_anon_struct }, | ||
| 1332 | .data = self.sortFields(fields_len), | ||
| 1333 | } }; | ||
| 1334 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.forward) }; | ||
| 1335 | }, | ||
| 1336 | .complete, .parameter, .global => { | ||
| 1337 | self.storage.anon.pl = .{ .complete = .{ | ||
| 1338 | .base = .{ .tag = .anon_struct }, | ||
| 1339 | .data = .{ | ||
| 1340 | .fields = self.sortFields(fields_len), | ||
| 1341 | .fwd_decl = fwd_idx, | ||
| 1342 | }, | ||
| 1343 | } }; | ||
| 1344 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; | ||
| 1345 | }, | ||
| 1346 | .payload => unreachable, | ||
| 1347 | } | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | fn initArrayParameter(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { | ||
| 1351 | if (switch (kind) { | ||
| 1352 | .forward_parameter => @as(Index, undefined), | ||
| 1353 | .parameter => try lookup.typeToIndex(ty, .forward_parameter), | ||
| 1354 | .forward, .complete, .global, .payload => unreachable, | ||
| 1355 | }) |fwd_idx| { | ||
| 1356 | if (try lookup.typeToIndex(ty, switch (kind) { | ||
| 1357 | .forward_parameter => .forward, | ||
| 1358 | .parameter => .complete, | ||
| 1359 | .forward, .complete, .global, .payload => unreachable, | ||
| 1360 | })) |array_idx| { | ||
| 1361 | self.storage = .{ .anon = undefined }; | ||
| 1362 | self.storage.anon.fields[0] = .{ | ||
| 1363 | .name = "array", | ||
| 1364 | .type = array_idx, | ||
| 1365 | .alignas = AlignAs.abiAlign(ty, lookup.getZcu()), | ||
| 1366 | }; | ||
| 1367 | self.initAnon(kind, fwd_idx, 1); | ||
| 1368 | } else self.init(switch (kind) { | ||
| 1369 | .forward_parameter => .fwd_anon_struct, | ||
| 1370 | .parameter => .anon_struct, | ||
| 1371 | .forward, .complete, .global, .payload => unreachable, | ||
| 1372 | }); | ||
| 1373 | } else self.init(.anon_struct); | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void { | ||
| 1377 | const zcu = lookup.getZcu(); | ||
| 1378 | const ip = &zcu.intern_pool; | ||
| 1379 | |||
| 1380 | self.* = undefined; | ||
| 1381 | if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) | ||
| 1382 | self.init(.void) | ||
| 1383 | else if (ty.isAbiInt(zcu)) switch (ty.ip_index) { | ||
| 1384 | .usize_type => self.init(.uintptr_t), | ||
| 1385 | .isize_type => self.init(.intptr_t), | ||
| 1386 | .c_char_type => self.init(.char), | ||
| 1387 | .c_short_type => self.init(.short), | ||
| 1388 | .c_ushort_type => self.init(.@"unsigned short"), | ||
| 1389 | .c_int_type => self.init(.int), | ||
| 1390 | .c_uint_type => self.init(.@"unsigned int"), | ||
| 1391 | .c_long_type => self.init(.long), | ||
| 1392 | .c_ulong_type => self.init(.@"unsigned long"), | ||
| 1393 | .c_longlong_type => self.init(.@"long long"), | ||
| 1394 | .c_ulonglong_type => self.init(.@"unsigned long long"), | ||
| 1395 | else => switch (tagFromIntInfo(ty.intInfo(zcu))) { | ||
| 1396 | .void => unreachable, | ||
| 1397 | else => |t| self.init(t), | ||
| 1398 | .array => switch (kind) { | ||
| 1399 | .forward, .complete, .global => { | ||
| 1400 | const abi_size = ty.abiSize(zcu); | ||
| 1401 | const abi_align = ty.abiAlignment(zcu).toByteUnits(0); | ||
| 1402 | self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{ | ||
| 1403 | .len = @divExact(abi_size, abi_align), | ||
| 1404 | .elem_type = tagFromIntInfo(.{ | ||
| 1405 | .signedness = .unsigned, | ||
| 1406 | .bits = @intCast(abi_align * 8), | ||
| 1407 | }).toIndex(), | ||
| 1408 | } } }; | ||
| 1409 | self.value = .{ .cty = initPayload(&self.storage.seq) }; | ||
| 1410 | }, | ||
| 1411 | .forward_parameter, | ||
| 1412 | .parameter, | ||
| 1413 | => try self.initArrayParameter(ty, kind, lookup), | ||
| 1414 | .payload => unreachable, | ||
| 1415 | }, | ||
| 1416 | }, | ||
| 1417 | } else switch (ty.zigTypeTag(zcu)) { | ||
| 1418 | .Frame => unreachable, | ||
| 1419 | .AnyFrame => unreachable, | ||
| 1420 | |||
| 1421 | .Int, | ||
| 1422 | .Enum, | ||
| 1423 | .ErrorSet, | ||
| 1424 | .Type, | ||
| 1425 | .Void, | ||
| 1426 | .NoReturn, | ||
| 1427 | .ComptimeFloat, | ||
| 1428 | .ComptimeInt, | ||
| 1429 | .Undefined, | ||
| 1430 | .Null, | ||
| 1431 | .EnumLiteral, | ||
| 1432 | => unreachable, | ||
| 1433 | |||
| 1434 | .Bool => self.init(.bool), | ||
| 1435 | |||
| 1436 | .Float => self.init(switch (ty.ip_index) { | ||
| 1437 | .f16_type => .zig_f16, | ||
| 1438 | .f32_type => .zig_f32, | ||
| 1439 | .f64_type => .zig_f64, | ||
| 1440 | .f80_type => .zig_f80, | ||
| 1441 | .f128_type => .zig_f128, | ||
| 1442 | .c_longdouble_type => .zig_c_longdouble, | ||
| 1443 | else => unreachable, | ||
| 1444 | }), | ||
| 1445 | |||
| 1446 | .Pointer => { | ||
| 1447 | const info = ty.ptrInfo(zcu); | ||
| 1448 | switch (info.flags.size) { | ||
| 1449 | .Slice => { | ||
| 1450 | if (switch (kind) { | ||
| 1451 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1452 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1453 | .payload => unreachable, | ||
| 1454 | }) |fwd_idx| { | ||
| 1455 | const ptr_ty = ty.slicePtrFieldType(zcu); | ||
| 1456 | if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| { | ||
| 1457 | self.storage = .{ .anon = undefined }; | ||
| 1458 | self.storage.anon.fields[0] = .{ | ||
| 1459 | .name = "ptr", | ||
| 1460 | .type = ptr_idx, | ||
| 1461 | .alignas = AlignAs.abiAlign(ptr_ty, zcu), | ||
| 1462 | }; | ||
| 1463 | self.storage.anon.fields[1] = .{ | ||
| 1464 | .name = "len", | ||
| 1465 | .type = Tag.uintptr_t.toIndex(), | ||
| 1466 | .alignas = AlignAs.abiAlign(Type.usize, zcu), | ||
| 1467 | }; | ||
| 1468 | self.initAnon(kind, fwd_idx, 2); | ||
| 1469 | } else self.init(switch (kind) { | ||
| 1470 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1471 | .complete, .parameter, .global => .anon_struct, | ||
| 1472 | .payload => unreachable, | ||
| 1473 | }); | ||
| 1474 | } else self.init(.anon_struct); | ||
| 1475 | }, | ||
| 1476 | |||
| 1477 | .One, .Many, .C => { | ||
| 1478 | const t: Tag = switch (info.flags.is_volatile) { | ||
| 1479 | false => switch (info.flags.is_const) { | ||
| 1480 | false => .pointer, | ||
| 1481 | true => .pointer_const, | ||
| 1482 | }, | ||
| 1483 | true => switch (info.flags.is_const) { | ||
| 1484 | false => .pointer_volatile, | ||
| 1485 | true => .pointer_const_volatile, | ||
| 1486 | }, | ||
| 1487 | }; | ||
| 1488 | |||
| 1489 | const pointee_ty = if (info.packed_offset.host_size > 0 and info.flags.vector_index == .none) | ||
| 1490 | try zcu.intType(.unsigned, info.packed_offset.host_size * 8) | ||
| 1491 | else if (info.flags.alignment == .none or | ||
| 1492 | info.flags.alignment.compareStrict(.gte, Type.fromInterned(info.child).abiAlignment(zcu))) | ||
| 1493 | Type.fromInterned(info.child) | ||
| 1494 | else | ||
| 1495 | try zcu.intType(.unsigned, @min( | ||
| 1496 | info.flags.alignment.toByteUnitsOptional().?, | ||
| 1497 | lookup.getModule().resolved_target.result.maxIntAlignment(), | ||
| 1498 | ) * 8); | ||
| 1499 | |||
| 1500 | if (try lookup.typeToIndex(pointee_ty, .forward)) |child_idx| { | ||
| 1501 | self.storage = .{ .child = .{ | ||
| 1502 | .base = .{ .tag = t }, | ||
| 1503 | .data = child_idx, | ||
| 1504 | } }; | ||
| 1505 | self.value = .{ .cty = initPayload(&self.storage.child) }; | ||
| 1506 | } else self.init(t); | ||
| 1507 | }, | ||
| 1508 | } | ||
| 1509 | }, | ||
| 1510 | |||
| 1511 | .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(zcu) == .@"packed") { | ||
| 1512 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { | ||
| 1513 | try self.initType(Type.fromInterned(packed_struct.backingIntType(ip).*), kind, lookup); | ||
| 1514 | } else { | ||
| 1515 | const bits: u16 = @intCast(ty.bitSize(zcu)); | ||
| 1516 | const int_ty = try zcu.intType(.unsigned, bits); | ||
| 1517 | try self.initType(int_ty, kind, lookup); | ||
| 1518 | } | ||
| 1519 | } else if (ty.isTupleOrAnonStruct(zcu)) { | ||
| 1520 | if (lookup.isMutable()) { | ||
| 1521 | for (0..switch (zig_ty_tag) { | ||
| 1522 | .Struct => ty.structFieldCount(zcu), | ||
| 1523 | .Union => zcu.typeToUnion(ty).?.field_types.len, | ||
| 1524 | else => unreachable, | ||
| 1525 | }) |field_i| { | ||
| 1526 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 1527 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or | ||
| 1528 | !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1529 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | ||
| 1530 | .forward, .forward_parameter => .forward, | ||
| 1531 | .complete, .parameter => .complete, | ||
| 1532 | .global => .global, | ||
| 1533 | .payload => unreachable, | ||
| 1534 | }); | ||
| 1535 | } | ||
| 1536 | switch (kind) { | ||
| 1537 | .forward, .forward_parameter => {}, | ||
| 1538 | .complete, .parameter, .global => _ = try lookup.typeToIndex(ty, .forward), | ||
| 1539 | .payload => unreachable, | ||
| 1540 | } | ||
| 1541 | } | ||
| 1542 | self.init(switch (kind) { | ||
| 1543 | .forward, .forward_parameter => switch (zig_ty_tag) { | ||
| 1544 | .Struct => .fwd_anon_struct, | ||
| 1545 | .Union => .fwd_anon_union, | ||
| 1546 | else => unreachable, | ||
| 1547 | }, | ||
| 1548 | .complete, .parameter, .global => switch (zig_ty_tag) { | ||
| 1549 | .Struct => .anon_struct, | ||
| 1550 | .Union => .anon_union, | ||
| 1551 | else => unreachable, | ||
| 1552 | }, | ||
| 1553 | .payload => unreachable, | ||
| 1554 | }); | ||
| 1555 | } else { | ||
| 1556 | const tag_ty = ty.unionTagTypeSafety(zcu); | ||
| 1557 | const is_tagged_union_wrapper = kind != .payload and tag_ty != null; | ||
| 1558 | const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper; | ||
| 1559 | switch (kind) { | ||
| 1560 | .forward, .forward_parameter => { | ||
| 1561 | self.storage = .{ .fwd = .{ | ||
| 1562 | .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union }, | ||
| 1563 | .data = ty.getOwnerDecl(zcu), | ||
| 1564 | } }; | ||
| 1565 | self.value = .{ .cty = initPayload(&self.storage.fwd) }; | ||
| 1566 | }, | ||
| 1567 | .complete, .parameter, .global, .payload => if (is_tagged_union_wrapper) { | ||
| 1568 | const fwd_idx = try lookup.typeToIndex(ty, .forward); | ||
| 1569 | const payload_idx = try lookup.typeToIndex(ty, .payload); | ||
| 1570 | const tag_idx = try lookup.typeToIndex(tag_ty.?, kind); | ||
| 1571 | if (fwd_idx != null and payload_idx != null and tag_idx != null) { | ||
| 1572 | self.storage = .{ .anon = undefined }; | ||
| 1573 | var field_count: usize = 0; | ||
| 1574 | if (payload_idx != Tag.void.toIndex()) { | ||
| 1575 | self.storage.anon.fields[field_count] = .{ | ||
| 1576 | .name = "payload", | ||
| 1577 | .type = payload_idx.?, | ||
| 1578 | .alignas = AlignAs.unionPayloadAlign(ty, zcu), | ||
| 1579 | }; | ||
| 1580 | field_count += 1; | ||
| 1581 | } | ||
| 1582 | if (tag_idx != Tag.void.toIndex()) { | ||
| 1583 | self.storage.anon.fields[field_count] = .{ | ||
| 1584 | .name = "tag", | ||
| 1585 | .type = tag_idx.?, | ||
| 1586 | .alignas = AlignAs.abiAlign(tag_ty.?, zcu), | ||
| 1587 | }; | ||
| 1588 | field_count += 1; | ||
| 1589 | } | ||
| 1590 | self.storage.anon.pl = .{ .complete = .{ | ||
| 1591 | .base = .{ .tag = .@"struct" }, | ||
| 1592 | .data = .{ | ||
| 1593 | .fields = self.sortFields(field_count), | ||
| 1594 | .fwd_decl = fwd_idx.?, | ||
| 1595 | }, | ||
| 1596 | } }; | ||
| 1597 | self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) }; | ||
| 1598 | } else self.init(.@"struct"); | ||
| 1599 | } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(zcu)) { | ||
| 1600 | self.init(.void); | ||
| 1601 | } else { | ||
| 1602 | var is_packed = false; | ||
| 1603 | for (0..switch (zig_ty_tag) { | ||
| 1604 | .Struct => ty.structFieldCount(zcu), | ||
| 1605 | .Union => zcu.typeToUnion(ty).?.field_types.len, | ||
| 1606 | else => unreachable, | ||
| 1607 | }) |field_i| { | ||
| 1608 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 1609 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1610 | |||
| 1611 | const field_align = AlignAs.fieldAlign(ty, field_i, zcu); | ||
| 1612 | if (field_align.abiOrder().compare(.lt)) { | ||
| 1613 | is_packed = true; | ||
| 1614 | if (!lookup.isMutable()) break; | ||
| 1615 | } | ||
| 1616 | |||
| 1617 | if (lookup.isMutable()) { | ||
| 1618 | _ = try lookup.typeToIndex(field_ty, switch (kind) { | ||
| 1619 | .forward, .forward_parameter => unreachable, | ||
| 1620 | .complete, .parameter, .payload => .complete, | ||
| 1621 | .global => .global, | ||
| 1622 | }); | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | switch (kind) { | ||
| 1626 | .forward, .forward_parameter => unreachable, | ||
| 1627 | .complete, .parameter, .global => { | ||
| 1628 | _ = try lookup.typeToIndex(ty, .forward); | ||
| 1629 | self.init(if (is_struct) | ||
| 1630 | if (is_packed) .packed_struct else .@"struct" | ||
| 1631 | else if (is_packed) .packed_union else .@"union"); | ||
| 1632 | }, | ||
| 1633 | .payload => self.init(if (is_packed) | ||
| 1634 | .packed_unnamed_union | ||
| 1635 | else | ||
| 1636 | .unnamed_union), | ||
| 1637 | } | ||
| 1638 | }, | ||
| 1639 | } | ||
| 1640 | }, | ||
| 1641 | |||
| 1642 | .Array, .Vector => |zig_ty_tag| { | ||
| 1643 | switch (kind) { | ||
| 1644 | .forward, .complete, .global => { | ||
| 1645 | const t: Tag = switch (zig_ty_tag) { | ||
| 1646 | .Array => .array, | ||
| 1647 | .Vector => .vector, | ||
| 1648 | else => unreachable, | ||
| 1649 | }; | ||
| 1650 | if (try lookup.typeToIndex(ty.childType(zcu), kind)) |child_idx| { | ||
| 1651 | self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{ | ||
| 1652 | .len = ty.arrayLenIncludingSentinel(zcu), | ||
| 1653 | .elem_type = child_idx, | ||
| 1654 | } } }; | ||
| 1655 | self.value = .{ .cty = initPayload(&self.storage.seq) }; | ||
| 1656 | } else self.init(t); | ||
| 1657 | }, | ||
| 1658 | .forward_parameter, .parameter => try self.initArrayParameter(ty, kind, lookup), | ||
| 1659 | .payload => unreachable, | ||
| 1660 | } | ||
| 1661 | }, | ||
| 1662 | |||
| 1663 | .Optional => { | ||
| 1664 | const payload_ty = ty.optionalChild(zcu); | ||
| 1665 | if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | ||
| 1666 | if (ty.optionalReprIsPayload(zcu)) { | ||
| 1667 | try self.initType(payload_ty, kind, lookup); | ||
| 1668 | } else if (switch (kind) { | ||
| 1669 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1670 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1671 | .payload => unreachable, | ||
| 1672 | }) |fwd_idx| { | ||
| 1673 | if (try lookup.typeToIndex(payload_ty, switch (kind) { | ||
| 1674 | .forward, .forward_parameter => .forward, | ||
| 1675 | .complete, .parameter => .complete, | ||
| 1676 | .global => .global, | ||
| 1677 | .payload => unreachable, | ||
| 1678 | })) |payload_idx| { | ||
| 1679 | self.storage = .{ .anon = undefined }; | ||
| 1680 | self.storage.anon.fields[0] = .{ | ||
| 1681 | .name = "payload", | ||
| 1682 | .type = payload_idx, | ||
| 1683 | .alignas = AlignAs.abiAlign(payload_ty, zcu), | ||
| 1684 | }; | ||
| 1685 | self.storage.anon.fields[1] = .{ | ||
| 1686 | .name = "is_null", | ||
| 1687 | .type = Tag.bool.toIndex(), | ||
| 1688 | .alignas = AlignAs.abiAlign(Type.bool, zcu), | ||
| 1689 | }; | ||
| 1690 | self.initAnon(kind, fwd_idx, 2); | ||
| 1691 | } else self.init(switch (kind) { | ||
| 1692 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1693 | .complete, .parameter, .global => .anon_struct, | ||
| 1694 | .payload => unreachable, | ||
| 1695 | }); | ||
| 1696 | } else self.init(.anon_struct); | ||
| 1697 | } else self.init(.bool); | ||
| 1698 | }, | ||
| 1699 | |||
| 1700 | .ErrorUnion => { | ||
| 1701 | if (switch (kind) { | ||
| 1702 | .forward, .forward_parameter => @as(Index, undefined), | ||
| 1703 | .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward), | ||
| 1704 | .payload => unreachable, | ||
| 1705 | }) |fwd_idx| { | ||
| 1706 | const payload_ty = ty.errorUnionPayload(zcu); | ||
| 1707 | if (try lookup.typeToIndex(payload_ty, switch (kind) { | ||
| 1708 | .forward, .forward_parameter => .forward, | ||
| 1709 | .complete, .parameter => .complete, | ||
| 1710 | .global => .global, | ||
| 1711 | .payload => unreachable, | ||
| 1712 | })) |payload_idx| { | ||
| 1713 | const error_ty = ty.errorUnionSet(zcu); | ||
| 1714 | if (payload_idx == Tag.void.toIndex()) { | ||
| 1715 | try self.initType(error_ty, kind, lookup); | ||
| 1716 | } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| { | ||
| 1717 | self.storage = .{ .anon = undefined }; | ||
| 1718 | self.storage.anon.fields[0] = .{ | ||
| 1719 | .name = "payload", | ||
| 1720 | .type = payload_idx, | ||
| 1721 | .alignas = AlignAs.abiAlign(payload_ty, zcu), | ||
| 1722 | }; | ||
| 1723 | self.storage.anon.fields[1] = .{ | ||
| 1724 | .name = "error", | ||
| 1725 | .type = error_idx, | ||
| 1726 | .alignas = AlignAs.abiAlign(error_ty, zcu), | ||
| 1727 | }; | ||
| 1728 | self.initAnon(kind, fwd_idx, 2); | ||
| 1729 | } else self.init(switch (kind) { | ||
| 1730 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1731 | .complete, .parameter, .global => .anon_struct, | ||
| 1732 | .payload => unreachable, | ||
| 1733 | }); | ||
| 1734 | } else self.init(switch (kind) { | ||
| 1735 | .forward, .forward_parameter => .fwd_anon_struct, | ||
| 1736 | .complete, .parameter, .global => .anon_struct, | ||
| 1737 | .payload => unreachable, | ||
| 1738 | }); | ||
| 1739 | } else self.init(.anon_struct); | ||
| 1740 | }, | ||
| 1741 | |||
| 1742 | .Opaque => self.init(.void), | ||
| 1743 | |||
| 1744 | .Fn => { | ||
| 1745 | const info = zcu.typeToFunc(ty).?; | ||
| 1746 | if (!info.is_generic) { | ||
| 1747 | if (lookup.isMutable()) { | ||
| 1748 | const param_kind: Kind = switch (kind) { | ||
| 1749 | .forward, .forward_parameter => .forward_parameter, | ||
| 1750 | .complete, .parameter, .global => .parameter, | ||
| 1751 | .payload => unreachable, | ||
| 1752 | }; | ||
| 1753 | _ = try lookup.typeToIndex(Type.fromInterned(info.return_type), param_kind); | ||
| 1754 | for (info.param_types.get(ip)) |param_type| { | ||
| 1755 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1756 | _ = try lookup.typeToIndex(Type.fromInterned(param_type), param_kind); | ||
| 1757 | } | ||
| 1758 | } | ||
| 1759 | self.init(if (info.is_var_args) .varargs_function else .function); | ||
| 1760 | } else self.init(.void); | ||
| 1761 | }, | ||
| 1762 | } | ||
| 1763 | } | ||
| 1764 | }; | ||
| 1765 | |||
| 1766 | pub fn copy(self: CType, arena: Allocator) !CType { | ||
| 1767 | return self.copyContext(struct { | ||
| 1768 | arena: Allocator, | ||
| 1769 | pub fn copyIndex(_: @This(), idx: Index) Index { | ||
| 1770 | return idx; | ||
| 1771 | } | ||
| 1772 | }{ .arena = arena }); | ||
| 1773 | } | ||
| 1774 | |||
| 1775 | fn copyFields(ctx: anytype, old_fields: Payload.Fields.Data) !Payload.Fields.Data { | ||
| 1776 | const new_fields = try ctx.arena.alloc(Payload.Fields.Field, old_fields.len); | ||
| 1777 | for (new_fields, old_fields) |*new_field, old_field| { | ||
| 1778 | new_field.name = try ctx.arena.dupeZ(u8, mem.span(old_field.name)); | ||
| 1779 | new_field.type = ctx.copyIndex(old_field.type); | ||
| 1780 | new_field.alignas = old_field.alignas; | ||
| 1781 | } | ||
| 1782 | return new_fields; | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | fn copyParams(ctx: anytype, old_param_types: []const Index) ![]const Index { | ||
| 1786 | const new_param_types = try ctx.arena.alloc(Index, old_param_types.len); | ||
| 1787 | for (new_param_types, old_param_types) |*new_param_type, old_param_type| | ||
| 1788 | new_param_type.* = ctx.copyIndex(old_param_type); | ||
| 1789 | return new_param_types; | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | pub fn copyContext(self: CType, ctx: anytype) !CType { | ||
| 1793 | switch (self.tag()) { | ||
| 1794 | .void, | ||
| 1795 | .char, | ||
| 1796 | .@"signed char", | ||
| 1797 | .short, | ||
| 1798 | .int, | ||
| 1799 | .long, | ||
| 1800 | .@"long long", | ||
| 1801 | ._Bool, | ||
| 1802 | .@"unsigned char", | ||
| 1803 | .@"unsigned short", | ||
| 1804 | .@"unsigned int", | ||
| 1805 | .@"unsigned long", | ||
| 1806 | .@"unsigned long long", | ||
| 1807 | .float, | ||
| 1808 | .double, | ||
| 1809 | .@"long double", | ||
| 1810 | .bool, | ||
| 1811 | .size_t, | ||
| 1812 | .ptrdiff_t, | ||
| 1813 | .uint8_t, | ||
| 1814 | .int8_t, | ||
| 1815 | .uint16_t, | ||
| 1816 | .int16_t, | ||
| 1817 | .uint32_t, | ||
| 1818 | .int32_t, | ||
| 1819 | .uint64_t, | ||
| 1820 | .int64_t, | ||
| 1821 | .uintptr_t, | ||
| 1822 | .intptr_t, | ||
| 1823 | .zig_u128, | ||
| 1824 | .zig_i128, | ||
| 1825 | .zig_f16, | ||
| 1826 | .zig_f32, | ||
| 1827 | .zig_f64, | ||
| 1828 | .zig_f80, | ||
| 1829 | .zig_f128, | ||
| 1830 | .zig_c_longdouble, | ||
| 1831 | => return self, | ||
| 1832 | |||
| 1833 | .pointer, | ||
| 1834 | .pointer_const, | ||
| 1835 | .pointer_volatile, | ||
| 1836 | .pointer_const_volatile, | ||
| 1837 | => { | ||
| 1838 | const pl = self.cast(Payload.Child).?; | ||
| 1839 | const new_pl = try ctx.arena.create(Payload.Child); | ||
| 1840 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = ctx.copyIndex(pl.data) }; | ||
| 1841 | return initPayload(new_pl); | ||
| 1842 | }, | ||
| 1843 | |||
| 1844 | .array, | ||
| 1845 | .vector, | ||
| 1846 | => { | ||
| 1847 | const pl = self.cast(Payload.Sequence).?; | ||
| 1848 | const new_pl = try ctx.arena.create(Payload.Sequence); | ||
| 1849 | new_pl.* = .{ | ||
| 1850 | .base = .{ .tag = pl.base.tag }, | ||
| 1851 | .data = .{ .len = pl.data.len, .elem_type = ctx.copyIndex(pl.data.elem_type) }, | ||
| 1852 | }; | ||
| 1853 | return initPayload(new_pl); | ||
| 1854 | }, | ||
| 1855 | |||
| 1856 | .fwd_anon_struct, | ||
| 1857 | .fwd_anon_union, | ||
| 1858 | => { | ||
| 1859 | const pl = self.cast(Payload.Fields).?; | ||
| 1860 | const new_pl = try ctx.arena.create(Payload.Fields); | ||
| 1861 | new_pl.* = .{ | ||
| 1862 | .base = .{ .tag = pl.base.tag }, | ||
| 1863 | .data = try copyFields(ctx, pl.data), | ||
| 1864 | }; | ||
| 1865 | return initPayload(new_pl); | ||
| 1866 | }, | ||
| 1867 | |||
| 1868 | .fwd_struct, | ||
| 1869 | .fwd_union, | ||
| 1870 | => { | ||
| 1871 | const pl = self.cast(Payload.FwdDecl).?; | ||
| 1872 | const new_pl = try ctx.arena.create(Payload.FwdDecl); | ||
| 1873 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = pl.data }; | ||
| 1874 | return initPayload(new_pl); | ||
| 1875 | }, | ||
| 1876 | |||
| 1877 | .unnamed_struct, | ||
| 1878 | .unnamed_union, | ||
| 1879 | .packed_unnamed_struct, | ||
| 1880 | .packed_unnamed_union, | ||
| 1881 | => { | ||
| 1882 | const pl = self.cast(Payload.Unnamed).?; | ||
| 1883 | const new_pl = try ctx.arena.create(Payload.Unnamed); | ||
| 1884 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1885 | .fields = try copyFields(ctx, pl.data.fields), | ||
| 1886 | .owner_decl = pl.data.owner_decl, | ||
| 1887 | .id = pl.data.id, | ||
| 1888 | } }; | ||
| 1889 | return initPayload(new_pl); | ||
| 1890 | }, | ||
| 1891 | |||
| 1892 | .anon_struct, | ||
| 1893 | .anon_union, | ||
| 1894 | .@"struct", | ||
| 1895 | .@"union", | ||
| 1896 | .packed_struct, | ||
| 1897 | .packed_union, | ||
| 1898 | => { | ||
| 1899 | const pl = self.cast(Payload.Aggregate).?; | ||
| 1900 | const new_pl = try ctx.arena.create(Payload.Aggregate); | ||
| 1901 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1902 | .fields = try copyFields(ctx, pl.data.fields), | ||
| 1903 | .fwd_decl = ctx.copyIndex(pl.data.fwd_decl), | ||
| 1904 | } }; | ||
| 1905 | return initPayload(new_pl); | ||
| 1906 | }, | ||
| 1907 | |||
| 1908 | .function, | ||
| 1909 | .varargs_function, | ||
| 1910 | => { | ||
| 1911 | const pl = self.cast(Payload.Function).?; | ||
| 1912 | const new_pl = try ctx.arena.create(Payload.Function); | ||
| 1913 | new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{ | ||
| 1914 | .return_type = ctx.copyIndex(pl.data.return_type), | ||
| 1915 | .param_types = try copyParams(ctx, pl.data.param_types), | ||
| 1916 | } }; | ||
| 1917 | return initPayload(new_pl); | ||
| 1918 | }, | ||
| 1919 | } | ||
| 1920 | } | ||
| 1921 | |||
| 1922 | fn createFromType(store: *Store.Promoted, ty: Type, zcu: *Zcu, mod: *Module, kind: Kind) !CType { | ||
| 1923 | var convert: Convert = undefined; | ||
| 1924 | try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .zcu = zcu } }); | ||
| 1925 | return createFromConvert(store, ty, zcu, mod, kind, &convert); | ||
| 1926 | } | ||
| 1927 | |||
| 1928 | fn createFromConvert( | ||
| 1929 | store: *Store.Promoted, | ||
| 1930 | ty: Type, | ||
| 1931 | zcu: *Zcu, | ||
| 1932 | mod: *Module, | ||
| 1933 | kind: Kind, | ||
| 1934 | convert: Convert, | ||
| 1935 | ) !CType { | ||
| 1936 | const ip = &zcu.intern_pool; | ||
| 1937 | const arena = store.arena.allocator(); | ||
| 1938 | switch (convert.value) { | ||
| 1939 | .cty => |c| return c.copy(arena), | ||
| 1940 | .tag => |t| switch (t) { | ||
| 1941 | .fwd_anon_struct, | ||
| 1942 | .fwd_anon_union, | ||
| 1943 | .unnamed_struct, | ||
| 1944 | .unnamed_union, | ||
| 1945 | .packed_unnamed_struct, | ||
| 1946 | .packed_unnamed_union, | ||
| 1947 | .anon_struct, | ||
| 1948 | .anon_union, | ||
| 1949 | .@"struct", | ||
| 1950 | .@"union", | ||
| 1951 | .packed_struct, | ||
| 1952 | .packed_union, | ||
| 1953 | => { | ||
| 1954 | const zig_ty_tag = ty.zigTypeTag(zcu); | ||
| 1955 | const fields_len = switch (zig_ty_tag) { | ||
| 1956 | .Struct => ty.structFieldCount(zcu), | ||
| 1957 | .Union => zcu.typeToUnion(ty).?.field_types.len, | ||
| 1958 | else => unreachable, | ||
| 1959 | }; | ||
| 1960 | |||
| 1961 | var c_fields_len: usize = 0; | ||
| 1962 | for (0..fields_len) |field_i| { | ||
| 1963 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 1964 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or | ||
| 1965 | !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1966 | c_fields_len += 1; | ||
| 1967 | } | ||
| 1968 | |||
| 1969 | const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len); | ||
| 1970 | var c_field_i: usize = 0; | ||
| 1971 | for (0..fields_len) |field_i_usize| { | ||
| 1972 | const field_i: u32 = @intCast(field_i_usize); | ||
| 1973 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 1974 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or | ||
| 1975 | !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 1976 | |||
| 1977 | defer c_field_i += 1; | ||
| 1978 | fields_pl[c_field_i] = .{ | ||
| 1979 | .name = try if (ty.isSimpleTuple(zcu)) | ||
| 1980 | std.fmt.allocPrintZ(arena, "f{}", .{field_i}) | ||
| 1981 | else | ||
| 1982 | arena.dupeZ(u8, ip.stringToSlice(switch (zig_ty_tag) { | ||
| 1983 | .Struct => ty.legacyStructFieldName(field_i, zcu), | ||
| 1984 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 1985 | else => unreachable, | ||
| 1986 | })), | ||
| 1987 | .type = store.set.typeToIndex(field_ty, zcu, mod, switch (kind) { | ||
| 1988 | .forward, .forward_parameter => .forward, | ||
| 1989 | .complete, .parameter, .payload => .complete, | ||
| 1990 | .global => .global, | ||
| 1991 | }).?, | ||
| 1992 | .alignas = AlignAs.fieldAlign(ty, field_i, zcu), | ||
| 1993 | }; | ||
| 1994 | } | ||
| 1995 | |||
| 1996 | switch (t) { | ||
| 1997 | .fwd_anon_struct, | ||
| 1998 | .fwd_anon_union, | ||
| 1999 | => { | ||
| 2000 | const anon_pl = try arena.create(Payload.Fields); | ||
| 2001 | anon_pl.* = .{ .base = .{ .tag = t }, .data = fields_pl }; | ||
| 2002 | return initPayload(anon_pl); | ||
| 2003 | }, | ||
| 2004 | |||
| 2005 | .unnamed_struct, | ||
| 2006 | .unnamed_union, | ||
| 2007 | .packed_unnamed_struct, | ||
| 2008 | .packed_unnamed_union, | ||
| 2009 | => { | ||
| 2010 | const unnamed_pl = try arena.create(Payload.Unnamed); | ||
| 2011 | unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 2012 | .fields = fields_pl, | ||
| 2013 | .owner_decl = ty.getOwnerDecl(zcu), | ||
| 2014 | .id = if (ty.unionTagTypeSafety(zcu)) |_| 0 else unreachable, | ||
| 2015 | } }; | ||
| 2016 | return initPayload(unnamed_pl); | ||
| 2017 | }, | ||
| 2018 | |||
| 2019 | .anon_struct, | ||
| 2020 | .anon_union, | ||
| 2021 | .@"struct", | ||
| 2022 | .@"union", | ||
| 2023 | .packed_struct, | ||
| 2024 | .packed_union, | ||
| 2025 | => { | ||
| 2026 | const struct_pl = try arena.create(Payload.Aggregate); | ||
| 2027 | struct_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 2028 | .fields = fields_pl, | ||
| 2029 | .fwd_decl = store.set.typeToIndex(ty, zcu, mod, .forward).?, | ||
| 2030 | } }; | ||
| 2031 | return initPayload(struct_pl); | ||
| 2032 | }, | ||
| 2033 | |||
| 2034 | else => unreachable, | ||
| 2035 | } | ||
| 2036 | }, | ||
| 2037 | |||
| 2038 | .function, | ||
| 2039 | .varargs_function, | ||
| 2040 | => { | ||
| 2041 | const info = zcu.typeToFunc(ty).?; | ||
| 2042 | assert(!info.is_generic); | ||
| 2043 | const param_kind: Kind = switch (kind) { | ||
| 2044 | .forward, .forward_parameter => .forward_parameter, | ||
| 2045 | .complete, .parameter, .global => .parameter, | ||
| 2046 | .payload => unreachable, | ||
| 2047 | }; | ||
| 2048 | |||
| 2049 | var c_params_len: usize = 0; | ||
| 2050 | for (info.param_types.get(ip)) |param_type| { | ||
| 2051 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2052 | c_params_len += 1; | ||
| 2053 | } | ||
| 2054 | |||
| 2055 | const params_pl = try arena.alloc(Index, c_params_len); | ||
| 2056 | var c_param_i: usize = 0; | ||
| 2057 | for (info.param_types.get(ip)) |param_type| { | ||
| 2058 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2059 | params_pl[c_param_i] = store.set.typeToIndex(Type.fromInterned(param_type), zcu, mod, param_kind).?; | ||
| 2060 | c_param_i += 1; | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | const fn_pl = try arena.create(Payload.Function); | ||
| 2064 | fn_pl.* = .{ .base = .{ .tag = t }, .data = .{ | ||
| 2065 | .return_type = store.set.typeToIndex(Type.fromInterned(info.return_type), zcu, mod, param_kind).?, | ||
| 2066 | .param_types = params_pl, | ||
| 2067 | } }; | ||
| 2068 | return initPayload(fn_pl); | ||
| 2069 | }, | ||
| 2070 | |||
| 2071 | else => unreachable, | ||
| 2072 | }, | ||
| 2073 | } | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | pub const TypeAdapter64 = struct { | ||
| 2077 | kind: Kind, | ||
| 2078 | lookup: Convert.Lookup, | ||
| 2079 | convert: *const Convert, | ||
| 2080 | |||
| 2081 | fn eqlRecurse(self: @This(), ty: Type, cty: Index, kind: Kind) bool { | ||
| 2082 | assert(!self.lookup.isMutable()); | ||
| 2083 | |||
| 2084 | var convert: Convert = undefined; | ||
| 2085 | convert.initType(ty, kind, self.lookup) catch unreachable; | ||
| 2086 | |||
| 2087 | const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert }; | ||
| 2088 | return self_recurse.eql(ty, self.lookup.indexToCType(cty).?); | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | pub fn eql(self: @This(), ty: Type, cty: CType) bool { | ||
| 2092 | const zcu = self.lookup.getZcu(); | ||
| 2093 | const ip = &zcu.intern_pool; | ||
| 2094 | switch (self.convert.value) { | ||
| 2095 | .cty => |c| return c.eql(cty), | ||
| 2096 | .tag => |t| { | ||
| 2097 | if (t != cty.tag()) return false; | ||
| 2098 | |||
| 2099 | switch (t) { | ||
| 2100 | .fwd_anon_struct, | ||
| 2101 | .fwd_anon_union, | ||
| 2102 | => { | ||
| 2103 | if (!ty.isTupleOrAnonStruct(zcu)) return false; | ||
| 2104 | |||
| 2105 | var name_buf: [ | ||
| 2106 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | ||
| 2107 | ]u8 = undefined; | ||
| 2108 | const c_fields = cty.cast(Payload.Fields).?.data; | ||
| 2109 | |||
| 2110 | const zig_ty_tag = ty.zigTypeTag(zcu); | ||
| 2111 | var c_field_i: usize = 0; | ||
| 2112 | for (0..switch (zig_ty_tag) { | ||
| 2113 | .Struct => ty.structFieldCount(zcu), | ||
| 2114 | .Union => zcu.typeToUnion(ty).?.field_types.len, | ||
| 2115 | else => unreachable, | ||
| 2116 | }) |field_i_usize| { | ||
| 2117 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2118 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 2119 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or | ||
| 2120 | !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2121 | |||
| 2122 | defer c_field_i += 1; | ||
| 2123 | const c_field = &c_fields[c_field_i]; | ||
| 2124 | |||
| 2125 | if (!self.eqlRecurse(field_ty, c_field.type, switch (self.kind) { | ||
| 2126 | .forward, .forward_parameter => .forward, | ||
| 2127 | .complete, .parameter => .complete, | ||
| 2128 | .global => .global, | ||
| 2129 | .payload => unreachable, | ||
| 2130 | }) or !mem.eql( | ||
| 2131 | u8, | ||
| 2132 | if (ty.isSimpleTuple(zcu)) | ||
| 2133 | std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable | ||
| 2134 | else | ||
| 2135 | ip.stringToSlice(switch (zig_ty_tag) { | ||
| 2136 | .Struct => ty.legacyStructFieldName(field_i, zcu), | ||
| 2137 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 2138 | else => unreachable, | ||
| 2139 | }), | ||
| 2140 | mem.span(c_field.name), | ||
| 2141 | ) or AlignAs.fieldAlign(ty, field_i, zcu).@"align" != | ||
| 2142 | c_field.alignas.@"align") return false; | ||
| 2143 | } | ||
| 2144 | return true; | ||
| 2145 | }, | ||
| 2146 | |||
| 2147 | .unnamed_struct, | ||
| 2148 | .unnamed_union, | ||
| 2149 | .packed_unnamed_struct, | ||
| 2150 | .packed_unnamed_union, | ||
| 2151 | => switch (self.kind) { | ||
| 2152 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, | ||
| 2153 | .payload => if (ty.unionTagTypeSafety(zcu)) |_| { | ||
| 2154 | const data = cty.cast(Payload.Unnamed).?.data; | ||
| 2155 | return ty.getOwnerDecl(zcu) == data.owner_decl and data.id == 0; | ||
| 2156 | } else unreachable, | ||
| 2157 | }, | ||
| 2158 | |||
| 2159 | .anon_struct, | ||
| 2160 | .anon_union, | ||
| 2161 | .@"struct", | ||
| 2162 | .@"union", | ||
| 2163 | .packed_struct, | ||
| 2164 | .packed_union, | ||
| 2165 | => return self.eqlRecurse( | ||
| 2166 | ty, | ||
| 2167 | cty.cast(Payload.Aggregate).?.data.fwd_decl, | ||
| 2168 | .forward, | ||
| 2169 | ), | ||
| 2170 | |||
| 2171 | .function, | ||
| 2172 | .varargs_function, | ||
| 2173 | => { | ||
| 2174 | if (ty.zigTypeTag(zcu) != .Fn) return false; | ||
| 2175 | |||
| 2176 | const info = zcu.typeToFunc(ty).?; | ||
| 2177 | assert(!info.is_generic); | ||
| 2178 | const data = cty.cast(Payload.Function).?.data; | ||
| 2179 | const param_kind: Kind = switch (self.kind) { | ||
| 2180 | .forward, .forward_parameter => .forward_parameter, | ||
| 2181 | .complete, .parameter, .global => .parameter, | ||
| 2182 | .payload => unreachable, | ||
| 2183 | }; | ||
| 2184 | |||
| 2185 | if (!self.eqlRecurse(Type.fromInterned(info.return_type), data.return_type, param_kind)) | ||
| 2186 | return false; | ||
| 2187 | |||
| 2188 | var c_param_i: usize = 0; | ||
| 2189 | for (info.param_types.get(ip)) |param_type| { | ||
| 2190 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2191 | |||
| 2192 | if (c_param_i >= data.param_types.len) return false; | ||
| 2193 | const param_cty = data.param_types[c_param_i]; | ||
| 2194 | c_param_i += 1; | ||
| 2195 | |||
| 2196 | if (!self.eqlRecurse(Type.fromInterned(param_type), param_cty, param_kind)) | ||
| 2197 | return false; | ||
| 2198 | } | ||
| 2199 | return c_param_i == data.param_types.len; | ||
| 2200 | }, | ||
| 2201 | |||
| 2202 | else => unreachable, | ||
| 2203 | } | ||
| 2204 | }, | ||
| 2205 | } | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | pub fn hash(self: @This(), ty: Type) u64 { | ||
| 2209 | var hasher = std.hash.Wyhash.init(0); | ||
| 2210 | self.updateHasher(&hasher, ty); | ||
| 2211 | return hasher.final(); | ||
| 2212 | } | ||
| 2213 | |||
| 2214 | fn updateHasherRecurse(self: @This(), hasher: anytype, ty: Type, kind: Kind) void { | ||
| 2215 | assert(!self.lookup.isMutable()); | ||
| 2216 | |||
| 2217 | var convert: Convert = undefined; | ||
| 2218 | convert.initType(ty, kind, self.lookup) catch unreachable; | ||
| 2219 | |||
| 2220 | const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert }; | ||
| 2221 | self_recurse.updateHasher(hasher, ty); | ||
| 2222 | } | ||
| 2223 | |||
| 2224 | pub fn updateHasher(self: @This(), hasher: anytype, ty: Type) void { | ||
| 2225 | switch (self.convert.value) { | ||
| 2226 | .cty => |c| return c.updateHasher(hasher, self.lookup.getSet().?.*), | ||
| 2227 | .tag => |t| { | ||
| 2228 | autoHash(hasher, t); | ||
| 2229 | |||
| 2230 | const zcu = self.lookup.getZcu(); | ||
| 2231 | const ip = &zcu.intern_pool; | ||
| 2232 | switch (t) { | ||
| 2233 | .fwd_anon_struct, | ||
| 2234 | .fwd_anon_union, | ||
| 2235 | => { | ||
| 2236 | var name_buf: [ | ||
| 2237 | std.fmt.count("f{}", .{std.math.maxInt(usize)}) | ||
| 2238 | ]u8 = undefined; | ||
| 2239 | |||
| 2240 | const zig_ty_tag = ty.zigTypeTag(zcu); | ||
| 2241 | for (0..switch (ty.zigTypeTag(zcu)) { | ||
| 2242 | .Struct => ty.structFieldCount(zcu), | ||
| 2243 | .Union => zcu.typeToUnion(ty).?.field_types.len, | ||
| 2244 | else => unreachable, | ||
| 2245 | }) |field_i_usize| { | ||
| 2246 | const field_i: u32 = @intCast(field_i_usize); | ||
| 2247 | const field_ty = ty.structFieldType(field_i, zcu); | ||
| 2248 | if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, zcu)) or | ||
| 2249 | !field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2250 | |||
| 2251 | self.updateHasherRecurse(hasher, field_ty, switch (self.kind) { | ||
| 2252 | .forward, .forward_parameter => .forward, | ||
| 2253 | .complete, .parameter => .complete, | ||
| 2254 | .global => .global, | ||
| 2255 | .payload => unreachable, | ||
| 2256 | }); | ||
| 2257 | hasher.update(if (ty.isSimpleTuple(zcu)) | ||
| 2258 | std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable | ||
| 2259 | else | ||
| 2260 | zcu.intern_pool.stringToSlice(switch (zig_ty_tag) { | ||
| 2261 | .Struct => ty.legacyStructFieldName(field_i, zcu), | ||
| 2262 | .Union => ip.loadUnionType(ty.toIntern()).loadTagType(ip).names.get(ip)[field_i], | ||
| 2263 | else => unreachable, | ||
| 2264 | })); | ||
| 2265 | autoHash(hasher, AlignAs.fieldAlign(ty, field_i, zcu).@"align"); | ||
| 2266 | } | ||
| 2267 | }, | ||
| 2268 | |||
| 2269 | .unnamed_struct, | ||
| 2270 | .unnamed_union, | ||
| 2271 | .packed_unnamed_struct, | ||
| 2272 | .packed_unnamed_union, | ||
| 2273 | => switch (self.kind) { | ||
| 2274 | .forward, .forward_parameter, .complete, .parameter, .global => unreachable, | ||
| 2275 | .payload => if (ty.unionTagTypeSafety(zcu)) |_| { | ||
| 2276 | autoHash(hasher, ty.getOwnerDecl(zcu)); | ||
| 2277 | autoHash(hasher, @as(u32, 0)); | ||
| 2278 | } else unreachable, | ||
| 2279 | }, | ||
| 2280 | |||
| 2281 | .anon_struct, | ||
| 2282 | .anon_union, | ||
| 2283 | .@"struct", | ||
| 2284 | .@"union", | ||
| 2285 | .packed_struct, | ||
| 2286 | .packed_union, | ||
| 2287 | => self.updateHasherRecurse(hasher, ty, .forward), | ||
| 2288 | |||
| 2289 | .function, | ||
| 2290 | .varargs_function, | ||
| 2291 | => { | ||
| 2292 | const info = zcu.typeToFunc(ty).?; | ||
| 2293 | assert(!info.is_generic); | ||
| 2294 | const param_kind: Kind = switch (self.kind) { | ||
| 2295 | .forward, .forward_parameter => .forward_parameter, | ||
| 2296 | .complete, .parameter, .global => .parameter, | ||
| 2297 | .payload => unreachable, | ||
| 2298 | }; | ||
| 2299 | |||
| 2300 | self.updateHasherRecurse(hasher, Type.fromInterned(info.return_type), param_kind); | ||
| 2301 | for (info.param_types.get(ip)) |param_type| { | ||
| 2302 | if (!Type.fromInterned(param_type).hasRuntimeBitsIgnoreComptime(zcu)) continue; | ||
| 2303 | self.updateHasherRecurse(hasher, Type.fromInterned(param_type), param_kind); | ||
| 2304 | } | ||
| 2305 | }, | ||
| 2306 | |||
| 2307 | else => unreachable, | ||
| 2308 | } | ||
| 2309 | }, | ||
| 2310 | } | ||
| 2311 | } | ||
| 2312 | }; | ||
| 2313 | |||
| 2314 | pub const TypeAdapter32 = struct { | ||
| 2315 | kind: Kind, | ||
| 2316 | lookup: Convert.Lookup, | ||
| 2317 | convert: *const Convert, | ||
| 2318 | |||
| 2319 | fn to64(self: @This()) TypeAdapter64 { | ||
| 2320 | return .{ .kind = self.kind, .lookup = self.lookup, .convert = self.convert }; | ||
| 2321 | } | ||
| 2322 | |||
| 2323 | pub fn eql(self: @This(), ty: Type, cty: CType, cty_index: usize) bool { | ||
| 2324 | _ = cty_index; | ||
| 2325 | return self.to64().eql(ty, cty); | ||
| 2326 | } | ||
| 2327 | |||
| 2328 | pub fn hash(self: @This(), ty: Type) u32 { | ||
| 2329 | return @as(u32, @truncate(self.to64().hash(ty))); | ||
| 2330 | } | ||
| 2331 | }; | ||
| 2332 | }; | ||
src/codegen/llvm.zig+24-24| ... | @@ -2033,7 +2033,7 @@ pub const Object = struct { | ... | @@ -2033,7 +2033,7 @@ pub const Object = struct { |
| 2033 | owner_decl.src_node + 1, // Line | 2033 | owner_decl.src_node + 1, // Line |
| 2034 | try o.lowerDebugType(int_ty), | 2034 | try o.lowerDebugType(int_ty), |
| 2035 | ty.abiSize(mod) * 8, | 2035 | ty.abiSize(mod) * 8, |
| 2036 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2036 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2037 | try o.builder.debugTuple(enumerators), | 2037 | try o.builder.debugTuple(enumerators), |
| 2038 | ); | 2038 | ); |
| 2039 | 2039 | ||
| ... | @@ -2120,7 +2120,7 @@ pub const Object = struct { | ... | @@ -2120,7 +2120,7 @@ pub const Object = struct { |
| 2120 | 0, // Line | 2120 | 0, // Line |
| 2121 | try o.lowerDebugType(ptr_ty), | 2121 | try o.lowerDebugType(ptr_ty), |
| 2122 | ptr_size * 8, | 2122 | ptr_size * 8, |
| 2123 | ptr_align.toByteUnits(0) * 8, | 2123 | (ptr_align.toByteUnits() orelse 0) * 8, |
| 2124 | 0, // Offset | 2124 | 0, // Offset |
| 2125 | ); | 2125 | ); |
| 2126 | 2126 | ||
| ... | @@ -2131,7 +2131,7 @@ pub const Object = struct { | ... | @@ -2131,7 +2131,7 @@ pub const Object = struct { |
| 2131 | 0, // Line | 2131 | 0, // Line |
| 2132 | try o.lowerDebugType(len_ty), | 2132 | try o.lowerDebugType(len_ty), |
| 2133 | len_size * 8, | 2133 | len_size * 8, |
| 2134 | len_align.toByteUnits(0) * 8, | 2134 | (len_align.toByteUnits() orelse 0) * 8, |
| 2135 | len_offset * 8, | 2135 | len_offset * 8, |
| 2136 | ); | 2136 | ); |
| 2137 | 2137 | ||
| ... | @@ -2142,7 +2142,7 @@ pub const Object = struct { | ... | @@ -2142,7 +2142,7 @@ pub const Object = struct { |
| 2142 | line, | 2142 | line, |
| 2143 | .none, // Underlying type | 2143 | .none, // Underlying type |
| 2144 | ty.abiSize(mod) * 8, | 2144 | ty.abiSize(mod) * 8, |
| 2145 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2145 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2146 | try o.builder.debugTuple(&.{ | 2146 | try o.builder.debugTuple(&.{ |
| 2147 | debug_ptr_type, | 2147 | debug_ptr_type, |
| 2148 | debug_len_type, | 2148 | debug_len_type, |
| ... | @@ -2170,7 +2170,7 @@ pub const Object = struct { | ... | @@ -2170,7 +2170,7 @@ pub const Object = struct { |
| 2170 | 0, // Line | 2170 | 0, // Line |
| 2171 | debug_elem_ty, | 2171 | debug_elem_ty, |
| 2172 | target.ptrBitWidth(), | 2172 | target.ptrBitWidth(), |
| 2173 | ty.ptrAlignment(mod).toByteUnits(0) * 8, | 2173 | (ty.ptrAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2174 | 0, // Offset | 2174 | 0, // Offset |
| 2175 | ); | 2175 | ); |
| 2176 | 2176 | ||
| ... | @@ -2217,7 +2217,7 @@ pub const Object = struct { | ... | @@ -2217,7 +2217,7 @@ pub const Object = struct { |
| 2217 | 0, // Line | 2217 | 0, // Line |
| 2218 | try o.lowerDebugType(ty.childType(mod)), | 2218 | try o.lowerDebugType(ty.childType(mod)), |
| 2219 | ty.abiSize(mod) * 8, | 2219 | ty.abiSize(mod) * 8, |
| 2220 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2220 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2221 | try o.builder.debugTuple(&.{ | 2221 | try o.builder.debugTuple(&.{ |
| 2222 | try o.builder.debugSubrange( | 2222 | try o.builder.debugSubrange( |
| 2223 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), | 2223 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | @@ -2260,7 +2260,7 @@ pub const Object = struct { | ... | @@ -2260,7 +2260,7 @@ pub const Object = struct { |
| 2260 | 0, // Line | 2260 | 0, // Line |
| 2261 | debug_elem_type, | 2261 | debug_elem_type, |
| 2262 | ty.abiSize(mod) * 8, | 2262 | ty.abiSize(mod) * 8, |
| 2263 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2263 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2264 | try o.builder.debugTuple(&.{ | 2264 | try o.builder.debugTuple(&.{ |
| 2265 | try o.builder.debugSubrange( | 2265 | try o.builder.debugSubrange( |
| 2266 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), | 2266 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | @@ -2316,7 +2316,7 @@ pub const Object = struct { | ... | @@ -2316,7 +2316,7 @@ pub const Object = struct { |
| 2316 | 0, // Line | 2316 | 0, // Line |
| 2317 | try o.lowerDebugType(child_ty), | 2317 | try o.lowerDebugType(child_ty), |
| 2318 | payload_size * 8, | 2318 | payload_size * 8, |
| 2319 | payload_align.toByteUnits(0) * 8, | 2319 | (payload_align.toByteUnits() orelse 0) * 8, |
| 2320 | 0, // Offset | 2320 | 0, // Offset |
| 2321 | ); | 2321 | ); |
| 2322 | 2322 | ||
| ... | @@ -2327,7 +2327,7 @@ pub const Object = struct { | ... | @@ -2327,7 +2327,7 @@ pub const Object = struct { |
| 2327 | 0, | 2327 | 0, |
| 2328 | try o.lowerDebugType(non_null_ty), | 2328 | try o.lowerDebugType(non_null_ty), |
| 2329 | non_null_size * 8, | 2329 | non_null_size * 8, |
| 2330 | non_null_align.toByteUnits(0) * 8, | 2330 | (non_null_align.toByteUnits() orelse 0) * 8, |
| 2331 | non_null_offset * 8, | 2331 | non_null_offset * 8, |
| 2332 | ); | 2332 | ); |
| 2333 | 2333 | ||
| ... | @@ -2338,7 +2338,7 @@ pub const Object = struct { | ... | @@ -2338,7 +2338,7 @@ pub const Object = struct { |
| 2338 | 0, // Line | 2338 | 0, // Line |
| 2339 | .none, // Underlying type | 2339 | .none, // Underlying type |
| 2340 | ty.abiSize(mod) * 8, | 2340 | ty.abiSize(mod) * 8, |
| 2341 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2341 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2342 | try o.builder.debugTuple(&.{ | 2342 | try o.builder.debugTuple(&.{ |
| 2343 | debug_data_type, | 2343 | debug_data_type, |
| 2344 | debug_some_type, | 2344 | debug_some_type, |
| ... | @@ -2396,7 +2396,7 @@ pub const Object = struct { | ... | @@ -2396,7 +2396,7 @@ pub const Object = struct { |
| 2396 | 0, // Line | 2396 | 0, // Line |
| 2397 | try o.lowerDebugType(Type.anyerror), | 2397 | try o.lowerDebugType(Type.anyerror), |
| 2398 | error_size * 8, | 2398 | error_size * 8, |
| 2399 | error_align.toByteUnits(0) * 8, | 2399 | (error_align.toByteUnits() orelse 0) * 8, |
| 2400 | error_offset * 8, | 2400 | error_offset * 8, |
| 2401 | ); | 2401 | ); |
| 2402 | fields[payload_index] = try o.builder.debugMemberType( | 2402 | fields[payload_index] = try o.builder.debugMemberType( |
| ... | @@ -2406,7 +2406,7 @@ pub const Object = struct { | ... | @@ -2406,7 +2406,7 @@ pub const Object = struct { |
| 2406 | 0, // Line | 2406 | 0, // Line |
| 2407 | try o.lowerDebugType(payload_ty), | 2407 | try o.lowerDebugType(payload_ty), |
| 2408 | payload_size * 8, | 2408 | payload_size * 8, |
| 2409 | payload_align.toByteUnits(0) * 8, | 2409 | (payload_align.toByteUnits() orelse 0) * 8, |
| 2410 | payload_offset * 8, | 2410 | payload_offset * 8, |
| 2411 | ); | 2411 | ); |
| 2412 | 2412 | ||
| ... | @@ -2417,7 +2417,7 @@ pub const Object = struct { | ... | @@ -2417,7 +2417,7 @@ pub const Object = struct { |
| 2417 | 0, // Line | 2417 | 0, // Line |
| 2418 | .none, // Underlying type | 2418 | .none, // Underlying type |
| 2419 | ty.abiSize(mod) * 8, | 2419 | ty.abiSize(mod) * 8, |
| 2420 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2420 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2421 | try o.builder.debugTuple(&fields), | 2421 | try o.builder.debugTuple(&fields), |
| 2422 | ); | 2422 | ); |
| 2423 | 2423 | ||
| ... | @@ -2485,7 +2485,7 @@ pub const Object = struct { | ... | @@ -2485,7 +2485,7 @@ pub const Object = struct { |
| 2485 | 0, | 2485 | 0, |
| 2486 | try o.lowerDebugType(Type.fromInterned(field_ty)), | 2486 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2487 | field_size * 8, | 2487 | field_size * 8, |
| 2488 | field_align.toByteUnits(0) * 8, | 2488 | (field_align.toByteUnits() orelse 0) * 8, |
| 2489 | field_offset * 8, | 2489 | field_offset * 8, |
| 2490 | )); | 2490 | )); |
| 2491 | } | 2491 | } |
| ... | @@ -2497,7 +2497,7 @@ pub const Object = struct { | ... | @@ -2497,7 +2497,7 @@ pub const Object = struct { |
| 2497 | 0, // Line | 2497 | 0, // Line |
| 2498 | .none, // Underlying type | 2498 | .none, // Underlying type |
| 2499 | ty.abiSize(mod) * 8, | 2499 | ty.abiSize(mod) * 8, |
| 2500 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2500 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2501 | try o.builder.debugTuple(fields.items), | 2501 | try o.builder.debugTuple(fields.items), |
| 2502 | ); | 2502 | ); |
| 2503 | 2503 | ||
| ... | @@ -2566,7 +2566,7 @@ pub const Object = struct { | ... | @@ -2566,7 +2566,7 @@ pub const Object = struct { |
| 2566 | 0, // Line | 2566 | 0, // Line |
| 2567 | try o.lowerDebugType(field_ty), | 2567 | try o.lowerDebugType(field_ty), |
| 2568 | field_size * 8, | 2568 | field_size * 8, |
| 2569 | field_align.toByteUnits(0) * 8, | 2569 | (field_align.toByteUnits() orelse 0) * 8, |
| 2570 | field_offset * 8, | 2570 | field_offset * 8, |
| 2571 | )); | 2571 | )); |
| 2572 | } | 2572 | } |
| ... | @@ -2578,7 +2578,7 @@ pub const Object = struct { | ... | @@ -2578,7 +2578,7 @@ pub const Object = struct { |
| 2578 | 0, // Line | 2578 | 0, // Line |
| 2579 | .none, // Underlying type | 2579 | .none, // Underlying type |
| 2580 | ty.abiSize(mod) * 8, | 2580 | ty.abiSize(mod) * 8, |
| 2581 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2581 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2582 | try o.builder.debugTuple(fields.items), | 2582 | try o.builder.debugTuple(fields.items), |
| 2583 | ); | 2583 | ); |
| 2584 | 2584 | ||
| ... | @@ -2621,7 +2621,7 @@ pub const Object = struct { | ... | @@ -2621,7 +2621,7 @@ pub const Object = struct { |
| 2621 | 0, // Line | 2621 | 0, // Line |
| 2622 | .none, // Underlying type | 2622 | .none, // Underlying type |
| 2623 | ty.abiSize(mod) * 8, | 2623 | ty.abiSize(mod) * 8, |
| 2624 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2624 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2625 | try o.builder.debugTuple( | 2625 | try o.builder.debugTuple( |
| 2626 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, | 2626 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, |
| 2627 | ), | 2627 | ), |
| ... | @@ -2661,7 +2661,7 @@ pub const Object = struct { | ... | @@ -2661,7 +2661,7 @@ pub const Object = struct { |
| 2661 | 0, // Line | 2661 | 0, // Line |
| 2662 | try o.lowerDebugType(Type.fromInterned(field_ty)), | 2662 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2663 | field_size * 8, | 2663 | field_size * 8, |
| 2664 | field_align.toByteUnits(0) * 8, | 2664 | (field_align.toByteUnits() orelse 0) * 8, |
| 2665 | 0, // Offset | 2665 | 0, // Offset |
| 2666 | )); | 2666 | )); |
| 2667 | } | 2667 | } |
| ... | @@ -2680,7 +2680,7 @@ pub const Object = struct { | ... | @@ -2680,7 +2680,7 @@ pub const Object = struct { |
| 2680 | 0, // Line | 2680 | 0, // Line |
| 2681 | .none, // Underlying type | 2681 | .none, // Underlying type |
| 2682 | ty.abiSize(mod) * 8, | 2682 | ty.abiSize(mod) * 8, |
| 2683 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2683 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2684 | try o.builder.debugTuple(fields.items), | 2684 | try o.builder.debugTuple(fields.items), |
| 2685 | ); | 2685 | ); |
| 2686 | 2686 | ||
| ... | @@ -2711,7 +2711,7 @@ pub const Object = struct { | ... | @@ -2711,7 +2711,7 @@ pub const Object = struct { |
| 2711 | 0, // Line | 2711 | 0, // Line |
| 2712 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), | 2712 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), |
| 2713 | layout.tag_size * 8, | 2713 | layout.tag_size * 8, |
| 2714 | layout.tag_align.toByteUnits(0) * 8, | 2714 | (layout.tag_align.toByteUnits() orelse 0) * 8, |
| 2715 | tag_offset * 8, | 2715 | tag_offset * 8, |
| 2716 | ); | 2716 | ); |
| 2717 | 2717 | ||
| ... | @@ -2722,7 +2722,7 @@ pub const Object = struct { | ... | @@ -2722,7 +2722,7 @@ pub const Object = struct { |
| 2722 | 0, // Line | 2722 | 0, // Line |
| 2723 | debug_union_type, | 2723 | debug_union_type, |
| 2724 | layout.payload_size * 8, | 2724 | layout.payload_size * 8, |
| 2725 | layout.payload_align.toByteUnits(0) * 8, | 2725 | (layout.payload_align.toByteUnits() orelse 0) * 8, |
| 2726 | payload_offset * 8, | 2726 | payload_offset * 8, |
| 2727 | ); | 2727 | ); |
| 2728 | 2728 | ||
| ... | @@ -2739,7 +2739,7 @@ pub const Object = struct { | ... | @@ -2739,7 +2739,7 @@ pub const Object = struct { |
| 2739 | 0, // Line | 2739 | 0, // Line |
| 2740 | .none, // Underlying type | 2740 | .none, // Underlying type |
| 2741 | ty.abiSize(mod) * 8, | 2741 | ty.abiSize(mod) * 8, |
| 2742 | ty.abiAlignment(mod).toByteUnits(0) * 8, | 2742 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, |
| 2743 | try o.builder.debugTuple(&full_fields), | 2743 | try o.builder.debugTuple(&full_fields), |
| 2744 | ); | 2744 | ); |
| 2745 | 2745 | ||
| ... | @@ -4473,7 +4473,7 @@ pub const Object = struct { | ... | @@ -4473,7 +4473,7 @@ pub const Object = struct { |
| 4473 | // The value cannot be undefined, because we use the `nonnull` annotation | 4473 | // The value cannot be undefined, because we use the `nonnull` annotation |
| 4474 | // for non-optional pointers. We also need to respect the alignment, even though | 4474 | // for non-optional pointers. We also need to respect the alignment, even though |
| 4475 | // the address will never be dereferenced. | 4475 | // the address will never be dereferenced. |
| 4476 | const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnitsOptional() orelse | 4476 | const int: u64 = ptr_ty.ptrInfo(mod).flags.alignment.toByteUnits() orelse |
| 4477 | // Note that these 0xaa values are appropriate even in release-optimized builds | 4477 | // Note that these 0xaa values are appropriate even in release-optimized builds |
| 4478 | // because we need a well-defined value that is not null, and LLVM does not | 4478 | // because we need a well-defined value that is not null, and LLVM does not |
| 4479 | // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR | 4479 | // have an "undef_but_not_null" attribute. As an example, if this `alloc` AIR |
src/crash_report.zig+1-1| ... | @@ -172,7 +172,7 @@ pub fn attachSegfaultHandler() void { | ... | @@ -172,7 +172,7 @@ pub fn attachSegfaultHandler() void { |
| 172 | }; | 172 | }; |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*const anyopaque) callconv(.C) noreturn { | 175 | fn handleSegfaultPosix(sig: i32, info: *const posix.siginfo_t, ctx_ptr: ?*anyopaque) callconv(.C) noreturn { |
| 176 | // TODO: use alarm() here to prevent infinite loops | 176 | // TODO: use alarm() here to prevent infinite loops |
| 177 | PanicSwitch.preDispatch(); | 177 | PanicSwitch.preDispatch(); |
| 178 | 178 |
src/link/C.zig+98-123| ... | @@ -69,13 +69,13 @@ pub const DeclBlock = struct { | ... | @@ -69,13 +69,13 @@ pub const DeclBlock = struct { |
| 69 | fwd_decl: String = String.empty, | 69 | fwd_decl: String = String.empty, |
| 70 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate | 70 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| 71 | /// over each `Decl` and generate the definition for each used `CType` once. | 71 | /// over each `Decl` and generate the definition for each used `CType` once. |
| 72 | ctypes: codegen.CType.Store = .{}, | 72 | ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty, |
| 73 | /// Key and Value storage use the ctype arena. | 73 | /// May contain string references to ctype_pool |
| 74 | lazy_fns: codegen.LazyFnMap = .{}, | 74 | lazy_fns: codegen.LazyFnMap = .{}, |
| 75 | 75 | ||
| 76 | fn deinit(db: *DeclBlock, gpa: Allocator) void { | 76 | fn deinit(db: *DeclBlock, gpa: Allocator) void { |
| 77 | db.lazy_fns.deinit(gpa); | 77 | db.lazy_fns.deinit(gpa); |
| 78 | db.ctypes.deinit(gpa); | 78 | db.ctype_pool.deinit(gpa); |
| 79 | db.* = undefined; | 79 | db.* = undefined; |
| 80 | } | 80 | } |
| 81 | }; | 81 | }; |
| ... | @@ -190,11 +190,12 @@ pub fn updateFunc( | ... | @@ -190,11 +190,12 @@ pub fn updateFunc( |
| 190 | const decl = zcu.declPtr(decl_index); | 190 | const decl = zcu.declPtr(decl_index); |
| 191 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | 191 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 192 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 192 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 193 | const ctypes = &gop.value_ptr.ctypes; | 193 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 194 | const lazy_fns = &gop.value_ptr.lazy_fns; | 194 | const lazy_fns = &gop.value_ptr.lazy_fns; |
| 195 | const fwd_decl = &self.fwd_decl_buf; | 195 | const fwd_decl = &self.fwd_decl_buf; |
| 196 | const code = &self.code_buf; | 196 | const code = &self.code_buf; |
| 197 | ctypes.clearRetainingCapacity(gpa); | 197 | try ctype_pool.init(gpa); |
| 198 | ctype_pool.clearRetainingCapacity(); | ||
| 198 | lazy_fns.clearRetainingCapacity(); | 199 | lazy_fns.clearRetainingCapacity(); |
| 199 | fwd_decl.clearRetainingCapacity(); | 200 | fwd_decl.clearRetainingCapacity(); |
| 200 | code.clearRetainingCapacity(); | 201 | code.clearRetainingCapacity(); |
| ... | @@ -213,7 +214,8 @@ pub fn updateFunc( | ... | @@ -213,7 +214,8 @@ pub fn updateFunc( |
| 213 | .pass = .{ .decl = decl_index }, | 214 | .pass = .{ .decl = decl_index }, |
| 214 | .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, | 215 | .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, |
| 215 | .fwd_decl = fwd_decl.toManaged(gpa), | 216 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 216 | .ctypes = ctypes.*, | 217 | .ctype_pool = ctype_pool.*, |
| 218 | .scratch = .{}, | ||
| 217 | .anon_decl_deps = self.anon_decls, | 219 | .anon_decl_deps = self.anon_decls, |
| 218 | .aligned_anon_decls = self.aligned_anon_decls, | 220 | .aligned_anon_decls = self.aligned_anon_decls, |
| 219 | }, | 221 | }, |
| ... | @@ -222,12 +224,16 @@ pub fn updateFunc( | ... | @@ -222,12 +224,16 @@ pub fn updateFunc( |
| 222 | }, | 224 | }, |
| 223 | .lazy_fns = lazy_fns.*, | 225 | .lazy_fns = lazy_fns.*, |
| 224 | }; | 226 | }; |
| 225 | |||
| 226 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; | 227 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 227 | defer { | 228 | defer { |
| 228 | self.anon_decls = function.object.dg.anon_decl_deps; | 229 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 229 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; | 230 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; |
| 230 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); | 231 | fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged(); |
| 232 | ctype_pool.* = function.object.dg.ctype_pool.move(); | ||
| 233 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 234 | function.object.dg.scratch.deinit(gpa); | ||
| 235 | lazy_fns.* = function.lazy_fns.move(); | ||
| 236 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); | ||
| 231 | code.* = function.object.code.moveToUnmanaged(); | 237 | code.* = function.object.code.moveToUnmanaged(); |
| 232 | function.deinit(); | 238 | function.deinit(); |
| 233 | } | 239 | } |
| ... | @@ -239,16 +245,8 @@ pub fn updateFunc( | ... | @@ -239,16 +245,8 @@ pub fn updateFunc( |
| 239 | }, | 245 | }, |
| 240 | else => |e| return e, | 246 | else => |e| return e, |
| 241 | }; | 247 | }; |
| 242 | |||
| 243 | ctypes.* = function.object.dg.ctypes.move(); | ||
| 244 | lazy_fns.* = function.lazy_fns.move(); | ||
| 245 | |||
| 246 | // Free excess allocated memory for this Decl. | ||
| 247 | ctypes.shrinkAndFree(gpa, ctypes.count()); | ||
| 248 | lazy_fns.shrinkAndFree(gpa, lazy_fns.count()); | ||
| 249 | |||
| 250 | gop.value_ptr.code = try self.addString(function.object.code.items); | ||
| 251 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); | 248 | gop.value_ptr.fwd_decl = try self.addString(function.object.dg.fwd_decl.items); |
| 249 | gop.value_ptr.code = try self.addString(function.object.code.items); | ||
| 252 | } | 250 | } |
| 253 | 251 | ||
| 254 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | 252 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| ... | @@ -269,7 +267,8 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | ... | @@ -269,7 +267,8 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 269 | .pass = .{ .anon = anon_decl }, | 267 | .pass = .{ .anon = anon_decl }, |
| 270 | .is_naked_fn = false, | 268 | .is_naked_fn = false, |
| 271 | .fwd_decl = fwd_decl.toManaged(gpa), | 269 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 272 | .ctypes = .{}, | 270 | .ctype_pool = codegen.CType.Pool.empty, |
| 271 | .scratch = .{}, | ||
| 273 | .anon_decl_deps = self.anon_decls, | 272 | .anon_decl_deps = self.anon_decls, |
| 274 | .aligned_anon_decls = self.aligned_anon_decls, | 273 | .aligned_anon_decls = self.aligned_anon_decls, |
| 275 | }, | 274 | }, |
| ... | @@ -277,14 +276,15 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | ... | @@ -277,14 +276,15 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 277 | .indent_writer = undefined, // set later so we can get a pointer to object.code | 276 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 278 | }; | 277 | }; |
| 279 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; | 278 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 280 | |||
| 281 | defer { | 279 | defer { |
| 282 | self.anon_decls = object.dg.anon_decl_deps; | 280 | self.anon_decls = object.dg.anon_decl_deps; |
| 283 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 281 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 284 | object.dg.ctypes.deinit(object.dg.gpa); | ||
| 285 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 282 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 283 | object.dg.ctype_pool.deinit(object.dg.gpa); | ||
| 284 | object.dg.scratch.deinit(gpa); | ||
| 286 | code.* = object.code.moveToUnmanaged(); | 285 | code.* = object.code.moveToUnmanaged(); |
| 287 | } | 286 | } |
| 287 | try object.dg.ctype_pool.init(gpa); | ||
| 288 | 288 | ||
| 289 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; | 289 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; |
| 290 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; | 290 | const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; |
| ... | @@ -297,13 +297,11 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { | ... | @@ -297,13 +297,11 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 297 | else => |e| return e, | 297 | else => |e| return e, |
| 298 | }; | 298 | }; |
| 299 | 299 | ||
| 300 | // Free excess allocated memory for this Decl. | 300 | object.dg.ctype_pool.freeUnusedCapacity(gpa); |
| 301 | object.dg.ctypes.shrinkAndFree(gpa, object.dg.ctypes.count()); | ||
| 302 | |||
| 303 | object.dg.anon_decl_deps.values()[i] = .{ | 301 | object.dg.anon_decl_deps.values()[i] = .{ |
| 304 | .code = try self.addString(object.code.items), | 302 | .code = try self.addString(object.code.items), |
| 305 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), | 303 | .fwd_decl = try self.addString(object.dg.fwd_decl.items), |
| 306 | .ctypes = object.dg.ctypes.move(), | 304 | .ctype_pool = object.dg.ctype_pool.move(), |
| 307 | }; | 305 | }; |
| 308 | } | 306 | } |
| 309 | 307 | ||
| ... | @@ -315,13 +313,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | ... | @@ -315,13 +313,13 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 315 | 313 | ||
| 316 | const decl = zcu.declPtr(decl_index); | 314 | const decl = zcu.declPtr(decl_index); |
| 317 | const gop = try self.decl_table.getOrPut(gpa, decl_index); | 315 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 318 | if (!gop.found_existing) { | 316 | errdefer _ = self.decl_table.pop(); |
| 319 | gop.value_ptr.* = .{}; | 317 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 320 | } | 318 | const ctype_pool = &gop.value_ptr.ctype_pool; |
| 321 | const ctypes = &gop.value_ptr.ctypes; | ||
| 322 | const fwd_decl = &self.fwd_decl_buf; | 319 | const fwd_decl = &self.fwd_decl_buf; |
| 323 | const code = &self.code_buf; | 320 | const code = &self.code_buf; |
| 324 | ctypes.clearRetainingCapacity(gpa); | 321 | try ctype_pool.init(gpa); |
| 322 | ctype_pool.clearRetainingCapacity(); | ||
| 325 | fwd_decl.clearRetainingCapacity(); | 323 | fwd_decl.clearRetainingCapacity(); |
| 326 | code.clearRetainingCapacity(); | 324 | code.clearRetainingCapacity(); |
| 327 | 325 | ||
| ... | @@ -334,7 +332,8 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | ... | @@ -334,7 +332,8 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 334 | .pass = .{ .decl = decl_index }, | 332 | .pass = .{ .decl = decl_index }, |
| 335 | .is_naked_fn = false, | 333 | .is_naked_fn = false, |
| 336 | .fwd_decl = fwd_decl.toManaged(gpa), | 334 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 337 | .ctypes = ctypes.*, | 335 | .ctype_pool = ctype_pool.*, |
| 336 | .scratch = .{}, | ||
| 338 | .anon_decl_deps = self.anon_decls, | 337 | .anon_decl_deps = self.anon_decls, |
| 339 | .aligned_anon_decls = self.aligned_anon_decls, | 338 | .aligned_anon_decls = self.aligned_anon_decls, |
| 340 | }, | 339 | }, |
| ... | @@ -345,8 +344,10 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | ... | @@ -345,8 +344,10 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 345 | defer { | 344 | defer { |
| 346 | self.anon_decls = object.dg.anon_decl_deps; | 345 | self.anon_decls = object.dg.anon_decl_deps; |
| 347 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 346 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 348 | object.dg.ctypes.deinit(object.dg.gpa); | ||
| 349 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 347 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 348 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 349 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 350 | object.dg.scratch.deinit(gpa); | ||
| 350 | code.* = object.code.moveToUnmanaged(); | 351 | code.* = object.code.moveToUnmanaged(); |
| 351 | } | 352 | } |
| 352 | 353 | ||
| ... | @@ -357,12 +358,6 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { | ... | @@ -357,12 +358,6 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 357 | }, | 358 | }, |
| 358 | else => |e| return e, | 359 | else => |e| return e, |
| 359 | }; | 360 | }; |
| 360 | |||
| 361 | ctypes.* = object.dg.ctypes.move(); | ||
| 362 | |||
| 363 | // Free excess allocated memory for this Decl. | ||
| 364 | ctypes.shrinkAndFree(gpa, ctypes.count()); | ||
| 365 | |||
| 366 | gop.value_ptr.code = try self.addString(object.code.items); | 361 | gop.value_ptr.code = try self.addString(object.code.items); |
| 367 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); | 362 | gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items); |
| 368 | } | 363 | } |
| ... | @@ -416,7 +411,10 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -416,7 +411,10 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 416 | // This code path happens exclusively with -ofmt=c. The flush logic for | 411 | // This code path happens exclusively with -ofmt=c. The flush logic for |
| 417 | // emit-h is in `flushEmitH` below. | 412 | // emit-h is in `flushEmitH` below. |
| 418 | 413 | ||
| 419 | var f: Flush = .{}; | 414 | var f: Flush = .{ |
| 415 | .ctype_pool = codegen.CType.Pool.empty, | ||
| 416 | .lazy_ctype_pool = codegen.CType.Pool.empty, | ||
| 417 | }; | ||
| 420 | defer f.deinit(gpa); | 418 | defer f.deinit(gpa); |
| 421 | 419 | ||
| 422 | const abi_defines = try self.abiDefines(zcu.getTarget()); | 420 | const abi_defines = try self.abiDefines(zcu.getTarget()); |
| ... | @@ -443,7 +441,8 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -443,7 +441,8 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 443 | 441 | ||
| 444 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); | 442 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); |
| 445 | self.lazy_code_buf.clearRetainingCapacity(); | 443 | self.lazy_code_buf.clearRetainingCapacity(); |
| 446 | try self.flushErrDecls(zcu, &f.lazy_ctypes); | 444 | try f.lazy_ctype_pool.init(gpa); |
| 445 | try self.flushErrDecls(zcu, &f.lazy_ctype_pool); | ||
| 447 | 446 | ||
| 448 | // Unlike other backends, the .c code we are emitting has order-dependent decls. | 447 | // Unlike other backends, the .c code we are emitting has order-dependent decls. |
| 449 | // `CType`s, forward decls, and non-functions first. | 448 | // `CType`s, forward decls, and non-functions first. |
| ... | @@ -471,15 +470,15 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -471,15 +470,15 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 471 | { | 470 | { |
| 472 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. | 471 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. |
| 473 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. | 472 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. |
| 474 | assert(f.ctypes.count() == 0); | 473 | try f.ctype_pool.init(gpa); |
| 475 | try self.flushCTypes(zcu, &f, .flush, f.lazy_ctypes); | 474 | try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); |
| 476 | 475 | ||
| 477 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { | 476 | for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| { |
| 478 | try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, decl_block.ctypes); | 477 | try self.flushCTypes(zcu, &f, .{ .anon = anon_decl }, &decl_block.ctype_pool); |
| 479 | } | 478 | } |
| 480 | 479 | ||
| 481 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { | 480 | for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| { |
| 482 | try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, decl_block.ctypes); | 481 | try self.flushCTypes(zcu, &f, .{ .decl = decl_index }, &decl_block.ctype_pool); |
| 483 | } | 482 | } |
| 484 | } | 483 | } |
| 485 | 484 | ||
| ... | @@ -510,11 +509,11 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v | ... | @@ -510,11 +509,11 @@ pub fn flushModule(self: *C, arena: Allocator, prog_node: *std.Progress.Node) !v |
| 510 | } | 509 | } |
| 511 | 510 | ||
| 512 | const Flush = struct { | 511 | const Flush = struct { |
| 513 | ctypes: codegen.CType.Store = .{}, | 512 | ctype_pool: codegen.CType.Pool, |
| 514 | ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{}, | 513 | ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .{}, |
| 515 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, | 514 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 516 | 515 | ||
| 517 | lazy_ctypes: codegen.CType.Store = .{}, | 516 | lazy_ctype_pool: codegen.CType.Pool, |
| 518 | lazy_fns: LazyFns = .{}, | 517 | lazy_fns: LazyFns = .{}, |
| 519 | 518 | ||
| 520 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, | 519 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | @@ -536,10 +535,11 @@ const Flush = struct { | ... | @@ -536,10 +535,11 @@ const Flush = struct { |
| 536 | f.all_buffers.deinit(gpa); | 535 | f.all_buffers.deinit(gpa); |
| 537 | f.asm_buf.deinit(gpa); | 536 | f.asm_buf.deinit(gpa); |
| 538 | f.lazy_fns.deinit(gpa); | 537 | f.lazy_fns.deinit(gpa); |
| 539 | f.lazy_ctypes.deinit(gpa); | 538 | f.lazy_ctype_pool.deinit(gpa); |
| 540 | f.ctypes_buf.deinit(gpa); | 539 | f.ctypes_buf.deinit(gpa); |
| 541 | f.ctypes_map.deinit(gpa); | 540 | assert(f.ctype_global_from_decl_map.items.len == 0); |
| 542 | f.ctypes.deinit(gpa); | 541 | f.ctype_global_from_decl_map.deinit(gpa); |
| 542 | f.ctype_pool.deinit(gpa); | ||
| 543 | } | 543 | } |
| 544 | }; | 544 | }; |
| 545 | 545 | ||
| ... | @@ -552,88 +552,59 @@ fn flushCTypes( | ... | @@ -552,88 +552,59 @@ fn flushCTypes( |
| 552 | zcu: *Zcu, | 552 | zcu: *Zcu, |
| 553 | f: *Flush, | 553 | f: *Flush, |
| 554 | pass: codegen.DeclGen.Pass, | 554 | pass: codegen.DeclGen.Pass, |
| 555 | decl_ctypes: codegen.CType.Store, | 555 | decl_ctype_pool: *const codegen.CType.Pool, |
| 556 | ) FlushDeclError!void { | 556 | ) FlushDeclError!void { |
| 557 | const gpa = self.base.comp.gpa; | 557 | const gpa = self.base.comp.gpa; |
| 558 | const global_ctype_pool = &f.ctype_pool; | ||
| 558 | 559 | ||
| 559 | const decl_ctypes_len = decl_ctypes.count(); | 560 | const global_from_decl_map = &f.ctype_global_from_decl_map; |
| 560 | f.ctypes_map.clearRetainingCapacity(); | 561 | assert(global_from_decl_map.items.len == 0); |
| 561 | try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len); | 562 | try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); |
| 562 | 563 | defer global_from_decl_map.clearRetainingCapacity(); | |
| 563 | var global_ctypes = f.ctypes.promote(gpa); | ||
| 564 | defer f.ctypes.demote(global_ctypes); | ||
| 565 | 564 | ||
| 566 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); | 565 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); |
| 567 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); | 566 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); |
| 568 | const writer = ctypes_buf.writer(); | 567 | const writer = ctypes_buf.writer(); |
| 569 | 568 | ||
| 570 | const slice = decl_ctypes.set.map.entries.slice(); | 569 | for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { |
| 571 | for (slice.items(.key), 0..) |decl_cty, decl_i| { | 570 | const PoolAdapter = struct { |
| 572 | const Context = struct { | 571 | global_from_decl_map: []const codegen.CType, |
| 573 | arena: Allocator, | 572 | pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool { |
| 574 | ctypes_map: []codegen.CType.Index, | 573 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| |
| 575 | cached_hash: codegen.CType.Store.Set.Map.Hash, | 574 | decl_pool_index < pool_adapter.global_from_decl_map.len and |
| 576 | idx: codegen.CType.Index, | 575 | pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype) |
| 577 | 576 | else | |
| 578 | pub fn hash(ctx: @This(), _: codegen.CType) codegen.CType.Store.Set.Map.Hash { | 577 | decl_ctype.index == global_ctype.index; |
| 579 | return ctx.cached_hash; | ||
| 580 | } | 578 | } |
| 581 | pub fn eql(ctx: @This(), lhs: codegen.CType, rhs: codegen.CType, _: usize) bool { | 579 | pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType { |
| 582 | return lhs.eqlContext(rhs, ctx); | 580 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| |
| 581 | pool_adapter.global_from_decl_map[decl_pool_index] | ||
| 582 | else | ||
| 583 | decl_ctype; | ||
| 583 | } | 584 | } |
| 584 | pub fn eqlIndex( | ||
| 585 | ctx: @This(), | ||
| 586 | lhs_idx: codegen.CType.Index, | ||
| 587 | rhs_idx: codegen.CType.Index, | ||
| 588 | ) bool { | ||
| 589 | if (lhs_idx < codegen.CType.Tag.no_payload_count or | ||
| 590 | rhs_idx < codegen.CType.Tag.no_payload_count) return lhs_idx == rhs_idx; | ||
| 591 | const lhs_i = lhs_idx - codegen.CType.Tag.no_payload_count; | ||
| 592 | if (lhs_i >= ctx.ctypes_map.len) return false; | ||
| 593 | return ctx.ctypes_map[lhs_i] == rhs_idx; | ||
| 594 | } | ||
| 595 | pub fn copyIndex(ctx: @This(), idx: codegen.CType.Index) codegen.CType.Index { | ||
| 596 | if (idx < codegen.CType.Tag.no_payload_count) return idx; | ||
| 597 | return ctx.ctypes_map[idx - codegen.CType.Tag.no_payload_count]; | ||
| 598 | } | ||
| 599 | }; | ||
| 600 | const decl_idx = @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + decl_i)); | ||
| 601 | const ctx = Context{ | ||
| 602 | .arena = global_ctypes.arena.allocator(), | ||
| 603 | .ctypes_map = f.ctypes_map.items, | ||
| 604 | .cached_hash = decl_ctypes.indexToHash(decl_idx), | ||
| 605 | .idx = decl_idx, | ||
| 606 | }; | 585 | }; |
| 607 | const gop = try global_ctypes.set.map.getOrPutContextAdapted(gpa, decl_cty, ctx, .{ | 586 | const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index); |
| 608 | .store = &global_ctypes.set, | 587 | const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted( |
| 609 | }); | 588 | gpa, |
| 610 | const global_idx = | 589 | decl_ctype_pool, |
| 611 | @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + gop.index)); | 590 | decl_ctype, |
| 612 | f.ctypes_map.appendAssumeCapacity(global_idx); | 591 | PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, |
| 613 | if (!gop.found_existing) { | 592 | ); |
| 614 | errdefer _ = global_ctypes.set.map.pop(); | 593 | global_from_decl_map.appendAssumeCapacity(global_ctype); |
| 615 | gop.key_ptr.* = try decl_cty.copyContext(ctx); | ||
| 616 | } | ||
| 617 | if (std.debug.runtime_safety) { | ||
| 618 | const global_cty = &global_ctypes.set.map.entries.items(.key)[gop.index]; | ||
| 619 | assert(global_cty == gop.key_ptr); | ||
| 620 | assert(decl_cty.eqlContext(global_cty.*, ctx)); | ||
| 621 | assert(decl_cty.hash(decl_ctypes.set) == global_cty.hash(global_ctypes.set)); | ||
| 622 | } | ||
| 623 | try codegen.genTypeDecl( | 594 | try codegen.genTypeDecl( |
| 624 | zcu, | 595 | zcu, |
| 625 | writer, | 596 | writer, |
| 626 | global_ctypes.set, | 597 | global_ctype_pool, |
| 627 | global_idx, | 598 | global_ctype, |
| 628 | pass, | 599 | pass, |
| 629 | decl_ctypes.set, | 600 | decl_ctype_pool, |
| 630 | decl_idx, | 601 | decl_ctype, |
| 631 | gop.found_existing, | 602 | found_existing, |
| 632 | ); | 603 | ); |
| 633 | } | 604 | } |
| 634 | } | 605 | } |
| 635 | 606 | ||
| 636 | fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclError!void { | 607 | fn flushErrDecls(self: *C, zcu: *Zcu, ctype_pool: *codegen.CType.Pool) FlushDeclError!void { |
| 637 | const gpa = self.base.comp.gpa; | 608 | const gpa = self.base.comp.gpa; |
| 638 | 609 | ||
| 639 | const fwd_decl = &self.lazy_fwd_decl_buf; | 610 | const fwd_decl = &self.lazy_fwd_decl_buf; |
| ... | @@ -648,7 +619,8 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr | ... | @@ -648,7 +619,8 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr |
| 648 | .pass = .flush, | 619 | .pass = .flush, |
| 649 | .is_naked_fn = false, | 620 | .is_naked_fn = false, |
| 650 | .fwd_decl = fwd_decl.toManaged(gpa), | 621 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 651 | .ctypes = ctypes.*, | 622 | .ctype_pool = ctype_pool.*, |
| 623 | .scratch = .{}, | ||
| 652 | .anon_decl_deps = self.anon_decls, | 624 | .anon_decl_deps = self.anon_decls, |
| 653 | .aligned_anon_decls = self.aligned_anon_decls, | 625 | .aligned_anon_decls = self.aligned_anon_decls, |
| 654 | }, | 626 | }, |
| ... | @@ -659,8 +631,10 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr | ... | @@ -659,8 +631,10 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr |
| 659 | defer { | 631 | defer { |
| 660 | self.anon_decls = object.dg.anon_decl_deps; | 632 | self.anon_decls = object.dg.anon_decl_deps; |
| 661 | self.aligned_anon_decls = object.dg.aligned_anon_decls; | 633 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 662 | object.dg.ctypes.deinit(gpa); | ||
| 663 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 634 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 635 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 636 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 637 | object.dg.scratch.deinit(gpa); | ||
| 664 | code.* = object.code.moveToUnmanaged(); | 638 | code.* = object.code.moveToUnmanaged(); |
| 665 | } | 639 | } |
| 666 | 640 | ||
| ... | @@ -668,15 +642,14 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr | ... | @@ -668,15 +642,14 @@ fn flushErrDecls(self: *C, zcu: *Zcu, ctypes: *codegen.CType.Store) FlushDeclErr |
| 668 | error.AnalysisFail => unreachable, | 642 | error.AnalysisFail => unreachable, |
| 669 | else => |e| return e, | 643 | else => |e| return e, |
| 670 | }; | 644 | }; |
| 671 | |||
| 672 | ctypes.* = object.dg.ctypes.move(); | ||
| 673 | } | 645 | } |
| 674 | 646 | ||
| 675 | fn flushLazyFn( | 647 | fn flushLazyFn( |
| 676 | self: *C, | 648 | self: *C, |
| 677 | zcu: *Zcu, | 649 | zcu: *Zcu, |
| 678 | mod: *Module, | 650 | mod: *Module, |
| 679 | ctypes: *codegen.CType.Store, | 651 | ctype_pool: *codegen.CType.Pool, |
| 652 | lazy_ctype_pool: *const codegen.CType.Pool, | ||
| 680 | lazy_fn: codegen.LazyFnMap.Entry, | 653 | lazy_fn: codegen.LazyFnMap.Entry, |
| 681 | ) FlushDeclError!void { | 654 | ) FlushDeclError!void { |
| 682 | const gpa = self.base.comp.gpa; | 655 | const gpa = self.base.comp.gpa; |
| ... | @@ -693,7 +666,8 @@ fn flushLazyFn( | ... | @@ -693,7 +666,8 @@ fn flushLazyFn( |
| 693 | .pass = .flush, | 666 | .pass = .flush, |
| 694 | .is_naked_fn = false, | 667 | .is_naked_fn = false, |
| 695 | .fwd_decl = fwd_decl.toManaged(gpa), | 668 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 696 | .ctypes = ctypes.*, | 669 | .ctype_pool = ctype_pool.*, |
| 670 | .scratch = .{}, | ||
| 697 | .anon_decl_deps = .{}, | 671 | .anon_decl_deps = .{}, |
| 698 | .aligned_anon_decls = .{}, | 672 | .aligned_anon_decls = .{}, |
| 699 | }, | 673 | }, |
| ... | @@ -706,17 +680,17 @@ fn flushLazyFn( | ... | @@ -706,17 +680,17 @@ fn flushLazyFn( |
| 706 | // `updateFunc()` does. | 680 | // `updateFunc()` does. |
| 707 | assert(object.dg.anon_decl_deps.count() == 0); | 681 | assert(object.dg.anon_decl_deps.count() == 0); |
| 708 | assert(object.dg.aligned_anon_decls.count() == 0); | 682 | assert(object.dg.aligned_anon_decls.count() == 0); |
| 709 | object.dg.ctypes.deinit(gpa); | ||
| 710 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); | 683 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 684 | ctype_pool.* = object.dg.ctype_pool.move(); | ||
| 685 | ctype_pool.freeUnusedCapacity(gpa); | ||
| 686 | object.dg.scratch.deinit(gpa); | ||
| 711 | code.* = object.code.moveToUnmanaged(); | 687 | code.* = object.code.moveToUnmanaged(); |
| 712 | } | 688 | } |
| 713 | 689 | ||
| 714 | codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) { | 690 | codegen.genLazyFn(&object, lazy_ctype_pool, lazy_fn) catch |err| switch (err) { |
| 715 | error.AnalysisFail => unreachable, | 691 | error.AnalysisFail => unreachable, |
| 716 | else => |e| return e, | 692 | else => |e| return e, |
| 717 | }; | 693 | }; |
| 718 | |||
| 719 | ctypes.* = object.dg.ctypes.move(); | ||
| 720 | } | 694 | } |
| 721 | 695 | ||
| 722 | fn flushLazyFns( | 696 | fn flushLazyFns( |
| ... | @@ -724,6 +698,7 @@ fn flushLazyFns( | ... | @@ -724,6 +698,7 @@ fn flushLazyFns( |
| 724 | zcu: *Zcu, | 698 | zcu: *Zcu, |
| 725 | mod: *Module, | 699 | mod: *Module, |
| 726 | f: *Flush, | 700 | f: *Flush, |
| 701 | lazy_ctype_pool: *const codegen.CType.Pool, | ||
| 727 | lazy_fns: codegen.LazyFnMap, | 702 | lazy_fns: codegen.LazyFnMap, |
| 728 | ) FlushDeclError!void { | 703 | ) FlushDeclError!void { |
| 729 | const gpa = self.base.comp.gpa; | 704 | const gpa = self.base.comp.gpa; |
| ... | @@ -734,7 +709,7 @@ fn flushLazyFns( | ... | @@ -734,7 +709,7 @@ fn flushLazyFns( |
| 734 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); | 709 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); |
| 735 | if (gop.found_existing) continue; | 710 | if (gop.found_existing) continue; |
| 736 | gop.value_ptr.* = {}; | 711 | gop.value_ptr.* = {}; |
| 737 | try self.flushLazyFn(zcu, mod, &f.lazy_ctypes, entry); | 712 | try self.flushLazyFn(zcu, mod, &f.lazy_ctype_pool, lazy_ctype_pool, entry); |
| 738 | } | 713 | } |
| 739 | } | 714 | } |
| 740 | 715 | ||
| ... | @@ -748,7 +723,7 @@ fn flushDeclBlock( | ... | @@ -748,7 +723,7 @@ fn flushDeclBlock( |
| 748 | extern_symbol_name: InternPool.OptionalNullTerminatedString, | 723 | extern_symbol_name: InternPool.OptionalNullTerminatedString, |
| 749 | ) FlushDeclError!void { | 724 | ) FlushDeclError!void { |
| 750 | const gpa = self.base.comp.gpa; | 725 | const gpa = self.base.comp.gpa; |
| 751 | try self.flushLazyFns(zcu, mod, f, decl_block.lazy_fns); | 726 | try self.flushLazyFns(zcu, mod, f, &decl_block.ctype_pool, decl_block.lazy_fns); |
| 752 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); | 727 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); |
| 753 | fwd_decl: { | 728 | fwd_decl: { |
| 754 | if (extern_symbol_name.unwrap()) |name| { | 729 | if (extern_symbol_name.unwrap()) |name| { |
src/link/Coff.zig+3-3| ... | @@ -1223,7 +1223,7 @@ fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: Int | ... | @@ -1223,7 +1223,7 @@ fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: Int |
| 1223 | atom.getSymbolPtr(self).value = try self.allocateAtom( | 1223 | atom.getSymbolPtr(self).value = try self.allocateAtom( |
| 1224 | atom_index, | 1224 | atom_index, |
| 1225 | atom.size, | 1225 | atom.size, |
| 1226 | @intCast(required_alignment.toByteUnitsOptional().?), | 1226 | @intCast(required_alignment.toByteUnits().?), |
| 1227 | ); | 1227 | ); |
| 1228 | errdefer self.freeAtom(atom_index); | 1228 | errdefer self.freeAtom(atom_index); |
| 1229 | 1229 | ||
| ... | @@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom( | ... | @@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom( |
| 1344 | symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1)); | 1344 | symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1)); |
| 1345 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; | 1345 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; |
| 1346 | 1346 | ||
| 1347 | const vaddr = try self.allocateAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits(0))); | 1347 | const vaddr = try self.allocateAtom(atom_index, code_len, @intCast(required_alignment.toByteUnits() orelse 0)); |
| 1348 | errdefer self.freeAtom(atom_index); | 1348 | errdefer self.freeAtom(atom_index); |
| 1349 | 1349 | ||
| 1350 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); | 1350 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); |
| ... | @@ -1428,7 +1428,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com | ... | @@ -1428,7 +1428,7 @@ fn updateDeclCode(self: *Coff, decl_index: InternPool.DeclIndex, code: []u8, com |
| 1428 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); | 1428 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 1429 | 1429 | ||
| 1430 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); | 1430 | log.debug("updateDeclCode {s}{*}", .{ decl_name, decl }); |
| 1431 | const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits(0)); | 1431 | const required_alignment: u32 = @intCast(decl.getAlignment(mod).toByteUnits() orelse 0); |
| 1432 | 1432 | ||
| 1433 | const decl_metadata = self.decls.get(decl_index).?; | 1433 | const decl_metadata = self.decls.get(decl_index).?; |
| 1434 | const atom_index = decl_metadata.atom; | 1434 | const atom_index = decl_metadata.atom; |
src/link/Elf.zig+1-1| ... | @@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void { | ... | @@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4051 | const padding = offset - shdr.sh_size; | 4051 | const padding = offset - shdr.sh_size; |
| 4052 | atom_ptr.value = offset; | 4052 | atom_ptr.value = offset; |
| 4053 | shdr.sh_size += padding + atom_ptr.size; | 4053 | shdr.sh_size += padding + atom_ptr.size; |
| 4054 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); | 4054 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 4055 | } | 4055 | } |
| 4056 | } | 4056 | } |
| 4057 | 4057 |
src/link/Elf/Atom.zig+1-1| ... | @@ -208,7 +208,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { | ... | @@ -208,7 +208,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void { |
| 208 | zig_object.debug_aranges_section_dirty = true; | 208 | zig_object.debug_aranges_section_dirty = true; |
| 209 | } | 209 | } |
| 210 | } | 210 | } |
| 211 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnitsOptional().?); | 211 | shdr.sh_addralign = @max(shdr.sh_addralign, self.alignment.toByteUnits().?); |
| 212 | 212 | ||
| 213 | // This function can also reallocate an atom. | 213 | // This function can also reallocate an atom. |
| 214 | // In this case we need to "unplug" it from its previous location before | 214 | // In this case we need to "unplug" it from its previous location before |
src/link/Elf/ZigObject.zig+1-1| ... | @@ -313,7 +313,7 @@ pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.El | ... | @@ -313,7 +313,7 @@ pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.El |
| 313 | shdr.sh_addr = 0; | 313 | shdr.sh_addr = 0; |
| 314 | shdr.sh_offset = 0; | 314 | shdr.sh_offset = 0; |
| 315 | shdr.sh_size = atom.size; | 315 | shdr.sh_size = atom.size; |
| 316 | shdr.sh_addralign = atom.alignment.toByteUnits(1); | 316 | shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1; |
| 317 | return shdr; | 317 | return shdr; |
| 318 | } | 318 | } |
| 319 | 319 |
src/link/Elf/relocatable.zig+1-1| ... | @@ -330,7 +330,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { | ... | @@ -330,7 +330,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { |
| 330 | const padding = offset - shdr.sh_size; | 330 | const padding = offset - shdr.sh_size; |
| 331 | atom_ptr.value = offset; | 331 | atom_ptr.value = offset; |
| 332 | shdr.sh_size += padding + atom_ptr.size; | 332 | shdr.sh_size += padding + atom_ptr.size; |
| 333 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits(1)); | 333 | shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits() orelse 1); |
| 334 | } | 334 | } |
| 335 | } | 335 | } |
| 336 | 336 |
src/link/Elf/thunks.zig+1-1| ... | @@ -63,7 +63,7 @@ fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 { | ... | @@ -63,7 +63,7 @@ fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 { |
| 63 | const offset = alignment.forward(shdr.sh_size); | 63 | const offset = alignment.forward(shdr.sh_size); |
| 64 | const padding = offset - shdr.sh_size; | 64 | const padding = offset - shdr.sh_size; |
| 65 | shdr.sh_size += padding + size; | 65 | shdr.sh_size += padding + size; |
| 66 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits(1)); | 66 | shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits() orelse 1); |
| 67 | return offset; | 67 | return offset; |
| 68 | } | 68 | } |
| 69 | 69 |
src/link/MachO.zig+1-1| ... | @@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void { | ... | @@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void { |
| 2060 | 2060 | ||
| 2061 | for (atoms.items) |atom_index| { | 2061 | for (atoms.items) |atom_index| { |
| 2062 | const atom = self.getAtom(atom_index).?; | 2062 | const atom = self.getAtom(atom_index).?; |
| 2063 | const atom_alignment = atom.alignment.toByteUnits(1); | 2063 | const atom_alignment = atom.alignment.toByteUnits() orelse 1; |
| 2064 | const offset = mem.alignForward(u64, header.size, atom_alignment); | 2064 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 2065 | const padding = offset - header.size; | 2065 | const padding = offset - header.size; |
| 2066 | atom.value = offset; | 2066 | atom.value = offset; |
src/link/MachO/relocatable.zig+1-1| ... | @@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { | ... | @@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { |
| 380 | if (atoms.items.len == 0) continue; | 380 | if (atoms.items.len == 0) continue; |
| 381 | for (atoms.items) |atom_index| { | 381 | for (atoms.items) |atom_index| { |
| 382 | const atom = macho_file.getAtom(atom_index).?; | 382 | const atom = macho_file.getAtom(atom_index).?; |
| 383 | const atom_alignment = atom.alignment.toByteUnits(1); | 383 | const atom_alignment = atom.alignment.toByteUnits() orelse 1; |
| 384 | const offset = mem.alignForward(u64, header.size, atom_alignment); | 384 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 385 | const padding = offset - header.size; | 385 | const padding = offset - header.size; |
| 386 | atom.value = offset; | 386 | atom.value = offset; |
src/link/Wasm.zig+1-1| ... | @@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void { | ... | @@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2263 | } | 2263 | } |
| 2264 | if (wasm.findGlobalSymbol("__tls_align")) |loc| { | 2264 | if (wasm.findGlobalSymbol("__tls_align")) |loc| { |
| 2265 | const sym = loc.getSymbol(wasm); | 2265 | const sym = loc.getSymbol(wasm); |
| 2266 | wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = @intCast(segment.alignment.toByteUnitsOptional().?); | 2266 | wasm.wasm_globals.items[sym.index - wasm.imported_globals_count].init.i32_const = @intCast(segment.alignment.toByteUnits().?); |
| 2267 | } | 2267 | } |
| 2268 | if (wasm.findGlobalSymbol("__tls_base")) |loc| { | 2268 | if (wasm.findGlobalSymbol("__tls_base")) |loc| { |
| 2269 | const sym = loc.getSymbol(wasm); | 2269 | const sym = loc.getSymbol(wasm); |
src/main.zig+1-5| ... | @@ -3544,11 +3544,7 @@ fn createModule( | ... | @@ -3544,11 +3544,7 @@ fn createModule( |
| 3544 | // If the target is not overridden, use the parent's target. Of course, | 3544 | // If the target is not overridden, use the parent's target. Of course, |
| 3545 | // if this is the root module then we need to proceed to resolve the | 3545 | // if this is the root module then we need to proceed to resolve the |
| 3546 | // target. | 3546 | // target. |
| 3547 | if (cli_mod.target_arch_os_abi == null and | 3547 | if (cli_mod.target_arch_os_abi == null and cli_mod.target_mcpu == null) { |
| 3548 | cli_mod.target_mcpu == null and | ||
| 3549 | create_module.dynamic_linker == null and | ||
| 3550 | create_module.object_format == null) | ||
| 3551 | { | ||
| 3552 | if (parent) |p| break :t p.resolved_target; | 3548 | if (parent) |p| break :t p.resolved_target; |
| 3553 | } | 3549 | } |
| 3554 | 3550 |
src/print_value.zig+1-1| ... | @@ -80,7 +80,7 @@ pub fn print( | ... | @@ -80,7 +80,7 @@ pub fn print( |
| 80 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), | 80 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), |
| 81 | .lazy_align => |ty| if (opt_sema) |sema| { | 81 | .lazy_align => |ty| if (opt_sema) |sema| { |
| 82 | const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; | 82 | const a = (try Type.fromInterned(ty).abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; |
| 83 | try writer.print("{}", .{a.toByteUnits(0)}); | 83 | try writer.print("{}", .{a.toByteUnits() orelse 0}); |
| 84 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), | 84 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), |
| 85 | .lazy_size => |ty| if (opt_sema) |sema| { | 85 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 86 | const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; | 86 | const s = (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar; |
src/target.zig+1-1| ... | @@ -525,7 +525,7 @@ pub fn backendSupportsFeature( | ... | @@ -525,7 +525,7 @@ pub fn backendSupportsFeature( |
| 525 | .error_return_trace => use_llvm, | 525 | .error_return_trace => use_llvm, |
| 526 | .is_named_enum_value => use_llvm, | 526 | .is_named_enum_value => use_llvm, |
| 527 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), | 527 | .error_set_has_value => use_llvm or cpu_arch.isWasm(), |
| 528 | .field_reordering => use_llvm, | 528 | .field_reordering => ofmt == .c or use_llvm, |
| 529 | .safety_checked_instructions => use_llvm, | 529 | .safety_checked_instructions => use_llvm, |
| 530 | }; | 530 | }; |
| 531 | } | 531 | } |
src/type.zig+25-27| ... | @@ -203,7 +203,7 @@ pub const Type = struct { | ... | @@ -203,7 +203,7 @@ pub const Type = struct { |
| 203 | info.flags.alignment | 203 | info.flags.alignment |
| 204 | else | 204 | else |
| 205 | Type.fromInterned(info.child).abiAlignment(mod); | 205 | Type.fromInterned(info.child).abiAlignment(mod); |
| 206 | try writer.print("align({d}", .{alignment.toByteUnits(0)}); | 206 | try writer.print("align({d}", .{alignment.toByteUnits() orelse 0}); |
| 207 | 207 | ||
| 208 | if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { | 208 | if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { |
| 209 | try writer.print(":{d}:{d}", .{ | 209 | try writer.print(":{d}:{d}", .{ |
| ... | @@ -863,7 +863,7 @@ pub const Type = struct { | ... | @@ -863,7 +863,7 @@ pub const Type = struct { |
| 863 | pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value { | 863 | pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value { |
| 864 | switch (try ty.abiAlignmentAdvanced(mod, .lazy)) { | 864 | switch (try ty.abiAlignmentAdvanced(mod, .lazy)) { |
| 865 | .val => |val| return val, | 865 | .val => |val| return val, |
| 866 | .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits(0)), | 866 | .scalar => |x| return mod.intValue(Type.comptime_int, x.toByteUnits() orelse 0), |
| 867 | } | 867 | } |
| 868 | } | 868 | } |
| 869 | 869 | ||
| ... | @@ -905,7 +905,7 @@ pub const Type = struct { | ... | @@ -905,7 +905,7 @@ pub const Type = struct { |
| 905 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; | 905 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; |
| 906 | }, | 906 | }, |
| 907 | .ptr_type, .anyframe_type => { | 907 | .ptr_type, .anyframe_type => { |
| 908 | return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) }; | 908 | return .{ .scalar = ptrAbiAlignment(target) }; |
| 909 | }, | 909 | }, |
| 910 | .array_type => |array_type| { | 910 | .array_type => |array_type| { |
| 911 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); | 911 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); |
| ... | @@ -920,6 +920,9 @@ pub const Type = struct { | ... | @@ -920,6 +920,9 @@ pub const Type = struct { |
| 920 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); | 920 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); |
| 921 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; | 921 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; |
| 922 | }, | 922 | }, |
| 923 | .stage2_c => { | ||
| 924 | return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat); | ||
| 925 | }, | ||
| 923 | .stage2_x86_64 => { | 926 | .stage2_x86_64 => { |
| 924 | if (vector_type.child == .bool_type) { | 927 | if (vector_type.child == .bool_type) { |
| 925 | if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" }; | 928 | if (vector_type.len > 256 and std.Target.x86.featureSetHas(target.cpu.features, .avx512f)) return .{ .scalar = .@"64" }; |
| ... | @@ -966,12 +969,12 @@ pub const Type = struct { | ... | @@ -966,12 +969,12 @@ pub const Type = struct { |
| 966 | 969 | ||
| 967 | .usize, | 970 | .usize, |
| 968 | .isize, | 971 | .isize, |
| 972 | => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) }, | ||
| 973 | |||
| 969 | .export_options, | 974 | .export_options, |
| 970 | .extern_options, | 975 | .extern_options, |
| 971 | .type_info, | 976 | .type_info, |
| 972 | => return .{ | 977 | => return .{ .scalar = ptrAbiAlignment(target) }, |
| 973 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | ||
| 974 | }, | ||
| 975 | 978 | ||
| 976 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, | 979 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, |
| 977 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, | 980 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, |
| ... | @@ -1160,9 +1163,7 @@ pub const Type = struct { | ... | @@ -1160,9 +1163,7 @@ pub const Type = struct { |
| 1160 | const child_type = ty.optionalChild(mod); | 1163 | const child_type = ty.optionalChild(mod); |
| 1161 | 1164 | ||
| 1162 | switch (child_type.zigTypeTag(mod)) { | 1165 | switch (child_type.zigTypeTag(mod)) { |
| 1163 | .Pointer => return .{ | 1166 | .Pointer => return .{ .scalar = ptrAbiAlignment(target) }, |
| 1164 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | ||
| 1165 | }, | ||
| 1166 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), | 1167 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), |
| 1167 | .NoReturn => return .{ .scalar = .@"1" }, | 1168 | .NoReturn => return .{ .scalar = .@"1" }, |
| 1168 | else => {}, | 1169 | else => {}, |
| ... | @@ -1274,6 +1275,10 @@ pub const Type = struct { | ... | @@ -1274,6 +1275,10 @@ pub const Type = struct { |
| 1274 | const total_bits = elem_bits * vector_type.len; | 1275 | const total_bits = elem_bits * vector_type.len; |
| 1275 | break :total_bytes (total_bits + 7) / 8; | 1276 | break :total_bytes (total_bits + 7) / 8; |
| 1276 | }, | 1277 | }, |
| 1278 | .stage2_c => total_bytes: { | ||
| 1279 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | ||
| 1280 | break :total_bytes elem_bytes * vector_type.len; | ||
| 1281 | }, | ||
| 1277 | .stage2_x86_64 => total_bytes: { | 1282 | .stage2_x86_64 => total_bytes: { |
| 1278 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; | 1283 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; |
| 1279 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); | 1284 | const elem_bytes: u32 = @intCast((try Type.fromInterned(vector_type.child).abiSizeAdvanced(mod, strat)).scalar); |
| ... | @@ -1527,15 +1532,19 @@ pub const Type = struct { | ... | @@ -1527,15 +1532,19 @@ pub const Type = struct { |
| 1527 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal | 1532 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| 1528 | // to the child type's ABI alignment. | 1533 | // to the child type's ABI alignment. |
| 1529 | return AbiSizeAdvanced{ | 1534 | return AbiSizeAdvanced{ |
| 1530 | .scalar = child_ty.abiAlignment(mod).toByteUnits(0) + payload_size, | 1535 | .scalar = (child_ty.abiAlignment(mod).toByteUnits() orelse 0) + payload_size, |
| 1531 | }; | 1536 | }; |
| 1532 | } | 1537 | } |
| 1533 | 1538 | ||
| 1534 | fn intAbiSize(bits: u16, target: Target) u64 { | 1539 | pub fn ptrAbiAlignment(target: Target) Alignment { |
| 1540 | return Alignment.fromNonzeroByteUnits(@divExact(target.ptrBitWidth(), 8)); | ||
| 1541 | } | ||
| 1542 | |||
| 1543 | pub fn intAbiSize(bits: u16, target: Target) u64 { | ||
| 1535 | return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); | 1544 | return intAbiAlignment(bits, target).forward(@as(u16, @intCast((@as(u17, bits) + 7) / 8))); |
| 1536 | } | 1545 | } |
| 1537 | 1546 | ||
| 1538 | fn intAbiAlignment(bits: u16, target: Target) Alignment { | 1547 | pub fn intAbiAlignment(bits: u16, target: Target) Alignment { |
| 1539 | return Alignment.fromByteUnits(@min( | 1548 | return Alignment.fromByteUnits(@min( |
| 1540 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), | 1549 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), |
| 1541 | target.maxIntAlignment(), | 1550 | target.maxIntAlignment(), |
| ... | @@ -1572,7 +1581,7 @@ pub const Type = struct { | ... | @@ -1572,7 +1581,7 @@ pub const Type = struct { |
| 1572 | if (len == 0) return 0; | 1581 | if (len == 0) return 0; |
| 1573 | const elem_ty = Type.fromInterned(array_type.child); | 1582 | const elem_ty = Type.fromInterned(array_type.child); |
| 1574 | const elem_size = @max( | 1583 | const elem_size = @max( |
| 1575 | (try elem_ty.abiAlignmentAdvanced(mod, strat)).scalar.toByteUnits(0), | 1584 | (try elem_ty.abiAlignmentAdvanced(mod, strat)).scalar.toByteUnits() orelse 0, |
| 1576 | (try elem_ty.abiSizeAdvanced(mod, strat)).scalar, | 1585 | (try elem_ty.abiSizeAdvanced(mod, strat)).scalar, |
| 1577 | ); | 1586 | ); |
| 1578 | if (elem_size == 0) return 0; | 1587 | if (elem_size == 0) return 0; |
| ... | @@ -3016,26 +3025,15 @@ pub const Type = struct { | ... | @@ -3016,26 +3025,15 @@ pub const Type = struct { |
| 3016 | } | 3025 | } |
| 3017 | 3026 | ||
| 3018 | /// Returns none in the case of a tuple which uses the integer index as the field name. | 3027 | /// Returns none in the case of a tuple which uses the integer index as the field name. |
| 3019 | pub fn structFieldName(ty: Type, field_index: u32, mod: *Module) InternPool.OptionalNullTerminatedString { | 3028 | pub fn structFieldName(ty: Type, index: usize, mod: *Module) InternPool.OptionalNullTerminatedString { |
| 3020 | const ip = &mod.intern_pool; | 3029 | const ip = &mod.intern_pool; |
| 3021 | return switch (ip.indexToKey(ty.toIntern())) { | 3030 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3022 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index), | 3031 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index), |
| 3023 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), | 3032 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index), |
| 3024 | else => unreachable, | 3033 | else => unreachable, |
| 3025 | }; | 3034 | }; |
| 3026 | } | 3035 | } |
| 3027 | 3036 | ||
| 3028 | /// When struct types have no field names, the names are implicitly understood to be | ||
| 3029 | /// strings corresponding to the field indexes in declaration order. It used to be the | ||
| 3030 | /// case that a NullTerminatedString would be stored for each field in this case, however, | ||
| 3031 | /// now, callers must handle the possibility that there are no names stored at all. | ||
| 3032 | /// Here we fake the previous behavior. Probably something better could be done by examining | ||
| 3033 | /// all the callsites of this function. | ||
| 3034 | pub fn legacyStructFieldName(ty: Type, i: u32, mod: *Module) InternPool.NullTerminatedString { | ||
| 3035 | return ty.structFieldName(i, mod).unwrap() orelse | ||
| 3036 | mod.intern_pool.getOrPutStringFmt(mod.gpa, "{d}", .{i}) catch @panic("OOM"); | ||
| 3037 | } | ||
| 3038 | |||
| 3039 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { | 3037 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { |
| 3040 | const ip = &mod.intern_pool; | 3038 | const ip = &mod.intern_pool; |
| 3041 | return switch (ip.indexToKey(ty.toIntern())) { | 3039 | return switch (ip.indexToKey(ty.toIntern())) { |
test/behavior/align.zig-1| ... | @@ -624,7 +624,6 @@ test "sub-aligned pointer field access" { | ... | @@ -624,7 +624,6 @@ test "sub-aligned pointer field access" { |
| 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 627 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 628 | 627 | ||
| 629 | // Originally reported at https://github.com/ziglang/zig/issues/14904 | 628 | // Originally reported at https://github.com/ziglang/zig/issues/14904 |
| 630 | 629 |
test/behavior/vector.zig+4| ... | @@ -1176,18 +1176,22 @@ test "@shlWithOverflow" { | ... | @@ -1176,18 +1176,22 @@ test "@shlWithOverflow" { |
| 1176 | test "alignment of vectors" { | 1176 | test "alignment of vectors" { |
| 1177 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { | 1177 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { |
| 1178 | else => 2, | 1178 | else => 2, |
| 1179 | .stage2_c => @alignOf(u8), | ||
| 1179 | .stage2_x86_64 => 16, | 1180 | .stage2_x86_64 => 16, |
| 1180 | }); | 1181 | }); |
| 1181 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { | 1182 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { |
| 1182 | else => 1, | 1183 | else => 1, |
| 1184 | .stage2_c => @alignOf(u1), | ||
| 1183 | .stage2_x86_64 => 16, | 1185 | .stage2_x86_64 => 16, |
| 1184 | }); | 1186 | }); |
| 1185 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { | 1187 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { |
| 1186 | else => 1, | 1188 | else => 1, |
| 1189 | .stage2_c => @alignOf(u1), | ||
| 1187 | .stage2_x86_64 => 16, | 1190 | .stage2_x86_64 => 16, |
| 1188 | }); | 1191 | }); |
| 1189 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { | 1192 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { |
| 1190 | else => 4, | 1193 | else => 4, |
| 1194 | .stage2_c => @alignOf(u16), | ||
| 1191 | .stage2_x86_64 => 16, | 1195 | .stage2_x86_64 => 16, |
| 1192 | }); | 1196 | }); |
| 1193 | } | 1197 | } |
test/tests.zig+12-5| ... | @@ -1164,19 +1164,26 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { | ... | @@ -1164,19 +1164,26 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { |
| 1164 | compile_c.addCSourceFile(.{ | 1164 | compile_c.addCSourceFile(.{ |
| 1165 | .file = these_tests.getEmittedBin(), | 1165 | .file = these_tests.getEmittedBin(), |
| 1166 | .flags = &.{ | 1166 | .flags = &.{ |
| 1167 | // TODO output -std=c89 compatible C code | 1167 | // Tracking issue for making the C backend generate C89 compatible code: |
| 1168 | // https://github.com/ziglang/zig/issues/19468 | ||
| 1168 | "-std=c99", | 1169 | "-std=c99", |
| 1169 | "-pedantic", | 1170 | "-pedantic", |
| 1170 | "-Werror", | 1171 | "-Werror", |
| 1171 | // TODO stop violating these pedantic errors. spotted everywhere | 1172 | |
| 1173 | // Tracking issue for making the C backend generate code | ||
| 1174 | // that does not trigger warnings: | ||
| 1175 | // https://github.com/ziglang/zig/issues/19467 | ||
| 1176 | |||
| 1177 | // spotted everywhere | ||
| 1172 | "-Wno-builtin-requires-header", | 1178 | "-Wno-builtin-requires-header", |
| 1173 | // TODO stop violating these pedantic errors. spotted on linux | 1179 | |
| 1174 | "-Wno-address-of-packed-member", | 1180 | // spotted on linux |
| 1175 | "-Wno-gnu-folding-constant", | 1181 | "-Wno-gnu-folding-constant", |
| 1176 | "-Wno-incompatible-function-pointer-types", | 1182 | "-Wno-incompatible-function-pointer-types", |
| 1177 | "-Wno-incompatible-pointer-types", | 1183 | "-Wno-incompatible-pointer-types", |
| 1178 | "-Wno-overlength-strings", | 1184 | "-Wno-overlength-strings", |
| 1179 | // TODO stop violating these pedantic errors. spotted on darwin | 1185 | |
| 1186 | // spotted on darwin | ||
| 1180 | "-Wno-dollar-in-identifier-extension", | 1187 | "-Wno-dollar-in-identifier-extension", |
| 1181 | "-Wno-absolute-value", | 1188 | "-Wno-absolute-value", |
| 1182 | }, | 1189 | }, |
tools/lldb_pretty_printers.py+4-4| ... | @@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None): | ... | @@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None): |
| 354 | def InstIndex_SummaryProvider(value, _=None): | 354 | def InstIndex_SummaryProvider(value, _=None): |
| 355 | return 'instructions[%d]' % value.unsigned | 355 | return 'instructions[%d]' % value.unsigned |
| 356 | 356 | ||
| 357 | class Module_Decl__Module_Decl_Index_SynthProvider: | 357 | class zig_DeclIndex_SynthProvider: |
| 358 | def __init__(self, value, _=None): self.value = value | 358 | def __init__(self, value, _=None): self.value = value |
| 359 | def update(self): | 359 | def update(self): |
| 360 | try: | 360 | try: |
| ... | @@ -425,7 +425,7 @@ def InternPool_Find(thread): | ... | @@ -425,7 +425,7 @@ def InternPool_Find(thread): |
| 425 | for frame in thread: | 425 | for frame in thread: |
| 426 | ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') | 426 | ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') |
| 427 | if ip: return ip | 427 | if ip: return ip |
| 428 | mod = frame.FindVariable('mod') or frame.FindVariable('module') | 428 | mod = frame.FindVariable('zcu') or frame.FindVariable('mod') or frame.FindVariable('module') |
| 429 | if mod: | 429 | if mod: |
| 430 | ip = mod.GetChildMemberWithName('intern_pool') | 430 | ip = mod.GetChildMemberWithName('intern_pool') |
| 431 | if ip: return ip | 431 | if ip: return ip |
| ... | @@ -617,7 +617,7 @@ type_tag_handlers = { | ... | @@ -617,7 +617,7 @@ type_tag_handlers = { |
| 617 | 617 | ||
| 618 | def value_Value_str_lit(payload): | 618 | def value_Value_str_lit(payload): |
| 619 | for frame in payload.thread: | 619 | for frame in payload.thread: |
| 620 | mod = frame.FindVariable('mod') or frame.FindVariable('module') | 620 | mod = frame.FindVariable('zcu') or frame.FindVariable('mod') or frame.FindVariable('module') |
| 621 | if mod: break | 621 | if mod: break |
| 622 | else: return | 622 | else: return |
| 623 | return '"%s"' % zig_String_decode(mod.GetChildMemberWithName('string_literal_bytes').GetChildMemberWithName('items'), payload.GetChildMemberWithName('index').unsigned, payload.GetChildMemberWithName('len').unsigned) | 623 | return '"%s"' % zig_String_decode(mod.GetChildMemberWithName('string_literal_bytes').GetChildMemberWithName('items'), payload.GetChildMemberWithName('index').unsigned, payload.GetChildMemberWithName('len').unsigned) |
| ... | @@ -714,7 +714,7 @@ def __lldb_init_module(debugger, _=None): | ... | @@ -714,7 +714,7 @@ def __lldb_init_module(debugger, _=None): |
| 714 | add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True) | 714 | add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True) |
| 715 | add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) | 715 | add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) |
| 716 | add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) | 716 | add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) |
| 717 | add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True) | 717 | add(debugger, category='zig.stage2', type='zig.DeclIndex', synth=True) |
| 718 | add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True) | 718 | add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True) |
| 719 | add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) | 719 | add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) |
| 720 | add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) | 720 | add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) |