| 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 | 564 | "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig" |
| 565 | 565 | "${CMAKE_SOURCE_DIR}/src/codegen.zig" |
| 566 | 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 | 568 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig" |
| 569 | 569 | "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig" |
| 570 | 570 | "${CMAKE_SOURCE_DIR}/src/glibc.zig" |
build.zig+1-3| ... | ... | @@ -16,9 +16,7 @@ pub fn build(b: *std.Build) !void { |
| 16 | 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 | 17 | const target = t: { |
| 18 | 18 | var default_target: std.zig.CrossTarget = .{}; |
| 19 | if (only_c) { | |
| 20 | default_target.ofmt = .c; | |
| 21 | } | |
| 19 | default_target.ofmt = b.option(std.Target.ObjectFormat, "ofmt", "Object format to target") orelse if (only_c) .c else null; | |
| 22 | 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 | 1150 | |
| 1151 | 1151 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. |
| 1152 | 1152 | pub const Sigaction = extern struct { |
| 1153 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 1154 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 1153 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 1154 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 1155 | 1155 | |
| 1156 | 1156 | handler: extern union { |
| 1157 | 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 | 690 | pub const sig_atomic_t = c_int; |
| 691 | 691 | |
| 692 | 692 | pub const Sigaction = extern struct { |
| 693 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 694 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 693 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 694 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 695 | 695 | |
| 696 | 696 | /// signal handler |
| 697 | 697 | handler: extern union { |
| ... | ... | @@ -702,7 +702,7 @@ pub const Sigaction = extern struct { |
| 702 | 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 | 707 | pub const SOCK = struct { |
| 708 | 708 | pub const STREAM = 1; |
lib/std/c/freebsd.zig+2-2| ... | ... | @@ -1171,8 +1171,8 @@ const NSIG = 32; |
| 1171 | 1171 | |
| 1172 | 1172 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 1173 | 1173 | pub const Sigaction = extern struct { |
| 1174 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 1175 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 1174 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 1175 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 1176 | 1176 | |
| 1177 | 1177 | /// signal handler |
| 1178 | 1178 | handler: extern union { |
lib/std/c/haiku.zig+1-1| ... | ... | @@ -501,7 +501,7 @@ pub const siginfo_t = extern struct { |
| 501 | 501 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 502 | 502 | pub const Sigaction = extern struct { |
| 503 | 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 | 506 | /// signal handler |
| 507 | 507 | handler: extern union { |
lib/std/c/netbsd.zig+2-2| ... | ... | @@ -864,8 +864,8 @@ pub const SIG = struct { |
| 864 | 864 | |
| 865 | 865 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 866 | 866 | pub const Sigaction = extern struct { |
| 867 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 868 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 867 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 868 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 869 | 869 | |
| 870 | 870 | /// signal handler |
| 871 | 871 | handler: extern union { |
lib/std/c/openbsd.zig+2-2| ... | ... | @@ -842,8 +842,8 @@ pub const SIG = struct { |
| 842 | 842 | |
| 843 | 843 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 844 | 844 | pub const Sigaction = extern struct { |
| 845 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 846 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 845 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 846 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 847 | 847 | |
| 848 | 848 | /// signal handler |
| 849 | 849 | handler: extern union { |
lib/std/c/solaris.zig+2-2| ... | ... | @@ -874,8 +874,8 @@ pub const SIG = struct { |
| 874 | 874 | |
| 875 | 875 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 876 | 876 | pub const Sigaction = extern struct { |
| 877 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 878 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 877 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 878 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 879 | 879 | |
| 880 | 880 | /// signal options |
| 881 | 881 | flags: c_uint, |
lib/std/debug.zig+1-1| ... | ... | @@ -2570,7 +2570,7 @@ fn resetSegfaultHandler() void { |
| 2570 | 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 | 2574 | // Reset to the default handler so that if a segfault happens in this handler it will crash |
| 2575 | 2575 | // the process. Also when this handler returns, the original instruction will be repeated |
| 2576 | 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 | 695 | }; |
| 696 | 696 | |
| 697 | 697 | pub const Sigaction = extern struct { |
| 698 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 699 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 698 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 699 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 700 | 700 | |
| 701 | 701 | handler: extern union { |
| 702 | 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 | 4301 | pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffffffff} ** 30; |
| 4302 | 4302 | |
| 4303 | 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 | 4305 | const restorer = *const fn () callconv(.C) void; |
| 4306 | 4306 | }; |
| 4307 | 4307 | |
| ... | ... | @@ -4328,8 +4328,8 @@ pub const k_sigaction = switch (native_arch) { |
| 4328 | 4328 | |
| 4329 | 4329 | /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. |
| 4330 | 4330 | pub const Sigaction = extern struct { |
| 4331 | pub const handler_fn = *align(1) const fn (c_int) callconv(.C) void; | |
| 4332 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 4331 | pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; | |
| 4332 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 4333 | 4333 | |
| 4334 | 4334 | handler: extern union { |
| 4335 | 4335 | handler: ?handler_fn, |
lib/std/os/plan9.zig+2-2| ... | ... | @@ -186,8 +186,8 @@ pub const empty_sigset = 0; |
| 186 | 186 | pub const siginfo_t = c_long; |
| 187 | 187 | // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we incude it here to be compatible. |
| 188 | 188 | pub const Sigaction = extern struct { |
| 189 | pub const handler_fn = *const fn (c_int) callconv(.C) void; | |
| 190 | pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 189 | pub const handler_fn = *const fn (i32) callconv(.C) void; | |
| 190 | pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; | |
| 191 | 191 | |
| 192 | 192 | handler: extern union { |
| 193 | 193 | handler: ?handler_fn, |
lib/std/start.zig+1-1| ... | ... | @@ -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 | 3457 | .pass = .{ .decl = decl_index }, |
| 3458 | 3458 | .is_naked_fn = false, |
| 3459 | 3459 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 3460 | .ctypes = .{}, | |
| 3460 | .ctype_pool = c_codegen.CType.Pool.empty, | |
| 3461 | .scratch = .{}, | |
| 3461 | 3462 | .anon_decl_deps = .{}, |
| 3462 | 3463 | .aligned_anon_decls = .{}, |
| 3463 | 3464 | }; |
| 3464 | 3465 | defer { |
| 3465 | dg.ctypes.deinit(gpa); | |
| 3466 | dg.fwd_decl.deinit(); | |
| 3466 | fwd_decl.* = dg.fwd_decl.moveToUnmanaged(); | |
| 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 | 3473 | c_codegen.genHeader(&dg) catch |err| switch (err) { |
| 3470 | 3474 | error.AnalysisFail => { |
| ... | ... | @@ -3473,9 +3477,6 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v |
| 3473 | 3477 | }, |
| 3474 | 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 | 712 | pub fn fieldName( |
| 713 | 713 | self: AnonStructType, |
| 714 | 714 | ip: *const InternPool, |
| 715 | index: u32, | |
| 715 | index: usize, | |
| 716 | 716 | ) OptionalNullTerminatedString { |
| 717 | 717 | if (self.names.len == 0) |
| 718 | 718 | return .none; |
| ... | ... | @@ -3879,20 +3879,13 @@ pub const Alignment = enum(u6) { |
| 3879 | 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 | 3883 | return switch (a) { |
| 3884 | 3884 | .none => null, |
| 3885 | 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 | 3889 | pub fn fromByteUnits(n: u64) Alignment { |
| 3897 | 3890 | if (n == 0) return .none; |
| 3898 | 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 | 5846 | return @as(u16, @intCast(big.bitCountTwosComp())); |
| 5847 | 5847 | }, |
| 5848 | 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 | 5851 | .lazy_size => |lazy_ty| { |
| 5852 | 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 | 6508 | const alignment = try sema.resolveAlign(block, operand_src, extra.operand); |
| 6509 | 6509 | if (alignment.order(Alignment.fromNonzeroByteUnits(256)).compare(.gt)) { |
| 6510 | 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 | 17804 | }, |
| 17805 | 17805 | .Pointer => { |
| 17806 | 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 | 17808 | try mod.intValue(Type.comptime_int, alignment) |
| 17809 | 17809 | else |
| 17810 | 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 | 18279 | // type: type, |
| 18280 | 18280 | field_ty, |
| 18281 | 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 | 18284 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18285 | 18285 | .ty = union_field_ty.toIntern(), |
| ... | ... | @@ -18436,7 +18436,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18436 | 18436 | // is_comptime: bool, |
| 18437 | 18437 | Value.makeBool(is_comptime).toIntern(), |
| 18438 | 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 | 18441 | struct_field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18442 | 18442 | .ty = struct_field_ty.toIntern(), |
| ... | ... | @@ -18505,7 +18505,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 18505 | 18505 | // is_comptime: bool, |
| 18506 | 18506 | Value.makeBool(field_is_comptime).toIntern(), |
| 18507 | 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 | 18510 | field_val.* = try mod.intern(.{ .aggregate = .{ |
| 18511 | 18511 | .ty = struct_field_ty.toIntern(), |
| ... | ... | @@ -22552,7 +22552,7 @@ fn zirPtrFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 22552 | 22552 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22553 | 22553 | } |
| 22554 | 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 | 22556 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22557 | 22557 | const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1); |
| 22558 | 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 | 22572 | try sema.addSafetyCheck(block, src, is_non_zero, .cast_to_null); |
| 22573 | 22573 | } |
| 22574 | 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 | 22576 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 22577 | 22577 | const remainder = try block.addBinOp(.bit_and, elem_coerced, align_minus_1); |
| 22578 | 22578 | const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); |
| ... | ... | @@ -22970,10 +22970,10 @@ fn ptrCastFull( |
| 22970 | 22970 | const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); |
| 22971 | 22971 | errdefer msg.destroy(sema.gpa); |
| 22972 | 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 | 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 | 22978 | try sema.errNote(block, src, msg, "use @alignCast to assert pointer alignment", .{}); |
| 22979 | 22979 | break :msg msg; |
| ... | ... | @@ -23067,7 +23067,7 @@ fn ptrCastFull( |
| 23067 | 23067 | if (!dest_align.check(addr)) { |
| 23068 | 23068 | return sema.fail(block, operand_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ |
| 23069 | 23069 | addr, |
| 23070 | dest_align.toByteUnitsOptional().?, | |
| 23070 | dest_align.toByteUnits().?, | |
| 23071 | 23071 | }); |
| 23072 | 23072 | } |
| 23073 | 23073 | } |
| ... | ... | @@ -23110,7 +23110,7 @@ fn ptrCastFull( |
| 23110 | 23110 | dest_align.compare(.gt, src_align) and |
| 23111 | 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 | 23114 | const align_minus_1 = Air.internedToRef((try mod.intValue(Type.usize, align_bytes_minus_1)).toIntern()); |
| 23115 | 23115 | const ptr_int = try block.addUnOp(.int_from_ptr, ptr); |
| 23116 | 23116 | const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); |
| ... | ... | @@ -27837,7 +27837,7 @@ fn structFieldPtrByIndex( |
| 27837 | 27837 | const elem_size_bits = Type.fromInterned(ptr_ty_data.child).bitSize(mod); |
| 27838 | 27838 | if (elem_size_bytes * 8 == elem_size_bits) { |
| 27839 | 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 | 27841 | assert(new_align != .none); |
| 27842 | 27842 | ptr_ty_data.flags.alignment = new_align; |
| 27843 | 27843 | ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 }; |
| ... | ... | @@ -29132,7 +29132,7 @@ fn coerceExtra( |
| 29132 | 29132 | .addr = .{ .int = if (dest_info.flags.alignment != .none) |
| 29133 | 29133 | (try mod.intValue( |
| 29134 | 29134 | Type.usize, |
| 29135 | dest_info.flags.alignment.toByteUnitsOptional().?, | |
| 29135 | dest_info.flags.alignment.toByteUnits().?, | |
| 29136 | 29136 | )).toIntern() |
| 29137 | 29137 | else |
| 29138 | 29138 | try mod.intern_pool.getCoercedInts( |
| ... | ... | @@ -29800,7 +29800,7 @@ const InMemoryCoercionResult = union(enum) { |
| 29800 | 29800 | }, |
| 29801 | 29801 | .ptr_alignment => |pair| { |
| 29802 | 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 | 29805 | break; |
| 29806 | 29806 | }, |
src/Value.zig+8-8| ... | ... | @@ -176,7 +176,7 @@ pub fn toBigIntAdvanced( |
| 176 | 176 | if (opt_sema) |sema| try sema.resolveTypeLayout(Type.fromInterned(ty)); |
| 177 | 177 | const x = switch (int.storage) { |
| 178 | 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 | 180 | .lazy_size => Type.fromInterned(ty).abiSize(mod), |
| 181 | 181 | }; |
| 182 | 182 | return BigIntMutable.init(&space.limbs, x).toConst(); |
| ... | ... | @@ -237,9 +237,9 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 |
| 237 | 237 | .u64 => |x| x, |
| 238 | 238 | .i64 => |x| std.math.cast(u64, x), |
| 239 | 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 | 241 | else |
| 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits(0), | |
| 242 | Type.fromInterned(ty).abiAlignment(mod).toByteUnits() orelse 0, | |
| 243 | 243 | .lazy_size => |ty| if (opt_sema) |sema| |
| 244 | 244 | (try Type.fromInterned(ty).abiSizeAdvanced(mod, .{ .sema = sema })).scalar |
| 245 | 245 | else |
| ... | ... | @@ -289,7 +289,7 @@ pub fn toSignedInt(val: Value, mod: *Module) i64 { |
| 289 | 289 | .big_int => |big_int| big_int.to(i64) catch unreachable, |
| 290 | 290 | .i64 => |x| x, |
| 291 | 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 | 293 | .lazy_size => |ty| @intCast(Type.fromInterned(ty).abiSize(mod)), |
| 294 | 294 | }, |
| 295 | 295 | else => unreachable, |
| ... | ... | @@ -497,7 +497,7 @@ pub fn writeToPackedMemory( |
| 497 | 497 | inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian), |
| 498 | 498 | .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian), |
| 499 | 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 | 501 | std.mem.writeVarPackedInt(buffer, bit_offset, bits, num, endian); |
| 502 | 502 | }, |
| 503 | 503 | .lazy_size => |lazy_size| { |
| ... | ... | @@ -890,7 +890,7 @@ pub fn toFloat(val: Value, comptime T: type, mod: *Module) T { |
| 890 | 890 | } |
| 891 | 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 | 894 | .lazy_size => |ty| @floatFromInt(Type.fromInterned(ty).abiSize(mod)), |
| 895 | 895 | }, |
| 896 | 896 | .float => |float| switch (float.storage) { |
| ... | ... | @@ -1529,9 +1529,9 @@ pub fn floatFromIntScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?* |
| 1529 | 1529 | }, |
| 1530 | 1530 | inline .u64, .i64 => |x| floatFromIntInner(x, float_ty, mod), |
| 1531 | 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 | 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 | 1536 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 1537 | 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 | 1296 | // subtract it from the current stack pointer |
| 1297 | 1297 | try prologue.append(.{ .tag = .i32_sub, .data = .{ .tag = {} } }); |
| 1298 | 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 | 1300 | // Bitwise-and the value to get the new stack pointer to ensure the pointers are aligned with the abi alignment |
| 1301 | 1301 | try prologue.append(.{ .tag = .i32_and, .data = .{ .tag = {} } }); |
| 1302 | 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 | 2107 | }); |
| 2108 | 2108 | try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2109 | 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 | 2113 | else => try func.emitWValue(operand), |
| ... | ... | @@ -2384,7 +2384,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE |
| 2384 | 2384 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2385 | 2385 | std.wasm.simdOpcode(.v128_store), |
| 2386 | 2386 | offset + lhs.offset(), |
| 2387 | @intCast(ty.abiAlignment(mod).toByteUnits(0)), | |
| 2387 | @intCast(ty.abiAlignment(mod).toByteUnits() orelse 0), | |
| 2388 | 2388 | }); |
| 2389 | 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 | 2440 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2441 | 2441 | .{ |
| 2442 | 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 | 2500 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 2501 | 2501 | std.wasm.simdOpcode(.v128_load), |
| 2502 | 2502 | offset + operand.offset(), |
| 2503 | @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 2503 | @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 2504 | 2504 | }); |
| 2505 | 2505 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 2506 | 2506 | return WValue{ .stack = {} }; |
| ... | ... | @@ -2518,7 +2518,7 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu |
| 2518 | 2518 | Mir.Inst.Tag.fromOpcode(opcode), |
| 2519 | 2519 | .{ |
| 2520 | 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 | 3456 | .i64 => |x| @as(i32, @intCast(x)), |
| 3457 | 3457 | .u64 => |x| @as(i32, @bitCast(@as(u32, @intCast(x)))), |
| 3458 | 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 | 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 | 4204 | if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) { |
| 4205 | 4205 | try func.addMemArg(.i32_load16_u, .{ |
| 4206 | 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 | 5141 | try func.mir_extra.appendSlice(func.gpa, &[_]u32{ |
| 5142 | 5142 | opcode, |
| 5143 | 5143 | operand.offset(), |
| 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 5144 | @intCast(elem_ty.abiAlignment(mod).toByteUnits().?), | |
| 5145 | 5145 | }); |
| 5146 | 5146 | try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } }); |
| 5147 | 5147 | try func.addLabel(.local_set, result.local.value); |
| ... | ... | @@ -6552,7 +6552,7 @@ fn lowerTry( |
| 6552 | 6552 | const err_offset = @as(u32, @intCast(errUnionErrorOffset(pl_ty, mod))); |
| 6553 | 6553 | try func.addMemArg(.i32_load16_u, .{ |
| 6554 | 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 | 6558 | try func.addTag(.i32_eqz); |
| ... | ... | @@ -7499,7 +7499,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7499 | 7499 | else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}), |
| 7500 | 7500 | }, .{ |
| 7501 | 7501 | .offset = ptr_operand.offset(), |
| 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 7502 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 7503 | 7503 | }); |
| 7504 | 7504 | try func.addLabel(.local_tee, val_local.local.value); |
| 7505 | 7505 | _ = try func.cmp(.stack, expected_val, ty, .eq); |
| ... | ... | @@ -7561,7 +7561,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7561 | 7561 | try func.emitWValue(ptr); |
| 7562 | 7562 | try func.addAtomicMemArg(tag, .{ |
| 7563 | 7563 | .offset = ptr.offset(), |
| 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 7564 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 7565 | 7565 | }); |
| 7566 | 7566 | } else { |
| 7567 | 7567 | _ = try func.load(ptr, ty, 0); |
| ... | ... | @@ -7622,7 +7622,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7622 | 7622 | }, |
| 7623 | 7623 | .{ |
| 7624 | 7624 | .offset = ptr.offset(), |
| 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 7625 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 7626 | 7626 | }, |
| 7627 | 7627 | ); |
| 7628 | 7628 | const select_res = try func.allocLocal(ty); |
| ... | ... | @@ -7682,7 +7682,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7682 | 7682 | }; |
| 7683 | 7683 | try func.addAtomicMemArg(tag, .{ |
| 7684 | 7684 | .offset = ptr.offset(), |
| 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 7685 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 7686 | 7686 | }); |
| 7687 | 7687 | const result = try WValue.toLocal(.stack, func, ty); |
| 7688 | 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 | 7781 | try func.lowerToStack(operand); |
| 7782 | 7782 | try func.addAtomicMemArg(tag, .{ |
| 7783 | 7783 | .offset = ptr.offset(), |
| 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnitsOptional().?), | |
| 7784 | .alignment = @intCast(ty.abiAlignment(mod).toByteUnits().?), | |
| 7785 | 7785 | }); |
| 7786 | 7786 | } else { |
| 7787 | 7787 | try func.store(ptr, operand, ty, 0); |
src/arch/x86_64/CodeGen.zig+3-3| ... | ... | @@ -18959,7 +18959,7 @@ fn resolveCallingConventionValues( |
| 18959 | 18959 | |
| 18960 | 18960 | const param_size: u31 = @intCast(ty.abiSize(mod)); |
| 18961 | 18961 | const param_align: u31 = |
| 18962 | @intCast(@max(ty.abiAlignment(mod).toByteUnitsOptional().?, 8)); | |
| 18962 | @intCast(@max(ty.abiAlignment(mod).toByteUnits().?, 8)); | |
| 18963 | 18963 | result.stack_byte_count = |
| 18964 | 18964 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 18965 | 18965 | arg.* = .{ .load_frame = .{ |
| ... | ... | @@ -19003,7 +19003,7 @@ fn resolveCallingConventionValues( |
| 19003 | 19003 | continue; |
| 19004 | 19004 | } |
| 19005 | 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 | 19007 | result.stack_byte_count = |
| 19008 | 19008 | mem.alignForward(u31, result.stack_byte_count, param_align); |
| 19009 | 19009 | arg.* = .{ .load_frame = .{ |
| ... | ... | @@ -19096,7 +19096,7 @@ fn splitType(self: *Self, ty: Type) ![2]Type { |
| 19096 | 19096 | .integer => switch (part_i) { |
| 19097 | 19097 | 0 => Type.u64, |
| 19098 | 19098 | 1 => part: { |
| 19099 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnitsOptional().?; | |
| 19099 | const elem_size = ty.abiAlignment(mod).minStrict(.@"8").toByteUnits().?; | |
| 19100 | 19100 | const elem_ty = try mod.intType(.unsigned, @intCast(elem_size * 8)); |
| 19101 | 19101 | break :part switch (@divExact(ty.abiSize(mod) - 8, elem_size)) { |
| 19102 | 19102 | 1 => elem_ty, |
src/codegen.zig+3-3| ... | ... | @@ -548,7 +548,7 @@ pub fn generateSymbol( |
| 548 | 548 | } |
| 549 | 549 | |
| 550 | 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 | 553 | const padding = math.cast( |
| 554 | 554 | usize, |
| ... | ... | @@ -893,12 +893,12 @@ fn genDeclRef( |
| 893 | 893 | // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? |
| 894 | 894 | if (ty.castPtrToFn(zcu)) |fn_ty| { |
| 895 | 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 | 898 | } else if (ty.zigTypeTag(zcu) == .Pointer) { |
| 899 | 899 | const elem_ty = ty.elemType2(zcu); |
| 900 | 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 | 22 | const BigIntLimb = std.math.big.Limb; |
| 23 | 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 | 27 | pub const CValue = union(enum) { |
| 28 | 28 | none: void, |
| ... | ... | @@ -62,7 +62,7 @@ pub const LazyFnKey = union(enum) { |
| 62 | 62 | never_inline: InternPool.DeclIndex, |
| 63 | 63 | }; |
| 64 | 64 | pub const LazyFnValue = struct { |
| 65 | fn_name: []const u8, | |
| 65 | fn_name: CType.String, | |
| 66 | 66 | data: Data, |
| 67 | 67 | |
| 68 | 68 | pub const Data = union { |
| ... | ... | @@ -74,19 +74,19 @@ pub const LazyFnValue = struct { |
| 74 | 74 | pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue); |
| 75 | 75 | |
| 76 | 76 | const Local = struct { |
| 77 | cty_idx: CType.Index, | |
| 77 | ctype: CType, | |
| 78 | 78 | flags: packed struct(u32) { |
| 79 | 79 | alignas: CType.AlignAs, |
| 80 | 80 | _: u20 = undefined, |
| 81 | 81 | }, |
| 82 | 82 | |
| 83 | 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 | 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 | 90 | const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void); |
| 91 | 91 | const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList); |
| 92 | 92 | |
| ... | ... | @@ -193,6 +193,7 @@ const reserved_idents = std.ComptimeStringMap(void, .{ |
| 193 | 193 | .{ "switch", {} }, |
| 194 | 194 | .{ "thread_local", {} }, |
| 195 | 195 | .{ "typedef", {} }, |
| 196 | .{ "typeof", {} }, | |
| 196 | 197 | .{ "uint16_t", {} }, |
| 197 | 198 | .{ "uint32_t", {} }, |
| 198 | 199 | .{ "uint64_t", {} }, |
| ... | ... | @@ -309,12 +310,14 @@ pub const Function = struct { |
| 309 | 310 | |
| 310 | 311 | const result: CValue = if (lowersToArray(ty, zcu)) result: { |
| 311 | 312 | const writer = f.object.codeHeaderWriter(); |
| 312 | const alignment: Alignment = .none; | |
| 313 | const decl_c_value = try f.allocLocalValue(ty, alignment); | |
| 313 | const decl_c_value = try f.allocLocalValue(.{ | |
| 314 | .ctype = try f.ctypeFromType(ty, .complete), | |
| 315 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(zcu)), | |
| 316 | }); | |
| 314 | 317 | const gpa = f.object.dg.gpa; |
| 315 | 318 | try f.allocs.put(gpa, decl_c_value.new_local, false); |
| 316 | 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 | 321 | try writer.writeAll(" = "); |
| 319 | 322 | try f.object.dg.renderValue(writer, val, .StaticInitializer); |
| 320 | 323 | try writer.writeAll(";\n "); |
| ... | ... | @@ -335,42 +338,39 @@ pub const Function = struct { |
| 335 | 338 | /// Skips the reuse logic. This function should be used for any persistent allocation, i.e. |
| 336 | 339 | /// those which go into `allocs`. This function does not add the resulting local into `allocs`; |
| 337 | 340 | /// that responsibility lies with the caller. |
| 338 | fn allocLocalValue(f: *Function, ty: Type, alignment: Alignment) !CValue { | |
| 339 | const zcu = f.object.dg.zcu; | |
| 340 | const gpa = f.object.dg.gpa; | |
| 341 | try f.locals.append(gpa, .{ | |
| 342 | .cty_idx = try f.typeToIndex(ty, .complete), | |
| 343 | .flags = .{ | |
| 344 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), | |
| 345 | }, | |
| 341 | fn allocLocalValue(f: *Function, local_type: LocalType) !CValue { | |
| 342 | try f.locals.ensureUnusedCapacity(f.object.dg.gpa, 1); | |
| 343 | defer f.locals.appendAssumeCapacity(.{ | |
| 344 | .ctype = local_type.ctype, | |
| 345 | .flags = .{ .alignas = local_type.alignas }, | |
| 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 | 350 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { |
| 351 | const result = try f.allocAlignedLocal(ty, .{}, .none); | |
| 352 | if (inst) |i| { | |
| 353 | log.debug("%{d}: allocating t{d}", .{ i, result.new_local }); | |
| 354 | } else { | |
| 355 | log.debug("allocating t{d}", .{result.new_local}); | |
| 356 | } | |
| 357 | return result; | |
| 351 | return f.allocAlignedLocal(inst, .{ | |
| 352 | .ctype = try f.ctypeFromType(ty, .complete), | |
| 353 | .alignas = CType.AlignAs.fromAbiAlignment(ty.abiAlignment(f.object.dg.zcu)), | |
| 354 | }); | |
| 358 | 355 | } |
| 359 | 356 | |
| 360 | 357 | /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should |
| 361 | 358 | /// not be used for persistent locals (i.e. those in `allocs`). |
| 362 | fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: Alignment) !CValue { | |
| 363 | const zcu = f.object.dg.zcu; | |
| 364 | if (f.free_locals_map.getPtr(.{ | |
| 365 | .cty_idx = try f.typeToIndex(ty, .complete), | |
| 366 | .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)), | |
| 367 | })) |locals_list| { | |
| 368 | if (locals_list.popOrNull()) |local_entry| { | |
| 369 | return .{ .new_local = local_entry.key }; | |
| 359 | fn allocAlignedLocal(f: *Function, inst: ?Air.Inst.Index, local_type: LocalType) !CValue { | |
| 360 | const result: CValue = result: { | |
| 361 | if (f.free_locals_map.getPtr(local_type)) |locals_list| { | |
| 362 | if (locals_list.popOrNull()) |local_entry| { | |
| 363 | break :result .{ .new_local = local_entry.key }; | |
| 364 | } | |
| 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 f.allocLocalValue(ty, alignment); | |
| 373 | return result; | |
| 374 | 374 | } |
| 375 | 375 | |
| 376 | 376 | fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void { |
| ... | ... | @@ -380,15 +380,20 @@ pub const Function = struct { |
| 380 | 380 | .local_ref => |i| { |
| 381 | 381 | const local = &f.locals.items[i]; |
| 382 | 382 | if (local.flags.alignas.abiOrder().compare(.lt)) { |
| 383 | const zcu = f.object.dg.zcu; | |
| 384 | const pointee_ty = try zcu.intType(.unsigned, @min( | |
| 385 | local.flags.alignas.@"align".toByteUnitsOptional().?, | |
| 386 | f.object.dg.mod.resolved_target.result.maxIntAlignment(), | |
| 387 | ) * 8); | |
| 388 | const ptr_ty = try zcu.singleMutPtrType(pointee_ty); | |
| 383 | const gpa = f.object.dg.gpa; | |
| 384 | const mod = f.object.dg.mod; | |
| 385 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 389 | 386 | |
| 390 | 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 | 397 | try w.writeByte(')'); |
| 393 | 398 | } |
| 394 | 399 | try w.print("&t{d}", .{i}); |
| ... | ... | @@ -460,28 +465,20 @@ pub const Function = struct { |
| 460 | 465 | return f.object.dg.fail(format, args); |
| 461 | 466 | } |
| 462 | 467 | |
| 463 | fn indexToCType(f: *Function, idx: CType.Index) CType { | |
| 464 | return f.object.dg.indexToCType(idx); | |
| 465 | } | |
| 466 | ||
| 467 | fn typeToIndex(f: *Function, ty: Type, kind: CType.Kind) !CType.Index { | |
| 468 | return f.object.dg.typeToIndex(ty, kind); | |
| 468 | fn ctypeFromType(f: *Function, ty: Type, kind: CType.Kind) !CType { | |
| 469 | return f.object.dg.ctypeFromType(ty, kind); | |
| 469 | 470 | } |
| 470 | 471 | |
| 471 | fn typeToCType(f: *Function, ty: Type, kind: CType.Kind) !CType { | |
| 472 | return f.object.dg.typeToCType(ty, kind); | |
| 472 | fn byteSize(f: *Function, ctype: CType) u64 { | |
| 473 | return f.object.dg.byteSize(ctype); | |
| 473 | 474 | } |
| 474 | 475 | |
| 475 | fn byteSize(f: *Function, cty: CType) u64 { | |
| 476 | return f.object.dg.byteSize(cty); | |
| 476 | fn renderType(f: *Function, w: anytype, ctype: Type) !void { | |
| 477 | return f.object.dg.renderType(w, ctype); | |
| 477 | 478 | } |
| 478 | 479 | |
| 479 | fn renderType(f: *Function, w: anytype, t: Type) !void { | |
| 480 | return f.object.dg.renderType(w, t); | |
| 481 | } | |
| 482 | ||
| 483 | fn renderCType(f: *Function, w: anytype, t: CType.Index) !void { | |
| 484 | return f.object.dg.renderCType(w, t); | |
| 480 | fn renderCType(f: *Function, w: anytype, ctype: CType) !void { | |
| 481 | return f.object.dg.renderCType(w, ctype); | |
| 485 | 482 | } |
| 486 | 483 | |
| 487 | 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 | 491 | |
| 495 | 492 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| 496 | 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 | 497 | const gop = try f.lazy_fns.getOrPut(gpa, key); |
| 498 | 498 | if (!gop.found_existing) { |
| 499 | 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 | 501 | gop.value_ptr.* = .{ |
| 507 | 502 | .fn_name = switch (key) { |
| 508 | 503 | .tag_name, |
| 509 | 504 | .never_tail, |
| 510 | 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 | 507 | @tagName(key), |
| 513 | 508 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), |
| 514 | 509 | @intFromEnum(owner_decl), |
| ... | ... | @@ -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 | 522 | pub fn deinit(f: *Function) void { |
| ... | ... | @@ -532,7 +527,6 @@ pub const Function = struct { |
| 532 | 527 | f.blocks.deinit(gpa); |
| 533 | 528 | f.value_map.deinit(); |
| 534 | 529 | f.lazy_fns.deinit(gpa); |
| 535 | f.object.dg.ctypes.deinit(gpa); | |
| 536 | 530 | } |
| 537 | 531 | |
| 538 | 532 | fn typeOf(f: *Function, inst: Air.Inst.Ref) Type { |
| ... | ... | @@ -575,7 +569,8 @@ pub const DeclGen = struct { |
| 575 | 569 | /// This is a borrowed reference from `link.C`. |
| 576 | 570 | fwd_decl: std.ArrayList(u8), |
| 577 | 571 | error_msg: ?*Zcu.ErrorMsg, |
| 578 | ctypes: CType.Store, | |
| 572 | ctype_pool: CType.Pool, | |
| 573 | scratch: std.ArrayListUnmanaged(u32), | |
| 579 | 574 | /// Keeps track of anonymous decls that need to be rendered before this |
| 580 | 575 | /// (named) Decl in the output C code. |
| 581 | 576 | anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), |
| ... | ... | @@ -610,6 +605,7 @@ pub const DeclGen = struct { |
| 610 | 605 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 611 | 606 | const zcu = dg.zcu; |
| 612 | 607 | const ip = &zcu.intern_pool; |
| 608 | const ctype_pool = &dg.ctype_pool; | |
| 613 | 609 | const decl_val = Value.fromInterned(anon_decl.val); |
| 614 | 610 | const decl_ty = decl_val.typeOf(zcu); |
| 615 | 611 | |
| ... | ... | @@ -631,10 +627,10 @@ pub const DeclGen = struct { |
| 631 | 627 | // them). The analysis until now should ensure that the C function |
| 632 | 628 | // pointers are compatible. If they are not, then there is a bug |
| 633 | 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; | |
| 635 | const decl_cty = try dg.typeToIndex(decl_ty, .complete); | |
| 636 | const need_cast = child_cty != decl_cty and | |
| 637 | (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); | |
| 630 | const elem_ctype = (try dg.ctypeFromType(ptr_ty, .complete)).info(ctype_pool).pointer.elem_ctype; | |
| 631 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | |
| 632 | const need_cast = !elem_ctype.eql(decl_ctype) and | |
| 633 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | |
| 638 | 634 | if (need_cast) { |
| 639 | 635 | try writer.writeAll("(("); |
| 640 | 636 | try dg.renderType(writer, ptr_ty); |
| ... | ... | @@ -655,7 +651,7 @@ pub const DeclGen = struct { |
| 655 | 651 | const explicit_alignment = ptr_type.flags.alignment; |
| 656 | 652 | if (explicit_alignment != .none) { |
| 657 | 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 | 655 | const aligned_gop = try dg.aligned_anon_decls.getOrPut(dg.gpa, anon_decl.val); |
| 660 | 656 | aligned_gop.value_ptr.* = if (aligned_gop.found_existing) |
| 661 | 657 | aligned_gop.value_ptr.maxStrict(explicit_alignment) |
| ... | ... | @@ -673,6 +669,7 @@ pub const DeclGen = struct { |
| 673 | 669 | location: ValueRenderLocation, |
| 674 | 670 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 675 | 671 | const zcu = dg.zcu; |
| 672 | const ctype_pool = &dg.ctype_pool; | |
| 676 | 673 | const decl = zcu.declPtr(decl_index); |
| 677 | 674 | assert(decl.has_tv); |
| 678 | 675 | |
| ... | ... | @@ -695,10 +692,10 @@ pub const DeclGen = struct { |
| 695 | 692 | // them). The analysis until now should ensure that the C function |
| 696 | 693 | // pointers are compatible. If they are not, then there is a bug |
| 697 | 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; | |
| 699 | const decl_cty = try dg.typeToIndex(decl_ty, .complete); | |
| 700 | const need_cast = child_cty != decl_cty and | |
| 701 | (dg.indexToCType(child_cty).tag() != .function or dg.indexToCType(decl_cty).tag() != .function); | |
| 695 | const elem_ctype = (try dg.ctypeFromType(ty, .complete)).info(ctype_pool).pointer.elem_ctype; | |
| 696 | const decl_ctype = try dg.ctypeFromType(decl_ty, .complete); | |
| 697 | const need_cast = !elem_ctype.eql(decl_ctype) and | |
| 698 | (elem_ctype.info(ctype_pool) != .function or decl_ctype.info(ctype_pool) != .function); | |
| 702 | 699 | if (need_cast) { |
| 703 | 700 | try writer.writeAll("(("); |
| 704 | 701 | try dg.renderType(writer, ty); |
| ... | ... | @@ -720,31 +717,31 @@ pub const DeclGen = struct { |
| 720 | 717 | const zcu = dg.zcu; |
| 721 | 718 | const ip = &zcu.intern_pool; |
| 722 | 719 | const ptr_ty = Type.fromInterned(ip.typeOf(ptr_val)); |
| 723 | const ptr_cty = try dg.typeToIndex(ptr_ty, .complete); | |
| 724 | const ptr_child_cty = dg.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; | |
| 720 | const ptr_ctype = try dg.ctypeFromType(ptr_ty, .complete); | |
| 721 | const ptr_child_ctype = ptr_ctype.info(&dg.ctype_pool).pointer.elem_ctype; | |
| 725 | 722 | const ptr = ip.indexToKey(ptr_val).ptr; |
| 726 | 723 | switch (ptr.addr) { |
| 727 | 724 | .decl => |d| try dg.renderDeclValue(writer, Value.fromInterned(ptr_val), d, location), |
| 728 | 725 | .anon_decl => |anon_decl| try dg.renderAnonDeclValue(writer, Value.fromInterned(ptr_val), anon_decl, location), |
| 729 | 726 | .int => |int| { |
| 730 | 727 | try writer.writeByte('('); |
| 731 | try dg.renderCType(writer, ptr_cty); | |
| 728 | try dg.renderCType(writer, ptr_ctype); | |
| 732 | 729 | try writer.print("){x}", .{try dg.fmtIntLiteral(Value.fromInterned(int), .Other)}); |
| 733 | 730 | }, |
| 734 | 731 | .eu_payload, .opt_payload => |base| { |
| 735 | 732 | const ptr_base_ty = Type.fromInterned(ip.typeOf(base)); |
| 736 | 733 | const base_ty = ptr_base_ty.childType(zcu); |
| 737 | 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 | 736 | const payload_ty = switch (ptr.addr) { |
| 740 | 737 | .eu_payload => base_ty.errorUnionPayload(zcu), |
| 741 | 738 | .opt_payload => base_ty.optionalChild(zcu), |
| 742 | 739 | else => unreachable, |
| 743 | 740 | }; |
| 744 | const payload_cty = try dg.typeToIndex(payload_ty, .forward); | |
| 745 | if (ptr_child_cty != payload_cty) { | |
| 741 | const payload_ctype = try dg.ctypeFromType(payload_ty, .forward); | |
| 742 | if (!ptr_child_ctype.eql(payload_ctype)) { | |
| 746 | 743 | try writer.writeByte('('); |
| 747 | try dg.renderCType(writer, ptr_cty); | |
| 744 | try dg.renderCType(writer, ptr_ctype); | |
| 748 | 745 | try writer.writeByte(')'); |
| 749 | 746 | } |
| 750 | 747 | try writer.writeAll("&("); |
| ... | ... | @@ -754,10 +751,10 @@ pub const DeclGen = struct { |
| 754 | 751 | .elem => |elem| { |
| 755 | 752 | const ptr_base_ty = Type.fromInterned(ip.typeOf(elem.base)); |
| 756 | 753 | const elem_ty = ptr_base_ty.elemType2(zcu); |
| 757 | const elem_cty = try dg.typeToIndex(elem_ty, .forward); | |
| 758 | if (ptr_child_cty != elem_cty) { | |
| 754 | const elem_ctype = try dg.ctypeFromType(elem_ty, .forward); | |
| 755 | if (!ptr_child_ctype.eql(elem_ctype)) { | |
| 759 | 756 | try writer.writeByte('('); |
| 760 | try dg.renderCType(writer, ptr_cty); | |
| 757 | try dg.renderCType(writer, ptr_ctype); | |
| 761 | 758 | try writer.writeByte(')'); |
| 762 | 759 | } |
| 763 | 760 | try writer.writeAll("&("); |
| ... | ... | @@ -769,14 +766,14 @@ pub const DeclGen = struct { |
| 769 | 766 | .field => |field| { |
| 770 | 767 | const ptr_base_ty = Type.fromInterned(ip.typeOf(field.base)); |
| 771 | 768 | const base_ty = ptr_base_ty.childType(zcu); |
| 772 | // Ensure complete type definition is visible before accessing fields. | |
| 773 | _ = try dg.typeToIndex(base_ty, .complete); | |
| 769 | // Ensure complete type definition is available before accessing fields. | |
| 770 | _ = try dg.ctypeFromType(base_ty, .complete); | |
| 774 | 771 | switch (fieldLocation(ptr_base_ty, ptr_ty, @as(u32, @intCast(field.index)), zcu)) { |
| 775 | 772 | .begin => { |
| 776 | const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); | |
| 777 | if (ptr_cty != ptr_base_cty) { | |
| 773 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); | |
| 774 | if (!ptr_ctype.eql(ptr_base_ctype)) { | |
| 778 | 775 | try writer.writeByte('('); |
| 779 | try dg.renderCType(writer, ptr_cty); | |
| 776 | try dg.renderCType(writer, ptr_ctype); | |
| 780 | 777 | try writer.writeByte(')'); |
| 781 | 778 | } |
| 782 | 779 | try dg.renderParentPtr(writer, field.base, location); |
| ... | ... | @@ -797,10 +794,10 @@ pub const DeclGen = struct { |
| 797 | 794 | }, |
| 798 | 795 | else => unreachable, |
| 799 | 796 | }; |
| 800 | const field_cty = try dg.typeToIndex(field_ty, .forward); | |
| 801 | if (ptr_child_cty != field_cty) { | |
| 797 | const field_ctype = try dg.ctypeFromType(field_ty, .forward); | |
| 798 | if (!ptr_child_ctype.eql(field_ctype)) { | |
| 802 | 799 | try writer.writeByte('('); |
| 803 | try dg.renderCType(writer, ptr_cty); | |
| 800 | try dg.renderCType(writer, ptr_ctype); | |
| 804 | 801 | try writer.writeByte(')'); |
| 805 | 802 | } |
| 806 | 803 | try writer.writeAll("&("); |
| ... | ... | @@ -810,15 +807,15 @@ pub const DeclGen = struct { |
| 810 | 807 | }, |
| 811 | 808 | .byte_offset => |byte_offset| { |
| 812 | 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 | 813 | try writer.writeByte('('); |
| 817 | try dg.renderCType(writer, ptr_cty); | |
| 814 | try dg.renderCType(writer, ptr_ctype); | |
| 818 | 815 | try writer.writeByte(')'); |
| 819 | 816 | } |
| 820 | 817 | try writer.writeAll("(("); |
| 821 | try dg.renderCType(writer, u8_ptr_cty); | |
| 818 | try dg.renderCType(writer, u8_ptr_ctype); | |
| 822 | 819 | try writer.writeByte(')'); |
| 823 | 820 | try dg.renderParentPtr(writer, field.base, location); |
| 824 | 821 | try writer.print(" + {})", .{ |
| ... | ... | @@ -826,10 +823,10 @@ pub const DeclGen = struct { |
| 826 | 823 | }); |
| 827 | 824 | }, |
| 828 | 825 | .end => { |
| 829 | const ptr_base_cty = try dg.typeToIndex(ptr_base_ty, .complete); | |
| 830 | if (ptr_cty != ptr_base_cty) { | |
| 826 | const ptr_base_ctype = try dg.ctypeFromType(ptr_base_ty, .complete); | |
| 827 | if (!ptr_ctype.eql(ptr_base_ctype)) { | |
| 831 | 828 | try writer.writeByte('('); |
| 832 | try dg.renderCType(writer, ptr_cty); | |
| 829 | try dg.renderCType(writer, ptr_ctype); | |
| 833 | 830 | try writer.writeByte(')'); |
| 834 | 831 | } |
| 835 | 832 | try writer.writeAll("(("); |
| ... | ... | @@ -1207,8 +1204,8 @@ pub const DeclGen = struct { |
| 1207 | 1204 | try writer.writeByte('}'); |
| 1208 | 1205 | }, |
| 1209 | 1206 | .struct_type => { |
| 1210 | const struct_type = ip.loadStructType(ty.toIntern()); | |
| 1211 | switch (struct_type.layout) { | |
| 1207 | const loaded_struct = ip.loadStructType(ty.toIntern()); | |
| 1208 | switch (loaded_struct.layout) { | |
| 1212 | 1209 | .auto, .@"extern" => { |
| 1213 | 1210 | if (!location.isInitializer()) { |
| 1214 | 1211 | try writer.writeByte('('); |
| ... | ... | @@ -1217,13 +1214,14 @@ pub const DeclGen = struct { |
| 1217 | 1214 | } |
| 1218 | 1215 | |
| 1219 | 1216 | try writer.writeByte('{'); |
| 1220 | var empty = true; | |
| 1221 | for (0..struct_type.field_types.len) |field_index| { | |
| 1222 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 1223 | if (struct_type.fieldIsComptime(ip, field_index)) continue; | |
| 1217 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 1218 | var need_comma = false; | |
| 1219 | while (field_it.next()) |field_index| { | |
| 1220 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1224 | 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 | 1225 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| 1228 | 1226 | .bytes => |bytes| try ip.get(zcu.gpa, .{ .int = .{ |
| 1229 | 1227 | .ty = field_ty.toIntern(), |
| ... | ... | @@ -1233,8 +1231,6 @@ pub const DeclGen = struct { |
| 1233 | 1231 | .repeated_elem => |elem| elem, |
| 1234 | 1232 | }; |
| 1235 | 1233 | try dg.renderValue(writer, Value.fromInterned(field_val), initializer_type); |
| 1236 | ||
| 1237 | empty = false; | |
| 1238 | 1234 | } |
| 1239 | 1235 | try writer.writeByte('}'); |
| 1240 | 1236 | }, |
| ... | ... | @@ -1247,8 +1243,8 @@ pub const DeclGen = struct { |
| 1247 | 1243 | var bit_offset: u64 = 0; |
| 1248 | 1244 | var eff_num_fields: usize = 0; |
| 1249 | 1245 | |
| 1250 | for (0..struct_type.field_types.len) |field_index| { | |
| 1251 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 1246 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 1247 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1252 | 1248 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1253 | 1249 | eff_num_fields += 1; |
| 1254 | 1250 | } |
| ... | ... | @@ -1268,8 +1264,8 @@ pub const DeclGen = struct { |
| 1268 | 1264 | |
| 1269 | 1265 | var eff_index: usize = 0; |
| 1270 | 1266 | var needs_closing_paren = false; |
| 1271 | for (0..struct_type.field_types.len) |field_index| { | |
| 1272 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 1267 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 1268 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1273 | 1269 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1274 | 1270 | |
| 1275 | 1271 | const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { |
| ... | ... | @@ -1304,8 +1300,8 @@ pub const DeclGen = struct { |
| 1304 | 1300 | try writer.writeByte('('); |
| 1305 | 1301 | // a << a_off | b << b_off | c << c_off |
| 1306 | 1302 | var empty = true; |
| 1307 | for (0..struct_type.field_types.len) |field_index| { | |
| 1308 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); | |
| 1303 | for (0..loaded_struct.field_types.len) |field_index| { | |
| 1304 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1309 | 1305 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; |
| 1310 | 1306 | |
| 1311 | 1307 | if (!empty) try writer.writeAll(" | "); |
| ... | ... | @@ -1341,10 +1337,10 @@ pub const DeclGen = struct { |
| 1341 | 1337 | else => unreachable, |
| 1342 | 1338 | }, |
| 1343 | 1339 | .un => |un| { |
| 1344 | const union_obj = zcu.typeToUnion(ty).?; | |
| 1340 | const loaded_union = ip.loadUnionType(ty.toIntern()); | |
| 1345 | 1341 | if (un.tag == .none) { |
| 1346 | 1342 | const backing_ty = try ty.unionBackingType(zcu); |
| 1347 | switch (union_obj.getLayout(ip)) { | |
| 1343 | switch (loaded_union.getLayout(ip)) { | |
| 1348 | 1344 | .@"packed" => { |
| 1349 | 1345 | if (!location.isInitializer()) { |
| 1350 | 1346 | try writer.writeByte('('); |
| ... | ... | @@ -1376,10 +1372,10 @@ pub const DeclGen = struct { |
| 1376 | 1372 | try writer.writeByte(')'); |
| 1377 | 1373 | } |
| 1378 | 1374 | |
| 1379 | const field_index = zcu.unionTagFieldIndex(union_obj, Value.fromInterned(un.tag)).?; | |
| 1380 | const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); | |
| 1381 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | |
| 1382 | if (union_obj.getLayout(ip) == .@"packed") { | |
| 1375 | const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; | |
| 1376 | const field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[field_index]); | |
| 1377 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; | |
| 1378 | if (loaded_union.getLayout(ip) == .@"packed") { | |
| 1383 | 1379 | if (field_ty.hasRuntimeBits(zcu)) { |
| 1384 | 1380 | if (field_ty.isPtrAtRuntime(zcu)) { |
| 1385 | 1381 | try writer.writeByte('('); |
| ... | ... | @@ -1399,7 +1395,7 @@ pub const DeclGen = struct { |
| 1399 | 1395 | |
| 1400 | 1396 | try writer.writeByte('{'); |
| 1401 | 1397 | if (ty.unionTagTypeSafety(zcu)) |_| { |
| 1402 | const layout = zcu.getUnionLayout(union_obj); | |
| 1398 | const layout = zcu.getUnionLayout(loaded_union); | |
| 1403 | 1399 | if (layout.tag_size != 0) { |
| 1404 | 1400 | try writer.writeAll(" .tag = "); |
| 1405 | 1401 | try dg.renderValue(writer, Value.fromInterned(un.tag), initializer_type); |
| ... | ... | @@ -1412,8 +1408,8 @@ pub const DeclGen = struct { |
| 1412 | 1408 | try writer.print(" .{ } = ", .{fmtIdent(ip.stringToSlice(field_name))}); |
| 1413 | 1409 | try dg.renderValue(writer, Value.fromInterned(un.val), initializer_type); |
| 1414 | 1410 | try writer.writeByte(' '); |
| 1415 | } else for (0..union_obj.field_types.len) |this_field_index| { | |
| 1416 | const this_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[this_field_index]); | |
| 1411 | } else for (0..loaded_union.field_types.len) |this_field_index| { | |
| 1412 | const this_field_ty = Type.fromInterned(loaded_union.field_types.get(ip)[this_field_index]); | |
| 1417 | 1413 | if (!this_field_ty.hasRuntimeBits(zcu)) continue; |
| 1418 | 1414 | try dg.renderUndefValue(writer, this_field_ty, initializer_type); |
| 1419 | 1415 | break; |
| ... | ... | @@ -1445,12 +1441,14 @@ pub const DeclGen = struct { |
| 1445 | 1441 | .ReleaseFast, .ReleaseSmall => false, |
| 1446 | 1442 | }; |
| 1447 | 1443 | |
| 1448 | switch (ty.zigTypeTag(zcu)) { | |
| 1449 | .Bool => try writer.writeAll(if (safety_on) "0xaa" else "false"), | |
| 1450 | .Int, .Enum, .ErrorSet => try writer.print("{x}", .{ | |
| 1451 | try dg.fmtIntLiteral(try zcu.undefValue(ty), location), | |
| 1452 | }), | |
| 1453 | .Float => { | |
| 1444 | switch (ty.toIntern()) { | |
| 1445 | .c_longdouble_type, | |
| 1446 | .f16_type, | |
| 1447 | .f32_type, | |
| 1448 | .f64_type, | |
| 1449 | .f80_type, | |
| 1450 | .f128_type, | |
| 1451 | => { | |
| 1454 | 1452 | const bits = ty.floatBits(target.*); |
| 1455 | 1453 | // All unsigned ints matching float types are pre-allocated. |
| 1456 | 1454 | const repr_ty = zcu.intType(.unsigned, bits) catch unreachable; |
| ... | ... | @@ -1468,49 +1466,90 @@ pub const DeclGen = struct { |
| 1468 | 1466 | } |
| 1469 | 1467 | try writer.writeAll(", "); |
| 1470 | 1468 | try dg.renderUndefValue(writer, repr_ty, .FunctionArgument); |
| 1471 | try writer.writeByte(')'); | |
| 1469 | return writer.writeByte(')'); | |
| 1472 | 1470 | }, |
| 1473 | .Pointer => if (ty.isSlice(zcu)) { | |
| 1474 | if (!location.isInitializer()) { | |
| 1475 | try writer.writeByte('('); | |
| 1471 | .bool_type => try writer.writeAll(if (safety_on) "0xaa" else "false"), | |
| 1472 | else => switch (ip.indexToKey(ty.toIntern())) { | |
| 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 | 1496 | try dg.renderType(writer, ty); |
| 1477 | try writer.writeByte(')'); | |
| 1478 | } | |
| 1497 | return writer.print("){x})", .{ | |
| 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("{("); | |
| 1481 | const ptr_ty = ty.slicePtrFieldType(zcu); | |
| 1482 | try dg.renderType(writer, ptr_ty); | |
| 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); | |
| 1504 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1505 | return dg.renderUndefValue(writer, Type.bool, location); | |
| 1506 | } | |
| 1491 | 1507 | |
| 1492 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1493 | return dg.renderUndefValue(writer, Type.bool, location); | |
| 1494 | } | |
| 1508 | if (ty.optionalReprIsPayload(zcu)) { | |
| 1509 | return dg.renderUndefValue(writer, payload_ty, location); | |
| 1510 | } | |
| 1495 | 1511 | |
| 1496 | if (ty.optionalReprIsPayload(zcu)) { | |
| 1497 | return dg.renderUndefValue(writer, payload_ty, location); | |
| 1498 | } | |
| 1512 | if (!location.isInitializer()) { | |
| 1513 | try writer.writeByte('('); | |
| 1514 | try dg.renderType(writer, ty); | |
| 1515 | try writer.writeByte(')'); | |
| 1516 | } | |
| 1499 | 1517 | |
| 1500 | if (!location.isInitializer()) { | |
| 1501 | try writer.writeByte('('); | |
| 1502 | try dg.renderType(writer, ty); | |
| 1503 | try writer.writeByte(')'); | |
| 1504 | } | |
| 1518 | try writer.writeAll("{ .payload = "); | |
| 1519 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | |
| 1520 | try writer.writeAll(", .is_null = "); | |
| 1521 | try dg.renderUndefValue(writer, Type.bool, initializer_type); | |
| 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 = "); | |
| 1507 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | |
| 1508 | try writer.writeAll(", .is_null = "); | |
| 1509 | try dg.renderUndefValue(writer, Type.bool, initializer_type); | |
| 1510 | try writer.writeAll(" }"); | |
| 1511 | }, | |
| 1512 | .Struct => switch (ty.containerLayout(zcu)) { | |
| 1513 | .auto, .@"extern" => { | |
| 1534 | try writer.writeByte('{'); | |
| 1535 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 1536 | var need_comma = false; | |
| 1537 | while (field_it.next()) |field_index| { | |
| 1538 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 1539 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 1540 | ||
| 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 | 1553 | if (!location.isInitializer()) { |
| 1515 | 1554 | try writer.writeByte('('); |
| 1516 | 1555 | try dg.renderType(writer, ty); |
| ... | ... | @@ -1518,116 +1557,125 @@ pub const DeclGen = struct { |
| 1518 | 1557 | } |
| 1519 | 1558 | |
| 1520 | 1559 | try writer.writeByte('{'); |
| 1521 | var empty = true; | |
| 1522 | for (0..ty.structFieldCount(zcu)) |field_index| { | |
| 1523 | if (ty.structFieldIsComptime(field_index, zcu)) continue; | |
| 1524 | const field_ty = ty.structFieldType(field_index, zcu); | |
| 1525 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 1560 | var need_comma = false; | |
| 1561 | for (0..anon_struct_info.types.len) |field_index| { | |
| 1562 | if (anon_struct_info.values.get(ip)[field_index] != .none) continue; | |
| 1563 | const field_ty = Type.fromInterned(anon_struct_info.types.get(ip)[field_index]); | |
| 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 | 1568 | try dg.renderUndefValue(writer, field_ty, initializer_type); |
| 1529 | ||
| 1530 | empty = false; | |
| 1531 | 1569 | } |
| 1532 | ||
| 1533 | try writer.writeByte('}'); | |
| 1570 | return writer.writeByte('}'); | |
| 1534 | 1571 | }, |
| 1535 | .@"packed" => try writer.print("{x}", .{ | |
| 1536 | try dg.fmtIntLiteral(try zcu.undefValue(ty), .Other), | |
| 1537 | }), | |
| 1538 | }, | |
| 1539 | .Union => { | |
| 1540 | if (!location.isInitializer()) { | |
| 1541 | try writer.writeByte('('); | |
| 1542 | try dg.renderType(writer, ty); | |
| 1543 | try writer.writeByte(')'); | |
| 1544 | } | |
| 1572 | .union_type => { | |
| 1573 | const loaded_union = ip.loadUnionType(ty.toIntern()); | |
| 1574 | switch (loaded_union.getLayout(ip)) { | |
| 1575 | .auto, .@"extern" => { | |
| 1576 | if (!location.isInitializer()) { | |
| 1577 | try writer.writeByte('('); | |
| 1578 | try dg.renderType(writer, ty); | |
| 1579 | try writer.writeByte(')'); | |
| 1580 | } | |
| 1545 | 1581 | |
| 1546 | try writer.writeByte('{'); | |
| 1547 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { | |
| 1548 | const layout = ty.unionGetLayout(zcu); | |
| 1549 | if (layout.tag_size != 0) { | |
| 1550 | try writer.writeAll(" .tag = "); | |
| 1551 | try dg.renderUndefValue(writer, tag_ty, initializer_type); | |
| 1582 | try writer.writeByte('{'); | |
| 1583 | if (ty.unionTagTypeSafety(zcu)) |tag_ty| { | |
| 1584 | const layout = ty.unionGetLayout(zcu); | |
| 1585 | if (layout.tag_size != 0) { | |
| 1586 | try writer.writeAll(" .tag = "); | |
| 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('}'); | |
| 1554 | if (layout.tag_size != 0) try writer.writeByte(','); | |
| 1555 | try writer.writeAll(" .payload = {"); | |
| 1556 | } | |
| 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 | } | |
| 1606 | }, | |
| 1607 | .error_union_type => { | |
| 1608 | const payload_ty = ty.errorUnionPayload(zcu); | |
| 1609 | const error_ty = ty.errorUnionSet(zcu); | |
| 1574 | 1610 | |
| 1575 | if (!location.isInitializer()) { | |
| 1576 | try writer.writeByte('('); | |
| 1577 | try dg.renderType(writer, ty); | |
| 1578 | try writer.writeByte(')'); | |
| 1579 | } | |
| 1611 | if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 1612 | return dg.renderUndefValue(writer, error_ty, location); | |
| 1613 | } | |
| 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 | 1615 | if (!location.isInitializer()) { |
| 1599 | 1616 | try writer.writeByte('('); |
| 1600 | 1617 | try dg.renderType(writer, ty); |
| 1601 | 1618 | try writer.writeByte(')'); |
| 1602 | 1619 | } |
| 1603 | 1620 | |
| 1604 | try writer.writeByte('{'); | |
| 1605 | const c_len = ty.arrayLenIncludingSentinel(zcu); | |
| 1606 | var index: u64 = 0; | |
| 1607 | while (index < c_len) : (index += 1) { | |
| 1608 | if (index > 0) try writer.writeAll(", "); | |
| 1609 | try dg.renderUndefValue(writer, ty.childType(zcu), initializer_type); | |
| 1621 | try writer.writeAll("{ .payload = "); | |
| 1622 | try dg.renderUndefValue(writer, payload_ty, initializer_type); | |
| 1623 | try writer.writeAll(", .error = "); | |
| 1624 | try dg.renderUndefValue(writer, error_ty, initializer_type); | |
| 1625 | return writer.writeAll(" }"); | |
| 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('}'); | |
| 1612 | } | |
| 1653 | }, | |
| 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 | 1689 | ident: []const u8, |
| 1642 | 1690 | }, |
| 1643 | 1691 | ) !void { |
| 1644 | const store = &dg.ctypes.set; | |
| 1645 | 1692 | const zcu = dg.zcu; |
| 1646 | 1693 | const ip = &zcu.intern_pool; |
| 1647 | 1694 | |
| 1648 | 1695 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 1649 | 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 | 1699 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1653 | 1700 | if (fn_info.cc == .Naked) { |
| ... | ... | @@ -1661,7 +1708,7 @@ pub const DeclGen = struct { |
| 1661 | 1708 | try w.writeAll("zig_cold "); |
| 1662 | 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 | 1713 | if (toCallingConvention(fn_info.cc)) |call_conv| { |
| 1667 | 1714 | try w.print("{}zig_callconv({s})", .{ trailing, call_conv }); |
| ... | ... | @@ -1670,7 +1717,7 @@ pub const DeclGen = struct { |
| 1670 | 1717 | |
| 1671 | 1718 | switch (kind) { |
| 1672 | 1719 | .forward => {}, |
| 1673 | .complete => if (fn_decl.alignment.toByteUnitsOptional()) |a| { | |
| 1720 | .complete => if (fn_decl.alignment.toByteUnits()) |a| { | |
| 1674 | 1721 | try w.print("{}zig_align_fn({})", .{ trailing, a }); |
| 1675 | 1722 | trailing = .maybe_space; |
| 1676 | 1723 | }, |
| ... | ... | @@ -1687,10 +1734,10 @@ pub const DeclGen = struct { |
| 1687 | 1734 | |
| 1688 | 1735 | try renderTypeSuffix( |
| 1689 | 1736 | dg.pass, |
| 1690 | store.*, | |
| 1737 | &dg.ctype_pool, | |
| 1691 | 1738 | zcu, |
| 1692 | 1739 | w, |
| 1693 | fn_cty_idx, | |
| 1740 | fn_ctype, | |
| 1694 | 1741 | .suffix, |
| 1695 | 1742 | CQualifiers.init(.{ .@"const" = switch (kind) { |
| 1696 | 1743 | .forward => false, |
| ... | ... | @@ -1701,7 +1748,7 @@ pub const DeclGen = struct { |
| 1701 | 1748 | |
| 1702 | 1749 | switch (kind) { |
| 1703 | 1750 | .forward => { |
| 1704 | if (fn_decl.alignment.toByteUnitsOptional()) |a| { | |
| 1751 | if (fn_decl.alignment.toByteUnits()) |a| { | |
| 1705 | 1752 | try w.print(" zig_align_fn({})", .{a}); |
| 1706 | 1753 | } |
| 1707 | 1754 | switch (name) { |
| ... | ... | @@ -1748,20 +1795,13 @@ pub const DeclGen = struct { |
| 1748 | 1795 | } |
| 1749 | 1796 | } |
| 1750 | 1797 | |
| 1751 | fn indexToCType(dg: *DeclGen, idx: CType.Index) CType { | |
| 1752 | return dg.ctypes.indexToCType(idx); | |
| 1798 | fn ctypeFromType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType { | |
| 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 { | |
| 1756 | return dg.ctypes.typeToIndex(dg.gpa, ty, dg.zcu, dg.mod, kind); | |
| 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); | |
| 1803 | fn byteSize(dg: *DeclGen, ctype: CType) u64 { | |
| 1804 | return ctype.byteSize(&dg.ctype_pool, dg.mod); | |
| 1765 | 1805 | } |
| 1766 | 1806 | |
| 1767 | 1807 | /// Renders a type as a single identifier, generating intermediate typedefs |
| ... | ... | @@ -1776,14 +1816,12 @@ pub const DeclGen = struct { |
| 1776 | 1816 | /// | `renderType` | "uint8_t *" | "uint8_t *[10]" | |
| 1777 | 1817 | /// |
| 1778 | 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 { | |
| 1783 | const store = &dg.ctypes.set; | |
| 1784 | const zcu = dg.zcu; | |
| 1785 | _ = try renderTypePrefix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); | |
| 1786 | try renderTypeSuffix(dg.pass, store.*, zcu, w, idx, .suffix, .{}); | |
| 1822 | fn renderCType(dg: *DeclGen, w: anytype, ctype: CType) error{ OutOfMemory, AnalysisFail }!void { | |
| 1823 | _ = try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); | |
| 1824 | try renderTypeSuffix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, .{}); | |
| 1787 | 1825 | } |
| 1788 | 1826 | |
| 1789 | 1827 | const IntCastContext = union(enum) { |
| ... | ... | @@ -1905,32 +1943,37 @@ pub const DeclGen = struct { |
| 1905 | 1943 | alignment: Alignment, |
| 1906 | 1944 | kind: CType.Kind, |
| 1907 | 1945 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1908 | const zcu = dg.zcu; | |
| 1909 | const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(zcu)); | |
| 1910 | try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas); | |
| 1946 | try dg.renderCTypeAndName( | |
| 1947 | w, | |
| 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 | 1958 | fn renderCTypeAndName( |
| 1914 | 1959 | dg: *DeclGen, |
| 1915 | 1960 | w: anytype, |
| 1916 | cty_idx: CType.Index, | |
| 1961 | ctype: CType, | |
| 1917 | 1962 | name: CValue, |
| 1918 | 1963 | qualifiers: CQualifiers, |
| 1919 | 1964 | alignas: CType.AlignAs, |
| 1920 | 1965 | ) error{ OutOfMemory, AnalysisFail }!void { |
| 1921 | const store = &dg.ctypes.set; | |
| 1922 | const zcu = dg.zcu; | |
| 1923 | ||
| 1924 | 1966 | switch (alignas.abiOrder()) { |
| 1925 | 1967 | .lt => try w.print("zig_under_align({}) ", .{alignas.toByteUnits()}), |
| 1926 | 1968 | .eq => {}, |
| 1927 | 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); | |
| 1931 | try w.print("{}", .{trailing}); | |
| 1972 | try w.print("{}", .{ | |
| 1973 | try renderTypePrefix(dg.pass, &dg.ctype_pool, dg.zcu, w, ctype, .suffix, qualifiers), | |
| 1974 | }); | |
| 1932 | 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 | 1979 | fn declIsGlobal(dg: *DeclGen, val: Value) bool { |
| ... | ... | @@ -2094,33 +2137,31 @@ pub const DeclGen = struct { |
| 2094 | 2137 | } |
| 2095 | 2138 | |
| 2096 | 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 { | |
| 2101 | switch (cty.tag()) { | |
| 2102 | else => try writer.print("{c}{d}", .{ | |
| 2103 | if (cty.isBool()) | |
| 2143 | fn renderCTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ctype: CType) !void { | |
| 2144 | switch (ctype.info(&dg.ctype_pool)) { | |
| 2145 | else => |ctype_info| try writer.print("{c}{d}", .{ | |
| 2146 | if (ctype.isBool()) | |
| 2104 | 2147 | signAbbrev(.unsigned) |
| 2105 | else if (cty.isInteger()) | |
| 2106 | signAbbrev(cty.signedness(dg.mod)) | |
| 2107 | else if (cty.isFloat()) | |
| 2148 | else if (ctype.isInteger()) | |
| 2149 | signAbbrev(ctype.signedness(dg.mod)) | |
| 2150 | else if (ctype.isFloat()) | |
| 2108 | 2151 | @as(u8, 'f') |
| 2109 | else if (cty.isPointer()) | |
| 2152 | else if (ctype_info == .pointer) | |
| 2110 | 2153 | @as(u8, 'p') |
| 2111 | 2154 | else |
| 2112 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{ | |
| 2113 | cty.tag(), | |
| 2114 | }), | |
| 2115 | if (cty.isFloat()) cty.floatActiveBits(dg.mod) else dg.byteSize(cty) * 8, | |
| 2155 | return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for {s} type", .{@tagName(ctype_info)}), | |
| 2156 | if (ctype.isFloat()) ctype.floatActiveBits(dg.mod) else dg.byteSize(ctype) * 8, | |
| 2116 | 2157 | }), |
| 2117 | 2158 | .array => try writer.writeAll("big"), |
| 2118 | 2159 | } |
| 2119 | 2160 | } |
| 2120 | 2161 | |
| 2121 | 2162 | fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void { |
| 2122 | const cty = try dg.typeToCType(ty, .complete); | |
| 2123 | const is_big = cty.tag() == .array; | |
| 2163 | const ctype = try dg.ctypeFromType(ty, .complete); | |
| 2164 | const is_big = ctype.info(&dg.ctype_pool) == .array; | |
| 2124 | 2165 | switch (info) { |
| 2125 | 2166 | .none => if (!is_big) return, |
| 2126 | 2167 | .bits => {}, |
| ... | ... | @@ -2155,7 +2196,7 @@ pub const DeclGen = struct { |
| 2155 | 2196 | .dg = dg, |
| 2156 | 2197 | .int_info = ty.intInfo(zcu), |
| 2157 | 2198 | .kind = kind, |
| 2158 | .cty = try dg.typeToCType(ty, kind), | |
| 2199 | .ctype = try dg.ctypeFromType(ty, kind), | |
| 2159 | 2200 | .val = val, |
| 2160 | 2201 | } }; |
| 2161 | 2202 | } |
| ... | ... | @@ -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 | 2232 | zcu: *Zcu, |
| 2189 | 2233 | w: anytype, |
| 2190 | idx: CType.Index, | |
| 2191 | cty: CType, | |
| 2234 | ctype: CType, | |
| 2235 | fwd_decl: CType.Info.FwdDecl, | |
| 2192 | 2236 | attributes: []const u8, |
| 2193 | 2237 | ) !void { |
| 2194 | switch (cty.tag()) { | |
| 2195 | else => unreachable, | |
| 2196 | ||
| 2197 | .fwd_anon_struct, | |
| 2198 | .fwd_anon_union, | |
| 2199 | => |tag| try w.print("{s} {s}anon__lazy_{d}", .{ | |
| 2200 | @tagName(tag)["fwd_anon_".len..], | |
| 2201 | attributes, | |
| 2202 | idx, | |
| 2238 | try w.print("{s} {s}", .{ @tagName(fwd_decl.tag), attributes }); | |
| 2239 | switch (fwd_decl.name) { | |
| 2240 | .anon => try w.print("anon__lazy_{d}", .{@intFromEnum(ctype.index)}), | |
| 2241 | .owner_decl => |owner_decl| try w.print("{}__{d}", .{ | |
| 2242 | fmtIdent(zcu.intern_pool.stringToSlice(zcu.declPtr(owner_decl).name)), | |
| 2243 | @intFromEnum(owner_decl), | |
| 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 | 2247 | fn renderTypePrefix( |
| 2219 | 2248 | pass: DeclGen.Pass, |
| 2220 | store: CType.Store.Set, | |
| 2249 | ctype_pool: *const CType.Pool, | |
| 2221 | 2250 | zcu: *Zcu, |
| 2222 | 2251 | w: anytype, |
| 2223 | idx: CType.Index, | |
| 2252 | ctype: CType, | |
| 2224 | 2253 | parent_fix: CTypeFix, |
| 2225 | 2254 | qualifiers: CQualifiers, |
| 2226 | 2255 | ) @TypeOf(w).Error!RenderCTypeTrailing { |
| 2227 | 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); | |
| 2230 | switch (cty.tag()) { | |
| 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( | |
| 2260 | .pointer => |pointer_info| { | |
| 2261 | try w.print("{}*", .{try renderTypePrefix( | |
| 2277 | 2262 | pass, |
| 2278 | store, | |
| 2263 | ctype_pool, | |
| 2279 | 2264 | zcu, |
| 2280 | 2265 | w, |
| 2281 | child_idx, | |
| 2266 | pointer_info.elem_ctype, | |
| 2282 | 2267 | .prefix, |
| 2283 | CQualifiers.init(.{ .@"const" = switch (tag) { | |
| 2284 | .pointer, .pointer_volatile => false, | |
| 2285 | .pointer_const, .pointer_const_volatile => true, | |
| 2286 | else => unreachable, | |
| 2287 | }, .@"volatile" = switch (tag) { | |
| 2288 | .pointer, .pointer_const => false, | |
| 2289 | .pointer_volatile, .pointer_const_volatile => true, | |
| 2290 | else => unreachable, | |
| 2291 | } }), | |
| 2292 | ); | |
| 2293 | try w.print("{}*", .{child_trailing}); | |
| 2268 | CQualifiers.init(.{ | |
| 2269 | .@"const" = pointer_info.@"const", | |
| 2270 | .@"volatile" = pointer_info.@"volatile", | |
| 2271 | }), | |
| 2272 | )}); | |
| 2294 | 2273 | trailing = .no_space; |
| 2295 | 2274 | }, |
| 2296 | 2275 | |
| 2297 | .array, | |
| 2298 | .vector, | |
| 2299 | => { | |
| 2300 | const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type; | |
| 2301 | const child_trailing = | |
| 2302 | try renderTypePrefix(pass, store, zcu, w, child_idx, .suffix, qualifiers); | |
| 2276 | .aligned => switch (pass) { | |
| 2277 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ | |
| 2278 | @intFromEnum(decl_index), @intFromEnum(ctype.index), | |
| 2279 | }), | |
| 2280 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ | |
| 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 | 2296 | switch (parent_fix) { |
| 2304 | 2297 | .prefix => { |
| 2305 | 2298 | try w.print("{}(", .{child_trailing}); |
| ... | ... | @@ -2309,56 +2302,46 @@ fn renderTypePrefix( |
| 2309 | 2302 | } |
| 2310 | 2303 | }, |
| 2311 | 2304 | |
| 2312 | .fwd_anon_struct, | |
| 2313 | .fwd_anon_union, | |
| 2314 | => switch (pass) { | |
| 2315 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }), | |
| 2316 | .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }), | |
| 2317 | .flush => try renderTypeName(zcu, w, idx, cty, ""), | |
| 2305 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 2306 | .anon => switch (pass) { | |
| 2307 | .decl => |decl_index| try w.print("decl__{d}_{d}", .{ | |
| 2308 | @intFromEnum(decl_index), @intFromEnum(ctype.index), | |
| 2309 | }), | |
| 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, | |
| 2321 | .fwd_union, | |
| 2322 | => try renderTypeName(zcu, w, idx, cty, ""), | |
| 2323 | ||
| 2324 | .unnamed_struct, | |
| 2325 | .unnamed_union, | |
| 2326 | .packed_unnamed_struct, | |
| 2327 | .packed_unnamed_union, | |
| 2328 | => |tag| { | |
| 2329 | try w.print("{s} {s}", .{ | |
| 2330 | @tagName(tag)["unnamed_".len..], | |
| 2331 | if (cty.isPacked()) "zig_packed(" else "", | |
| 2332 | }); | |
| 2333 | try renderAggregateFields(zcu, w, store, cty, 1); | |
| 2334 | if (cty.isPacked()) try w.writeByte(')'); | |
| 2318 | .aggregate => |aggregate_info| switch (aggregate_info.name) { | |
| 2319 | .anon => { | |
| 2320 | try w.print("{s} {s}", .{ | |
| 2321 | @tagName(aggregate_info.tag), | |
| 2322 | if (aggregate_info.@"packed") "zig_packed(" else "", | |
| 2323 | }); | |
| 2324 | try renderFields(zcu, w, ctype_pool, aggregate_info, 1); | |
| 2325 | if (aggregate_info.@"packed") try w.writeByte(')'); | |
| 2326 | }, | |
| 2327 | .fwd_decl => |fwd_decl| return renderTypePrefix( | |
| 2328 | pass, | |
| 2329 | ctype_pool, | |
| 2330 | zcu, | |
| 2331 | w, | |
| 2332 | fwd_decl, | |
| 2333 | parent_fix, | |
| 2334 | qualifiers, | |
| 2335 | ), | |
| 2335 | 2336 | }, |
| 2336 | 2337 | |
| 2337 | .anon_struct, | |
| 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 | => { | |
| 2338 | .function => |function_info| { | |
| 2356 | 2339 | const child_trailing = try renderTypePrefix( |
| 2357 | 2340 | pass, |
| 2358 | store, | |
| 2341 | ctype_pool, | |
| 2359 | 2342 | zcu, |
| 2360 | 2343 | w, |
| 2361 | cty.cast(CType.Payload.Function).?.data.return_type, | |
| 2344 | function_info.return_ctype, | |
| 2362 | 2345 | .suffix, |
| 2363 | 2346 | .{}, |
| 2364 | 2347 | ); |
| ... | ... | @@ -2371,170 +2354,107 @@ fn renderTypePrefix( |
| 2371 | 2354 | } |
| 2372 | 2355 | }, |
| 2373 | 2356 | } |
| 2374 | ||
| 2375 | 2357 | var qualifier_it = qualifiers.iterator(); |
| 2376 | 2358 | while (qualifier_it.next()) |qualifier| { |
| 2377 | 2359 | try w.print("{}{s}", .{ trailing, @tagName(qualifier) }); |
| 2378 | 2360 | trailing = .maybe_space; |
| 2379 | 2361 | } |
| 2380 | ||
| 2381 | 2362 | return trailing; |
| 2382 | 2363 | } |
| 2383 | 2364 | fn renderTypeSuffix( |
| 2384 | 2365 | pass: DeclGen.Pass, |
| 2385 | store: CType.Store.Set, | |
| 2366 | ctype_pool: *const CType.Pool, | |
| 2386 | 2367 | zcu: *Zcu, |
| 2387 | 2368 | w: anytype, |
| 2388 | idx: CType.Index, | |
| 2369 | ctype: CType, | |
| 2389 | 2370 | parent_fix: CTypeFix, |
| 2390 | 2371 | qualifiers: CQualifiers, |
| 2391 | 2372 | ) @TypeOf(w).Error!void { |
| 2392 | const cty = store.indexToCType(idx); | |
| 2393 | switch (cty.tag()) { | |
| 2394 | .void, | |
| 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( | |
| 2373 | switch (ctype.info(ctype_pool)) { | |
| 2374 | .basic, .aligned, .fwd_decl, .aggregate => {}, | |
| 2375 | .pointer => |pointer_info| try renderTypeSuffix( | |
| 2438 | 2376 | pass, |
| 2439 | store, | |
| 2377 | ctype_pool, | |
| 2440 | 2378 | zcu, |
| 2441 | 2379 | w, |
| 2442 | cty.cast(CType.Payload.Child).?.data, | |
| 2380 | pointer_info.elem_ctype, | |
| 2443 | 2381 | .prefix, |
| 2444 | 2382 | .{}, |
| 2445 | 2383 | ), |
| 2446 | ||
| 2447 | .array, | |
| 2448 | .vector, | |
| 2449 | => { | |
| 2384 | .array, .vector => |sequence_info| { | |
| 2450 | 2385 | switch (parent_fix) { |
| 2451 | 2386 | .prefix => try w.writeByte(')'), |
| 2452 | 2387 | .suffix => {}, |
| 2453 | 2388 | } |
| 2454 | 2389 | |
| 2455 | try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len}); | |
| 2456 | try renderTypeSuffix( | |
| 2457 | pass, | |
| 2458 | store, | |
| 2459 | zcu, | |
| 2460 | w, | |
| 2461 | cty.cast(CType.Payload.Sequence).?.data.elem_type, | |
| 2462 | .suffix, | |
| 2463 | .{}, | |
| 2464 | ); | |
| 2390 | try w.print("[{}]", .{sequence_info.len}); | |
| 2391 | try renderTypeSuffix(pass, ctype_pool, zcu, w, sequence_info.elem_ctype, .suffix, .{}); | |
| 2465 | 2392 | }, |
| 2466 | ||
| 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| { | |
| 2393 | .function => |function_info| { | |
| 2486 | 2394 | switch (parent_fix) { |
| 2487 | 2395 | .prefix => try w.writeByte(')'), |
| 2488 | 2396 | .suffix => {}, |
| 2489 | 2397 | } |
| 2490 | 2398 | |
| 2491 | const data = cty.cast(CType.Payload.Function).?.data; | |
| 2492 | ||
| 2493 | 2399 | try w.writeByte('('); |
| 2494 | 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 | 2403 | if (need_comma) try w.writeAll(", "); |
| 2497 | 2404 | need_comma = true; |
| 2498 | 2405 | const trailing = |
| 2499 | try renderTypePrefix(pass, store, zcu, w, param_type, .suffix, qualifiers); | |
| 2500 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i }); | |
| 2501 | try renderTypeSuffix(pass, store, zcu, w, param_type, .suffix, .{}); | |
| 2406 | try renderTypePrefix(pass, ctype_pool, zcu, w, param_type, .suffix, qualifiers); | |
| 2407 | if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_index }); | |
| 2408 | try renderTypeSuffix(pass, ctype_pool, zcu, w, param_type, .suffix, .{}); | |
| 2502 | 2409 | } |
| 2503 | switch (tag) { | |
| 2504 | .function => {}, | |
| 2505 | .varargs_function => { | |
| 2506 | if (need_comma) try w.writeAll(", "); | |
| 2507 | need_comma = true; | |
| 2508 | try w.writeAll("..."); | |
| 2509 | }, | |
| 2510 | else => unreachable, | |
| 2410 | if (function_info.varargs) { | |
| 2411 | if (need_comma) try w.writeAll(", "); | |
| 2412 | need_comma = true; | |
| 2413 | try w.writeAll("..."); | |
| 2511 | 2414 | } |
| 2512 | 2415 | if (!need_comma) try w.writeAll("void"); |
| 2513 | 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 | 2423 | zcu: *Zcu, |
| 2521 | 2424 | writer: anytype, |
| 2522 | store: CType.Store.Set, | |
| 2523 | cty: CType, | |
| 2425 | ctype_pool: *const CType.Pool, | |
| 2426 | aggregate_info: CType.Info.Aggregate, | |
| 2524 | 2427 | indent: usize, |
| 2525 | 2428 | ) !void { |
| 2526 | 2429 | try writer.writeAll("{\n"); |
| 2527 | const fields = cty.fields(); | |
| 2528 | for (fields) |field| { | |
| 2430 | for (0..aggregate_info.fields.len) |field_index| { | |
| 2431 | const field_info = aggregate_info.fields.at(field_index, ctype_pool); | |
| 2529 | 2432 | try writer.writeByteNTimes(' ', indent + 1); |
| 2530 | switch (field.alignas.abiOrder()) { | |
| 2531 | .lt => try writer.print("zig_under_align({}) ", .{field.alignas.toByteUnits()}), | |
| 2532 | .eq => {}, | |
| 2533 | .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}), | |
| 2433 | switch (field_info.alignas.abiOrder()) { | |
| 2434 | .lt => { | |
| 2435 | std.debug.assert(aggregate_info.@"packed"); | |
| 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, .{}); | |
| 2536 | try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) }); | |
| 2537 | try renderTypeSuffix(.flush, store, zcu, writer, field.type, .suffix, .{}); | |
| 2447 | const trailing = try renderTypePrefix( | |
| 2448 | .flush, | |
| 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 | 2458 | try writer.writeAll(";\n"); |
| 2539 | 2459 | } |
| 2540 | 2460 | try writer.writeByteNTimes(' ', indent); |
| ... | ... | @@ -2544,77 +2464,77 @@ fn renderAggregateFields( |
| 2544 | 2464 | pub fn genTypeDecl( |
| 2545 | 2465 | zcu: *Zcu, |
| 2546 | 2466 | writer: anytype, |
| 2547 | global_store: CType.Store.Set, | |
| 2548 | global_idx: CType.Index, | |
| 2467 | global_ctype_pool: *const CType.Pool, | |
| 2468 | global_ctype: CType, | |
| 2549 | 2469 | pass: DeclGen.Pass, |
| 2550 | decl_store: CType.Store.Set, | |
| 2551 | decl_idx: CType.Index, | |
| 2470 | decl_ctype_pool: *const CType.Pool, | |
| 2471 | decl_ctype: CType, | |
| 2552 | 2472 | found_existing: bool, |
| 2553 | 2473 | ) !void { |
| 2554 | const global_cty = global_store.indexToCType(global_idx); | |
| 2555 | switch (global_cty.tag()) { | |
| 2556 | .fwd_anon_struct => if (pass != .flush) { | |
| 2557 | try writer.writeAll("typedef "); | |
| 2558 | _ = try renderTypePrefix(.flush, global_store, zcu, writer, global_idx, .suffix, .{}); | |
| 2559 | try writer.writeByte(' '); | |
| 2560 | _ = try renderTypePrefix(pass, decl_store, zcu, writer, decl_idx, .suffix, .{}); | |
| 2561 | try writer.writeAll(";\n"); | |
| 2562 | }, | |
| 2563 | ||
| 2564 | .fwd_struct, | |
| 2565 | .fwd_union, | |
| 2566 | .anon_struct, | |
| 2567 | .anon_union, | |
| 2568 | .@"struct", | |
| 2569 | .@"union", | |
| 2570 | .packed_struct, | |
| 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 | ); | |
| 2474 | switch (global_ctype.info(global_ctype_pool)) { | |
| 2475 | .basic, .pointer, .array, .vector, .function => {}, | |
| 2476 | .aligned => |aligned_info| { | |
| 2477 | if (!found_existing) { | |
| 2478 | try writer.writeAll("typedef "); | |
| 2479 | try writer.print("{}", .{ | |
| 2480 | try renderTypePrefix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}), | |
| 2481 | }); | |
| 2482 | try renderAlignedTypeName(writer, global_ctype); | |
| 2483 | try renderTypeSuffix(pass, global_ctype_pool, zcu, writer, aligned_info.ctype, .suffix, .{}); | |
| 2484 | std.debug.assert(aligned_info.alignas.abiOrder().compare(.lt)); | |
| 2485 | try writer.print(" zig_under_align({d});\n", .{aligned_info.alignas.toByteUnits()}); | |
| 2486 | } | |
| 2487 | switch (pass) { | |
| 2488 | .decl, .anon => { | |
| 2489 | try writer.writeAll("typedef "); | |
| 2490 | _ = try renderTypePrefix(.flush, global_ctype_pool, zcu, writer, global_ctype, .suffix, .{}); | |
| 2607 | 2491 | try writer.writeByte(' '); |
| 2608 | try renderAggregateFields(zcu, writer, global_store, global_cty, 0); | |
| 2609 | if (global_cty.isPacked()) try writer.writeByte(')'); | |
| 2492 | _ = try renderTypePrefix(pass, decl_ctype_pool, zcu, writer, decl_ctype, .suffix, .{}); | |
| 2610 | 2493 | try writer.writeAll(";\n"); |
| 2611 | 2494 | }, |
| 2612 | ||
| 2613 | else => unreachable, | |
| 2495 | .flush => {}, | |
| 2614 | 2496 | } |
| 2615 | 2497 | }, |
| 2616 | ||
| 2617 | else => {}, | |
| 2498 | .fwd_decl => |fwd_decl_info| switch (fwd_decl_info.name) { | |
| 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 | 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 | 2695 | const zcu = o.dg.zcu; |
| 2776 | 2696 | const ip = &zcu.intern_pool; |
| 2697 | const ctype_pool = &o.dg.ctype_pool; | |
| 2777 | 2698 | const w = o.writer(); |
| 2778 | 2699 | const key = lazy_fn.key_ptr.*; |
| 2779 | 2700 | const val = lazy_fn.value_ptr; |
| 2780 | const fn_name = val.fn_name; | |
| 2781 | 2701 | switch (key) { |
| 2782 | 2702 | .tag_name => { |
| 2783 | 2703 | const enum_ty = val.data.tag_name; |
| ... | ... | @@ -2787,7 +2707,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2787 | 2707 | try w.writeAll("static "); |
| 2788 | 2708 | try o.dg.renderType(w, name_slice_ty); |
| 2789 | 2709 | try w.writeByte(' '); |
| 2790 | try w.writeAll(fn_name); | |
| 2710 | try w.writeAll(val.fn_name.slice(lazy_ctype_pool)); | |
| 2791 | 2711 | try w.writeByte('('); |
| 2792 | 2712 | try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, .none, .complete); |
| 2793 | 2713 | try w.writeAll(") {\n switch (tag) {\n"); |
| ... | ... | @@ -2829,8 +2749,9 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2829 | 2749 | }, |
| 2830 | 2750 | .never_tail, .never_inline => |fn_decl_index| { |
| 2831 | 2751 | const fn_decl = zcu.declPtr(fn_decl_index); |
| 2832 | const fn_cty = try o.dg.typeToCType(fn_decl.typeOf(zcu), .complete); | |
| 2833 | const fn_info = fn_cty.cast(CType.Payload.Function).?.data; | |
| 2752 | const fn_ctype = try o.dg.ctypeFromType(fn_decl.typeOf(zcu), .complete); | |
| 2753 | const fn_info = fn_ctype.info(ctype_pool).function; | |
| 2754 | const fn_name = val.fn_name.slice(lazy_ctype_pool); | |
| 2834 | 2755 | |
| 2835 | 2756 | const fwd_decl_writer = o.dg.fwdDeclWriter(); |
| 2836 | 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 | 2764 | try fwd_decl_writer.writeAll(";\n"); |
| 2844 | 2765 | |
| 2845 | 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 | 2770 | try w.writeAll(" {\n return "); |
| 2848 | 2771 | try o.dg.renderDeclName(w, fn_decl_index, 0); |
| 2849 | 2772 | try w.writeByte('('); |
| 2850 | for (0..fn_info.param_types.len) |arg| { | |
| 2773 | for (0..fn_info.param_ctypes.len) |arg| { | |
| 2851 | 2774 | if (arg > 0) try w.writeAll(", "); |
| 2852 | 2775 | try o.dg.writeCValue(w, .{ .arg = arg }); |
| 2853 | 2776 | } |
| ... | ... | @@ -2931,7 +2854,7 @@ pub fn genFunc(f: *Function) !void { |
| 2931 | 2854 | for (free_locals.values()) |list| { |
| 2932 | 2855 | for (list.keys()) |local_index| { |
| 2933 | 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 | 2858 | try w.writeAll(";\n "); |
| 2936 | 2859 | } |
| 2937 | 2860 | } |
| ... | ... | @@ -3451,11 +3374,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3451 | 3374 | |
| 3452 | 3375 | const inst_ty = f.typeOfIndex(inst); |
| 3453 | 3376 | const ptr_ty = f.typeOf(bin_op.lhs); |
| 3454 | const ptr_align = ptr_ty.ptrAlignment(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); | |
| 3377 | const elem_has_bits = ptr_ty.elemType2(zcu).hasRuntimeBitsIgnoreComptime(zcu); | |
| 3459 | 3378 | |
| 3460 | 3379 | const ptr = try f.resolveInst(bin_op.lhs); |
| 3461 | 3380 | const index = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -3470,22 +3389,13 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3470 | 3389 | try f.renderType(writer, inst_ty); |
| 3471 | 3390 | try writer.writeByte(')'); |
| 3472 | 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 | 3393 | // It's a pointer to an array, so we need to de-reference. |
| 3475 | 3394 | try f.writeCValueDeref(writer, ptr); |
| 3476 | 3395 | } else try f.writeCValue(writer, ptr, .Other); |
| 3477 | 3396 | if (elem_has_bits) { |
| 3478 | 3397 | try writer.writeByte('['); |
| 3479 | 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 | 3399 | try writer.writeByte(']'); |
| 3490 | 3400 | } |
| 3491 | 3401 | try a.end(f, writer); |
| ... | ... | @@ -3577,13 +3487,16 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3577 | 3487 | fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3578 | 3488 | const zcu = f.object.dg.zcu; |
| 3579 | 3489 | const inst_ty = f.typeOfIndex(inst); |
| 3580 | const elem_type = inst_ty.childType(zcu); | |
| 3581 | if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | |
| 3490 | const elem_ty = inst_ty.childType(zcu); | |
| 3491 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; | |
| 3582 | 3492 | |
| 3583 | const local = try f.allocLocalValue( | |
| 3584 | elem_type, | |
| 3585 | inst_ty.ptrAlignment(zcu), | |
| 3586 | ); | |
| 3493 | const local = try f.allocLocalValue(.{ | |
| 3494 | .ctype = try f.ctypeFromType(elem_ty, .complete), | |
| 3495 | .alignas = CType.AlignAs.fromAlignment(.{ | |
| 3496 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3497 | .abi = elem_ty.abiAlignment(zcu), | |
| 3498 | }), | |
| 3499 | }); | |
| 3587 | 3500 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3588 | 3501 | const gpa = f.object.dg.zcu.gpa; |
| 3589 | 3502 | try f.allocs.put(gpa, local.new_local, true); |
| ... | ... | @@ -3596,10 +3509,13 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3596 | 3509 | const elem_ty = inst_ty.childType(zcu); |
| 3597 | 3510 | if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(zcu)) return .{ .undef = inst_ty }; |
| 3598 | 3511 | |
| 3599 | const local = try f.allocLocalValue( | |
| 3600 | elem_ty, | |
| 3601 | inst_ty.ptrAlignment(zcu), | |
| 3602 | ); | |
| 3512 | const local = try f.allocLocalValue(.{ | |
| 3513 | .ctype = try f.ctypeFromType(elem_ty, .complete), | |
| 3514 | .alignas = CType.AlignAs.fromAlignment(.{ | |
| 3515 | .@"align" = inst_ty.ptrInfo(zcu).flags.alignment, | |
| 3516 | .abi = elem_ty.abiAlignment(zcu), | |
| 3517 | }), | |
| 3518 | }); | |
| 3603 | 3519 | log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local }); |
| 3604 | 3520 | const gpa = f.object.dg.zcu.gpa; |
| 3605 | 3521 | try f.allocs.put(gpa, local.new_local, true); |
| ... | ... | @@ -3608,14 +3524,14 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3608 | 3524 | |
| 3609 | 3525 | fn airArg(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3610 | 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 | 3529 | const i = f.next_arg_index; |
| 3614 | 3530 | f.next_arg_index += 1; |
| 3615 | const result: CValue = if (inst_cty != try f.typeToIndex(inst_ty, .complete)) | |
| 3616 | .{ .arg_array = i } | |
| 3531 | const result: CValue = if (inst_ctype.eql(try f.ctypeFromType(inst_ty, .complete))) | |
| 3532 | .{ .arg = i } | |
| 3617 | 3533 | else |
| 3618 | .{ .arg = i }; | |
| 3534 | .{ .arg_array = i }; | |
| 3619 | 3535 | |
| 3620 | 3536 | if (f.liveness.isUnused(inst)) { |
| 3621 | 3537 | const writer = f.object.writer(); |
| ... | ... | @@ -3649,7 +3565,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3649 | 3565 | try reap(f, inst, &.{ty_op.operand}); |
| 3650 | 3566 | |
| 3651 | 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 | 3569 | else |
| 3654 | 3570 | true; |
| 3655 | 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 | 3640 | const op_inst = un_op.toIndex(); |
| 3725 | 3641 | const op_ty = f.typeOf(un_op); |
| 3726 | 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 | 3645 | if (op_inst != null and f.air.instructions.items(.tag)[@intFromEnum(op_inst.?)] == .call_always_tail) { |
| 3730 | 3646 | try reap(f, inst, &.{un_op}); |
| 3731 | 3647 | _ = try airCall(f, op_inst.?, .always_tail); |
| 3732 | } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 3648 | } else if (ret_ctype.index != .void) { | |
| 3733 | 3649 | const operand = try f.resolveInst(un_op); |
| 3734 | 3650 | try reap(f, inst, &.{un_op}); |
| 3735 | 3651 | var deref = is_ptr; |
| 3736 | 3652 | const is_array = lowersToArray(ret_ty, zcu); |
| 3737 | 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 | 3658 | try writer.writeAll("memcpy("); |
| 3740 | 3659 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 3741 | 3660 | try writer.writeAll(", "); |
| ... | ... | @@ -3921,7 +3840,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue { |
| 3921 | 3840 | } |
| 3922 | 3841 | |
| 3923 | 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 | 3844 | else |
| 3926 | 3845 | true; |
| 3927 | 3846 | const is_array = lowersToArray(Type.fromInterned(ptr_info.child), zcu); |
| ... | ... | @@ -4397,22 +4316,23 @@ fn airCall( |
| 4397 | 4316 | defer gpa.free(resolved_args); |
| 4398 | 4317 | for (resolved_args, args) |*resolved_arg, arg| { |
| 4399 | 4318 | const arg_ty = f.typeOf(arg); |
| 4400 | const arg_cty = try f.typeToIndex(arg_ty, .parameter); | |
| 4401 | if (f.indexToCType(arg_cty).tag() == .void) { | |
| 4319 | const arg_ctype = try f.ctypeFromType(arg_ty, .parameter); | |
| 4320 | if (arg_ctype.index == .void) { | |
| 4402 | 4321 | resolved_arg.* = .none; |
| 4403 | 4322 | continue; |
| 4404 | 4323 | } |
| 4405 | 4324 | resolved_arg.* = try f.resolveInst(arg); |
| 4406 | if (arg_cty != try f.typeToIndex(arg_ty, .complete)) { | |
| 4407 | const lowered_arg_ty = try lowerFnRetTy(arg_ty, zcu); | |
| 4408 | ||
| 4409 | const array_local = try f.allocLocal(inst, lowered_arg_ty); | |
| 4325 | if (!arg_ctype.eql(try f.ctypeFromType(arg_ty, .complete))) { | |
| 4326 | const array_local = try f.allocAlignedLocal(inst, .{ | |
| 4327 | .ctype = arg_ctype, | |
| 4328 | .alignas = CType.AlignAs.fromAbiAlignment(arg_ty.abiAlignment(zcu)), | |
| 4329 | }); | |
| 4410 | 4330 | try writer.writeAll("memcpy("); |
| 4411 | 4331 | try f.writeCValueMember(writer, array_local, .{ .identifier = "array" }); |
| 4412 | 4332 | try writer.writeAll(", "); |
| 4413 | 4333 | try f.writeCValue(writer, resolved_arg.*, .FunctionArgument); |
| 4414 | 4334 | try writer.writeAll(", sizeof("); |
| 4415 | try f.renderType(writer, lowered_arg_ty); | |
| 4335 | try f.renderCType(writer, arg_ctype); | |
| 4416 | 4336 | try writer.writeAll("));\n"); |
| 4417 | 4337 | resolved_arg.* = array_local; |
| 4418 | 4338 | } |
| ... | ... | @@ -4433,21 +4353,27 @@ fn airCall( |
| 4433 | 4353 | else => unreachable, |
| 4434 | 4354 | }).?; |
| 4435 | 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 | 4361 | const result_local = result: { |
| 4439 | 4362 | if (modifier == .always_tail) { |
| 4440 | 4363 | try writer.writeAll("zig_always_tail return "); |
| 4441 | 4364 | break :result .none; |
| 4442 | } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { | |
| 4365 | } else if (ret_ctype.index == .void) { | |
| 4443 | 4366 | break :result .none; |
| 4444 | 4367 | } else if (f.liveness.isUnused(inst)) { |
| 4445 | 4368 | try writer.writeByte('('); |
| 4446 | try f.renderType(writer, Type.void); | |
| 4369 | try f.renderCType(writer, .{ .index = .void }); | |
| 4447 | 4370 | try writer.writeByte(')'); |
| 4448 | 4371 | break :result .none; |
| 4449 | 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 | 4377 | try f.writeCValue(writer, local, .Other); |
| 4452 | 4378 | try writer.writeAll(" = "); |
| 4453 | 4379 | break :result local; |
| ... | ... | @@ -4767,6 +4693,7 @@ const LocalResult = struct { |
| 4767 | 4693 | fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult { |
| 4768 | 4694 | const zcu = f.object.dg.zcu; |
| 4769 | 4695 | const target = &f.object.dg.mod.resolved_target.result; |
| 4696 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 4770 | 4697 | const writer = f.object.writer(); |
| 4771 | 4698 | |
| 4772 | 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 | 4752 | |
| 4826 | 4753 | // Ensure padding bits have the expected value. |
| 4827 | 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 | 4756 | const dest_info = dest_ty.intInfo(zcu); |
| 4830 | 4757 | var bits: u16 = dest_info.bits; |
| 4831 | var wrap_cty: ?CType = null; | |
| 4758 | var wrap_ctype: ?CType = null; | |
| 4832 | 4759 | var need_bitcasts = false; |
| 4833 | 4760 | |
| 4834 | 4761 | try f.writeCValue(writer, local, .Other); |
| 4835 | if (dest_cty.castTag(.array)) |pl| { | |
| 4836 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | |
| 4837 | .little => pl.data.len - 1, | |
| 4838 | .big => 0, | |
| 4839 | }}); | |
| 4840 | const elem_cty = f.indexToCType(pl.data.elem_type); | |
| 4841 | wrap_cty = elem_cty.toSignedness(dest_info.signedness); | |
| 4842 | need_bitcasts = wrap_cty.?.tag() == .zig_i128; | |
| 4843 | bits -= 1; | |
| 4844 | bits %= @as(u16, @intCast(f.byteSize(elem_cty) * 8)); | |
| 4845 | bits += 1; | |
| 4762 | switch (dest_ctype.info(ctype_pool)) { | |
| 4763 | else => {}, | |
| 4764 | .array => |array_info| { | |
| 4765 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | |
| 4766 | .little => array_info.len - 1, | |
| 4767 | .big => 0, | |
| 4768 | }}); | |
| 4769 | wrap_ctype = array_info.elem_ctype.toSignedness(dest_info.signedness); | |
| 4770 | need_bitcasts = wrap_ctype.?.index == .zig_i128; | |
| 4771 | bits -= 1; | |
| 4772 | bits %= @as(u16, @intCast(f.byteSize(array_info.elem_ctype) * 8)); | |
| 4773 | bits += 1; | |
| 4774 | }, | |
| 4846 | 4775 | } |
| 4847 | 4776 | try writer.writeAll(" = "); |
| 4848 | 4777 | if (need_bitcasts) { |
| 4849 | 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 | 4780 | try writer.writeByte('('); |
| 4852 | 4781 | } |
| 4853 | 4782 | try writer.writeAll("zig_wrap_"); |
| 4854 | 4783 | const info_ty = try zcu.intType(dest_info.signedness, bits); |
| 4855 | if (wrap_cty) |cty| | |
| 4856 | try f.object.dg.renderCTypeForBuiltinFnName(writer, cty) | |
| 4784 | if (wrap_ctype) |ctype| | |
| 4785 | try f.object.dg.renderCTypeForBuiltinFnName(writer, ctype) | |
| 4857 | 4786 | else |
| 4858 | 4787 | try f.object.dg.renderTypeForBuiltinFnName(writer, info_ty); |
| 4859 | 4788 | try writer.writeByte('('); |
| 4860 | 4789 | if (need_bitcasts) { |
| 4861 | 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 | 4792 | try writer.writeByte('('); |
| 4864 | 4793 | } |
| 4865 | 4794 | try f.writeCValue(writer, local, .Other); |
| 4866 | if (dest_cty.castTag(.array)) |pl| { | |
| 4867 | try writer.print("[{d}]", .{switch (target.cpu.arch.endian()) { | |
| 4868 | .little => pl.data.len - 1, | |
| 4869 | .big => 0, | |
| 4870 | }}); | |
| 4795 | switch (dest_ctype.info(ctype_pool)) { | |
| 4796 | else => {}, | |
| 4797 | .array => |array_info| try writer.print("[{d}]", .{ | |
| 4798 | switch (target.cpu.arch.endian()) { | |
| 4799 | .little => array_info.len - 1, | |
| 4800 | .big => 0, | |
| 4801 | }, | |
| 4802 | }), | |
| 4871 | 4803 | } |
| 4872 | 4804 | if (need_bitcasts) try writer.writeByte(')'); |
| 4873 | 4805 | try f.object.dg.renderBuiltinInfo(writer, info_ty, .bits); |
| ... | ... | @@ -5131,10 +5063,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5131 | 5063 | if (is_reg) { |
| 5132 | 5064 | const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(zcu); |
| 5133 | 5065 | try writer.writeAll("register "); |
| 5134 | const alignment: Alignment = .none; | |
| 5135 | const local_value = try f.allocLocalValue(output_ty, alignment); | |
| 5066 | const local_value = try f.allocLocal(inst, output_ty); | |
| 5136 | 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 | 5069 | try writer.writeAll(" __asm(\""); |
| 5139 | 5070 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| 5140 | 5071 | try writer.writeAll("\")"); |
| ... | ... | @@ -5164,10 +5095,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5164 | 5095 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 5165 | 5096 | const input_ty = f.typeOf(input); |
| 5166 | 5097 | if (is_reg) try writer.writeAll("register "); |
| 5167 | const alignment: Alignment = .none; | |
| 5168 | const local_value = try f.allocLocalValue(input_ty, alignment); | |
| 5098 | const local_value = try f.allocLocal(inst, input_ty); | |
| 5169 | 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 | 5101 | if (is_reg) { |
| 5172 | 5102 | try writer.writeAll(" __asm(\""); |
| 5173 | 5103 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | ... | @@ -5512,59 +5442,74 @@ fn fieldLocation( |
| 5512 | 5442 | end: void, |
| 5513 | 5443 | } { |
| 5514 | 5444 | const ip = &zcu.intern_pool; |
| 5515 | const container_ty = container_ptr_ty.childType(zcu); | |
| 5516 | return switch (container_ty.zigTypeTag(zcu)) { | |
| 5517 | .Struct => blk: { | |
| 5518 | if (zcu.typeToPackedStruct(container_ty)) |struct_type| { | |
| 5519 | if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) | |
| 5520 | break :blk .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(struct_type, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } | |
| 5445 | const container_ty = Type.fromInterned(ip.indexToKey(container_ptr_ty.toIntern()).ptr_type.child); | |
| 5446 | switch (ip.indexToKey(container_ty.toIntern())) { | |
| 5447 | .struct_type => { | |
| 5448 | const loaded_struct = ip.loadStructType(container_ty.toIntern()); | |
| 5449 | switch (loaded_struct.layout) { | |
| 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 | 5468 | else |
| 5522 | break :blk .begin; | |
| 5469 | .begin, | |
| 5523 | 5470 | } |
| 5524 | ||
| 5525 | for (field_index..container_ty.structFieldCount(zcu)) |next_field_index_usize| { | |
| 5526 | const next_field_index: u32 = @intCast(next_field_index_usize); | |
| 5527 | if (container_ty.structFieldIsComptime(next_field_index, zcu)) continue; | |
| 5528 | const field_ty = container_ty.structFieldType(next_field_index, zcu); | |
| 5529 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 5530 | ||
| 5531 | break :blk .{ .field = if (container_ty.isSimpleTuple(zcu)) | |
| 5532 | .{ .field = next_field_index } | |
| 5471 | }, | |
| 5472 | .anon_struct_type => |anon_struct_info| { | |
| 5473 | for (field_index..anon_struct_info.types.len) |next_field_index| { | |
| 5474 | if (anon_struct_info.values.get(ip)[next_field_index] != .none) continue; | |
| 5475 | const field_type = Type.fromInterned(anon_struct_info.types.get(ip)[next_field_index]); | |
| 5476 | if (!field_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 5477 | return .{ .field = if (anon_struct_info.fieldName(ip, next_field_index).unwrap()) |field_name| | |
| 5478 | .{ .identifier = ip.stringToSlice(field_name) } | |
| 5533 | 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 => { | |
| 5539 | const union_obj = zcu.typeToUnion(container_ty).?; | |
| 5540 | return switch (union_obj.getLayout(ip)) { | |
| 5484 | .union_type => { | |
| 5485 | const loaded_union = ip.loadUnionType(container_ty.toIntern()); | |
| 5486 | switch (loaded_union.getLayout(ip)) { | |
| 5541 | 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 | 5489 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) |
| 5544 | return if (container_ty.unionTagTypeSafety(zcu) != null and | |
| 5545 | !container_ty.unionHasAllZeroBitFieldTypes(zcu)) | |
| 5490 | return if (loaded_union.hasTag(ip) and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) | |
| 5546 | 5491 | .{ .field = .{ .identifier = "payload" } } |
| 5547 | 5492 | else |
| 5548 | 5493 | .begin; |
| 5549 | const field_name = union_obj.loadTagType(ip).names.get(ip)[field_index]; | |
| 5550 | return .{ .field = if (container_ty.unionTagTypeSafety(zcu)) |_| | |
| 5494 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; | |
| 5495 | return .{ .field = if (loaded_union.hasTag(ip)) | |
| 5551 | 5496 | .{ .payload_identifier = ip.stringToSlice(field_name) } |
| 5552 | 5497 | else |
| 5553 | 5498 | .{ .identifier = ip.stringToSlice(field_name) } }; |
| 5554 | 5499 | }, |
| 5555 | .@"packed" => .begin, | |
| 5556 | }; | |
| 5500 | .@"packed" => return .begin, | |
| 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 | 5505 | .Slice => switch (field_index) { |
| 5560 | 0 => .{ .field = .{ .identifier = "ptr" } }, | |
| 5561 | 1 => .{ .field = .{ .identifier = "len" } }, | |
| 5506 | 0 => return .{ .field = .{ .identifier = "ptr" } }, | |
| 5507 | 1 => return .{ .field = .{ .identifier = "len" } }, | |
| 5562 | 5508 | else => unreachable, |
| 5563 | 5509 | }, |
| 5564 | .One, .Many, .C => unreachable, | |
| 5565 | 5510 | }, |
| 5566 | 5511 | else => unreachable, |
| 5567 | }; | |
| 5512 | } | |
| 5568 | 5513 | } |
| 5569 | 5514 | |
| 5570 | 5515 | fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue { |
| ... | ... | @@ -5653,7 +5598,7 @@ fn fieldPtr( |
| 5653 | 5598 | const field_ptr_ty = f.typeOfIndex(inst); |
| 5654 | 5599 | |
| 5655 | 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 | 5603 | const writer = f.object.writer(); |
| 5659 | 5604 | const local = try f.allocLocal(inst, field_ptr_ty); |
| ... | ... | @@ -5708,109 +5653,109 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5708 | 5653 | const writer = f.object.writer(); |
| 5709 | 5654 | |
| 5710 | 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())) { | |
| 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); | |
| 5669 | const bit_offset_ty = try zcu.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1)); | |
| 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)) | |
| 5728 | inst_ty.intInfo(zcu).signedness | |
| 5729 | else | |
| 5730 | .unsigned; | |
| 5731 | const field_int_ty = try zcu.intType(field_int_signedness, @as(u16, @intCast(inst_ty.bitSize(zcu)))); | |
| 5732 | ||
| 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); | |
| 5679 | const temp_local = try f.allocLocal(inst, field_int_ty); | |
| 5680 | try f.writeCValue(writer, temp_local, .Other); | |
| 5681 | try writer.writeAll(" = zig_wrap_"); | |
| 5682 | try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty); | |
| 5683 | try writer.writeAll("(("); | |
| 5684 | try f.renderType(writer, field_int_ty); | |
| 5756 | 5685 | try writer.writeByte(')'); |
| 5757 | } | |
| 5758 | if (cant_cast) try writer.writeByte(')'); | |
| 5759 | try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .bits); | |
| 5760 | try writer.writeAll(");\n"); | |
| 5761 | if (inst_ty.eql(field_int_ty, f.object.dg.zcu)) return temp_local; | |
| 5686 | const cant_cast = int_info.bits > 64; | |
| 5687 | if (cant_cast) { | |
| 5688 | if (field_int_ty.bitSize(zcu) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{}); | |
| 5689 | try writer.writeAll("zig_lo_"); | |
| 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); | |
| 5764 | try writer.writeAll("memcpy("); | |
| 5765 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | |
| 5766 | try writer.writeAll(", "); | |
| 5767 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | |
| 5768 | try writer.writeAll(", sizeof("); | |
| 5769 | try f.renderType(writer, inst_ty); | |
| 5770 | try writer.writeAll("));\n"); | |
| 5771 | try freeLocal(f, inst, temp_local.new_local, null); | |
| 5772 | return local; | |
| 5773 | }, | |
| 5707 | const local = try f.allocLocal(inst, inst_ty); | |
| 5708 | try writer.writeAll("memcpy("); | |
| 5709 | try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument); | |
| 5710 | try writer.writeAll(", "); | |
| 5711 | try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument); | |
| 5712 | try writer.writeAll(", sizeof("); | |
| 5713 | try f.renderType(writer, inst_ty); | |
| 5714 | try writer.writeAll("));\n"); | |
| 5715 | try freeLocal(f, inst, temp_local.new_local, null); | |
| 5716 | return local; | |
| 5717 | }, | |
| 5718 | } | |
| 5774 | 5719 | }, |
| 5775 | ||
| 5776 | .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0) | |
| 5777 | .{ .field = extra.field_index } | |
| 5720 | .anon_struct_type => |anon_struct_info| if (anon_struct_info.fieldName(ip, extra.field_index).unwrap()) |field_name| | |
| 5721 | .{ .identifier = ip.stringToSlice(field_name) } | |
| 5778 | 5722 | else |
| 5779 | .{ .identifier = ip.stringToSlice(struct_ty.legacyStructFieldName(extra.field_index, zcu)) }, | |
| 5780 | ||
| 5723 | .{ .field = extra.field_index }, | |
| 5781 | 5724 | .union_type => field_name: { |
| 5782 | const union_obj = ip.loadUnionType(struct_ty.toIntern()); | |
| 5783 | if (union_obj.flagsPtr(ip).layout == .@"packed") { | |
| 5784 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5785 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5786 | try f.writeCValue(writer, operand_local, .Other); | |
| 5787 | try writer.writeAll(" = "); | |
| 5788 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5789 | try writer.writeAll(";\n"); | |
| 5790 | break :blk operand_local; | |
| 5791 | } else struct_byval; | |
| 5792 | ||
| 5793 | const local = try f.allocLocal(inst, inst_ty); | |
| 5794 | try writer.writeAll("memcpy(&"); | |
| 5795 | try f.writeCValue(writer, local, .Other); | |
| 5796 | try writer.writeAll(", &"); | |
| 5797 | try f.writeCValue(writer, operand_lval, .Other); | |
| 5798 | try writer.writeAll(", sizeof("); | |
| 5799 | try f.renderType(writer, inst_ty); | |
| 5800 | try writer.writeAll("));\n"); | |
| 5801 | ||
| 5802 | if (struct_byval == .constant) { | |
| 5803 | try freeLocal(f, inst, operand_lval.new_local, null); | |
| 5804 | } | |
| 5725 | const loaded_union = ip.loadUnionType(struct_ty.toIntern()); | |
| 5726 | switch (loaded_union.getLayout(ip)) { | |
| 5727 | .auto, .@"extern" => { | |
| 5728 | const name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 5729 | break :field_name if (loaded_union.hasTag(ip)) | |
| 5730 | .{ .payload_identifier = ip.stringToSlice(name) } | |
| 5731 | else | |
| 5732 | .{ .identifier = ip.stringToSlice(name) }; | |
| 5733 | }, | |
| 5734 | .@"packed" => { | |
| 5735 | const operand_lval = if (struct_byval == .constant) blk: { | |
| 5736 | const operand_local = try f.allocLocal(inst, struct_ty); | |
| 5737 | try f.writeCValue(writer, operand_local, .Other); | |
| 5738 | try writer.writeAll(" = "); | |
| 5739 | try f.writeCValue(writer, struct_byval, .Initializer); | |
| 5740 | try writer.writeAll(";\n"); | |
| 5741 | break :blk operand_local; | |
| 5742 | } else struct_byval; | |
| 5743 | ||
| 5744 | const local = try f.allocLocal(inst, inst_ty); | |
| 5745 | try writer.writeAll("memcpy(&"); | |
| 5746 | try f.writeCValue(writer, local, .Other); | |
| 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; | |
| 5807 | } else { | |
| 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 | }; | |
| 5757 | return local; | |
| 5758 | }, | |
| 5814 | 5759 | } |
| 5815 | 5760 | }, |
| 5816 | 5761 | else => unreachable, |
| ... | ... | @@ -6089,6 +6034,7 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const |
| 6089 | 6034 | |
| 6090 | 6035 | fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6091 | 6036 | const zcu = f.object.dg.zcu; |
| 6037 | const ctype_pool = &f.object.dg.ctype_pool; | |
| 6092 | 6038 | const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 6093 | 6039 | |
| 6094 | 6040 | const operand = try f.resolveInst(ty_op.operand); |
| ... | ... | @@ -6107,18 +6053,18 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6107 | 6053 | if (operand == .undef) { |
| 6108 | 6054 | try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(zcu) }, .Initializer); |
| 6109 | 6055 | } else { |
| 6110 | const ptr_cty = try f.typeToIndex(ptr_ty, .complete); | |
| 6111 | const ptr_child_cty = f.indexToCType(ptr_cty).cast(CType.Payload.Child).?.data; | |
| 6056 | const ptr_ctype = try f.ctypeFromType(ptr_ty, .complete); | |
| 6057 | const ptr_child_ctype = ptr_ctype.info(ctype_pool).pointer.elem_ctype; | |
| 6112 | 6058 | const elem_ty = array_ty.childType(zcu); |
| 6113 | const elem_cty = try f.typeToIndex(elem_ty, .complete); | |
| 6114 | if (ptr_child_cty != elem_cty) { | |
| 6059 | const elem_ctype = try f.ctypeFromType(elem_ty, .complete); | |
| 6060 | if (!ptr_child_ctype.eql(elem_ctype)) { | |
| 6115 | 6061 | try writer.writeByte('('); |
| 6116 | try f.renderCType(writer, ptr_cty); | |
| 6062 | try f.renderCType(writer, ptr_ctype); | |
| 6117 | 6063 | try writer.writeByte(')'); |
| 6118 | 6064 | } |
| 6119 | const operand_cty = try f.typeToCType(operand_ty, .complete); | |
| 6120 | const operand_child_cty = operand_cty.cast(CType.Payload.Child).?.data; | |
| 6121 | if (f.indexToCType(operand_child_cty).tag() == .array) { | |
| 6065 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | |
| 6066 | const operand_child_ctype = operand_ctype.info(ctype_pool).pointer.elem_ctype; | |
| 6067 | if (operand_child_ctype.info(ctype_pool) == .array) { | |
| 6122 | 6068 | try writer.writeByte('&'); |
| 6123 | 6069 | try f.writeCValueDeref(writer, operand); |
| 6124 | 6070 | try writer.print("[{}]", .{try f.fmtIntLiteral(try zcu.intValue(Type.usize, 0))}); |
| ... | ... | @@ -6229,8 +6175,8 @@ fn airUnBuiltinCall( |
| 6229 | 6175 | const operand_ty = f.typeOf(ty_op.operand); |
| 6230 | 6176 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6231 | 6177 | |
| 6232 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | |
| 6233 | const ref_ret = inst_scalar_cty.tag() == .array; | |
| 6178 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6179 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 6234 | 6180 | |
| 6235 | 6181 | const writer = f.object.writer(); |
| 6236 | 6182 | const local = try f.allocLocal(inst, inst_ty); |
| ... | ... | @@ -6267,8 +6213,8 @@ fn airBinBuiltinCall( |
| 6267 | 6213 | const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 6268 | 6214 | |
| 6269 | 6215 | const operand_ty = f.typeOf(bin_op.lhs); |
| 6270 | const operand_cty = try f.typeToCType(operand_ty, .complete); | |
| 6271 | const is_big = operand_cty.tag() == .array; | |
| 6216 | const operand_ctype = try f.ctypeFromType(operand_ty, .complete); | |
| 6217 | const is_big = operand_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 6272 | 6218 | |
| 6273 | 6219 | const lhs = try f.resolveInst(bin_op.lhs); |
| 6274 | 6220 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -6278,8 +6224,8 @@ fn airBinBuiltinCall( |
| 6278 | 6224 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 6279 | 6225 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6280 | 6226 | |
| 6281 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | |
| 6282 | const ref_ret = inst_scalar_cty.tag() == .array; | |
| 6227 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6228 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 6283 | 6229 | |
| 6284 | 6230 | const writer = f.object.writer(); |
| 6285 | 6231 | const local = try f.allocLocal(inst, inst_ty); |
| ... | ... | @@ -6328,8 +6274,8 @@ fn airCmpBuiltinCall( |
| 6328 | 6274 | const operand_ty = f.typeOf(data.lhs); |
| 6329 | 6275 | const scalar_ty = operand_ty.scalarType(zcu); |
| 6330 | 6276 | |
| 6331 | const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete); | |
| 6332 | const ref_ret = inst_scalar_cty.tag() == .array; | |
| 6277 | const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); | |
| 6278 | const ref_ret = inst_scalar_ctype.info(&f.object.dg.ctype_pool) == .array; | |
| 6333 | 6279 | |
| 6334 | 6280 | const writer = f.object.writer(); |
| 6335 | 6281 | const local = try f.allocLocal(inst, inst_ty); |
| ... | ... | @@ -7112,9 +7058,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7112 | 7058 | |
| 7113 | 7059 | const writer = f.object.writer(); |
| 7114 | 7060 | const local = try f.allocLocal(inst, inst_ty); |
| 7115 | switch (inst_ty.zigTypeTag(zcu)) { | |
| 7116 | .Array, .Vector => { | |
| 7117 | const a = try Assignment.init(f, inst_ty.childType(zcu)); | |
| 7061 | switch (ip.indexToKey(inst_ty.toIntern())) { | |
| 7062 | inline .array_type, .vector_type => |info, tag| { | |
| 7063 | const a = try Assignment.init(f, Type.fromInterned(info.child)); | |
| 7118 | 7064 | for (resolved_elements, 0..) |element, i| { |
| 7119 | 7065 | try a.restart(f, writer); |
| 7120 | 7066 | try f.writeCValue(writer, local, .Other); |
| ... | ... | @@ -7123,94 +7069,112 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7123 | 7069 | try f.writeCValue(writer, element, .Other); |
| 7124 | 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 | 7073 | try a.restart(f, writer); |
| 7128 | 7074 | try f.writeCValue(writer, local, .Other); |
| 7129 | try writer.print("[{d}]", .{resolved_elements.len}); | |
| 7075 | try writer.print("[{d}]", .{info.len}); | |
| 7130 | 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 | 7078 | try a.end(f, writer); |
| 7133 | 7079 | } |
| 7134 | 7080 | }, |
| 7135 | .Struct => switch (inst_ty.containerLayout(zcu)) { | |
| 7136 | .auto, .@"extern" => for (resolved_elements, 0..) |element, field_index| { | |
| 7137 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | |
| 7138 | const field_ty = inst_ty.structFieldType(field_index, zcu); | |
| 7139 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 7140 | ||
| 7141 | const a = try Assignment.start(f, writer, field_ty); | |
| 7142 | try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(zcu)) | |
| 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); | |
| 7081 | .struct_type => { | |
| 7082 | const loaded_struct = ip.loadStructType(inst_ty.toIntern()); | |
| 7083 | switch (loaded_struct.layout) { | |
| 7084 | .auto, .@"extern" => { | |
| 7085 | var field_it = loaded_struct.iterateRuntimeOrder(ip); | |
| 7086 | while (field_it.next()) |field_index| { | |
| 7087 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); | |
| 7088 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 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; | |
| 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; | |
| 7107 | var bit_offset: u64 = 0; | |
| 7164 | 7108 | |
| 7165 | if (!empty) { | |
| 7166 | try writer.writeAll("zig_or_"); | |
| 7167 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | |
| 7168 | try writer.writeByte('('); | |
| 7109 | var empty = true; | |
| 7110 | for (0..elements.len) |field_index| { | |
| 7111 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | |
| 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; | |
| 7171 | } | |
| 7172 | empty = true; | |
| 7173 | for (resolved_elements, 0..) |element, field_index| { | |
| 7174 | if (inst_ty.structFieldIsComptime(field_index, 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('('); | |
| 7122 | empty = true; | |
| 7123 | for (resolved_elements, 0..) |element, field_index| { | |
| 7124 | if (inst_ty.structFieldIsComptime(field_index, zcu)) continue; | |
| 7125 | const field_ty = inst_ty.structFieldType(field_index, zcu); | |
| 7126 | if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; | |
| 7183 | 7127 | |
| 7184 | if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { | |
| 7185 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); | |
| 7186 | } else { | |
| 7128 | if (!empty) try writer.writeAll(", "); | |
| 7129 | // TODO: Skip this entire shift if val is 0? | |
| 7130 | try writer.writeAll("zig_shlw_"); | |
| 7131 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty); | |
| 7187 | 7132 | try writer.writeByte('('); |
| 7188 | try f.renderType(writer, inst_ty); | |
| 7189 | try writer.writeByte(')'); | |
| 7190 | if (field_ty.isPtrAtRuntime(zcu)) { | |
| 7133 | ||
| 7134 | if (inst_ty.isAbiInt(zcu) and (field_ty.isAbiInt(zcu) or field_ty.isPtrAtRuntime(zcu))) { | |
| 7135 | try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument); | |
| 7136 | } else { | |
| 7191 | 7137 | try writer.writeByte('('); |
| 7192 | try f.renderType(writer, switch (int_info.signedness) { | |
| 7193 | .unsigned => Type.usize, | |
| 7194 | .signed => Type.isize, | |
| 7195 | }); | |
| 7138 | try f.renderType(writer, inst_ty); | |
| 7196 | 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); | |
| 7209 | empty = false; | |
| 7210 | } | |
| 7151 | try writer.print(", {}", .{ | |
| 7152 | try f.fmtIntLiteral(try zcu.intValue(bit_offset_ty, bit_offset)), | |
| 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"); | |
| 7213 | }, | |
| 7158 | bit_offset += field_ty.bitSize(zcu); | |
| 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 | 7179 | else => unreachable, |
| 7216 | 7180 | } |
| ... | ... | @@ -7225,15 +7189,15 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7225 | 7189 | const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data; |
| 7226 | 7190 | |
| 7227 | 7191 | const union_ty = f.typeOfIndex(inst); |
| 7228 | const union_obj = zcu.typeToUnion(union_ty).?; | |
| 7229 | const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 7192 | const loaded_union = ip.loadUnionType(union_ty.toIntern()); | |
| 7193 | const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; | |
| 7230 | 7194 | const payload_ty = f.typeOf(extra.init); |
| 7231 | 7195 | const payload = try f.resolveInst(extra.init); |
| 7232 | 7196 | try reap(f, inst, &.{extra.init}); |
| 7233 | 7197 | |
| 7234 | 7198 | const writer = f.object.writer(); |
| 7235 | 7199 | const local = try f.allocLocal(inst, union_ty); |
| 7236 | if (union_obj.getLayout(ip) == .@"packed") { | |
| 7200 | if (loaded_union.getLayout(ip) == .@"packed") { | |
| 7237 | 7201 | try f.writeCValue(writer, local, .Other); |
| 7238 | 7202 | try writer.writeAll(" = "); |
| 7239 | 7203 | try f.writeCValue(writer, payload, .Initializer); |
| ... | ... | @@ -7465,16 +7429,16 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7465 | 7429 | const inst_ty = f.typeOfIndex(inst); |
| 7466 | 7430 | const decl_index = f.object.dg.pass.decl; |
| 7467 | 7431 | const decl = zcu.declPtr(decl_index); |
| 7468 | const fn_cty = try f.typeToCType(decl.typeOf(zcu), .complete); | |
| 7469 | const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len; | |
| 7432 | const function_ctype = try f.ctypeFromType(decl.typeOf(zcu), .complete); | |
| 7433 | const params_len = function_ctype.info(&f.object.dg.ctype_pool).function.param_ctypes.len; | |
| 7470 | 7434 | |
| 7471 | 7435 | const writer = f.object.writer(); |
| 7472 | 7436 | const local = try f.allocLocal(inst, inst_ty); |
| 7473 | 7437 | try writer.writeAll("va_start(*(va_list *)&"); |
| 7474 | 7438 | try f.writeCValue(writer, local, .Other); |
| 7475 | if (param_len > 0) { | |
| 7439 | if (params_len > 0) { | |
| 7476 | 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 | 7443 | try writer.writeAll(");\n"); |
| 7480 | 7444 | return local; |
| ... | ... | @@ -7823,7 +7787,7 @@ const FormatIntLiteralContext = struct { |
| 7823 | 7787 | dg: *DeclGen, |
| 7824 | 7788 | int_info: InternPool.Key.IntType, |
| 7825 | 7789 | kind: CType.Kind, |
| 7826 | cty: CType, | |
| 7790 | ctype: CType, | |
| 7827 | 7791 | val: Value, |
| 7828 | 7792 | }; |
| 7829 | 7793 | fn formatIntLiteral( |
| ... | ... | @@ -7834,6 +7798,7 @@ fn formatIntLiteral( |
| 7834 | 7798 | ) @TypeOf(writer).Error!void { |
| 7835 | 7799 | const zcu = data.dg.zcu; |
| 7836 | 7800 | const target = &data.dg.mod.resolved_target.result; |
| 7801 | const ctype_pool = &data.dg.ctype_pool; | |
| 7837 | 7802 | |
| 7838 | 7803 | const ExpectedContents = struct { |
| 7839 | 7804 | const base = 10; |
| ... | ... | @@ -7867,7 +7832,7 @@ fn formatIntLiteral( |
| 7867 | 7832 | } else data.val.toBigInt(&int_buf, zcu); |
| 7868 | 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 | 7836 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 7872 | 7837 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 7873 | 7838 | |
| ... | ... | @@ -7879,45 +7844,45 @@ fn formatIntLiteral( |
| 7879 | 7844 | defer allocator.free(wrap.limbs); |
| 7880 | 7845 | |
| 7881 | 7846 | const c_limb_info: struct { |
| 7882 | cty: CType, | |
| 7847 | ctype: CType, | |
| 7883 | 7848 | count: usize, |
| 7884 | 7849 | endian: std.builtin.Endian, |
| 7885 | 7850 | homogeneous: bool, |
| 7886 | } = switch (data.cty.tag()) { | |
| 7887 | else => .{ | |
| 7888 | .cty = CType.initTag(.void), | |
| 7889 | .count = 1, | |
| 7890 | .endian = .little, | |
| 7891 | .homogeneous = true, | |
| 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(), | |
| 7851 | } = switch (data.ctype.info(ctype_pool)) { | |
| 7852 | .basic => |basic_info| switch (basic_info) { | |
| 7853 | else => .{ | |
| 7854 | .ctype = .{ .index = .void }, | |
| 7855 | .count = 1, | |
| 7856 | .endian = .little, | |
| 7905 | 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 | 7874 | if (c_limb_info.count == 1) { |
| 7910 | 7875 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 7911 | 7876 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 7912 | 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 | 7879 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 7915 | 7880 | }), |
| 7916 | 7881 | if (int.positive) "MAX" else "MIN", |
| 7917 | 7882 | }); |
| 7918 | 7883 | |
| 7919 | 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 | 7887 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { |
| 7923 | 7888 | 0 => .{ .base = 10 }, |
| ... | ... | @@ -7948,7 +7913,7 @@ fn formatIntLiteral( |
| 7948 | 7913 | defer allocator.free(string); |
| 7949 | 7914 | try writer.writeAll(string); |
| 7950 | 7915 | } else { |
| 7951 | try data.cty.renderLiteralPrefix(writer, data.kind); | |
| 7916 | try data.ctype.renderLiteralPrefix(writer, data.kind, ctype_pool); | |
| 7952 | 7917 | wrap.convertToTwosComplement(int, data.int_info.signedness, c_bits); |
| 7953 | 7918 | @memset(wrap.limbs[wrap.len..], 0); |
| 7954 | 7919 | wrap.len = wrap.limbs.len; |
| ... | ... | @@ -7958,7 +7923,7 @@ fn formatIntLiteral( |
| 7958 | 7923 | .signedness = undefined, |
| 7959 | 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 | 7928 | var limb_offset: usize = 0; |
| 7964 | 7929 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; |
| ... | ... | @@ -7979,7 +7944,7 @@ fn formatIntLiteral( |
| 7979 | 7944 | { |
| 7980 | 7945 | // most significant limb is actually signed |
| 7981 | 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 | 7949 | c_limb_mut.positive = wrap.positive; |
| 7985 | 7950 | c_limb_mut.truncate( |
| ... | ... | @@ -7989,7 +7954,7 @@ fn formatIntLiteral( |
| 7989 | 7954 | ); |
| 7990 | 7955 | } else { |
| 7991 | 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 | 7960 | if (limb_offset > 0) try writer.writeAll(", "); |
| ... | ... | @@ -7997,12 +7962,12 @@ fn formatIntLiteral( |
| 7997 | 7962 | .dg = data.dg, |
| 7998 | 7963 | .int_info = c_limb_int_info, |
| 7999 | 7964 | .kind = data.kind, |
| 8000 | .cty = c_limb_cty, | |
| 7965 | .ctype = c_limb_ctype, | |
| 8001 | 7966 | .val = try zcu.intValue_big(Type.comptime_int, c_limb_mut.toConst()), |
| 8002 | 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 | 7973 | const Materialize = struct { |
| ... | ... | @@ -8045,10 +8010,10 @@ const Materialize = struct { |
| 8045 | 8010 | }; |
| 8046 | 8011 | |
| 8047 | 8012 | const Assignment = struct { |
| 8048 | cty: CType.Index, | |
| 8013 | ctype: CType, | |
| 8049 | 8014 | |
| 8050 | 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 | 8019 | pub fn start(f: *Function, writer: anytype, ty: Type) !Assignment { |
| ... | ... | @@ -8076,7 +8041,7 @@ const Assignment = struct { |
| 8076 | 8041 | .assign => {}, |
| 8077 | 8042 | .memcpy => { |
| 8078 | 8043 | try writer.writeAll(", sizeof("); |
| 8079 | try f.renderCType(writer, self.cty); | |
| 8044 | try f.renderCType(writer, self.ctype); | |
| 8080 | 8045 | try writer.writeAll("))"); |
| 8081 | 8046 | }, |
| 8082 | 8047 | } |
| ... | ... | @@ -8084,7 +8049,7 @@ const Assignment = struct { |
| 8084 | 8049 | } |
| 8085 | 8050 | |
| 8086 | 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 | 8053 | else => .assign, |
| 8089 | 8054 | .array, .vector => .memcpy, |
| 8090 | 8055 | }; |
| ... | ... | @@ -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 | 8097 | fn lowersToArray(ty: Type, zcu: *Zcu) bool { |
| 8155 | 8098 | return switch (ty.zigTypeTag(zcu)) { |
| 8156 | 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 | 2033 | owner_decl.src_node + 1, // Line |
| 2034 | 2034 | try o.lowerDebugType(int_ty), |
| 2035 | 2035 | ty.abiSize(mod) * 8, |
| 2036 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2036 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2037 | 2037 | try o.builder.debugTuple(enumerators), |
| 2038 | 2038 | ); |
| 2039 | 2039 | |
| ... | ... | @@ -2120,7 +2120,7 @@ pub const Object = struct { |
| 2120 | 2120 | 0, // Line |
| 2121 | 2121 | try o.lowerDebugType(ptr_ty), |
| 2122 | 2122 | ptr_size * 8, |
| 2123 | ptr_align.toByteUnits(0) * 8, | |
| 2123 | (ptr_align.toByteUnits() orelse 0) * 8, | |
| 2124 | 2124 | 0, // Offset |
| 2125 | 2125 | ); |
| 2126 | 2126 | |
| ... | ... | @@ -2131,7 +2131,7 @@ pub const Object = struct { |
| 2131 | 2131 | 0, // Line |
| 2132 | 2132 | try o.lowerDebugType(len_ty), |
| 2133 | 2133 | len_size * 8, |
| 2134 | len_align.toByteUnits(0) * 8, | |
| 2134 | (len_align.toByteUnits() orelse 0) * 8, | |
| 2135 | 2135 | len_offset * 8, |
| 2136 | 2136 | ); |
| 2137 | 2137 | |
| ... | ... | @@ -2142,7 +2142,7 @@ pub const Object = struct { |
| 2142 | 2142 | line, |
| 2143 | 2143 | .none, // Underlying type |
| 2144 | 2144 | ty.abiSize(mod) * 8, |
| 2145 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2145 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2146 | 2146 | try o.builder.debugTuple(&.{ |
| 2147 | 2147 | debug_ptr_type, |
| 2148 | 2148 | debug_len_type, |
| ... | ... | @@ -2170,7 +2170,7 @@ pub const Object = struct { |
| 2170 | 2170 | 0, // Line |
| 2171 | 2171 | debug_elem_ty, |
| 2172 | 2172 | target.ptrBitWidth(), |
| 2173 | ty.ptrAlignment(mod).toByteUnits(0) * 8, | |
| 2173 | (ty.ptrAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2174 | 2174 | 0, // Offset |
| 2175 | 2175 | ); |
| 2176 | 2176 | |
| ... | ... | @@ -2217,7 +2217,7 @@ pub const Object = struct { |
| 2217 | 2217 | 0, // Line |
| 2218 | 2218 | try o.lowerDebugType(ty.childType(mod)), |
| 2219 | 2219 | ty.abiSize(mod) * 8, |
| 2220 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2220 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2221 | 2221 | try o.builder.debugTuple(&.{ |
| 2222 | 2222 | try o.builder.debugSubrange( |
| 2223 | 2223 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | ... | @@ -2260,7 +2260,7 @@ pub const Object = struct { |
| 2260 | 2260 | 0, // Line |
| 2261 | 2261 | debug_elem_type, |
| 2262 | 2262 | ty.abiSize(mod) * 8, |
| 2263 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2263 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2264 | 2264 | try o.builder.debugTuple(&.{ |
| 2265 | 2265 | try o.builder.debugSubrange( |
| 2266 | 2266 | try o.builder.debugConstant(try o.builder.intConst(.i64, 0)), |
| ... | ... | @@ -2316,7 +2316,7 @@ pub const Object = struct { |
| 2316 | 2316 | 0, // Line |
| 2317 | 2317 | try o.lowerDebugType(child_ty), |
| 2318 | 2318 | payload_size * 8, |
| 2319 | payload_align.toByteUnits(0) * 8, | |
| 2319 | (payload_align.toByteUnits() orelse 0) * 8, | |
| 2320 | 2320 | 0, // Offset |
| 2321 | 2321 | ); |
| 2322 | 2322 | |
| ... | ... | @@ -2327,7 +2327,7 @@ pub const Object = struct { |
| 2327 | 2327 | 0, |
| 2328 | 2328 | try o.lowerDebugType(non_null_ty), |
| 2329 | 2329 | non_null_size * 8, |
| 2330 | non_null_align.toByteUnits(0) * 8, | |
| 2330 | (non_null_align.toByteUnits() orelse 0) * 8, | |
| 2331 | 2331 | non_null_offset * 8, |
| 2332 | 2332 | ); |
| 2333 | 2333 | |
| ... | ... | @@ -2338,7 +2338,7 @@ pub const Object = struct { |
| 2338 | 2338 | 0, // Line |
| 2339 | 2339 | .none, // Underlying type |
| 2340 | 2340 | ty.abiSize(mod) * 8, |
| 2341 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2341 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2342 | 2342 | try o.builder.debugTuple(&.{ |
| 2343 | 2343 | debug_data_type, |
| 2344 | 2344 | debug_some_type, |
| ... | ... | @@ -2396,7 +2396,7 @@ pub const Object = struct { |
| 2396 | 2396 | 0, // Line |
| 2397 | 2397 | try o.lowerDebugType(Type.anyerror), |
| 2398 | 2398 | error_size * 8, |
| 2399 | error_align.toByteUnits(0) * 8, | |
| 2399 | (error_align.toByteUnits() orelse 0) * 8, | |
| 2400 | 2400 | error_offset * 8, |
| 2401 | 2401 | ); |
| 2402 | 2402 | fields[payload_index] = try o.builder.debugMemberType( |
| ... | ... | @@ -2406,7 +2406,7 @@ pub const Object = struct { |
| 2406 | 2406 | 0, // Line |
| 2407 | 2407 | try o.lowerDebugType(payload_ty), |
| 2408 | 2408 | payload_size * 8, |
| 2409 | payload_align.toByteUnits(0) * 8, | |
| 2409 | (payload_align.toByteUnits() orelse 0) * 8, | |
| 2410 | 2410 | payload_offset * 8, |
| 2411 | 2411 | ); |
| 2412 | 2412 | |
| ... | ... | @@ -2417,7 +2417,7 @@ pub const Object = struct { |
| 2417 | 2417 | 0, // Line |
| 2418 | 2418 | .none, // Underlying type |
| 2419 | 2419 | ty.abiSize(mod) * 8, |
| 2420 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2420 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2421 | 2421 | try o.builder.debugTuple(&fields), |
| 2422 | 2422 | ); |
| 2423 | 2423 | |
| ... | ... | @@ -2485,7 +2485,7 @@ pub const Object = struct { |
| 2485 | 2485 | 0, |
| 2486 | 2486 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2487 | 2487 | field_size * 8, |
| 2488 | field_align.toByteUnits(0) * 8, | |
| 2488 | (field_align.toByteUnits() orelse 0) * 8, | |
| 2489 | 2489 | field_offset * 8, |
| 2490 | 2490 | )); |
| 2491 | 2491 | } |
| ... | ... | @@ -2497,7 +2497,7 @@ pub const Object = struct { |
| 2497 | 2497 | 0, // Line |
| 2498 | 2498 | .none, // Underlying type |
| 2499 | 2499 | ty.abiSize(mod) * 8, |
| 2500 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2500 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2501 | 2501 | try o.builder.debugTuple(fields.items), |
| 2502 | 2502 | ); |
| 2503 | 2503 | |
| ... | ... | @@ -2566,7 +2566,7 @@ pub const Object = struct { |
| 2566 | 2566 | 0, // Line |
| 2567 | 2567 | try o.lowerDebugType(field_ty), |
| 2568 | 2568 | field_size * 8, |
| 2569 | field_align.toByteUnits(0) * 8, | |
| 2569 | (field_align.toByteUnits() orelse 0) * 8, | |
| 2570 | 2570 | field_offset * 8, |
| 2571 | 2571 | )); |
| 2572 | 2572 | } |
| ... | ... | @@ -2578,7 +2578,7 @@ pub const Object = struct { |
| 2578 | 2578 | 0, // Line |
| 2579 | 2579 | .none, // Underlying type |
| 2580 | 2580 | ty.abiSize(mod) * 8, |
| 2581 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2581 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2582 | 2582 | try o.builder.debugTuple(fields.items), |
| 2583 | 2583 | ); |
| 2584 | 2584 | |
| ... | ... | @@ -2621,7 +2621,7 @@ pub const Object = struct { |
| 2621 | 2621 | 0, // Line |
| 2622 | 2622 | .none, // Underlying type |
| 2623 | 2623 | ty.abiSize(mod) * 8, |
| 2624 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2624 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2625 | 2625 | try o.builder.debugTuple( |
| 2626 | 2626 | &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, |
| 2627 | 2627 | ), |
| ... | ... | @@ -2661,7 +2661,7 @@ pub const Object = struct { |
| 2661 | 2661 | 0, // Line |
| 2662 | 2662 | try o.lowerDebugType(Type.fromInterned(field_ty)), |
| 2663 | 2663 | field_size * 8, |
| 2664 | field_align.toByteUnits(0) * 8, | |
| 2664 | (field_align.toByteUnits() orelse 0) * 8, | |
| 2665 | 2665 | 0, // Offset |
| 2666 | 2666 | )); |
| 2667 | 2667 | } |
| ... | ... | @@ -2680,7 +2680,7 @@ pub const Object = struct { |
| 2680 | 2680 | 0, // Line |
| 2681 | 2681 | .none, // Underlying type |
| 2682 | 2682 | ty.abiSize(mod) * 8, |
| 2683 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2683 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2684 | 2684 | try o.builder.debugTuple(fields.items), |
| 2685 | 2685 | ); |
| 2686 | 2686 | |
| ... | ... | @@ -2711,7 +2711,7 @@ pub const Object = struct { |
| 2711 | 2711 | 0, // Line |
| 2712 | 2712 | try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), |
| 2713 | 2713 | layout.tag_size * 8, |
| 2714 | layout.tag_align.toByteUnits(0) * 8, | |
| 2714 | (layout.tag_align.toByteUnits() orelse 0) * 8, | |
| 2715 | 2715 | tag_offset * 8, |
| 2716 | 2716 | ); |
| 2717 | 2717 | |
| ... | ... | @@ -2722,7 +2722,7 @@ pub const Object = struct { |
| 2722 | 2722 | 0, // Line |
| 2723 | 2723 | debug_union_type, |
| 2724 | 2724 | layout.payload_size * 8, |
| 2725 | layout.payload_align.toByteUnits(0) * 8, | |
| 2725 | (layout.payload_align.toByteUnits() orelse 0) * 8, | |
| 2726 | 2726 | payload_offset * 8, |
| 2727 | 2727 | ); |
| 2728 | 2728 | |
| ... | ... | @@ -2739,7 +2739,7 @@ pub const Object = struct { |
| 2739 | 2739 | 0, // Line |
| 2740 | 2740 | .none, // Underlying type |
| 2741 | 2741 | ty.abiSize(mod) * 8, |
| 2742 | ty.abiAlignment(mod).toByteUnits(0) * 8, | |
| 2742 | (ty.abiAlignment(mod).toByteUnits() orelse 0) * 8, | |
| 2743 | 2743 | try o.builder.debugTuple(&full_fields), |
| 2744 | 2744 | ); |
| 2745 | 2745 | |
| ... | ... | @@ -4473,7 +4473,7 @@ pub const Object = struct { |
| 4473 | 4473 | // The value cannot be undefined, because we use the `nonnull` annotation |
| 4474 | 4474 | // for non-optional pointers. We also need to respect the alignment, even though |
| 4475 | 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 | 4477 | // Note that these 0xaa values are appropriate even in release-optimized builds |
| 4478 | 4478 | // because we need a well-defined value that is not null, and LLVM does not |
| 4479 | 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 | 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 | 176 | // TODO: use alarm() here to prevent infinite loops |
| 177 | 177 | PanicSwitch.preDispatch(); |
| 178 | 178 |
src/link/C.zig+98-123| ... | ... | @@ -69,13 +69,13 @@ pub const DeclBlock = struct { |
| 69 | 69 | fwd_decl: String = String.empty, |
| 70 | 70 | /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate |
| 71 | 71 | /// over each `Decl` and generate the definition for each used `CType` once. |
| 72 | ctypes: codegen.CType.Store = .{}, | |
| 73 | /// Key and Value storage use the ctype arena. | |
| 72 | ctype_pool: codegen.CType.Pool = codegen.CType.Pool.empty, | |
| 73 | /// May contain string references to ctype_pool | |
| 74 | 74 | lazy_fns: codegen.LazyFnMap = .{}, |
| 75 | 75 | |
| 76 | 76 | fn deinit(db: *DeclBlock, gpa: Allocator) void { |
| 77 | 77 | db.lazy_fns.deinit(gpa); |
| 78 | db.ctypes.deinit(gpa); | |
| 78 | db.ctype_pool.deinit(gpa); | |
| 79 | 79 | db.* = undefined; |
| 80 | 80 | } |
| 81 | 81 | }; |
| ... | ... | @@ -190,11 +190,12 @@ pub fn updateFunc( |
| 190 | 190 | const decl = zcu.declPtr(decl_index); |
| 191 | 191 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 192 | 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 | 194 | const lazy_fns = &gop.value_ptr.lazy_fns; |
| 195 | 195 | const fwd_decl = &self.fwd_decl_buf; |
| 196 | 196 | const code = &self.code_buf; |
| 197 | ctypes.clearRetainingCapacity(gpa); | |
| 197 | try ctype_pool.init(gpa); | |
| 198 | ctype_pool.clearRetainingCapacity(); | |
| 198 | 199 | lazy_fns.clearRetainingCapacity(); |
| 199 | 200 | fwd_decl.clearRetainingCapacity(); |
| 200 | 201 | code.clearRetainingCapacity(); |
| ... | ... | @@ -213,7 +214,8 @@ pub fn updateFunc( |
| 213 | 214 | .pass = .{ .decl = decl_index }, |
| 214 | 215 | .is_naked_fn = decl.typeOf(zcu).fnCallingConvention(zcu) == .Naked, |
| 215 | 216 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 216 | .ctypes = ctypes.*, | |
| 217 | .ctype_pool = ctype_pool.*, | |
| 218 | .scratch = .{}, | |
| 217 | 219 | .anon_decl_deps = self.anon_decls, |
| 218 | 220 | .aligned_anon_decls = self.aligned_anon_decls, |
| 219 | 221 | }, |
| ... | ... | @@ -222,12 +224,16 @@ pub fn updateFunc( |
| 222 | 224 | }, |
| 223 | 225 | .lazy_fns = lazy_fns.*, |
| 224 | 226 | }; |
| 225 | ||
| 226 | 227 | function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() }; |
| 227 | 228 | defer { |
| 228 | 229 | self.anon_decls = function.object.dg.anon_decl_deps; |
| 229 | 230 | self.aligned_anon_decls = function.object.dg.aligned_anon_decls; |
| 230 | 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 | 237 | code.* = function.object.code.moveToUnmanaged(); |
| 232 | 238 | function.deinit(); |
| 233 | 239 | } |
| ... | ... | @@ -239,16 +245,8 @@ pub fn updateFunc( |
| 239 | 245 | }, |
| 240 | 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 | 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 | 252 | fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| ... | ... | @@ -269,7 +267,8 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 269 | 267 | .pass = .{ .anon = anon_decl }, |
| 270 | 268 | .is_naked_fn = false, |
| 271 | 269 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 272 | .ctypes = .{}, | |
| 270 | .ctype_pool = codegen.CType.Pool.empty, | |
| 271 | .scratch = .{}, | |
| 273 | 272 | .anon_decl_deps = self.anon_decls, |
| 274 | 273 | .aligned_anon_decls = self.aligned_anon_decls, |
| 275 | 274 | }, |
| ... | ... | @@ -277,14 +276,15 @@ fn updateAnonDecl(self: *C, zcu: *Zcu, i: usize) !void { |
| 277 | 276 | .indent_writer = undefined, // set later so we can get a pointer to object.code |
| 278 | 277 | }; |
| 279 | 278 | object.indent_writer = .{ .underlying_writer = object.code.writer() }; |
| 280 | ||
| 281 | 279 | defer { |
| 282 | 280 | self.anon_decls = object.dg.anon_decl_deps; |
| 283 | 281 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 284 | object.dg.ctypes.deinit(object.dg.gpa); | |
| 285 | 282 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 283 | object.dg.ctype_pool.deinit(object.dg.gpa); | |
| 284 | object.dg.scratch.deinit(gpa); | |
| 286 | 285 | code.* = object.code.moveToUnmanaged(); |
| 287 | 286 | } |
| 287 | try object.dg.ctype_pool.init(gpa); | |
| 288 | 288 | |
| 289 | 289 | const c_value: codegen.CValue = .{ .constant = Value.fromInterned(anon_decl) }; |
| 290 | 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 | 297 | else => |e| return e, |
| 298 | 298 | }; |
| 299 | 299 | |
| 300 | // Free excess allocated memory for this Decl. | |
| 301 | object.dg.ctypes.shrinkAndFree(gpa, object.dg.ctypes.count()); | |
| 302 | ||
| 300 | object.dg.ctype_pool.freeUnusedCapacity(gpa); | |
| 303 | 301 | object.dg.anon_decl_deps.values()[i] = .{ |
| 304 | 302 | .code = try self.addString(object.code.items), |
| 305 | 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 | 313 | |
| 316 | 314 | const decl = zcu.declPtr(decl_index); |
| 317 | 315 | const gop = try self.decl_table.getOrPut(gpa, decl_index); |
| 318 | if (!gop.found_existing) { | |
| 319 | gop.value_ptr.* = .{}; | |
| 320 | } | |
| 321 | const ctypes = &gop.value_ptr.ctypes; | |
| 316 | errdefer _ = self.decl_table.pop(); | |
| 317 | if (!gop.found_existing) gop.value_ptr.* = .{}; | |
| 318 | const ctype_pool = &gop.value_ptr.ctype_pool; | |
| 322 | 319 | const fwd_decl = &self.fwd_decl_buf; |
| 323 | 320 | const code = &self.code_buf; |
| 324 | ctypes.clearRetainingCapacity(gpa); | |
| 321 | try ctype_pool.init(gpa); | |
| 322 | ctype_pool.clearRetainingCapacity(); | |
| 325 | 323 | fwd_decl.clearRetainingCapacity(); |
| 326 | 324 | code.clearRetainingCapacity(); |
| 327 | 325 | |
| ... | ... | @@ -334,7 +332,8 @@ pub fn updateDecl(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void { |
| 334 | 332 | .pass = .{ .decl = decl_index }, |
| 335 | 333 | .is_naked_fn = false, |
| 336 | 334 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 337 | .ctypes = ctypes.*, | |
| 335 | .ctype_pool = ctype_pool.*, | |
| 336 | .scratch = .{}, | |
| 338 | 337 | .anon_decl_deps = self.anon_decls, |
| 339 | 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 | 344 | defer { |
| 346 | 345 | self.anon_decls = object.dg.anon_decl_deps; |
| 347 | 346 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 348 | object.dg.ctypes.deinit(object.dg.gpa); | |
| 349 | 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 | 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 | 358 | }, |
| 358 | 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 | 361 | gop.value_ptr.code = try self.addString(object.code.items); |
| 367 | 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 | 411 | // This code path happens exclusively with -ofmt=c. The flush logic for |
| 417 | 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 | 418 | defer f.deinit(gpa); |
| 421 | 419 | |
| 422 | 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 | 441 | |
| 444 | 442 | self.lazy_fwd_decl_buf.clearRetainingCapacity(); |
| 445 | 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 | 447 | // Unlike other backends, the .c code we are emitting has order-dependent decls. |
| 449 | 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 | 470 | { |
| 472 | 471 | // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes. |
| 473 | 472 | // This ensures that every lazy CType.Index exactly matches the global CType.Index. |
| 474 | assert(f.ctypes.count() == 0); | |
| 475 | try self.flushCTypes(zcu, &f, .flush, f.lazy_ctypes); | |
| 473 | try f.ctype_pool.init(gpa); | |
| 474 | try self.flushCTypes(zcu, &f, .flush, &f.lazy_ctype_pool); | |
| 476 | 475 | |
| 477 | 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 | 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 | 509 | } |
| 511 | 510 | |
| 512 | 511 | const Flush = struct { |
| 513 | ctypes: codegen.CType.Store = .{}, | |
| 514 | ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{}, | |
| 512 | ctype_pool: codegen.CType.Pool, | |
| 513 | ctype_global_from_decl_map: std.ArrayListUnmanaged(codegen.CType) = .{}, | |
| 515 | 514 | ctypes_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 516 | 515 | |
| 517 | lazy_ctypes: codegen.CType.Store = .{}, | |
| 516 | lazy_ctype_pool: codegen.CType.Pool, | |
| 518 | 517 | lazy_fns: LazyFns = .{}, |
| 519 | 518 | |
| 520 | 519 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, |
| ... | ... | @@ -536,10 +535,11 @@ const Flush = struct { |
| 536 | 535 | f.all_buffers.deinit(gpa); |
| 537 | 536 | f.asm_buf.deinit(gpa); |
| 538 | 537 | f.lazy_fns.deinit(gpa); |
| 539 | f.lazy_ctypes.deinit(gpa); | |
| 538 | f.lazy_ctype_pool.deinit(gpa); | |
| 540 | 539 | f.ctypes_buf.deinit(gpa); |
| 541 | f.ctypes_map.deinit(gpa); | |
| 542 | f.ctypes.deinit(gpa); | |
| 540 | assert(f.ctype_global_from_decl_map.items.len == 0); | |
| 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 | 552 | zcu: *Zcu, |
| 553 | 553 | f: *Flush, |
| 554 | 554 | pass: codegen.DeclGen.Pass, |
| 555 | decl_ctypes: codegen.CType.Store, | |
| 555 | decl_ctype_pool: *const codegen.CType.Pool, | |
| 556 | 556 | ) FlushDeclError!void { |
| 557 | 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 | f.ctypes_map.clearRetainingCapacity(); | |
| 561 | try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len); | |
| 562 | ||
| 563 | var global_ctypes = f.ctypes.promote(gpa); | |
| 564 | defer f.ctypes.demote(global_ctypes); | |
| 560 | const global_from_decl_map = &f.ctype_global_from_decl_map; | |
| 561 | assert(global_from_decl_map.items.len == 0); | |
| 562 | try global_from_decl_map.ensureTotalCapacity(gpa, decl_ctype_pool.items.len); | |
| 563 | defer global_from_decl_map.clearRetainingCapacity(); | |
| 565 | 564 | |
| 566 | 565 | var ctypes_buf = f.ctypes_buf.toManaged(gpa); |
| 567 | 566 | defer f.ctypes_buf = ctypes_buf.moveToUnmanaged(); |
| 568 | 567 | const writer = ctypes_buf.writer(); |
| 569 | 568 | |
| 570 | const slice = decl_ctypes.set.map.entries.slice(); | |
| 571 | for (slice.items(.key), 0..) |decl_cty, decl_i| { | |
| 572 | const Context = struct { | |
| 573 | arena: Allocator, | |
| 574 | ctypes_map: []codegen.CType.Index, | |
| 575 | cached_hash: codegen.CType.Store.Set.Map.Hash, | |
| 576 | idx: codegen.CType.Index, | |
| 577 | ||
| 578 | pub fn hash(ctx: @This(), _: codegen.CType) codegen.CType.Store.Set.Map.Hash { | |
| 579 | return ctx.cached_hash; | |
| 569 | for (0..decl_ctype_pool.items.len) |decl_ctype_pool_index| { | |
| 570 | const PoolAdapter = struct { | |
| 571 | global_from_decl_map: []const codegen.CType, | |
| 572 | pub fn eql(pool_adapter: @This(), decl_ctype: codegen.CType, global_ctype: codegen.CType) bool { | |
| 573 | return if (decl_ctype.toPoolIndex()) |decl_pool_index| | |
| 574 | decl_pool_index < pool_adapter.global_from_decl_map.len and | |
| 575 | pool_adapter.global_from_decl_map[decl_pool_index].eql(global_ctype) | |
| 576 | else | |
| 577 | decl_ctype.index == global_ctype.index; | |
| 580 | 578 | } |
| 581 | pub fn eql(ctx: @This(), lhs: codegen.CType, rhs: codegen.CType, _: usize) bool { | |
| 582 | return lhs.eqlContext(rhs, ctx); | |
| 579 | pub fn copy(pool_adapter: @This(), decl_ctype: codegen.CType) codegen.CType { | |
| 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, .{ | |
| 608 | .store = &global_ctypes.set, | |
| 609 | }); | |
| 610 | const global_idx = | |
| 611 | @as(codegen.CType.Index, @intCast(codegen.CType.Tag.no_payload_count + gop.index)); | |
| 612 | f.ctypes_map.appendAssumeCapacity(global_idx); | |
| 613 | if (!gop.found_existing) { | |
| 614 | errdefer _ = global_ctypes.set.map.pop(); | |
| 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 | } | |
| 586 | const decl_ctype = codegen.CType.fromPoolIndex(decl_ctype_pool_index); | |
| 587 | const global_ctype, const found_existing = try global_ctype_pool.getOrPutAdapted( | |
| 588 | gpa, | |
| 589 | decl_ctype_pool, | |
| 590 | decl_ctype, | |
| 591 | PoolAdapter{ .global_from_decl_map = global_from_decl_map.items }, | |
| 592 | ); | |
| 593 | global_from_decl_map.appendAssumeCapacity(global_ctype); | |
| 623 | 594 | try codegen.genTypeDecl( |
| 624 | 595 | zcu, |
| 625 | 596 | writer, |
| 626 | global_ctypes.set, | |
| 627 | global_idx, | |
| 597 | global_ctype_pool, | |
| 598 | global_ctype, | |
| 628 | 599 | pass, |
| 629 | decl_ctypes.set, | |
| 630 | decl_idx, | |
| 631 | gop.found_existing, | |
| 600 | decl_ctype_pool, | |
| 601 | decl_ctype, | |
| 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 | 608 | const gpa = self.base.comp.gpa; |
| 638 | 609 | |
| 639 | 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 | 619 | .pass = .flush, |
| 649 | 620 | .is_naked_fn = false, |
| 650 | 621 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 651 | .ctypes = ctypes.*, | |
| 622 | .ctype_pool = ctype_pool.*, | |
| 623 | .scratch = .{}, | |
| 652 | 624 | .anon_decl_deps = self.anon_decls, |
| 653 | 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 | 631 | defer { |
| 660 | 632 | self.anon_decls = object.dg.anon_decl_deps; |
| 661 | 633 | self.aligned_anon_decls = object.dg.aligned_anon_decls; |
| 662 | object.dg.ctypes.deinit(gpa); | |
| 663 | 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 | 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 | 642 | error.AnalysisFail => unreachable, |
| 669 | 643 | else => |e| return e, |
| 670 | 644 | }; |
| 671 | ||
| 672 | ctypes.* = object.dg.ctypes.move(); | |
| 673 | 645 | } |
| 674 | 646 | |
| 675 | 647 | fn flushLazyFn( |
| 676 | 648 | self: *C, |
| 677 | 649 | zcu: *Zcu, |
| 678 | 650 | mod: *Module, |
| 679 | ctypes: *codegen.CType.Store, | |
| 651 | ctype_pool: *codegen.CType.Pool, | |
| 652 | lazy_ctype_pool: *const codegen.CType.Pool, | |
| 680 | 653 | lazy_fn: codegen.LazyFnMap.Entry, |
| 681 | 654 | ) FlushDeclError!void { |
| 682 | 655 | const gpa = self.base.comp.gpa; |
| ... | ... | @@ -693,7 +666,8 @@ fn flushLazyFn( |
| 693 | 666 | .pass = .flush, |
| 694 | 667 | .is_naked_fn = false, |
| 695 | 668 | .fwd_decl = fwd_decl.toManaged(gpa), |
| 696 | .ctypes = ctypes.*, | |
| 669 | .ctype_pool = ctype_pool.*, | |
| 670 | .scratch = .{}, | |
| 697 | 671 | .anon_decl_deps = .{}, |
| 698 | 672 | .aligned_anon_decls = .{}, |
| 699 | 673 | }, |
| ... | ... | @@ -706,17 +680,17 @@ fn flushLazyFn( |
| 706 | 680 | // `updateFunc()` does. |
| 707 | 681 | assert(object.dg.anon_decl_deps.count() == 0); |
| 708 | 682 | assert(object.dg.aligned_anon_decls.count() == 0); |
| 709 | object.dg.ctypes.deinit(gpa); | |
| 710 | 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 | 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 | 691 | error.AnalysisFail => unreachable, |
| 716 | 692 | else => |e| return e, |
| 717 | 693 | }; |
| 718 | ||
| 719 | ctypes.* = object.dg.ctypes.move(); | |
| 720 | 694 | } |
| 721 | 695 | |
| 722 | 696 | fn flushLazyFns( |
| ... | ... | @@ -724,6 +698,7 @@ fn flushLazyFns( |
| 724 | 698 | zcu: *Zcu, |
| 725 | 699 | mod: *Module, |
| 726 | 700 | f: *Flush, |
| 701 | lazy_ctype_pool: *const codegen.CType.Pool, | |
| 727 | 702 | lazy_fns: codegen.LazyFnMap, |
| 728 | 703 | ) FlushDeclError!void { |
| 729 | 704 | const gpa = self.base.comp.gpa; |
| ... | ... | @@ -734,7 +709,7 @@ fn flushLazyFns( |
| 734 | 709 | const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*); |
| 735 | 710 | if (gop.found_existing) continue; |
| 736 | 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 | 723 | extern_symbol_name: InternPool.OptionalNullTerminatedString, |
| 749 | 724 | ) FlushDeclError!void { |
| 750 | 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 | 727 | try f.all_buffers.ensureUnusedCapacity(gpa, 1); |
| 753 | 728 | fwd_decl: { |
| 754 | 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 | 1223 | atom.getSymbolPtr(self).value = try self.allocateAtom( |
| 1224 | 1224 | atom_index, |
| 1225 | 1225 | atom.size, |
| 1226 | @intCast(required_alignment.toByteUnitsOptional().?), | |
| 1226 | @intCast(required_alignment.toByteUnits().?), | |
| 1227 | 1227 | ); |
| 1228 | 1228 | errdefer self.freeAtom(atom_index); |
| 1229 | 1229 | |
| ... | ... | @@ -1344,7 +1344,7 @@ fn updateLazySymbolAtom( |
| 1344 | 1344 | symbol.section_number = @as(coff.SectionNumber, @enumFromInt(section_index + 1)); |
| 1345 | 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 | 1348 | errdefer self.freeAtom(atom_index); |
| 1349 | 1349 | |
| 1350 | 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 | 1428 | const decl_name = mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)); |
| 1429 | 1429 | |
| 1430 | 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 | 1433 | const decl_metadata = self.decls.get(decl_index).?; |
| 1434 | 1434 | const atom_index = decl_metadata.atom; |
src/link/Elf.zig+1-1| ... | ... | @@ -4051,7 +4051,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4051 | 4051 | const padding = offset - shdr.sh_size; |
| 4052 | 4052 | atom_ptr.value = offset; |
| 4053 | 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 | 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 | 213 | // This function can also reallocate an atom. |
| 214 | 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 | 313 | shdr.sh_addr = 0; |
| 314 | 314 | shdr.sh_offset = 0; |
| 315 | 315 | shdr.sh_size = atom.size; |
| 316 | shdr.sh_addralign = atom.alignment.toByteUnits(1); | |
| 316 | shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1; | |
| 317 | 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 | 330 | const padding = offset - shdr.sh_size; |
| 331 | 331 | atom_ptr.value = offset; |
| 332 | 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 | 63 | const offset = alignment.forward(shdr.sh_size); |
| 64 | 64 | const padding = offset - shdr.sh_size; |
| 65 | 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 | 67 | return offset; |
| 68 | 68 | } |
| 69 | 69 |
src/link/MachO.zig+1-1| ... | ... | @@ -2060,7 +2060,7 @@ fn calcSectionSizes(self: *MachO) !void { |
| 2060 | 2060 | |
| 2061 | 2061 | for (atoms.items) |atom_index| { |
| 2062 | 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 | 2064 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 2065 | 2065 | const padding = offset - header.size; |
| 2066 | 2066 | atom.value = offset; |
src/link/MachO/relocatable.zig+1-1| ... | ... | @@ -380,7 +380,7 @@ fn calcSectionSizes(macho_file: *MachO) !void { |
| 380 | 380 | if (atoms.items.len == 0) continue; |
| 381 | 381 | for (atoms.items) |atom_index| { |
| 382 | 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 | 384 | const offset = mem.alignForward(u64, header.size, atom_alignment); |
| 385 | 385 | const padding = offset - header.size; |
| 386 | 386 | atom.value = offset; |
src/link/Wasm.zig+1-1| ... | ... | @@ -2263,7 +2263,7 @@ fn setupMemory(wasm: *Wasm) !void { |
| 2263 | 2263 | } |
| 2264 | 2264 | if (wasm.findGlobalSymbol("__tls_align")) |loc| { |
| 2265 | 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 | 2268 | if (wasm.findGlobalSymbol("__tls_base")) |loc| { |
| 2269 | 2269 | const sym = loc.getSymbol(wasm); |
src/main.zig+1-5| ... | ... | @@ -3544,11 +3544,7 @@ fn createModule( |
| 3544 | 3544 | // If the target is not overridden, use the parent's target. Of course, |
| 3545 | 3545 | // if this is the root module then we need to proceed to resolve the |
| 3546 | 3546 | // target. |
| 3547 | if (cli_mod.target_arch_os_abi == null and | |
| 3548 | cli_mod.target_mcpu == null and | |
| 3549 | create_module.dynamic_linker == null and | |
| 3550 | create_module.object_format == null) | |
| 3551 | { | |
| 3547 | if (cli_mod.target_arch_os_abi == null and cli_mod.target_mcpu == null) { | |
| 3552 | 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 | 80 | inline .u64, .i64, .big_int => |x| try writer.print("{}", .{x}), |
| 81 | 81 | .lazy_align => |ty| if (opt_sema) |sema| { |
| 82 | 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 | 84 | } else try writer.print("@alignOf({})", .{Type.fromInterned(ty).fmt(mod)}), |
| 85 | 85 | .lazy_size => |ty| if (opt_sema) |sema| { |
| 86 | 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 | 525 | .error_return_trace => use_llvm, |
| 526 | 526 | .is_named_enum_value => use_llvm, |
| 527 | 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 | 529 | .safety_checked_instructions => use_llvm, |
| 530 | 530 | }; |
| 531 | 531 | } |
src/type.zig+25-27| ... | ... | @@ -203,7 +203,7 @@ pub const Type = struct { |
| 203 | 203 | info.flags.alignment |
| 204 | 204 | else |
| 205 | 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 | 208 | if (info.packed_offset.bit_offset != 0 or info.packed_offset.host_size != 0) { |
| 209 | 209 | try writer.print(":{d}:{d}", .{ |
| ... | ... | @@ -863,7 +863,7 @@ pub const Type = struct { |
| 863 | 863 | pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value { |
| 864 | 864 | switch (try ty.abiAlignmentAdvanced(mod, .lazy)) { |
| 865 | 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 | 905 | return .{ .scalar = intAbiAlignment(int_type.bits, target) }; |
| 906 | 906 | }, |
| 907 | 907 | .ptr_type, .anyframe_type => { |
| 908 | return .{ .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)) }; | |
| 908 | return .{ .scalar = ptrAbiAlignment(target) }; | |
| 909 | 909 | }, |
| 910 | 910 | .array_type => |array_type| { |
| 911 | 911 | return Type.fromInterned(array_type.child).abiAlignmentAdvanced(mod, strat); |
| ... | ... | @@ -920,6 +920,9 @@ pub const Type = struct { |
| 920 | 920 | const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes); |
| 921 | 921 | return .{ .scalar = Alignment.fromByteUnits(alignment) }; |
| 922 | 922 | }, |
| 923 | .stage2_c => { | |
| 924 | return Type.fromInterned(vector_type.child).abiAlignmentAdvanced(mod, strat); | |
| 925 | }, | |
| 923 | 926 | .stage2_x86_64 => { |
| 924 | 927 | if (vector_type.child == .bool_type) { |
| 925 | 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 | 969 | |
| 967 | 970 | .usize, |
| 968 | 971 | .isize, |
| 972 | => return .{ .scalar = intAbiAlignment(target.ptrBitWidth(), target) }, | |
| 973 | ||
| 969 | 974 | .export_options, |
| 970 | 975 | .extern_options, |
| 971 | 976 | .type_info, |
| 972 | => return .{ | |
| 973 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | |
| 974 | }, | |
| 977 | => return .{ .scalar = ptrAbiAlignment(target) }, | |
| 975 | 978 | |
| 976 | 979 | .c_char => return .{ .scalar = cTypeAlign(target, .char) }, |
| 977 | 980 | .c_short => return .{ .scalar = cTypeAlign(target, .short) }, |
| ... | ... | @@ -1160,9 +1163,7 @@ pub const Type = struct { |
| 1160 | 1163 | const child_type = ty.optionalChild(mod); |
| 1161 | 1164 | |
| 1162 | 1165 | switch (child_type.zigTypeTag(mod)) { |
| 1163 | .Pointer => return .{ | |
| 1164 | .scalar = Alignment.fromByteUnits(@divExact(target.ptrBitWidth(), 8)), | |
| 1165 | }, | |
| 1166 | .Pointer => return .{ .scalar = ptrAbiAlignment(target) }, | |
| 1166 | 1167 | .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat), |
| 1167 | 1168 | .NoReturn => return .{ .scalar = .@"1" }, |
| 1168 | 1169 | else => {}, |
| ... | ... | @@ -1274,6 +1275,10 @@ pub const Type = struct { |
| 1274 | 1275 | const total_bits = elem_bits * vector_type.len; |
| 1275 | 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 | 1282 | .stage2_x86_64 => total_bytes: { |
| 1278 | 1283 | if (vector_type.child == .bool_type) break :total_bytes std.math.divCeil(u32, vector_type.len, 8) catch unreachable; |
| 1279 | 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 | 1532 | // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal |
| 1528 | 1533 | // to the child type's ABI alignment. |
| 1529 | 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 | 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 | 1548 | return Alignment.fromByteUnits(@min( |
| 1540 | 1549 | std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), |
| 1541 | 1550 | target.maxIntAlignment(), |
| ... | ... | @@ -1572,7 +1581,7 @@ pub const Type = struct { |
| 1572 | 1581 | if (len == 0) return 0; |
| 1573 | 1582 | const elem_ty = Type.fromInterned(array_type.child); |
| 1574 | 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 | 1585 | (try elem_ty.abiSizeAdvanced(mod, strat)).scalar, |
| 1577 | 1586 | ); |
| 1578 | 1587 | if (elem_size == 0) return 0; |
| ... | ... | @@ -3016,26 +3025,15 @@ pub const Type = struct { |
| 3016 | 3025 | } |
| 3017 | 3026 | |
| 3018 | 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 | 3029 | const ip = &mod.intern_pool; |
| 3021 | 3030 | return switch (ip.indexToKey(ty.toIntern())) { |
| 3022 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, field_index), | |
| 3023 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, field_index), | |
| 3031 | .struct_type => ip.loadStructType(ty.toIntern()).fieldName(ip, index), | |
| 3032 | .anon_struct_type => |anon_struct| anon_struct.fieldName(ip, index), | |
| 3024 | 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 | 3037 | pub fn structFieldCount(ty: Type, mod: *Module) u32 { |
| 3040 | 3038 | const ip = &mod.intern_pool; |
| 3041 | 3039 | return switch (ip.indexToKey(ty.toIntern())) { |
test/behavior/align.zig-1| ... | ... | @@ -624,7 +624,6 @@ test "sub-aligned pointer field access" { |
| 624 | 624 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 625 | 625 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 626 | 626 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 627 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 628 | 627 | |
| 629 | 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 | 1176 | test "alignment of vectors" { |
| 1177 | 1177 | try expect(@alignOf(@Vector(2, u8)) == switch (builtin.zig_backend) { |
| 1178 | 1178 | else => 2, |
| 1179 | .stage2_c => @alignOf(u8), | |
| 1179 | 1180 | .stage2_x86_64 => 16, |
| 1180 | 1181 | }); |
| 1181 | 1182 | try expect(@alignOf(@Vector(2, u1)) == switch (builtin.zig_backend) { |
| 1182 | 1183 | else => 1, |
| 1184 | .stage2_c => @alignOf(u1), | |
| 1183 | 1185 | .stage2_x86_64 => 16, |
| 1184 | 1186 | }); |
| 1185 | 1187 | try expect(@alignOf(@Vector(1, u1)) == switch (builtin.zig_backend) { |
| 1186 | 1188 | else => 1, |
| 1189 | .stage2_c => @alignOf(u1), | |
| 1187 | 1190 | .stage2_x86_64 => 16, |
| 1188 | 1191 | }); |
| 1189 | 1192 | try expect(@alignOf(@Vector(2, u16)) == switch (builtin.zig_backend) { |
| 1190 | 1193 | else => 4, |
| 1194 | .stage2_c => @alignOf(u16), | |
| 1191 | 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 | 1164 | compile_c.addCSourceFile(.{ |
| 1165 | 1165 | .file = these_tests.getEmittedBin(), |
| 1166 | 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 | 1169 | "-std=c99", |
| 1169 | 1170 | "-pedantic", |
| 1170 | 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 | 1178 | "-Wno-builtin-requires-header", |
| 1173 | // TODO stop violating these pedantic errors. spotted on linux | |
| 1174 | "-Wno-address-of-packed-member", | |
| 1179 | ||
| 1180 | // spotted on linux | |
| 1175 | 1181 | "-Wno-gnu-folding-constant", |
| 1176 | 1182 | "-Wno-incompatible-function-pointer-types", |
| 1177 | 1183 | "-Wno-incompatible-pointer-types", |
| 1178 | 1184 | "-Wno-overlength-strings", |
| 1179 | // TODO stop violating these pedantic errors. spotted on darwin | |
| 1185 | ||
| 1186 | // spotted on darwin | |
| 1180 | 1187 | "-Wno-dollar-in-identifier-extension", |
| 1181 | 1188 | "-Wno-absolute-value", |
| 1182 | 1189 | }, |
tools/lldb_pretty_printers.py+4-4| ... | ... | @@ -354,7 +354,7 @@ def InstRef_SummaryProvider(value, _=None): |
| 354 | 354 | def InstIndex_SummaryProvider(value, _=None): |
| 355 | 355 | return 'instructions[%d]' % value.unsigned |
| 356 | 356 | |
| 357 | class Module_Decl__Module_Decl_Index_SynthProvider: | |
| 357 | class zig_DeclIndex_SynthProvider: | |
| 358 | 358 | def __init__(self, value, _=None): self.value = value |
| 359 | 359 | def update(self): |
| 360 | 360 | try: |
| ... | ... | @@ -425,7 +425,7 @@ def InternPool_Find(thread): |
| 425 | 425 | for frame in thread: |
| 426 | 426 | ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool') |
| 427 | 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 | 429 | if mod: |
| 430 | 430 | ip = mod.GetChildMemberWithName('intern_pool') |
| 431 | 431 | if ip: return ip |
| ... | ... | @@ -617,7 +617,7 @@ type_tag_handlers = { |
| 617 | 617 | |
| 618 | 618 | def value_Value_str_lit(payload): |
| 619 | 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 | 621 | if mod: break |
| 622 | 622 | else: return |
| 623 | 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 | 714 | add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Index', identifier='InstIndex', summary=True) |
| 715 | 715 | add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) |
| 716 | 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 | 718 | add(debugger, category='zig.stage2', type='Module.Namespace::Module.Namespace.Index', synth=True) |
| 719 | 719 | add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) |
| 720 | 720 | add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) |